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.

3798 lines
108 KiB

  1. // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil -*- (for GNU Emacs)
  2. //
  3. // Copyright (c) 1998-2000 Microsoft Corporation
  4. //
  5. // This file is part of the Microsoft Research IPv6 Network Protocol Stack.
  6. // You should have received a copy of the Microsoft End-User License Agreement
  7. // for this software along with this release; see the file "license.txt".
  8. // If not, please see http://www.research.microsoft.com/msripv6/license.htm,
  9. // or write to Microsoft Research, One Microsoft Way, Redmond, WA 98052-6399.
  10. //
  11. // Abstract:
  12. //
  13. // Dump current IPv6 state information.
  14. //
  15. #include <nt.h>
  16. #include <ntrtl.h>
  17. #include <nturtl.h>
  18. #include <winsock2.h>
  19. #include <ws2tcpip.h>
  20. #include <ws2ip6.h>
  21. #include <wspiapi.h>
  22. #include <ntddip6.h>
  23. #include <ip6.h>
  24. #include <stdio.h>
  25. #include <stdlib.h>
  26. //
  27. // Localization library and MessageIds.
  28. //
  29. #include <nls.h>
  30. #include <winnlsp.h>
  31. #include "localmsg.h"
  32. HANDLE Handle;
  33. int Verbose = FALSE;
  34. int AdminAccess = TRUE;
  35. int Persistent = FALSE;
  36. void QueryInterface(int argc, char *argv[]);
  37. void CreateInterface(int argc, char *argv[]);
  38. void UpdateInterface(int argc, char *argv[]);
  39. void DeleteInterface(int argc, char *argv[]);
  40. void UpdateRouterLinkAddress(int argc, char *argv[]);
  41. void QueryNeighborCache(int argc, char *argv[]);
  42. void QueryRouteCache(int argc, char *argv[]);
  43. void QueryRouteTable(int argc, char *argv[]);
  44. void UpdateRouteTable(int argc, char *argv[]);
  45. void UpdateAddress(int argc, char *argv[]);
  46. void QueryBindingCache(int argc, char *argv[]);
  47. void FlushNeighborCache(int argc, char *argv[]);
  48. void FlushRouteCache(int argc, char *argv[]);
  49. void QuerySitePrefixTable(int argc, char *argv[]);
  50. void UpdateSitePrefixTable(int argc, char *argv[]);
  51. void QueryGlobalParameters(int argc, char *argv[]);
  52. void UpdateGlobalParameters(int argc, char *argv[]);
  53. void QueryPrefixPolicy(int argc, char *argv[]);
  54. void UpdatePrefixPolicy(int argc, char *argv[]);
  55. void DeletePrefixPolicy(int argc, char *argv[]);
  56. void ResetManualConfig(int argc, char *argv[]);
  57. void RenewInterface(int argc, char *argv[]);
  58. void AddOrRemoveIpv6(BOOL fAddIpv6);
  59. BOOL IsIpv6Installed();
  60. void
  61. usage(void)
  62. {
  63. NlsPutMsg(STDOUT, IPV6_MESSAGE_14);
  64. // printf("usage: ipv6 [-p] [-v] if [ifindex]\n");
  65. // printf(" ipv6 [-p] ifcr v6v4 v4src v4dst [nd] [pmld]\n");
  66. // printf(" ipv6 [-p] ifcr 6over4 v4src\n");
  67. // printf(" ipv6 [-p] ifc ifindex [forwards] [-forwards] [advertises] [-advertises] [mtu #bytes] [site site-identifier] [preference P]\n");
  68. // printf(" ipv6 rlu ifindex v4dst\n");
  69. // printf(" ipv6 [-p] ifd ifindex\n");
  70. // printf(" ipv6 [-p] adu ifindex/address [life validlifetime[/preflifetime]] [anycast] [unicast]\n");
  71. // printf(" ipv6 nc [ifindex [address]]\n");
  72. // printf(" ipv6 ncf [ifindex [address]]\n");
  73. // printf(" ipv6 rc [ifindex address]\n");
  74. // printf(" ipv6 rcf [ifindex [address]]\n");
  75. // printf(" ipv6 bc\n");
  76. // printf(" ipv6 [-p] [-v] rt\n");
  77. // printf(" ipv6 [-p] rtu prefix ifindex[/address] [life valid[/pref]] [preference P] [publish] [age] [spl SitePrefixLength]\n");
  78. // printf(" ipv6 spt\n");
  79. // printf(" ipv6 spu prefix ifindex [life L]\n");
  80. // printf(" ipv6 [-p] gp\n");
  81. // printf(" ipv6 [-p] gpu [parameter value] ... (try -?)\n");
  82. // printf(" ipv6 renew [ifindex]\n");
  83. // printf(" ipv6 [-p] ppt\n");
  84. // printf(" ipv6 [-p] ppu prefix precedence P srclabel SL [dstlabel DL]\n");
  85. // printf(" ipv6 [-p] ppd prefix\n");
  86. // printf(" ipv6 [-p] reset\n");
  87. // printf(" ipv6 install\n");
  88. // printf(" ipv6 uninstall\n");
  89. // printf("Some subcommands require local Administrator privileges.\n");
  90. exit(1);
  91. }
  92. void
  93. ausage(void)
  94. {
  95. NlsPutMsg(STDOUT, IPV6_MESSAGE_15);
  96. // printf("You do not have local Administrator privileges.\n");
  97. exit(1);
  98. }
  99. int __cdecl
  100. main(int argc, char **argv)
  101. {
  102. WSADATA wsaData;
  103. int i;
  104. //
  105. // This will ensure the correct language message is displayed when
  106. // NlsPutMsg is called.
  107. //
  108. SetThreadUILanguage(0);
  109. //
  110. // Parse any global options.
  111. //
  112. for (i = 1; i < argc; i++) {
  113. if (!strcmp(argv[i], "-v"))
  114. Verbose = TRUE;
  115. else if (!strcmp(argv[i], "-p"))
  116. Persistent = TRUE;
  117. else
  118. break;
  119. }
  120. argc -= i;
  121. argv += i;
  122. if (argc < 1) {
  123. usage();
  124. }
  125. if (!strcmp(argv[0], "install")) {
  126. if (argc != 1)
  127. usage();
  128. AddOrRemoveIpv6(TRUE);
  129. }
  130. else if (!strcmp(argv[0], "uninstall")) {
  131. if (argc != 1)
  132. usage();
  133. AddOrRemoveIpv6(FALSE);
  134. }
  135. else {
  136. //
  137. // We initialize Winsock only to have access
  138. // to WSAStringToAddress and WSAAddressToString.
  139. //
  140. if (WSAStartup(MAKEWORD(2, 0), &wsaData)) {
  141. NlsPutMsg(STDOUT, IPV6_MESSAGE_18);
  142. // printf("WSAStartup failed\n");
  143. exit(1);
  144. }
  145. //
  146. // First request write access.
  147. // This will fail if the process does not have appropriate privs.
  148. //
  149. Handle = CreateFileW(WIN_IPV6_DEVICE_NAME,
  150. GENERIC_WRITE,
  151. FILE_SHARE_READ | FILE_SHARE_WRITE,
  152. NULL, // security attributes
  153. OPEN_EXISTING,
  154. 0, // flags & attributes
  155. NULL); // template file
  156. if (Handle == INVALID_HANDLE_VALUE) {
  157. //
  158. // We will not have Administrator access to the stack.
  159. //
  160. AdminAccess = FALSE;
  161. Handle = CreateFileW(WIN_IPV6_DEVICE_NAME,
  162. 0,
  163. FILE_SHARE_READ | FILE_SHARE_WRITE,
  164. NULL, // security attributes
  165. OPEN_EXISTING,
  166. 0, // flags & attributes
  167. NULL); // template file
  168. if (Handle == INVALID_HANDLE_VALUE) {
  169. if (IsIpv6Installed()) {
  170. NlsPutMsg(STDOUT, IPV6_MESSAGE_IPV6_NOT_RUNNING);
  171. // printf("Could not access IPv6 protocol stack - the stack is not running.\n");
  172. // printf("To start it, please use 'net start tcpip6'.\n");
  173. } else {
  174. NlsPutMsg(STDOUT, IPV6_MESSAGE_IPV6_NOT_INSTALLED);
  175. // printf("Could not access IPv6 protocol stack - the stack is not installed.\n");
  176. // printf("To install, please use 'ipv6 install'.\n");
  177. }
  178. exit(1);
  179. }
  180. }
  181. if (!strcmp(argv[0], "if")) {
  182. QueryInterface(argc - 1, argv + 1);
  183. }
  184. else if (!strcmp(argv[0], "ifcr")) {
  185. if (! AdminAccess)
  186. ausage();
  187. CreateInterface(argc - 1, argv + 1);
  188. }
  189. else if (!strcmp(argv[0], "ifc")) {
  190. if (! AdminAccess)
  191. ausage();
  192. UpdateInterface(argc - 1, argv + 1);
  193. }
  194. else if (!strcmp(argv[0], "ifd")) {
  195. if (! AdminAccess)
  196. ausage();
  197. DeleteInterface(argc - 1, argv + 1);
  198. }
  199. else if (!strcmp(argv[0], "renew")) {
  200. if (! AdminAccess)
  201. ausage();
  202. RenewInterface(argc - 1, argv + 1);
  203. }
  204. else if (!strcmp(argv[0], "adu")) {
  205. if (! AdminAccess)
  206. ausage();
  207. UpdateAddress(argc - 1, argv + 1);
  208. }
  209. else if (!strcmp(argv[0], "nc")) {
  210. QueryNeighborCache(argc - 1, argv + 1);
  211. }
  212. else if (!strcmp(argv[0], "ncf")) {
  213. if (! AdminAccess)
  214. ausage();
  215. FlushNeighborCache(argc - 1, argv + 1);
  216. }
  217. else if (!strcmp(argv[0], "rc")) {
  218. QueryRouteCache(argc - 1, argv + 1);
  219. }
  220. else if (!strcmp(argv[0], "rcf")) {
  221. if (! AdminAccess)
  222. ausage();
  223. FlushRouteCache(argc - 1, argv + 1);
  224. }
  225. else if (!strcmp(argv[0], "rlu")) {
  226. if (! AdminAccess)
  227. ausage();
  228. UpdateRouterLinkAddress(argc - 1, argv + 1);
  229. }
  230. else if (!strcmp(argv[0], "rt")) {
  231. QueryRouteTable(argc - 1, argv + 1);
  232. }
  233. else if (!strcmp(argv[0], "rtu")) {
  234. if (! AdminAccess)
  235. ausage();
  236. UpdateRouteTable(argc - 1, argv + 1);
  237. }
  238. else if (!strcmp(argv[0], "spt")) {
  239. QuerySitePrefixTable(argc - 1, argv + 1);
  240. }
  241. else if (!strcmp(argv[0], "spu")) {
  242. if (! AdminAccess)
  243. ausage();
  244. UpdateSitePrefixTable(argc - 1, argv + 1);
  245. }
  246. else if (!strcmp(argv[0], "bc")) {
  247. QueryBindingCache(argc - 1, argv + 1);
  248. }
  249. else if (!strcmp(argv[0], "gp")) {
  250. QueryGlobalParameters(argc - 1, argv + 1);
  251. }
  252. else if (!strcmp(argv[0], "gpu")) {
  253. if (! AdminAccess)
  254. ausage();
  255. UpdateGlobalParameters(argc - 1, argv + 1);
  256. }
  257. else if (!strcmp(argv[0], "ppt")) {
  258. QueryPrefixPolicy(argc - 1, argv + 1);
  259. }
  260. else if (!strcmp(argv[0], "ppu")) {
  261. if (! AdminAccess)
  262. ausage();
  263. UpdatePrefixPolicy(argc - 1, argv + 1);
  264. }
  265. else if (!strcmp(argv[0], "ppd")) {
  266. if (! AdminAccess)
  267. ausage();
  268. DeletePrefixPolicy(argc - 1, argv + 1);
  269. }
  270. else if (!strcmp(argv[0], "reset")) {
  271. if (! AdminAccess)
  272. ausage();
  273. ResetManualConfig(argc - 1, argv + 1);
  274. }
  275. else {
  276. usage();
  277. }
  278. }
  279. return 0;
  280. }
  281. int
  282. GetNumber(char *astr, u_int *number)
  283. {
  284. u_int num;
  285. num = 0;
  286. while (*astr != '\0') {
  287. if (('0' <= *astr) && (*astr <= '9'))
  288. num = 10 * num + (*astr - '0');
  289. else
  290. return FALSE;
  291. astr++;
  292. }
  293. *number = num;
  294. return TRUE;
  295. }
  296. int
  297. GetGuid(char *astr, GUID *Guid)
  298. {
  299. WCHAR GuidStr[40+1];
  300. UNICODE_STRING UGuidStr;
  301. MultiByteToWideChar(CP_ACP, 0, astr, -1, GuidStr, 40);
  302. RtlInitUnicodeString(&UGuidStr, GuidStr);
  303. return RtlGUIDFromString(&UGuidStr, Guid) == STATUS_SUCCESS;
  304. }
  305. char *
  306. FormatGuid(const GUID *pGuid)
  307. {
  308. static char buffer[40];
  309. sprintf(buffer,
  310. "{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
  311. pGuid->Data1,
  312. pGuid->Data2,
  313. pGuid->Data3,
  314. pGuid->Data4[0],
  315. pGuid->Data4[1],
  316. pGuid->Data4[2],
  317. pGuid->Data4[3],
  318. pGuid->Data4[4],
  319. pGuid->Data4[5],
  320. pGuid->Data4[6],
  321. pGuid->Data4[7]);
  322. return buffer;
  323. }
  324. int
  325. GetInterface(char *astr, IPV6_QUERY_INTERFACE *Query)
  326. {
  327. if (*astr == '{') {
  328. //
  329. // Read a guid.
  330. //
  331. Query->Index = 0;
  332. return GetGuid(astr, &Query->Guid);
  333. } else {
  334. //
  335. // Read a non-zero interface index.
  336. //
  337. return GetNumber(astr, &Query->Index) && (Query->Index != 0);
  338. }
  339. }
  340. #define SECONDS 1
  341. #define MINUTES (60 * SECONDS)
  342. #define HOURS (60 * MINUTES)
  343. #define DAYS (24 * HOURS)
  344. int
  345. GetLifetime(char *astr, u_int *number)
  346. {
  347. char *pUnit;
  348. u_int units;
  349. u_int value;
  350. *number = 0;
  351. while ((pUnit = strpbrk(astr, "sSmMhHdD")) != NULL) {
  352. switch (*pUnit) {
  353. case 's':
  354. case 'S':
  355. units = SECONDS;
  356. break;
  357. case 'm':
  358. case 'M':
  359. units = MINUTES;
  360. break;
  361. case 'h':
  362. case 'H':
  363. units = HOURS;
  364. break;
  365. case 'd':
  366. case 'D':
  367. units = DAYS;
  368. break;
  369. }
  370. *pUnit = '\0';
  371. if (! GetNumber(astr, &value))
  372. return FALSE;
  373. *number += units * value;
  374. astr = pUnit + 1;
  375. if (*astr == '\0')
  376. return TRUE;
  377. }
  378. if (! GetNumber(astr, &value))
  379. return FALSE;
  380. *number += value;
  381. return TRUE;
  382. }
  383. int
  384. GetLifetimes(char *astr, u_int *valid, u_int *preferred)
  385. {
  386. char *slash;
  387. u_int length;
  388. slash = strchr(astr, '/');
  389. if (slash == NULL) {
  390. if (strcmp(astr, "infinite")) {
  391. if (! GetLifetime(astr, valid))
  392. return FALSE;
  393. if (preferred != NULL)
  394. *preferred = *valid;
  395. }
  396. return TRUE;
  397. }
  398. if (preferred == NULL)
  399. return FALSE;
  400. *slash = '\0';
  401. if (strcmp(astr, "infinite"))
  402. if (! GetLifetime(astr, valid))
  403. return FALSE;
  404. if (strcmp(slash+1, "infinite"))
  405. if (! GetLifetime(slash+1, preferred))
  406. return FALSE;
  407. return TRUE;
  408. }
  409. char *
  410. FormatLifetime(u_int Life)
  411. {
  412. static char buffer[64];
  413. char *s = buffer;
  414. u_int Days, Hours, Minutes;
  415. if (Life == INFINITE_LIFETIME)
  416. return "infinite";
  417. if (Verbose)
  418. goto FormatSeconds;
  419. if (Life < 2 * MINUTES)
  420. goto FormatSeconds;
  421. if (Life < 2 * HOURS)
  422. goto FormatMinutes;
  423. if (Life < 2 * DAYS)
  424. goto FormatHours;
  425. Days = Life / DAYS;
  426. if (Days != 0)
  427. s += sprintf(s, "%ud", Days);
  428. Life -= Days * DAYS;
  429. FormatHours:
  430. Hours = Life / HOURS;
  431. if (Hours != 0)
  432. s += sprintf(s, "%uh", Hours);
  433. Life -= Hours * HOURS;
  434. FormatMinutes:
  435. Minutes = Life / MINUTES;
  436. if (Minutes != 0)
  437. s += sprintf(s, "%um", Minutes);
  438. Life -= Minutes * MINUTES;
  439. if (Life == 0)
  440. return buffer;
  441. FormatSeconds:
  442. (void) sprintf(s, "%us", Life);
  443. return buffer;
  444. }
  445. char *
  446. FormatLifetimes(u_int Valid, u_int Preferred)
  447. {
  448. static char buffer[128];
  449. char *s = buffer;
  450. s += sprintf(s, "%s", FormatLifetime(Valid));
  451. if (Preferred != Valid)
  452. s += sprintf(s, "/%s", FormatLifetime(Preferred));
  453. return buffer;
  454. }
  455. int
  456. GetAddress(char *astr, IPv6Addr *address)
  457. {
  458. struct sockaddr_in6 sin6;
  459. int addrlen = sizeof sin6;
  460. sin6.sin6_family = AF_INET6; // shouldn't be required but is
  461. if ((WSAStringToAddress(astr, AF_INET6, NULL,
  462. (struct sockaddr *)&sin6, &addrlen)
  463. == SOCKET_ERROR) ||
  464. (sin6.sin6_port != 0) ||
  465. (sin6.sin6_scope_id != 0))
  466. return FALSE;
  467. // The user gave us a numeric IPv6 address.
  468. memcpy(address, &sin6.sin6_addr, sizeof *address);
  469. return TRUE;
  470. }
  471. int
  472. GetPrefix(char *astr, IPv6Addr *prefix, u_int *prefixlen)
  473. {
  474. struct sockaddr_in6 sin6;
  475. int addrlen = sizeof sin6;
  476. char *slash;
  477. u_int length;
  478. slash = strchr(astr, '/');
  479. if (slash == NULL)
  480. return FALSE;
  481. *slash = '\0';
  482. if (! GetNumber(slash+1, &length))
  483. return FALSE;
  484. if (length > 128)
  485. return FALSE;
  486. sin6.sin6_family = AF_INET6; // shouldn't be required but is
  487. if ((WSAStringToAddress(astr, AF_INET6, NULL,
  488. (struct sockaddr *)&sin6, &addrlen)
  489. == SOCKET_ERROR) ||
  490. (sin6.sin6_port != 0) ||
  491. (sin6.sin6_scope_id != 0))
  492. return FALSE;
  493. // The user gave us a numeric IPv6 address.
  494. memcpy(prefix, &sin6.sin6_addr, sizeof *prefix);
  495. *prefixlen = length;
  496. return TRUE;
  497. }
  498. const char *PrefixConfStr[] = {
  499. "other", "manual", "well-known", "dhcp", "ra",
  500. NULL
  501. };
  502. #define MAX_PREFIX_CONF (sizeof(PrefixConfStr) / sizeof(char *))
  503. const char *InterfaceIdConfStr[] = {
  504. "other", "manual", "well-known", "dhcp", "LL-address-derived", "random",
  505. NULL
  506. };
  507. #define MAX_IID_CONF (sizeof(InterfaceIdConfStr) / sizeof(char *))
  508. int
  509. GetPrefixOrigin(char *astr, u_int *origin)
  510. {
  511. int i;
  512. for (i=0; PrefixConfStr[i]; i++) {
  513. if (!strcmp(astr, PrefixConfStr[i])) {
  514. *origin = i;
  515. return TRUE;
  516. }
  517. }
  518. return FALSE;
  519. }
  520. int
  521. GetInterfaceIdOrigin(char *astr, u_int *origin)
  522. {
  523. int i;
  524. for (i=0; InterfaceIdConfStr[i]; i++) {
  525. if (!strcmp(astr, InterfaceIdConfStr[i])) {
  526. *origin = i;
  527. return TRUE;
  528. }
  529. }
  530. return FALSE;
  531. }
  532. int
  533. GetNeighbor(char *astr, IPV6_QUERY_INTERFACE *IF, IPv6Addr *addr)
  534. {
  535. struct sockaddr_in6 sin6;
  536. int addrlen = sizeof sin6;
  537. char *slash;
  538. u_int length;
  539. slash = strchr(astr, '/');
  540. if (slash != NULL)
  541. *slash = '\0';
  542. if (! GetInterface(astr, IF))
  543. return FALSE;
  544. if (slash == NULL) {
  545. *addr = in6addr_any;
  546. return TRUE;
  547. }
  548. sin6.sin6_family = AF_INET6; // shouldn't be required but is
  549. if ((WSAStringToAddress(slash+1, AF_INET6, NULL,
  550. (struct sockaddr *)&sin6, &addrlen)
  551. == SOCKET_ERROR) ||
  552. (sin6.sin6_port != 0) ||
  553. (sin6.sin6_scope_id != 0))
  554. return FALSE;
  555. // The user gave us a numeric IPv6 address.
  556. *addr = sin6.sin6_addr;
  557. return TRUE;
  558. }
  559. char *
  560. FormatIPv6Address(IPv6Addr *Address)
  561. {
  562. static char buffer[128];
  563. DWORD buflen = sizeof buffer;
  564. struct sockaddr_in6 sin6;
  565. memset(&sin6, 0, sizeof sin6);
  566. sin6.sin6_family = AF_INET6;
  567. sin6.sin6_addr = *Address;
  568. if (WSAAddressToString((struct sockaddr *) &sin6,
  569. sizeof sin6,
  570. NULL, // LPWSAPROTOCOL_INFO
  571. buffer,
  572. &buflen) == SOCKET_ERROR)
  573. strcpy(buffer, "<invalid>");
  574. return buffer;
  575. }
  576. char *
  577. FormatIPv4Address(struct in_addr *Address)
  578. {
  579. static char buffer[128];
  580. DWORD buflen = sizeof buffer;
  581. struct sockaddr_in sin;
  582. memset(&sin, 0, sizeof sin);
  583. sin.sin_family = AF_INET;
  584. sin.sin_addr = *Address;
  585. if (WSAAddressToString((struct sockaddr *) &sin,
  586. sizeof sin,
  587. NULL, // LPWSAPROTOCOL_INFO
  588. buffer,
  589. &buflen) == SOCKET_ERROR)
  590. strcpy(buffer, "<invalid>");
  591. return buffer;
  592. }
  593. char *
  594. FormatLinkLayerAddress(u_int length, u_char *addr)
  595. {
  596. static char buffer[128];
  597. switch (length) {
  598. case 6: {
  599. int i, digit;
  600. char *s = buffer;
  601. for (i = 0; i < 6; i++) {
  602. if (i != 0)
  603. *s++ = '-';
  604. digit = addr[i] >> 4;
  605. if (digit < 10)
  606. *s++ = digit + '0';
  607. else
  608. *s++ = digit - 10 + 'a';
  609. digit = addr[i] & 0xf;
  610. if (digit < 10)
  611. *s++ = digit + '0';
  612. else
  613. *s++ = digit - 10 + 'a';
  614. }
  615. *s = '\0';
  616. break;
  617. }
  618. case 4:
  619. //
  620. // IPv4 address (6-over-4 link)
  621. //
  622. strcpy(buffer, FormatIPv4Address((struct in_addr *)addr));
  623. break;
  624. case 0:
  625. //
  626. // Null or loop-back address
  627. //
  628. buffer[0] = '\0';
  629. break;
  630. default:
  631. NlsPutMsg(STDOUT, IPV6_MESSAGE_21);
  632. // printf("unrecognized link-layer address format\n");
  633. exit(1);
  634. }
  635. return buffer;
  636. }
  637. void
  638. ForEachAddress(IPV6_INFO_INTERFACE *IF,
  639. void (*func)(IPV6_INFO_INTERFACE *IF, IPV6_INFO_ADDRESS *))
  640. {
  641. IPV6_QUERY_ADDRESS Query;
  642. IPV6_INFO_ADDRESS ADE;
  643. u_int BytesReturned;
  644. Query.IF = IF->This;
  645. Query.Address = in6addr_any;
  646. for (;;) {
  647. if (!DeviceIoControl(Handle, IOCTL_IPV6_QUERY_ADDRESS,
  648. &Query, sizeof Query,
  649. &ADE, sizeof ADE, &BytesReturned,
  650. NULL)) {
  651. NlsPutMsg(STDOUT, IPV6_MESSAGE_22, FormatIPv6Address(&Query.Address));
  652. // printf("bad address %s\n", FormatIPv6Address(&Query.Address));
  653. exit(1);
  654. }
  655. if (!IN6_ADDR_EQUAL(&Query.Address, &in6addr_any)) {
  656. if (BytesReturned != sizeof ADE) {
  657. NlsPutMsg(STDOUT, IPV6_MESSAGE_INCONSISTENT_ADDRESS);
  658. // printf("inconsistent address info length\n");
  659. exit(1);
  660. }
  661. (*func)(IF, &ADE);
  662. }
  663. else {
  664. if (BytesReturned != sizeof ADE.Next) {
  665. NlsPutMsg(STDOUT, IPV6_MESSAGE_INCONSISTENT_ADDRESS);
  666. // printf("inconsistent address info length\n");
  667. exit(1);
  668. }
  669. }
  670. if (IN6_ADDR_EQUAL(&ADE.Next.Address, &in6addr_any))
  671. break;
  672. Query = ADE.Next;
  673. }
  674. }
  675. void
  676. ForEachPersistentAddress(IPV6_INFO_INTERFACE *IF,
  677. void (*func)(IPV6_INFO_INTERFACE *IF, IPV6_UPDATE_ADDRESS *))
  678. {
  679. IPV6_PERSISTENT_QUERY_ADDRESS Query;
  680. IPV6_UPDATE_ADDRESS ADE;
  681. u_int BytesReturned;
  682. Query.IF.RegistryIndex = (u_int) -1;
  683. Query.IF.Guid = IF->This.Guid;
  684. for (Query.RegistryIndex = 0;; Query.RegistryIndex++) {
  685. if (!DeviceIoControl(Handle,
  686. IOCTL_IPV6_PERSISTENT_QUERY_ADDRESS,
  687. &Query, sizeof Query,
  688. &ADE, sizeof ADE, &BytesReturned,
  689. NULL) ||
  690. (BytesReturned != sizeof ADE)) {
  691. if (GetLastError() == ERROR_NO_MORE_ITEMS)
  692. break;
  693. NlsPutMsg(STDOUT, IPV6_MESSAGE_22, FormatIPv6Address(&Query.Address));
  694. // printf("bad address %s\n", FormatIPv6Address(&Query.Address));
  695. exit(1);
  696. }
  697. (*func)(IF, &ADE);
  698. }
  699. }
  700. const char *
  701. FormatDADState(u_int DADState)
  702. {
  703. static char buffer[128];
  704. switch (DADState) {
  705. case DAD_STATE_INVALID:
  706. return "invalid";
  707. case DAD_STATE_DUPLICATE:
  708. return "duplicate";
  709. case DAD_STATE_TENTATIVE:
  710. return "tentative";
  711. case DAD_STATE_DEPRECATED:
  712. return "deprecated";
  713. case DAD_STATE_PREFERRED:
  714. return "preferred";
  715. default:
  716. sprintf(buffer, "DAD state %u>", DADState);
  717. return buffer;
  718. }
  719. }
  720. const char *
  721. FormatScopeAdj(u_int Scope)
  722. {
  723. static char buffer[128];
  724. switch (Scope) {
  725. case ADE_INTERFACE_LOCAL:
  726. return "interface-local";
  727. case ADE_LINK_LOCAL:
  728. return "link-local";
  729. case ADE_SUBNET_LOCAL:
  730. return "subnet-local";
  731. case ADE_ADMIN_LOCAL:
  732. return "admin-local";
  733. case ADE_SITE_LOCAL:
  734. return "site-local";
  735. case ADE_ORG_LOCAL:
  736. return "org-local";
  737. case ADE_GLOBAL:
  738. return "global";
  739. default:
  740. sprintf(buffer, "scope %u", Scope);
  741. return buffer;
  742. }
  743. }
  744. const char *
  745. FormatScopeNoun(u_int Scope)
  746. {
  747. static char buffer[128];
  748. switch (Scope) {
  749. case ADE_INTERFACE_LOCAL:
  750. return "if";
  751. case ADE_LINK_LOCAL:
  752. return "link";
  753. case ADE_SUBNET_LOCAL:
  754. return "subnet";
  755. case ADE_ADMIN_LOCAL:
  756. return "admin";
  757. case ADE_SITE_LOCAL:
  758. return "site";
  759. case ADE_ORG_LOCAL:
  760. return "org";
  761. case ADE_GLOBAL:
  762. return "global";
  763. default:
  764. sprintf(buffer, "zone%u", Scope);
  765. return buffer;
  766. }
  767. }
  768. void
  769. PrintAddrOrigin(u_int PrefixConf, u_int InterfaceIdConf)
  770. {
  771. if ((PrefixConf == PREFIX_CONF_MANUAL) &&
  772. (InterfaceIdConf == IID_CONF_MANUAL)) {
  773. NlsPutMsg(STDOUT, IPV6_MESSAGE_25);
  774. // printf(" (manual)");
  775. } else if ((PrefixConf == PREFIX_CONF_RA) &&
  776. (InterfaceIdConf == IID_CONF_LL_ADDRESS)) {
  777. NlsPutMsg(STDOUT, IPV6_MESSAGE_26);
  778. // printf(" (public)");
  779. } else if ((PrefixConf == PREFIX_CONF_RA) &&
  780. (InterfaceIdConf == IID_CONF_RANDOM)) {
  781. NlsPutMsg(STDOUT, IPV6_MESSAGE_27);
  782. // printf(" (temporary)");
  783. } else if ((PrefixConf == PREFIX_CONF_DHCP) &&
  784. (InterfaceIdConf == IID_CONF_DHCP)) {
  785. NlsPutMsg(STDOUT, IPV6_MESSAGE_28);
  786. // printf(" (dhcp)");
  787. }
  788. if (Verbose) {
  789. //
  790. // Show prefix origin / interface id origin
  791. //
  792. NlsPutMsg(STDOUT, IPV6_MESSAGE_29);
  793. // printf(" (");
  794. if (PrefixConf >= MAX_PREFIX_CONF)
  795. NlsPutMsg(STDOUT, IPV6_MESSAGE_30, PrefixConf);
  796. // printf("unknown prefix origin %u", PrefixConf);
  797. else
  798. printf(PrefixConfStr[PrefixConf]);
  799. NlsPutMsg(STDOUT, IPV6_MESSAGE_32);
  800. // printf("/");
  801. if (InterfaceIdConf >= MAX_IID_CONF)
  802. NlsPutMsg(STDOUT, IPV6_MESSAGE_33, InterfaceIdConf);
  803. // printf("unknown ifid origin %u", InterfaceIdConf);
  804. else
  805. printf(InterfaceIdConfStr[InterfaceIdConf]);
  806. NlsPutMsg(STDOUT, IPV6_MESSAGE_35);
  807. // printf(")");
  808. }
  809. }
  810. void
  811. PrintAddress(IPV6_INFO_INTERFACE *IF, IPV6_INFO_ADDRESS *ADE)
  812. {
  813. if (!Verbose) {
  814. //
  815. // Suppress invalid addresses.
  816. //
  817. if ((ADE->Type == ADE_UNICAST) &&
  818. (ADE->DADState == DAD_STATE_INVALID))
  819. return;
  820. }
  821. switch (ADE->Type) {
  822. case ADE_UNICAST:
  823. NlsPutMsg(STDOUT, IPV6_MESSAGE_23,
  824. FormatDADState(ADE->DADState),
  825. FormatScopeAdj(ADE->Scope),
  826. FormatIPv6Address(&ADE->This.Address));
  827. // printf(" %s %s %s, ",
  828. // FormatDADState(ADE->DADState),
  829. // FormatScopeAdj(ADE->Scope),
  830. // FormatIPv6Address(&ADE->This.Address));
  831. NlsPutMsg(STDOUT, IPV6_MESSAGE_24,
  832. FormatLifetimes(ADE->ValidLifetime, ADE->PreferredLifetime));
  833. // printf("life %s",
  834. // FormatLifetimes(ADE->ValidLifetime, ADE->PreferredLifetime));
  835. PrintAddrOrigin(ADE->PrefixConf, ADE->InterfaceIdConf);
  836. NlsPutMsg(STDOUT, IPV6_MESSAGE_36);
  837. // printf("\n");
  838. break;
  839. case ADE_ANYCAST:
  840. NlsPutMsg(STDOUT, IPV6_MESSAGE_37,
  841. FormatScopeAdj(ADE->Scope),
  842. FormatIPv6Address(&ADE->This.Address));
  843. // printf(" anycast %s %s\n",
  844. // FormatScopeAdj(ADE->Scope),
  845. // FormatIPv6Address(&ADE->This.Address));
  846. break;
  847. case ADE_MULTICAST:
  848. NlsPutMsg(STDOUT, IPV6_MESSAGE_38,
  849. FormatScopeAdj(ADE->Scope),
  850. FormatIPv6Address(&ADE->This.Address),
  851. ADE->MCastRefCount);
  852. // printf(" multicast %s %s, %u refs",
  853. // FormatScopeAdj(ADE->Scope),
  854. // FormatIPv6Address(&ADE->This.Address),
  855. // ADE->MCastRefCount);
  856. if (!(ADE->MCastFlags & 0x01))
  857. NlsPutMsg(STDOUT, IPV6_MESSAGE_39);
  858. // printf(", not reportable");
  859. if (ADE->MCastFlags & 0x02)
  860. NlsPutMsg(STDOUT, IPV6_MESSAGE_40);
  861. // printf(", last reporter");
  862. if (ADE->MCastTimer != 0)
  863. NlsPutMsg(STDOUT, IPV6_MESSAGE_41, ADE->MCastTimer);
  864. // printf(", %u seconds until report", ADE->MCastTimer);
  865. NlsPutMsg(STDOUT, IPV6_MESSAGE_36);
  866. // printf("\n");
  867. break;
  868. default:
  869. NlsPutMsg(STDOUT, IPV6_MESSAGE_42,
  870. FormatScopeAdj(ADE->Scope), ADE->Type);
  871. // printf(" unknown %s address type %u\n",
  872. // FormatScopeAdj(ADE->Scope), ADE->Type);
  873. break;
  874. }
  875. }
  876. u_int
  877. AddressScope(IPv6Addr *Address)
  878. {
  879. if (IN6_IS_ADDR_LINKLOCAL(Address))
  880. return ADE_LINK_LOCAL;
  881. else if (IN6_IS_ADDR_SITELOCAL(Address))
  882. return ADE_SITE_LOCAL;
  883. else if (IN6_IS_ADDR_LOOPBACK(Address))
  884. return ADE_LINK_LOCAL;
  885. else
  886. return ADE_GLOBAL;
  887. }
  888. void
  889. PrintPersistentAddress(IPV6_INFO_INTERFACE *IF, IPV6_UPDATE_ADDRESS *ADE)
  890. {
  891. NlsPutMsg(STDOUT, IPV6_MESSAGE_23,
  892. ((ADE->Type == ADE_ANYCAST) ?
  893. "anycast" :
  894. FormatDADState((ADE->PreferredLifetime == 0) ?
  895. DAD_STATE_DEPRECATED : DAD_STATE_PREFERRED)),
  896. FormatScopeAdj(AddressScope(&ADE->This.Address)),
  897. FormatIPv6Address(&ADE->This.Address));
  898. // printf(" %s %s %s, ",
  899. NlsPutMsg(STDOUT, IPV6_MESSAGE_24,
  900. FormatLifetimes(ADE->ValidLifetime, ADE->PreferredLifetime));
  901. // printf("life %s",
  902. PrintAddrOrigin(ADE->PrefixConf, ADE->InterfaceIdConf);
  903. NlsPutMsg(STDOUT, IPV6_MESSAGE_36);
  904. // printf("\n");
  905. }
  906. IPV6_INFO_INTERFACE *
  907. GetInterfaceInfo(IPV6_QUERY_INTERFACE *Query)
  908. {
  909. IPV6_INFO_INTERFACE *IF;
  910. u_int InfoSize, BytesReturned;
  911. InfoSize = sizeof *IF + 2 * MAX_LINK_LAYER_ADDRESS_LENGTH;
  912. IF = malloc(InfoSize);
  913. if (IF == NULL) {
  914. NlsPutMsg(STDOUT, IPV6_MESSAGE_43);
  915. // printf("malloc failed\n");
  916. exit(1);
  917. }
  918. if (!DeviceIoControl(Handle,
  919. IOCTL_IPV6_QUERY_INTERFACE,
  920. Query, sizeof *Query,
  921. IF, InfoSize, &BytesReturned,
  922. NULL)) {
  923. NlsPutMsg(STDOUT, IPV6_MESSAGE_44, Query->Index);
  924. // printf("bad index %u\n", Query->Index);
  925. exit(1);
  926. }
  927. if ((BytesReturned < sizeof *IF) ||
  928. (IF->Length < sizeof *IF) ||
  929. (BytesReturned != IF->Length +
  930. ((IF->LocalLinkLayerAddress != 0) ?
  931. IF->LinkLayerAddressLength : 0) +
  932. ((IF->RemoteLinkLayerAddress != 0) ?
  933. IF->LinkLayerAddressLength : 0))) {
  934. NlsPutMsg(STDOUT, IPV6_MESSAGE_45);
  935. // printf("inconsistent interface info length\n");
  936. exit(1);
  937. }
  938. return IF;
  939. }
  940. IPV6_INFO_INTERFACE *
  941. GetPersistentInterfaceInfo(IPV6_PERSISTENT_QUERY_INTERFACE *Query)
  942. {
  943. IPV6_INFO_INTERFACE *IF;
  944. u_int InfoSize, BytesReturned;
  945. InfoSize = sizeof *IF + 2 * MAX_LINK_LAYER_ADDRESS_LENGTH;
  946. IF = malloc(InfoSize);
  947. if (IF == NULL) {
  948. NlsPutMsg(STDOUT, IPV6_MESSAGE_43);
  949. // printf("malloc failed\n");
  950. exit(1);
  951. }
  952. if (!DeviceIoControl(Handle,
  953. IOCTL_IPV6_PERSISTENT_QUERY_INTERFACE,
  954. Query, sizeof *Query,
  955. IF, InfoSize, &BytesReturned,
  956. NULL)) {
  957. NlsPutMsg(STDOUT, IPV6_MESSAGE_44, Query->RegistryIndex);
  958. // printf("bad index %u\n", Query->RegistryIndex);
  959. exit(1);
  960. }
  961. if ((BytesReturned < sizeof *IF) ||
  962. (IF->Length < sizeof *IF) ||
  963. (BytesReturned != IF->Length +
  964. ((IF->LocalLinkLayerAddress != 0) ?
  965. IF->LinkLayerAddressLength : 0) +
  966. ((IF->RemoteLinkLayerAddress != 0) ?
  967. IF->LinkLayerAddressLength : 0))) {
  968. NlsPutMsg(STDOUT, IPV6_MESSAGE_45);
  969. // printf("inconsistent interface info length\n");
  970. exit(1);
  971. }
  972. return IF;
  973. }
  974. void
  975. ForEachInterface(void (*func)(IPV6_INFO_INTERFACE *))
  976. {
  977. IPV6_QUERY_INTERFACE Query;
  978. IPV6_INFO_INTERFACE *IF;
  979. u_int InfoSize, BytesReturned;
  980. InfoSize = sizeof *IF + 2 * MAX_LINK_LAYER_ADDRESS_LENGTH;
  981. IF = malloc(InfoSize);
  982. if (IF == NULL) {
  983. NlsPutMsg(STDOUT, IPV6_MESSAGE_43);
  984. // printf("malloc failed\n");
  985. exit(1);
  986. }
  987. Query.Index = (u_int) -1;
  988. for (;;) {
  989. if (!DeviceIoControl(Handle, IOCTL_IPV6_QUERY_INTERFACE,
  990. &Query, sizeof Query,
  991. IF, InfoSize, &BytesReturned,
  992. NULL)) {
  993. NlsPutMsg(STDOUT, IPV6_MESSAGE_46, Query.Index);
  994. // printf("bad index %u\n", Query.Index);
  995. exit(1);
  996. }
  997. if (Query.Index != (u_int) -1) {
  998. if ((BytesReturned < sizeof *IF) ||
  999. (IF->Length < sizeof *IF) ||
  1000. (BytesReturned != IF->Length +
  1001. ((IF->LocalLinkLayerAddress != 0) ?
  1002. IF->LinkLayerAddressLength : 0) +
  1003. ((IF->RemoteLinkLayerAddress != 0) ?
  1004. IF->LinkLayerAddressLength : 0))) {
  1005. NlsPutMsg(STDOUT, IPV6_MESSAGE_45);
  1006. // printf("inconsistent interface info length\n");
  1007. exit(1);
  1008. }
  1009. (*func)(IF);
  1010. }
  1011. else {
  1012. if (BytesReturned != sizeof IF->Next) {
  1013. NlsPutMsg(STDOUT, IPV6_MESSAGE_45);
  1014. // printf("inconsistent interface info length\n");
  1015. exit(1);
  1016. }
  1017. }
  1018. if (IF->Next.Index == (u_int) -1)
  1019. break;
  1020. Query = IF->Next;
  1021. }
  1022. free(IF);
  1023. }
  1024. void
  1025. ForEachPersistentInterface(void (*func)(IPV6_INFO_INTERFACE *))
  1026. {
  1027. IPV6_PERSISTENT_QUERY_INTERFACE Query;
  1028. IPV6_INFO_INTERFACE *IF;
  1029. u_int InfoSize, BytesReturned;
  1030. InfoSize = sizeof *IF + 2 * MAX_LINK_LAYER_ADDRESS_LENGTH;
  1031. IF = malloc(InfoSize);
  1032. if (IF == NULL) {
  1033. NlsPutMsg(STDOUT, IPV6_MESSAGE_43);
  1034. // printf("malloc failed\n");
  1035. exit(1);
  1036. }
  1037. for (Query.RegistryIndex = 0;; Query.RegistryIndex++) {
  1038. if (!DeviceIoControl(Handle,
  1039. IOCTL_IPV6_PERSISTENT_QUERY_INTERFACE,
  1040. &Query, sizeof Query,
  1041. IF, InfoSize, &BytesReturned,
  1042. NULL)) {
  1043. if (GetLastError() == ERROR_NO_MORE_ITEMS)
  1044. break;
  1045. NlsPutMsg(STDOUT, IPV6_MESSAGE_46, Query.RegistryIndex);
  1046. // printf("bad index %u\n", Query.RegistryIndex);
  1047. exit(1);
  1048. }
  1049. if ((BytesReturned < sizeof *IF) ||
  1050. (IF->Length < sizeof *IF) ||
  1051. (BytesReturned != IF->Length +
  1052. ((IF->LocalLinkLayerAddress != 0) ?
  1053. IF->LinkLayerAddressLength : 0) +
  1054. ((IF->RemoteLinkLayerAddress != 0) ?
  1055. IF->LinkLayerAddressLength : 0))) {
  1056. NlsPutMsg(STDOUT, IPV6_MESSAGE_45);
  1057. // printf("inconsistent interface info length\n");
  1058. exit(1);
  1059. }
  1060. (*func)(IF);
  1061. }
  1062. free(IF);
  1063. }
  1064. #ifndef IP_TYPES_INCLUDED
  1065. //
  1066. // The real version of this structure in iptypes.h
  1067. // has more fields, but these are all we need here.
  1068. //
  1069. #define MAX_ADAPTER_DESCRIPTION_LENGTH 128 // arb.
  1070. #define MAX_ADAPTER_NAME_LENGTH 256 // arb.
  1071. #define MAX_ADAPTER_ADDRESS_LENGTH 8 // arb.
  1072. typedef struct _IP_ADAPTER_INFO {
  1073. struct _IP_ADAPTER_INFO* Next;
  1074. DWORD ComboIndex;
  1075. char AdapterName[MAX_ADAPTER_NAME_LENGTH + 4];
  1076. char Description[MAX_ADAPTER_DESCRIPTION_LENGTH + 4];
  1077. UINT AddressLength;
  1078. BYTE Address[MAX_ADAPTER_ADDRESS_LENGTH];
  1079. DWORD Index;
  1080. } IP_ADAPTER_INFO;
  1081. #endif // IP_TYPES_INCLUDED
  1082. DWORD (WINAPI *pGetAdaptersInfo)(IP_ADAPTER_INFO *pAdapterInfo, ULONG *pOutBufLen);
  1083. IP_ADAPTER_INFO *pAdapterInfo;
  1084. HRESULT (WINAPI *pHrLanConnectionNameFromGuidOrPath)(
  1085. const GUID *pGuid,
  1086. LPCWSTR pszwPath,
  1087. LPWSTR pszwName,
  1088. LPDWORD pcchMax);
  1089. #define IPHLPAPI_LIBRARY_NAME "iphlpapi.dll"
  1090. #define NETMAN_LIBRARY_NAME "netman.dll"
  1091. void
  1092. InitializeAdaptersInfo(void)
  1093. {
  1094. HMODULE hModule;
  1095. CHAR SystemDir[MAX_PATH + 1];
  1096. CHAR Path[MAX_PATH + sizeof(IPHLPAPI_LIBRARY_NAME) + 2];
  1097. pAdapterInfo = NULL;
  1098. if (GetSystemDirectory(SystemDir, MAX_PATH) == 0) {
  1099. return;
  1100. }
  1101. //
  1102. // Check if the GetAdaptersInfo API is available on this system.
  1103. //
  1104. lstrcpy(Path, SystemDir);
  1105. lstrcat(Path, "\\" IPHLPAPI_LIBRARY_NAME);
  1106. hModule = LoadLibrary(Path);
  1107. if (hModule != NULL) {
  1108. pGetAdaptersInfo = (DWORD (WINAPI *)(IP_ADAPTER_INFO *, ULONG *))
  1109. GetProcAddress(hModule, "GetAdaptersInfo");
  1110. //
  1111. // We don't release hModule, to keep the module loaded.
  1112. //
  1113. if (pGetAdaptersInfo != NULL) {
  1114. ULONG BufLen = 0;
  1115. DWORD error;
  1116. //
  1117. // If this returns something other than buffer-overflow,
  1118. // it probably means that GetAdaptersInfo is not supported.
  1119. //
  1120. error = (*pGetAdaptersInfo)(NULL, &BufLen);
  1121. if (error == ERROR_BUFFER_OVERFLOW) {
  1122. pAdapterInfo = (IP_ADAPTER_INFO *) malloc(BufLen);
  1123. if (pAdapterInfo != NULL) {
  1124. error = (*pGetAdaptersInfo)(pAdapterInfo, &BufLen);
  1125. if (error != 0) {
  1126. free(pAdapterInfo);
  1127. pAdapterInfo = NULL;
  1128. }
  1129. }
  1130. }
  1131. }
  1132. }
  1133. //
  1134. // Only bother with HrLanConnectionNameFromGuidOrPath
  1135. // if we could get pAdapterInfo.
  1136. //
  1137. if (pAdapterInfo != NULL) {
  1138. lstrcpy(Path, SystemDir);
  1139. lstrcat(Path, "\\" NETMAN_LIBRARY_NAME);
  1140. hModule = LoadLibrary(Path);
  1141. if (hModule != NULL) {
  1142. pHrLanConnectionNameFromGuidOrPath =
  1143. (HRESULT (WINAPI *)(const GUID *, LPCWSTR, LPWSTR, LPDWORD))
  1144. GetProcAddress(hModule, "HrLanConnectionNameFromGuidOrPath");
  1145. //
  1146. // We don't release hModule, to keep the module loaded.
  1147. //
  1148. }
  1149. if (pHrLanConnectionNameFromGuidOrPath == NULL) {
  1150. free(pAdapterInfo);
  1151. pAdapterInfo = NULL;
  1152. }
  1153. }
  1154. }
  1155. #define MAX_FRIENDLY_NAME_LENGTH 2000
  1156. LPSTR
  1157. MapAdapterNameToFriendly(LPSTR AdapterName)
  1158. {
  1159. WCHAR wszAdapterName[MAX_ADAPTER_NAME_LENGTH];
  1160. WCHAR wszFriendlyName[MAX_FRIENDLY_NAME_LENGTH];
  1161. DWORD cchFriendlyName = MAX_FRIENDLY_NAME_LENGTH;
  1162. static CHAR FriendlyName[MAX_FRIENDLY_NAME_LENGTH];
  1163. MultiByteToWideChar(CP_ACP, 0, AdapterName, -1,
  1164. wszAdapterName, MAX_ADAPTER_NAME_LENGTH);
  1165. if((*pHrLanConnectionNameFromGuidOrPath)(
  1166. NULL, wszAdapterName, wszFriendlyName, &cchFriendlyName))
  1167. return NULL;
  1168. WideCharToMultiByte(CP_ACP, 0, wszFriendlyName, -1,
  1169. FriendlyName, MAX_FRIENDLY_NAME_LENGTH,
  1170. NULL, NULL);
  1171. return FriendlyName;
  1172. }
  1173. LPSTR
  1174. MapAdapterAddressToFriendly(u_char *Address, u_int AddressLength)
  1175. {
  1176. IP_ADAPTER_INFO *pAdapter;
  1177. for (pAdapter = pAdapterInfo;
  1178. pAdapter != NULL;
  1179. pAdapter = pAdapter->Next) {
  1180. if ((AddressLength == pAdapter->AddressLength) &&
  1181. ! memcmp(Address, pAdapter->Address, AddressLength))
  1182. return MapAdapterNameToFriendly(pAdapter->AdapterName);
  1183. }
  1184. return NULL;
  1185. }
  1186. int
  1187. ShouldPrintZones(IPV6_INFO_INTERFACE *IF)
  1188. {
  1189. u_int Scope;
  1190. for (Scope = ADE_SMALLEST_SCOPE; Scope <= ADE_LINK_LOCAL; Scope++)
  1191. if (IF->ZoneIndices[Scope] != IF->This.Index)
  1192. return TRUE;
  1193. for (; Scope <= ADE_LARGEST_SCOPE; Scope++)
  1194. if (IF->ZoneIndices[Scope] != 1)
  1195. return TRUE;
  1196. return FALSE;
  1197. }
  1198. void
  1199. PrintInterface(IPV6_INFO_INTERFACE *IF)
  1200. {
  1201. LPSTR FriendlyName;
  1202. u_int Scope;
  1203. if (IF->LocalLinkLayerAddress == 0)
  1204. FriendlyName = NULL;
  1205. else
  1206. FriendlyName = MapAdapterAddressToFriendly(
  1207. (u_char *)IF + IF->LocalLinkLayerAddress,
  1208. IF->LinkLayerAddressLength);
  1209. NlsPutMsg(STDOUT, IPV6_MESSAGE_47, IF->This.Index);
  1210. // printf("Interface %u:", IF->This.Index);
  1211. switch (IF->Type) {
  1212. case IPV6_IF_TYPE_LOOPBACK:
  1213. NlsPutMsg(STDOUT, IPV6_MESSAGE_48);
  1214. // printf(" Loopback Pseudo-Interface");
  1215. break;
  1216. case IPV6_IF_TYPE_ETHERNET:
  1217. NlsPutMsg(STDOUT, IPV6_MESSAGE_49);
  1218. // printf(" Ethernet");
  1219. break;
  1220. case IPV6_IF_TYPE_FDDI:
  1221. NlsPutMsg(STDOUT, IPV6_MESSAGE_50);
  1222. // printf(" FDDI");
  1223. break;
  1224. case IPV6_IF_TYPE_TUNNEL_AUTO:
  1225. NlsPutMsg(STDOUT, IPV6_MESSAGE_51);
  1226. // printf(" Automatic Tunneling Pseudo-Interface");
  1227. break;
  1228. case IPV6_IF_TYPE_TUNNEL_6OVER4:
  1229. NlsPutMsg(STDOUT, IPV6_MESSAGE_52);
  1230. // printf(" 6-over-4 Virtual Interface");
  1231. break;
  1232. case IPV6_IF_TYPE_TUNNEL_V6V4:
  1233. NlsPutMsg(STDOUT, IPV6_MESSAGE_53);
  1234. // printf(" Configured Tunnel Interface");
  1235. break;
  1236. case IPV6_IF_TYPE_TUNNEL_6TO4:
  1237. NlsPutMsg(STDOUT, IPV6_6TO4_INTERFACE);
  1238. // printf(" 6to4 Tunneling Pseudo-Interface");
  1239. break;
  1240. case IPV6_IF_TYPE_TUNNEL_TEREDO:
  1241. NlsPutMsg(STDOUT, IPV6_TEREDO_INTERFACE);
  1242. // printf(" Teredo Tunneling Pseudo-Interface");
  1243. break;
  1244. }
  1245. if (FriendlyName != NULL)
  1246. NlsPutMsg(STDOUT, IPV6_MESSAGE_54, FriendlyName);
  1247. // printf(": %s", FriendlyName);
  1248. NlsPutMsg(STDOUT, IPV6_MESSAGE_36);
  1249. // printf("\n");
  1250. NlsPutMsg(STDOUT, IPV6_MESSAGE_GUID, FormatGuid(&IF->This.Guid));
  1251. // printf(" Guid %s\n", FormatGuid(&IF->This.Guid));
  1252. if (Verbose || ShouldPrintZones(IF)) {
  1253. NlsPutMsg(STDOUT, IPV6_MESSAGE_55);
  1254. // printf(" zones:");
  1255. for (Scope = ADE_LINK_LOCAL; Scope < ADE_GLOBAL; Scope++) {
  1256. u_int Expected;
  1257. if ((Scope == ADE_LINK_LOCAL) ||
  1258. (Scope == ADE_SITE_LOCAL))
  1259. Expected = 0; // Always print link & site.
  1260. else
  1261. Expected = IF->ZoneIndices[Scope + 1];
  1262. if (IF->ZoneIndices[Scope] != Expected)
  1263. NlsPutMsg(STDOUT, IPV6_MESSAGE_56,
  1264. FormatScopeNoun(Scope),
  1265. IF->ZoneIndices[Scope]);
  1266. // printf(" %s %u",
  1267. // FormatScopeNoun(Scope),
  1268. // IF->ZoneIndices[Scope]);
  1269. }
  1270. NlsPutMsg(STDOUT, IPV6_MESSAGE_36);
  1271. // printf("\n");
  1272. }
  1273. switch (IF->MediaStatus) {
  1274. case IPV6_IF_MEDIA_STATUS_DISCONNECTED:
  1275. NlsPutMsg(STDOUT, IPV6_MESSAGE_57);
  1276. // printf(" cable unplugged\n");
  1277. break;
  1278. case IPV6_IF_MEDIA_STATUS_RECONNECTED:
  1279. NlsPutMsg(STDOUT, IPV6_MESSAGE_58);
  1280. // printf(" cable reconnected\n");
  1281. break;
  1282. case IPV6_IF_MEDIA_STATUS_CONNECTED:
  1283. break;
  1284. }
  1285. if (IF->NeighborDiscovers)
  1286. NlsPutMsg(STDOUT, IPV6_MESSAGE_USES_ND);
  1287. // printf(" uses Neighbor Discovery\n");
  1288. else
  1289. NlsPutMsg(STDOUT, IPV6_MESSAGE_DOESNT_USE_ND);
  1290. // printf(" does not use Neighbor Discovery\n");
  1291. if (IF->RouterDiscovers)
  1292. NlsPutMsg(STDOUT, IPV6_MESSAGE_USES_RD);
  1293. else
  1294. NlsPutMsg(STDOUT, IPV6_MESSAGE_DOESNT_USE_RD);
  1295. if (IF->Advertises)
  1296. NlsPutMsg(STDOUT, IPV6_MESSAGE_SENDS_RAs);
  1297. // printf(" sends Router Advertisements\n");
  1298. if (IF->Forwards)
  1299. NlsPutMsg(STDOUT, IPV6_MESSAGE_FORWARDS);
  1300. // printf(" forwards packets\n");
  1301. if (IF->PeriodicMLD)
  1302. NlsPutMsg(STDOUT, IPV6_MESSAGE_SENDS_PERIODIC_MLD);
  1303. // printf(" periodically sends MLD Reports\n");
  1304. if (IF->Preference != 0)
  1305. NlsPutMsg(STDOUT, IPV6_MESSAGE_64, IF->Preference);
  1306. // printf(" routing preference %u\n", IF->Preference);
  1307. if (IF->Type == IPV6_IF_TYPE_TUNNEL_AUTO) {
  1308. if (IF->LocalLinkLayerAddress != 0) {
  1309. NlsPutMsg(STDOUT, IPV6_MESSAGE_TOKEN_ADDRESS,
  1310. FormatLinkLayerAddress(IF->LinkLayerAddressLength,
  1311. (u_char *)IF + IF->LocalLinkLayerAddress));
  1312. // printf(" EUI-64 embedded IPv4 address: %s\n",
  1313. }
  1314. if (IF->RemoteLinkLayerAddress != 0) {
  1315. NlsPutMsg(STDOUT, IPV6_MESSAGE_ROUTER_LL_ADDRESS,
  1316. FormatLinkLayerAddress(IF->LinkLayerAddressLength,
  1317. (u_char *)IF + IF->RemoteLinkLayerAddress));
  1318. // printf(" router link-layer address: %s\n",
  1319. }
  1320. }
  1321. else {
  1322. if (IF->LocalLinkLayerAddress != 0) {
  1323. NlsPutMsg(STDOUT, IPV6_MESSAGE_65,
  1324. FormatLinkLayerAddress(IF->LinkLayerAddressLength,
  1325. (u_char *)IF + IF->LocalLinkLayerAddress));
  1326. // printf(" link-layer address: %s\n",
  1327. }
  1328. if (IF->RemoteLinkLayerAddress != 0) {
  1329. NlsPutMsg(STDOUT, IPV6_MESSAGE_66,
  1330. FormatLinkLayerAddress(IF->LinkLayerAddressLength,
  1331. (u_char *)IF + IF->RemoteLinkLayerAddress));
  1332. // printf(" remote link-layer address: %s\n",
  1333. }
  1334. }
  1335. ForEachAddress(IF, PrintAddress);
  1336. NlsPutMsg(STDOUT, IPV6_MESSAGE_67, IF->LinkMTU, IF->TrueLinkMTU);
  1337. // printf(" link MTU %u (true link MTU %u)\n",
  1338. // IF->LinkMTU, IF->TrueLinkMTU);
  1339. NlsPutMsg(STDOUT, IPV6_MESSAGE_68, IF->CurHopLimit);
  1340. // printf(" current hop limit %u\n", IF->CurHopLimit);
  1341. NlsPutMsg(STDOUT, IPV6_MESSAGE_69,
  1342. IF->ReachableTime, IF->BaseReachableTime);
  1343. // printf(" reachable time %ums (base %ums)\n",
  1344. // IF->ReachableTime, IF->BaseReachableTime);
  1345. NlsPutMsg(STDOUT, IPV6_MESSAGE_70, IF->RetransTimer);
  1346. // printf(" retransmission interval %ums\n", IF->RetransTimer);
  1347. NlsPutMsg(STDOUT, IPV6_MESSAGE_71, IF->DupAddrDetectTransmits);
  1348. // printf(" DAD transmits %u\n", IF->DupAddrDetectTransmits);
  1349. NlsPutMsg(STDOUT, IPV6_MESSAGE_DEFAULT_SITE_PREFIX_LENGTH,
  1350. IF->DefSitePrefixLength);
  1351. // printf(" default site prefix length %u\n",
  1352. }
  1353. void
  1354. PrintPersistentInterface(IPV6_INFO_INTERFACE *IF)
  1355. {
  1356. u_int Scope;
  1357. NlsPutMsg(STDOUT, IPV6_MESSAGE_INTERFACE);
  1358. // printf("Interface:"
  1359. switch (IF->Type) {
  1360. case IPV6_IF_TYPE_LOOPBACK:
  1361. NlsPutMsg(STDOUT, IPV6_MESSAGE_48);
  1362. // printf(" Loopback Pseudo-Interface");
  1363. break;
  1364. case IPV6_IF_TYPE_ETHERNET:
  1365. NlsPutMsg(STDOUT, IPV6_MESSAGE_49);
  1366. // printf(" Ethernet");
  1367. break;
  1368. case IPV6_IF_TYPE_FDDI:
  1369. NlsPutMsg(STDOUT, IPV6_MESSAGE_50);
  1370. // printf(" FDDI");
  1371. break;
  1372. case IPV6_IF_TYPE_TUNNEL_AUTO:
  1373. NlsPutMsg(STDOUT, IPV6_MESSAGE_51);
  1374. // printf(" Automatic Tunneling Pseudo-Interface");
  1375. break;
  1376. case IPV6_IF_TYPE_TUNNEL_6OVER4:
  1377. NlsPutMsg(STDOUT, IPV6_MESSAGE_52);
  1378. // printf(" 6-over-4 Virtual Interface");
  1379. break;
  1380. case IPV6_IF_TYPE_TUNNEL_V6V4:
  1381. NlsPutMsg(STDOUT, IPV6_MESSAGE_53);
  1382. // printf(" Configured Tunnel Interface");
  1383. break;
  1384. case IPV6_IF_TYPE_TUNNEL_6TO4:
  1385. NlsPutMsg(STDOUT, IPV6_6TO4_INTERFACE);
  1386. // printf(" 6to4 Tunneling Pseudo-Interface");
  1387. break;
  1388. }
  1389. NlsPutMsg(STDOUT, IPV6_MESSAGE_36);
  1390. // printf("\n");
  1391. NlsPutMsg(STDOUT, IPV6_MESSAGE_GUID, FormatGuid(&IF->This.Guid));
  1392. // printf(" Guid %s\n", FormatGuid(&IF->This.Guid));
  1393. if (IF->NeighborDiscovers == TRUE)
  1394. NlsPutMsg(STDOUT, IPV6_MESSAGE_USES_ND);
  1395. // printf(" uses Neighbor Discovery\n");
  1396. else if (IF->NeighborDiscovers == FALSE)
  1397. NlsPutMsg(STDOUT, IPV6_MESSAGE_DOESNT_USE_ND);
  1398. // printf(" does not use Neighbor Discovery\n");
  1399. if (IF->RouterDiscovers == TRUE)
  1400. NlsPutMsg(STDOUT, IPV6_MESSAGE_USES_RD);
  1401. else if (IF->RouterDiscovers == FALSE)
  1402. NlsPutMsg(STDOUT, IPV6_MESSAGE_DOESNT_USE_RD);
  1403. if (IF->Advertises == TRUE)
  1404. NlsPutMsg(STDOUT, IPV6_MESSAGE_SENDS_RAs);
  1405. // printf(" sends Router Advertisements\n");
  1406. else if (IF->Advertises == FALSE)
  1407. NlsPutMsg(STDOUT, IPV6_MESSAGE_DOESNT_SEND_RAs);
  1408. // printf(" does not send Router Advertisements\n");
  1409. if (IF->Forwards == TRUE)
  1410. NlsPutMsg(STDOUT, IPV6_MESSAGE_FORWARDS);
  1411. // printf(" forwards packets\n");
  1412. else if (IF->Forwards == FALSE)
  1413. NlsPutMsg(STDOUT, IPV6_MESSAGE_DOESNT_FORWARD);
  1414. // printf(" does not forward packets\n");
  1415. if (IF->PeriodicMLD == TRUE)
  1416. NlsPutMsg(STDOUT, IPV6_MESSAGE_SENDS_PERIODIC_MLD);
  1417. // printf(" periodically sends MLD Reports\n");
  1418. else if (IF->PeriodicMLD == FALSE)
  1419. NlsPutMsg(STDOUT, IPV6_MESSAGE_DOESNT_SEND_PERIODIC_MLD);
  1420. // printf(" does not periodically send MLD Reports\n");
  1421. if (IF->Preference != (u_int)-1)
  1422. NlsPutMsg(STDOUT, IPV6_MESSAGE_64, IF->Preference);
  1423. // printf(" routing preference %u\n", IF->Preference);
  1424. if (IF->Type == IPV6_IF_TYPE_TUNNEL_AUTO) {
  1425. if (IF->LocalLinkLayerAddress != 0) {
  1426. NlsPutMsg(STDOUT, IPV6_MESSAGE_TOKEN_ADDRESS,
  1427. FormatLinkLayerAddress(IF->LinkLayerAddressLength,
  1428. (u_char *)IF + IF->LocalLinkLayerAddress));
  1429. // printf(" EUI-64 embedded IPv4 address: %s\n",
  1430. }
  1431. if (IF->RemoteLinkLayerAddress != 0) {
  1432. NlsPutMsg(STDOUT, IPV6_MESSAGE_ROUTER_LL_ADDRESS,
  1433. FormatLinkLayerAddress(IF->LinkLayerAddressLength,
  1434. (u_char *)IF + IF->RemoteLinkLayerAddress));
  1435. // printf(" router link-layer address: %s\n",
  1436. }
  1437. }
  1438. else {
  1439. if (IF->LocalLinkLayerAddress != 0) {
  1440. NlsPutMsg(STDOUT, IPV6_MESSAGE_65,
  1441. FormatLinkLayerAddress(IF->LinkLayerAddressLength,
  1442. (u_char *)IF + IF->LocalLinkLayerAddress));
  1443. // printf(" link-layer address: %s\n",
  1444. }
  1445. if (IF->RemoteLinkLayerAddress != 0) {
  1446. NlsPutMsg(STDOUT, IPV6_MESSAGE_66,
  1447. FormatLinkLayerAddress(IF->LinkLayerAddressLength,
  1448. (u_char *)IF + IF->RemoteLinkLayerAddress));
  1449. // printf(" remote link-layer address: %s\n",
  1450. }
  1451. }
  1452. ForEachPersistentAddress(IF, PrintPersistentAddress);
  1453. if (IF->LinkMTU != 0) {
  1454. NlsPutMsg(STDOUT, IPV6_MESSAGE_LINK_MTU, IF->LinkMTU);
  1455. // printf(" link MTU %u\n",
  1456. }
  1457. if (IF->CurHopLimit != (u_int)-1) {
  1458. NlsPutMsg(STDOUT, IPV6_MESSAGE_68, IF->CurHopLimit);
  1459. // printf(" current hop limit %u\n", IF->CurHopLimit);
  1460. }
  1461. if (IF->BaseReachableTime != 0) {
  1462. NlsPutMsg(STDOUT, IPV6_MESSAGE_BASE_REACHABLE_TIME,
  1463. IF->BaseReachableTime);
  1464. // printf(" base reachable time %ums\n",
  1465. }
  1466. if (IF->RetransTimer != 0) {
  1467. NlsPutMsg(STDOUT, IPV6_MESSAGE_70, IF->RetransTimer);
  1468. // printf(" retransmission interval %ums\n", IF->RetransTimer);
  1469. }
  1470. if (IF->DupAddrDetectTransmits != (u_int)-1) {
  1471. NlsPutMsg(STDOUT, IPV6_MESSAGE_71, IF->DupAddrDetectTransmits);
  1472. // printf(" DAD transmits %u\n", IF->DupAddrDetectTransmits);
  1473. }
  1474. if (IF->DefSitePrefixLength != (u_int)-1) {
  1475. NlsPutMsg(STDOUT, IPV6_MESSAGE_DEFAULT_SITE_PREFIX_LENGTH,
  1476. IF->DefSitePrefixLength);
  1477. // printf(" default site prefix length %u\n",
  1478. }
  1479. }
  1480. IPV6_INFO_NEIGHBOR_CACHE *
  1481. GetNeighborCacheEntry(IPV6_QUERY_NEIGHBOR_CACHE *Query)
  1482. {
  1483. IPV6_INFO_NEIGHBOR_CACHE *NCE;
  1484. u_int InfoSize, BytesReturned;
  1485. InfoSize = sizeof *NCE + MAX_LINK_LAYER_ADDRESS_LENGTH;
  1486. NCE = (IPV6_INFO_NEIGHBOR_CACHE *) malloc(InfoSize);
  1487. if (NCE == NULL) {
  1488. NlsPutMsg(STDOUT, IPV6_MESSAGE_36);
  1489. // printf("malloc failed\n");
  1490. exit(1);
  1491. }
  1492. if (!DeviceIoControl(Handle, IOCTL_IPV6_QUERY_NEIGHBOR_CACHE,
  1493. Query, sizeof *Query,
  1494. NCE, InfoSize, &BytesReturned,
  1495. NULL)) {
  1496. NlsPutMsg(STDOUT, IPV6_MESSAGE_72, FormatIPv6Address(&Query->Address));
  1497. // printf("bad address %s\n", FormatIPv6Address(&Query->Address));
  1498. exit(1);
  1499. }
  1500. if ((BytesReturned < sizeof *NCE) ||
  1501. (BytesReturned != sizeof *NCE + NCE->LinkLayerAddressLength)) {
  1502. NlsPutMsg(STDOUT, IPV6_MESSAGE_73);
  1503. // printf("inconsistent neighbor cache info length\n");
  1504. exit(1);
  1505. }
  1506. NCE->Query = *Query;
  1507. return NCE;
  1508. }
  1509. void
  1510. ForEachNeighborCacheEntry(IPV6_QUERY_INTERFACE *IF,
  1511. void (*func)(IPV6_INFO_NEIGHBOR_CACHE *))
  1512. {
  1513. IPV6_QUERY_NEIGHBOR_CACHE Query, NextQuery;
  1514. IPV6_INFO_NEIGHBOR_CACHE *NCE;
  1515. u_int InfoSize, BytesReturned;
  1516. InfoSize = sizeof *NCE + MAX_LINK_LAYER_ADDRESS_LENGTH;
  1517. NCE = (IPV6_INFO_NEIGHBOR_CACHE *) malloc(InfoSize);
  1518. if (NCE == NULL) {
  1519. NlsPutMsg(STDOUT, IPV6_MESSAGE_36);
  1520. // printf("malloc failed\n");
  1521. exit(1);
  1522. }
  1523. NextQuery.IF = *IF;
  1524. NextQuery.Address = in6addr_any;
  1525. for (;;) {
  1526. Query = NextQuery;
  1527. if (!DeviceIoControl(Handle, IOCTL_IPV6_QUERY_NEIGHBOR_CACHE,
  1528. &Query, sizeof Query,
  1529. NCE, InfoSize, &BytesReturned,
  1530. NULL)) {
  1531. NlsPutMsg(STDOUT, IPV6_MESSAGE_72,
  1532. FormatIPv6Address(&Query.Address));
  1533. // printf("bad address %s\n", FormatIPv6Address(&Query.Address));
  1534. exit(1);
  1535. }
  1536. NextQuery = NCE->Query;
  1537. if (!IN6_ADDR_EQUAL(&Query.Address, &in6addr_any)) {
  1538. if ((BytesReturned < sizeof *NCE) ||
  1539. (BytesReturned != sizeof *NCE + NCE->LinkLayerAddressLength)) {
  1540. NlsPutMsg(STDOUT, IPV6_MESSAGE_73);
  1541. // printf("inconsistent neighbor cache info length\n");
  1542. exit(1);
  1543. }
  1544. NCE->Query = Query;
  1545. (*func)(NCE);
  1546. }
  1547. if (IN6_ADDR_EQUAL(&NextQuery.Address, &in6addr_any))
  1548. break;
  1549. }
  1550. free(NCE);
  1551. }
  1552. void
  1553. PrintNeighborCacheEntry(IPV6_INFO_NEIGHBOR_CACHE *NCE)
  1554. {
  1555. NlsPutMsg(STDOUT, IPV6_MESSAGE_74, NCE->Query.IF.Index,
  1556. FormatIPv6Address(&NCE->Query.Address));
  1557. // printf("%u: %18s", NCE->Query.IF.Index,
  1558. // FormatIPv6Address(&NCE->Query.Address));
  1559. if (NCE->NDState != 0)
  1560. NlsPutMsg(STDOUT, IPV6_MESSAGE_75,
  1561. FormatLinkLayerAddress(
  1562. NCE->LinkLayerAddressLength, (u_char *)(NCE + 1)));
  1563. // printf(" %-17s", FormatLinkLayerAddress(NCE->LinkLayerAddressLength,
  1564. // (u_char *)(NCE + 1)));
  1565. else
  1566. NlsPutMsg(STDOUT, IPV6_MESSAGE_75, "");
  1567. // printf(" %-17s", "");
  1568. switch (NCE->NDState) {
  1569. case ND_STATE_INCOMPLETE:
  1570. NlsPutMsg(STDOUT, IPV6_MESSAGE_76);
  1571. // printf(" incomplete");
  1572. break;
  1573. case ND_STATE_PROBE:
  1574. NlsPutMsg(STDOUT, IPV6_MESSAGE_77);
  1575. // printf(" probe");
  1576. break;
  1577. case ND_STATE_DELAY:
  1578. NlsPutMsg(STDOUT, IPV6_MESSAGE_78);
  1579. // printf(" delay");
  1580. break;
  1581. case ND_STATE_STALE:
  1582. NlsPutMsg(STDOUT, IPV6_MESSAGE_79);
  1583. // printf(" stale");
  1584. break;
  1585. case ND_STATE_REACHABLE:
  1586. NlsPutMsg(STDOUT, IPV6_MESSAGE_80, NCE->ReachableTimer);
  1587. // printf(" reachable (%ums)", NCE->ReachableTimer);
  1588. break;
  1589. case ND_STATE_PERMANENT:
  1590. NlsPutMsg(STDOUT, IPV6_MESSAGE_81);
  1591. // printf(" permanent");
  1592. break;
  1593. default:
  1594. NlsPutMsg(STDOUT, IPV6_MESSAGE_82, NCE->NDState);
  1595. // printf(" unknown ND state %u", NCE->NDState);
  1596. break;
  1597. }
  1598. if (NCE->IsRouter)
  1599. NlsPutMsg(STDOUT, IPV6_MESSAGE_83);
  1600. // printf(" (router)");
  1601. if (NCE->IsUnreachable)
  1602. NlsPutMsg(STDOUT, IPV6_MESSAGE_84);
  1603. // printf(" (unreachable)");
  1604. NlsPutMsg(STDOUT, IPV6_MESSAGE_36);
  1605. // printf("\n");
  1606. }
  1607. void
  1608. QueryInterface(int argc, char *argv[])
  1609. {
  1610. InitializeAdaptersInfo();
  1611. if (argc == 0) {
  1612. if (Persistent)
  1613. ForEachPersistentInterface(PrintPersistentInterface);
  1614. else
  1615. ForEachInterface(PrintInterface);
  1616. }
  1617. else if (argc == 1) {
  1618. IPV6_INFO_INTERFACE *IF;
  1619. if (Persistent) {
  1620. IPV6_PERSISTENT_QUERY_INTERFACE Query;
  1621. Query.RegistryIndex = (u_int)-1;
  1622. if (! GetGuid(argv[0], &Query.Guid))
  1623. usage();
  1624. IF = GetPersistentInterfaceInfo(&Query);
  1625. PrintPersistentInterface(IF);
  1626. free(IF);
  1627. }
  1628. else {
  1629. IPV6_QUERY_INTERFACE Query;
  1630. if (! GetInterface(argv[0], &Query))
  1631. usage();
  1632. IF = GetInterfaceInfo(&Query);
  1633. PrintInterface(IF);
  1634. free(IF);
  1635. }
  1636. }
  1637. else {
  1638. usage();
  1639. }
  1640. }
  1641. void
  1642. RenewViaReconnect(IPV6_INFO_INTERFACE *IF)
  1643. {
  1644. u_int BytesReturned;
  1645. if (!DeviceIoControl(Handle, IOCTL_IPV6_RENEW_INTERFACE,
  1646. &IF->This, sizeof IF->This,
  1647. NULL, 0, &BytesReturned, NULL)) {
  1648. NlsPutMsg(STDOUT, IPV6_MESSAGE_RENEW_INTERFACE, GetLastError());
  1649. // printf("renew interface error: %x\n", GetLastError());
  1650. exit(1);
  1651. }
  1652. }
  1653. VOID
  1654. Poke6to4Service()
  1655. {
  1656. SC_HANDLE Service, SCManager;
  1657. SERVICE_STATUS Status;
  1658. SCManager = OpenSCManager(NULL, NULL, GENERIC_READ);
  1659. if (SCManager == NULL) {
  1660. return;
  1661. }
  1662. Service = OpenService(SCManager, "6to4", SERVICE_ALL_ACCESS);
  1663. if (Service != NULL) {
  1664. //
  1665. // Tell the 6to4 service to re-read its configuration information.
  1666. //
  1667. (VOID) ControlService(Service, SERVICE_CONTROL_PARAMCHANGE, &Status);
  1668. CloseServiceHandle(Service);
  1669. }
  1670. CloseServiceHandle(SCManager);
  1671. }
  1672. void
  1673. RenewInterface(int argc, char *argv[])
  1674. {
  1675. BOOL PokeService = FALSE;
  1676. if (argc == 0) {
  1677. ForEachInterface(RenewViaReconnect);
  1678. PokeService = TRUE;
  1679. }
  1680. else if (argc == 1) {
  1681. IPV6_QUERY_INTERFACE Query;
  1682. IPV6_INFO_INTERFACE *IF;
  1683. if (! GetInterface(argv[0], &Query))
  1684. usage();
  1685. IF = GetInterfaceInfo(&Query);
  1686. RenewViaReconnect(IF);
  1687. //
  1688. // Poke the 6to4 service if it manages the interface being renewed.
  1689. //
  1690. PokeService = (IF->Type == IPV6_IF_TYPE_TUNNEL_6TO4) ||
  1691. (IF->Type == IPV6_IF_TYPE_TUNNEL_TEREDO) ||
  1692. (IF->Type == IPV6_IF_TYPE_TUNNEL_AUTO);
  1693. free(IF);
  1694. }
  1695. else {
  1696. usage();
  1697. }
  1698. if (PokeService) {
  1699. Poke6to4Service();
  1700. }
  1701. }
  1702. int
  1703. GetV4Address(char *astr, struct in_addr *address)
  1704. {
  1705. struct addrinfo hints;
  1706. struct addrinfo *result;
  1707. memset(&hints, 0, sizeof hints);
  1708. hints.ai_family = PF_INET;
  1709. if (getaddrinfo(astr, NULL, &hints, &result))
  1710. return FALSE;
  1711. *address = ((struct sockaddr_in *)result->ai_addr)->sin_addr;
  1712. freeaddrinfo(result);
  1713. return TRUE;
  1714. }
  1715. void
  1716. CreateInterface(int argc, char *argv[])
  1717. {
  1718. struct {
  1719. IPV6_INFO_INTERFACE Info;
  1720. struct in_addr SrcAddr;
  1721. struct in_addr DstAddr;
  1722. } Create;
  1723. IPV6_QUERY_INTERFACE Result;
  1724. u_int BytesReturned;
  1725. u_int FlagsOn, FlagsOff;
  1726. int i;
  1727. IPV6_INIT_INFO_INTERFACE(&Create.Info);
  1728. if (argc < 1)
  1729. usage();
  1730. if (!strcmp(argv[0], "v6v4")) {
  1731. i = 3;
  1732. if (argc < i)
  1733. usage();
  1734. if (! GetV4Address(argv[1], &Create.SrcAddr))
  1735. usage();
  1736. if (! GetV4Address(argv[2], &Create.DstAddr))
  1737. usage();
  1738. Create.Info.Type = IPV6_IF_TYPE_TUNNEL_V6V4;
  1739. Create.Info.LinkLayerAddressLength = sizeof(struct in_addr);
  1740. Create.Info.LocalLinkLayerAddress = (u_int)
  1741. ((char *)&Create.SrcAddr - (char *)&Create.Info);
  1742. Create.Info.RemoteLinkLayerAddress = (u_int)
  1743. ((char *)&Create.DstAddr - (char *)&Create.Info);
  1744. }
  1745. else if (!strcmp(argv[0], "6over4")) {
  1746. i = 2;
  1747. if (argc < i)
  1748. usage();
  1749. if (! GetV4Address(argv[1], &Create.SrcAddr))
  1750. usage();
  1751. Create.Info.Type = IPV6_IF_TYPE_TUNNEL_6OVER4;
  1752. Create.Info.LinkLayerAddressLength = sizeof(struct in_addr);
  1753. Create.Info.LocalLinkLayerAddress = (u_int)
  1754. ((char *)&Create.SrcAddr - (char *)&Create.Info);
  1755. }
  1756. else
  1757. usage();
  1758. for (; i < argc; i++) {
  1759. if (!strcmp(argv[i], "nd")) {
  1760. Create.Info.NeighborDiscovers = TRUE;
  1761. Create.Info.RouterDiscovers = TRUE;
  1762. }
  1763. else if (!strcmp(argv[i], "pmld")) {
  1764. Create.Info.PeriodicMLD = TRUE;
  1765. }
  1766. else if (!strcmp(argv[i], "nond")) {
  1767. Create.Info.NeighborDiscovers = FALSE;
  1768. Create.Info.RouterDiscovers = FALSE;
  1769. }
  1770. else
  1771. usage();
  1772. }
  1773. if (!DeviceIoControl(Handle,
  1774. (Persistent ?
  1775. IOCTL_IPV6_PERSISTENT_CREATE_INTERFACE :
  1776. IOCTL_IPV6_CREATE_INTERFACE),
  1777. &Create, sizeof Create,
  1778. &Result, sizeof Result, &BytesReturned, NULL) ||
  1779. (BytesReturned != sizeof Result)) {
  1780. NlsPutMsg(STDOUT, IPV6_MESSAGE_85, GetLastError());
  1781. // printf("control interface error: %x\n", GetLastError());
  1782. exit(1);
  1783. }
  1784. NlsPutMsg(STDOUT, IPV6_MESSAGE_86, Result.Index);
  1785. // printf("Created interface %u.\n", Result.Index);
  1786. }
  1787. void
  1788. UpdateInterface(int argc, char *argv[])
  1789. {
  1790. IPV6_INFO_INTERFACE Update;
  1791. u_int BytesReturned;
  1792. int i;
  1793. IPV6_INIT_INFO_INTERFACE(&Update);
  1794. if (argc < 1)
  1795. usage();
  1796. if (! GetInterface(argv[0], &Update.This))
  1797. usage();
  1798. for (i = 1; i < argc; i++) {
  1799. if (!strncmp(argv[i], "advertises", strlen(argv[i])))
  1800. Update.Advertises = TRUE;
  1801. else if (!strncmp(argv[i], "-advertises", strlen(argv[i])))
  1802. Update.Advertises = FALSE;
  1803. else if (!strncmp(argv[i], "forwards", strlen(argv[i])))
  1804. Update.Forwards = TRUE;
  1805. else if (!strncmp(argv[i], "-forwards", strlen(argv[i])))
  1806. Update.Forwards = FALSE;
  1807. else if (!strcmp(argv[i], "mtu") && (i+1 < argc)) {
  1808. if (! GetNumber(argv[i+1], &Update.LinkMTU))
  1809. usage();
  1810. i++;
  1811. }
  1812. else if (!strncmp(argv[i], "preference", strlen(argv[i])) &&
  1813. (i+1 < argc)) {
  1814. if (! GetNumber(argv[++i], &Update.Preference))
  1815. usage();
  1816. }
  1817. else if (!strncmp(argv[i], "basereachabletime", strlen(argv[i])) &&
  1818. (i+1 < argc)) {
  1819. if (! GetNumber(argv[++i], &Update.BaseReachableTime))
  1820. usage();
  1821. }
  1822. else if (!strncmp(argv[i], "retranstimer", strlen(argv[i])) &&
  1823. (i+1 < argc)) {
  1824. if (! GetNumber(argv[++i], &Update.RetransTimer))
  1825. usage();
  1826. }
  1827. else if (!strncmp(argv[i], "dupaddrdetecttransmits", strlen(argv[i])) &&
  1828. (i+1 < argc)) {
  1829. if (! GetNumber(argv[++i], &Update.DupAddrDetectTransmits))
  1830. usage();
  1831. }
  1832. else if (!strncmp(argv[i], "curhoplimit", strlen(argv[i])) &&
  1833. (i+1 < argc)) {
  1834. if (! GetNumber(argv[++i], &Update.CurHopLimit))
  1835. usage();
  1836. }
  1837. else if ((!strncmp(argv[i], "defsiteprefixlength", strlen(argv[i])) ||
  1838. !strcmp(argv[i], "spl")) &&
  1839. (i+1 < argc)) {
  1840. if (! GetNumber(argv[++i], &Update.DefSitePrefixLength))
  1841. usage();
  1842. }
  1843. else if (!strcmp(argv[i], "link") && (i+1 < argc)) {
  1844. if (! GetNumber(argv[i+1], &Update.ZoneIndices[ADE_LINK_LOCAL]))
  1845. usage();
  1846. i++;
  1847. }
  1848. else if (!strcmp(argv[i], "subnet") && (i+1 < argc)) {
  1849. if (! GetNumber(argv[i+1], &Update.ZoneIndices[ADE_SUBNET_LOCAL]))
  1850. usage();
  1851. i++;
  1852. }
  1853. else if (!strcmp(argv[i], "admin") && (i+1 < argc)) {
  1854. if (! GetNumber(argv[i+1], &Update.ZoneIndices[ADE_ADMIN_LOCAL]))
  1855. usage();
  1856. i++;
  1857. }
  1858. else if (!strcmp(argv[i], "site") && (i+1 < argc)) {
  1859. if (! GetNumber(argv[i+1], &Update.ZoneIndices[ADE_SITE_LOCAL]))
  1860. usage();
  1861. i++;
  1862. }
  1863. else if (!strcmp(argv[i], "org") && (i+1 < argc)) {
  1864. if (! GetNumber(argv[i+1], &Update.ZoneIndices[ADE_ORG_LOCAL]))
  1865. usage();
  1866. i++;
  1867. }
  1868. else
  1869. usage();
  1870. }
  1871. if (!DeviceIoControl(Handle,
  1872. (Persistent ?
  1873. IOCTL_IPV6_PERSISTENT_UPDATE_INTERFACE :
  1874. IOCTL_IPV6_UPDATE_INTERFACE),
  1875. &Update, sizeof Update,
  1876. NULL, 0, &BytesReturned, NULL)) {
  1877. NlsPutMsg(STDOUT, IPV6_MESSAGE_85, GetLastError());
  1878. // printf("control interface error: %x\n", GetLastError());
  1879. exit(1);
  1880. }
  1881. }
  1882. void
  1883. UpdateRouterLinkAddress(int argc, char *argv[])
  1884. {
  1885. char Buffer[sizeof(IPV6_UPDATE_ROUTER_LL_ADDRESS) + 2 * sizeof(IN_ADDR)];
  1886. IPV6_UPDATE_ROUTER_LL_ADDRESS *Update =
  1887. (IPV6_UPDATE_ROUTER_LL_ADDRESS *)Buffer;
  1888. IN_ADDR *Addr = (IN_ADDR *)(Update + 1);
  1889. u_int BytesReturned;
  1890. SOCKET s;
  1891. SOCKADDR_IN sinRemote, sinLocal;
  1892. if (argc != 2)
  1893. usage();
  1894. if (! GetInterface(argv[0], &Update->IF))
  1895. usage();
  1896. if (! GetV4Address(argv[1], &Addr[1]))
  1897. usage();
  1898. s = socket(AF_INET, SOCK_DGRAM, 0);
  1899. if (s == INVALID_SOCKET) {
  1900. NlsPutMsg(STDOUT, IPV6_MESSAGE_85, WSAGetLastError());
  1901. exit(1);
  1902. }
  1903. sinRemote.sin_family = AF_INET;
  1904. sinRemote.sin_addr = Addr[1];
  1905. if (WSAIoctl(s, SIO_ROUTING_INTERFACE_QUERY,
  1906. &sinRemote, sizeof sinRemote,
  1907. &sinLocal, sizeof sinLocal,
  1908. &BytesReturned, NULL, NULL) == SOCKET_ERROR) {
  1909. NlsPutMsg(STDOUT, IPV6_MESSAGE_85, WSAGetLastError());
  1910. exit(1);
  1911. }
  1912. closesocket(s);
  1913. Addr[0] = sinLocal.sin_addr;
  1914. if (Addr[0].s_addr == htonl(INADDR_LOOPBACK)) {
  1915. //
  1916. // We're the router.
  1917. //
  1918. Addr[0] = Addr[1];
  1919. }
  1920. if (!DeviceIoControl(Handle, IOCTL_IPV6_UPDATE_ROUTER_LL_ADDRESS,
  1921. Buffer, sizeof Buffer,
  1922. NULL, 0, &BytesReturned, NULL)) {
  1923. NlsPutMsg(STDOUT, IPV6_MESSAGE_85, GetLastError());
  1924. // printf("control interface error: %x\n", GetLastError());
  1925. exit(1);
  1926. }
  1927. }
  1928. void
  1929. DeleteInterface(int argc, char *argv[])
  1930. {
  1931. IPV6_QUERY_INTERFACE Query;
  1932. u_int BytesReturned;
  1933. if (argc != 1)
  1934. usage();
  1935. if (! GetInterface(argv[0], &Query))
  1936. usage();
  1937. if (!DeviceIoControl(Handle,
  1938. (Persistent ?
  1939. IOCTL_IPV6_PERSISTENT_DELETE_INTERFACE :
  1940. IOCTL_IPV6_DELETE_INTERFACE),
  1941. &Query, sizeof Query,
  1942. NULL, 0, &BytesReturned, NULL)) {
  1943. NlsPutMsg(STDOUT, IPV6_MESSAGE_87, GetLastError());
  1944. // printf("delete interface error: %x\n", GetLastError());
  1945. exit(1);
  1946. }
  1947. }
  1948. void
  1949. PrintNeighborCache(IPV6_INFO_INTERFACE *IF)
  1950. {
  1951. ForEachNeighborCacheEntry(&IF->This, PrintNeighborCacheEntry);
  1952. }
  1953. void
  1954. QueryNeighborCache(int argc, char *argv[])
  1955. {
  1956. if (argc == 0) {
  1957. ForEachInterface(PrintNeighborCache);
  1958. }
  1959. else if (argc == 1) {
  1960. IPV6_QUERY_INTERFACE Query;
  1961. if (! GetInterface(argv[0], &Query))
  1962. usage();
  1963. ForEachNeighborCacheEntry(&Query, PrintNeighborCacheEntry);
  1964. }
  1965. else if (argc == 2) {
  1966. IPV6_QUERY_NEIGHBOR_CACHE Query;
  1967. IPV6_INFO_NEIGHBOR_CACHE *NCE;
  1968. if (! GetInterface(argv[0], &Query.IF))
  1969. usage();
  1970. if (! GetAddress(argv[1], &Query.Address))
  1971. usage();
  1972. NCE = GetNeighborCacheEntry(&Query);
  1973. PrintNeighborCacheEntry(NCE);
  1974. free(NCE);
  1975. }
  1976. else {
  1977. usage();
  1978. }
  1979. }
  1980. IPV6_INFO_ROUTE_CACHE *
  1981. GetRouteCacheEntry(IPV6_QUERY_ROUTE_CACHE *Query)
  1982. {
  1983. IPV6_INFO_ROUTE_CACHE *RCE;
  1984. u_int BytesReturned;
  1985. RCE = (IPV6_INFO_ROUTE_CACHE *) malloc(sizeof *RCE);
  1986. if (RCE == NULL) {
  1987. NlsPutMsg(STDOUT, IPV6_MESSAGE_36);
  1988. // printf("malloc failed\n");
  1989. exit(1);
  1990. }
  1991. if (!DeviceIoControl(Handle, IOCTL_IPV6_QUERY_ROUTE_CACHE,
  1992. Query, sizeof *Query,
  1993. RCE, sizeof *RCE, &BytesReturned,
  1994. NULL)) {
  1995. NlsPutMsg(STDOUT, IPV6_MESSAGE_88);
  1996. // printf("bad index or address\n");
  1997. exit(1);
  1998. }
  1999. RCE->Query = *Query;
  2000. return RCE;
  2001. }
  2002. void
  2003. ForEachDestination(void (*func)(IPV6_INFO_ROUTE_CACHE *))
  2004. {
  2005. IPV6_QUERY_ROUTE_CACHE Query, NextQuery;
  2006. IPV6_INFO_ROUTE_CACHE RCE;
  2007. u_int BytesReturned;
  2008. NextQuery.IF.Index = 0;
  2009. for (;;) {
  2010. Query = NextQuery;
  2011. if (!DeviceIoControl(Handle, IOCTL_IPV6_QUERY_ROUTE_CACHE,
  2012. &Query, sizeof Query,
  2013. &RCE, sizeof RCE, &BytesReturned,
  2014. NULL)) {
  2015. NlsPutMsg(STDOUT, IPV6_MESSAGE_89, Query.IF.Index);
  2016. // printf("bad index %u\n", Query.IF.Index);
  2017. exit(1);
  2018. }
  2019. NextQuery = RCE.Query;
  2020. if (Query.IF.Index != 0) {
  2021. RCE.Query = Query;
  2022. (*func)(&RCE);
  2023. }
  2024. if (NextQuery.IF.Index == 0)
  2025. break;
  2026. }
  2027. }
  2028. void
  2029. PrintRouteCacheEntry(IPV6_INFO_ROUTE_CACHE *RCE)
  2030. {
  2031. NlsPutMsg(STDOUT, IPV6_MESSAGE_90, FormatIPv6Address(&RCE->Query.Address));
  2032. // printf("%s via ", FormatIPv6Address(&RCE->Query.Address));
  2033. NlsPutMsg(STDOUT, IPV6_MESSAGE_91, RCE->NextHopInterface,
  2034. FormatIPv6Address(&RCE->NextHopAddress));
  2035. // printf("%u/%s", RCE->NextHopInterface,
  2036. // FormatIPv6Address(&RCE->NextHopAddress));
  2037. if (! RCE->Valid)
  2038. NlsPutMsg(STDOUT, IPV6_MESSAGE_92);
  2039. // printf(" (stale)");
  2040. switch (RCE->Type) {
  2041. case RCE_TYPE_COMPUTED:
  2042. break;
  2043. case RCE_TYPE_REDIRECT:
  2044. NlsPutMsg(STDOUT, IPV6_MESSAGE_93);
  2045. // printf(" (redirect)");
  2046. break;
  2047. default:
  2048. NlsPutMsg(STDOUT, IPV6_MESSAGE_94, RCE->Type);
  2049. // printf(" (unknown type %u)", RCE->Type);
  2050. break;
  2051. }
  2052. switch (RCE->Flags) {
  2053. case RCE_FLAG_CONSTRAINED:
  2054. NlsPutMsg(STDOUT, IPV6_MESSAGE_95);
  2055. // printf(" (interface-specific)\n");
  2056. break;
  2057. case RCE_FLAG_CONSTRAINED_SCOPEID:
  2058. NlsPutMsg(STDOUT, IPV6_MESSAGE_96);
  2059. // printf(" (zone-specific)\n");
  2060. break;
  2061. case 0:
  2062. NlsPutMsg(STDOUT, IPV6_MESSAGE_36);
  2063. // printf("\n");
  2064. break;
  2065. default:
  2066. NlsPutMsg(STDOUT, IPV6_MESSAGE_97, RCE->Flags);
  2067. // printf(" (flags 0x%x)\n", RCE->Flags);
  2068. }
  2069. NlsPutMsg(STDOUT, IPV6_MESSAGE_98,
  2070. RCE->Query.IF.Index, FormatIPv6Address(&RCE->SourceAddress));
  2071. // printf(" src %u/%s\n",
  2072. // RCE->Query.IF.Index,
  2073. // FormatIPv6Address(&RCE->SourceAddress));
  2074. if (RCE->PathMTU == 0)
  2075. NlsPutMsg(STDOUT, IPV6_MESSAGE_99, IPv6_MINIMUM_MTU);
  2076. // printf(" PMTU %u-", IPv6_MINIMUM_MTU);
  2077. else
  2078. NlsPutMsg(STDOUT, IPV6_MESSAGE_100, RCE->PathMTU);
  2079. // printf(" PMTU %u", RCE->PathMTU);
  2080. if (RCE->PMTUProbeTimer != INFINITE_LIFETIME)
  2081. NlsPutMsg(STDOUT, IPV6_MESSAGE_101, RCE->PMTUProbeTimer/1000);
  2082. // printf(" (%u seconds until PMTU probe)\n", RCE->PMTUProbeTimer/1000);
  2083. else
  2084. NlsPutMsg(STDOUT, IPV6_MESSAGE_36);
  2085. // printf("\n");
  2086. if ((RCE->ICMPLastError != 0) &&
  2087. (RCE->ICMPLastError < 10*60*1000))
  2088. NlsPutMsg(STDOUT, IPV6_MESSAGE_102, RCE->ICMPLastError/1000);
  2089. // printf(" %d seconds since ICMP error\n", RCE->ICMPLastError/1000);
  2090. if ((RCE->BindingSeqNumber != 0) ||
  2091. (RCE->BindingLifetime != 0) ||
  2092. ! IN6_ADDR_EQUAL(&RCE->CareOfAddress, &in6addr_any))
  2093. NlsPutMsg(STDOUT, IPV6_MESSAGE_103,
  2094. FormatIPv6Address(&RCE->CareOfAddress),
  2095. RCE->BindingSeqNumber,
  2096. RCE->BindingLifetime);
  2097. // printf(" careof %s seq %u life %us\n",
  2098. // FormatIPv6Address(&RCE->CareOfAddress),
  2099. // RCE->BindingSeqNumber,
  2100. // RCE->BindingLifetime);
  2101. }
  2102. void
  2103. QueryRouteCache(int argc, char *argv[])
  2104. {
  2105. if (argc == 0) {
  2106. ForEachDestination(PrintRouteCacheEntry);
  2107. }
  2108. else if (argc == 2) {
  2109. IPV6_QUERY_ROUTE_CACHE Query;
  2110. IPV6_INFO_ROUTE_CACHE *RCE;
  2111. if (! GetInterface(argv[0], &Query.IF))
  2112. usage();
  2113. if (! GetAddress(argv[1], &Query.Address))
  2114. usage();
  2115. RCE = GetRouteCacheEntry(&Query);
  2116. PrintRouteCacheEntry(RCE);
  2117. free(RCE);
  2118. }
  2119. else {
  2120. usage();
  2121. }
  2122. }
  2123. void
  2124. ForEachRoute(void (*func)(IPV6_INFO_ROUTE_TABLE *))
  2125. {
  2126. IPV6_QUERY_ROUTE_TABLE Query, NextQuery;
  2127. IPV6_INFO_ROUTE_TABLE RTE;
  2128. u_int BytesReturned;
  2129. NextQuery.Neighbor.IF.Index = 0;
  2130. for (;;) {
  2131. Query = NextQuery;
  2132. if (!DeviceIoControl(Handle, IOCTL_IPV6_QUERY_ROUTE_TABLE,
  2133. &Query, sizeof Query,
  2134. &RTE, sizeof RTE, &BytesReturned,
  2135. NULL)) {
  2136. NlsPutMsg(STDOUT, IPV6_MESSAGE_104, Query.Neighbor.IF.Index);
  2137. // printf("bad index %u\n", Query.Neighbor.IF.Index);
  2138. exit(1);
  2139. }
  2140. NextQuery = RTE.Next;
  2141. if (Query.Neighbor.IF.Index != 0) {
  2142. RTE.This = Query;
  2143. (*func)(&RTE);
  2144. }
  2145. if (NextQuery.Neighbor.IF.Index == 0)
  2146. break;
  2147. }
  2148. }
  2149. void
  2150. ForEachPersistentRoute(IPV6_INFO_INTERFACE *IF,
  2151. void (*func)(IPV6_INFO_ROUTE_TABLE *))
  2152. {
  2153. IPV6_PERSISTENT_QUERY_ROUTE_TABLE Query;
  2154. IPV6_INFO_ROUTE_TABLE RTE;
  2155. u_int BytesReturned;
  2156. Query.IF.RegistryIndex = (u_int) -1;
  2157. Query.IF.Guid = IF->This.Guid;
  2158. for (Query.RegistryIndex = 0;; Query.RegistryIndex++) {
  2159. if (!DeviceIoControl(Handle,
  2160. IOCTL_IPV6_PERSISTENT_QUERY_ROUTE_TABLE,
  2161. &Query, sizeof Query,
  2162. &RTE, sizeof RTE, &BytesReturned,
  2163. NULL) ||
  2164. (BytesReturned != sizeof RTE)) {
  2165. if (GetLastError() == ERROR_NO_MORE_ITEMS)
  2166. break;
  2167. NlsPutMsg(STDOUT, IPV6_MESSAGE_104, Query.RegistryIndex);
  2168. // printf("bad index %u\n", Query.RegistryIndex);
  2169. exit(1);
  2170. }
  2171. (*func)(&RTE);
  2172. }
  2173. }
  2174. void
  2175. PrintRouteTableEntry(IPV6_INFO_ROUTE_TABLE *RTE)
  2176. {
  2177. IPV6_INFO_INTERFACE *IF;
  2178. if (!Verbose) {
  2179. //
  2180. // Suppress system routes (used for loopback).
  2181. //
  2182. if (RTE->Type == RTE_TYPE_SYSTEM)
  2183. return;
  2184. }
  2185. NlsPutMsg(STDOUT, IPV6_MESSAGE_105,
  2186. FormatIPv6Address(&RTE->This.Prefix),
  2187. RTE->This.PrefixLength,
  2188. RTE->This.Neighbor.IF.Index);
  2189. // printf("%s/%u -> %u",
  2190. if (! IN6_ADDR_EQUAL(&RTE->This.Neighbor.Address, &in6addr_any))
  2191. NlsPutMsg(STDOUT, IPV6_MESSAGE_106,
  2192. FormatIPv6Address(&RTE->This.Neighbor.Address));
  2193. // printf("/%s", FormatIPv6Address(&RTE->This.Neighbor.Address));
  2194. IF = GetInterfaceInfo(&RTE->This.Neighbor.IF);
  2195. if (IF != NULL) {
  2196. if (IF->Preference != 0) {
  2197. NlsPutMsg(STDOUT, IPV6_MESSAGE_107,
  2198. IF->Preference, RTE->Preference,
  2199. IF->Preference + RTE->Preference);
  2200. // printf(" pref %uif+%u=%u ",
  2201. // IF->Preference, RTE->Preference,
  2202. // IF->Preference + RTE->Preference);
  2203. }
  2204. else {
  2205. NlsPutMsg(STDOUT, IPV6_MESSAGE_108, RTE->Preference);
  2206. // printf(" pref %u ", RTE->Preference);
  2207. }
  2208. free(IF);
  2209. }
  2210. else {
  2211. NlsPutMsg(STDOUT, IPV6_MESSAGE_108, RTE->Preference);
  2212. // printf(" pref %u ", RTE->Preference);
  2213. }
  2214. NlsPutMsg(STDOUT, IPV6_MESSAGE_109,
  2215. FormatLifetimes(RTE->ValidLifetime, RTE->PreferredLifetime));
  2216. // printf("life %s",
  2217. // FormatLifetimes(RTE->ValidLifetime, RTE->PreferredLifetime));
  2218. if (RTE->Publish)
  2219. NlsPutMsg(STDOUT, IPV6_MESSAGE_110);
  2220. // printf(", publish");
  2221. if (RTE->Immortal)
  2222. NlsPutMsg(STDOUT, IPV6_MESSAGE_111);
  2223. // printf(", no aging");
  2224. if (RTE->SitePrefixLength != 0)
  2225. NlsPutMsg(STDOUT, IPV6_MESSAGE_112, RTE->SitePrefixLength);
  2226. // printf(", spl %u", RTE->SitePrefixLength);
  2227. NlsPutMsg(STDOUT, IPV6_MESSAGE_113);
  2228. // printf(" (");
  2229. switch (RTE->Type) {
  2230. case RTE_TYPE_SYSTEM:
  2231. NlsPutMsg(STDOUT, IPV6_MESSAGE_114);
  2232. // printf("system");
  2233. break;
  2234. case RTE_TYPE_MANUAL:
  2235. NlsPutMsg(STDOUT, IPV6_MESSAGE_115);
  2236. // printf("manual");
  2237. break;
  2238. case RTE_TYPE_AUTOCONF:
  2239. NlsPutMsg(STDOUT, IPV6_MESSAGE_116);
  2240. // printf("autoconf");
  2241. break;
  2242. case RTE_TYPE_RIP:
  2243. NlsPutMsg(STDOUT, IPV6_MESSAGE_117);
  2244. // printf("RIP");
  2245. break;
  2246. case RTE_TYPE_OSPF:
  2247. NlsPutMsg(STDOUT, IPV6_MESSAGE_118);
  2248. // printf("OSPF");
  2249. break;
  2250. case RTE_TYPE_BGP:
  2251. NlsPutMsg(STDOUT, IPV6_MESSAGE_119);
  2252. // printf("BGP");
  2253. break;
  2254. case RTE_TYPE_IDRP:
  2255. NlsPutMsg(STDOUT, IPV6_MESSAGE_120);
  2256. // printf("IDRP");
  2257. break;
  2258. case RTE_TYPE_IGRP:
  2259. NlsPutMsg(STDOUT, IPV6_MESSAGE_121);
  2260. // printf("IGRP");
  2261. break;
  2262. default:
  2263. NlsPutMsg(STDOUT, IPV6_MESSAGE_122, RTE->Type);
  2264. // printf("type %u", RTE->Type);
  2265. break;
  2266. }
  2267. NlsPutMsg(STDOUT, IPV6_MESSAGE_123);
  2268. // printf(")\n");
  2269. }
  2270. void
  2271. PrintPersistentRouteTableEntry(IPV6_INFO_ROUTE_TABLE *RTE)
  2272. {
  2273. IPV6_INFO_INTERFACE *IF;
  2274. NlsPutMsg(STDOUT, IPV6_MESSAGE_PRINT_PERSISTENT_ROUTE,
  2275. FormatIPv6Address(&RTE->This.Prefix),
  2276. RTE->This.PrefixLength,
  2277. FormatGuid(&RTE->This.Neighbor.IF.Guid));
  2278. // printf("%s/%u -> %s",
  2279. if (! IN6_ADDR_EQUAL(&RTE->This.Neighbor.Address, &in6addr_any))
  2280. NlsPutMsg(STDOUT, IPV6_MESSAGE_106,
  2281. FormatIPv6Address(&RTE->This.Neighbor.Address));
  2282. // printf("/%s", FormatIPv6Address(&RTE->This.Neighbor.Address));
  2283. NlsPutMsg(STDOUT, IPV6_MESSAGE_108, RTE->Preference);
  2284. // printf(" pref %u ", RTE->Preference);
  2285. NlsPutMsg(STDOUT, IPV6_MESSAGE_109,
  2286. FormatLifetimes(RTE->ValidLifetime, RTE->PreferredLifetime));
  2287. // printf("life %s",
  2288. // FormatLifetimes(RTE->ValidLifetime, RTE->PreferredLifetime));
  2289. if (RTE->Publish)
  2290. NlsPutMsg(STDOUT, IPV6_MESSAGE_110);
  2291. // printf(", publish");
  2292. if (RTE->Immortal)
  2293. NlsPutMsg(STDOUT, IPV6_MESSAGE_111);
  2294. // printf(", no aging");
  2295. if (RTE->SitePrefixLength != 0)
  2296. NlsPutMsg(STDOUT, IPV6_MESSAGE_112, RTE->SitePrefixLength);
  2297. // printf(", spl %u", RTE->SitePrefixLength);
  2298. NlsPutMsg(STDOUT, IPV6_MESSAGE_36);
  2299. // printf("\n");
  2300. }
  2301. void
  2302. PrintPersistentRoutesOnInterface(IPV6_INFO_INTERFACE *IF)
  2303. {
  2304. ForEachPersistentRoute(IF, PrintPersistentRouteTableEntry);
  2305. }
  2306. void
  2307. QueryRouteTable(int argc, char *argv[])
  2308. {
  2309. if (argc == 0) {
  2310. if (Persistent)
  2311. ForEachPersistentInterface(PrintPersistentRoutesOnInterface);
  2312. else
  2313. ForEachRoute(PrintRouteTableEntry);
  2314. }
  2315. else {
  2316. usage();
  2317. }
  2318. }
  2319. void
  2320. UpdateRouteTable(int argc, char *argv[])
  2321. {
  2322. IPV6_INFO_ROUTE_TABLE Route;
  2323. u_int BytesReturned;
  2324. int i;
  2325. Route.SitePrefixLength = 0;
  2326. Route.ValidLifetime = INFINITE_LIFETIME;
  2327. Route.PreferredLifetime = INFINITE_LIFETIME;
  2328. Route.Preference = ROUTE_PREF_HIGHEST;
  2329. Route.Type = RTE_TYPE_MANUAL;
  2330. Route.Publish = FALSE;
  2331. Route.Immortal = -1;
  2332. if (argc < 2)
  2333. usage();
  2334. if (! GetNeighbor(argv[1],
  2335. &Route.This.Neighbor.IF,
  2336. &Route.This.Neighbor.Address))
  2337. usage();
  2338. if (! GetPrefix(argv[0],
  2339. &Route.This.Prefix,
  2340. &Route.This.PrefixLength))
  2341. usage();
  2342. for (i = 2; i < argc; i++) {
  2343. if (!strncmp(argv[i], "lifetime", strlen(argv[i])) &&
  2344. (i+1 < argc)) {
  2345. if (! GetLifetimes(argv[++i],
  2346. &Route.ValidLifetime,
  2347. &Route.PreferredLifetime))
  2348. usage();
  2349. }
  2350. else if (!strncmp(argv[i], "preference", strlen(argv[i])) &&
  2351. (i+1 < argc)) {
  2352. i++;
  2353. if (!strncmp(argv[i], "low", strlen(argv[i])))
  2354. Route.Preference = ROUTE_PREF_LOW;
  2355. else if (!strncmp(argv[i], "medium", strlen(argv[i])))
  2356. Route.Preference = ROUTE_PREF_MEDIUM;
  2357. else if (!strncmp(argv[i], "high", strlen(argv[i])))
  2358. Route.Preference = ROUTE_PREF_HIGH;
  2359. else if (!strncmp(argv[i], "onlink", strlen(argv[i])))
  2360. Route.Preference = ROUTE_PREF_ON_LINK;
  2361. else if (!strncmp(argv[i], "loopback", strlen(argv[i])))
  2362. Route.Preference = ROUTE_PREF_LOOPBACK;
  2363. else if (! GetNumber(argv[i], &Route.Preference))
  2364. usage();
  2365. }
  2366. else if (!strcmp(argv[i], "spl") && (i+1 < argc)) {
  2367. if (! GetNumber(argv[++i], &Route.SitePrefixLength))
  2368. usage();
  2369. }
  2370. else if (!strncmp(argv[i], "advertise", strlen(argv[i])) ||
  2371. !strncmp(argv[i], "publish", strlen(argv[i]))) {
  2372. Route.Publish = TRUE;
  2373. }
  2374. else if (!strncmp(argv[i], "immortal", strlen(argv[i])) ||
  2375. !strncmp(argv[i], "noaging", strlen(argv[i])) ||
  2376. !strcmp(argv[i], "noage")) {
  2377. Route.Immortal = TRUE;
  2378. }
  2379. else if (!strncmp(argv[i], "aging", strlen(argv[i])) ||
  2380. !strcmp(argv[i], "age")) {
  2381. Route.Immortal = FALSE;
  2382. }
  2383. else if (!strcmp(argv[i], "system")) {
  2384. Route.Type = RTE_TYPE_SYSTEM;
  2385. }
  2386. else if (!strcmp(argv[i], "manual")) {
  2387. Route.Type = RTE_TYPE_MANUAL;
  2388. }
  2389. else if (!strcmp(argv[i], "autoconf")) {
  2390. Route.Type = RTE_TYPE_AUTOCONF;
  2391. }
  2392. else if (!strcmp(argv[i], "rip")) {
  2393. Route.Type = RTE_TYPE_RIP;
  2394. }
  2395. else if (!strcmp(argv[i], "ospf")) {
  2396. Route.Type = RTE_TYPE_OSPF;
  2397. }
  2398. else if (!strcmp(argv[i], "bgp")) {
  2399. Route.Type = RTE_TYPE_BGP;
  2400. }
  2401. else if (!strcmp(argv[i], "idrp")) {
  2402. Route.Type = RTE_TYPE_IDRP;
  2403. }
  2404. else if (!strcmp(argv[i], "igrp")) {
  2405. Route.Type = RTE_TYPE_IGRP;
  2406. }
  2407. else
  2408. usage();
  2409. }
  2410. if (Route.Immortal == -1)
  2411. Route.Immortal = Route.Publish;
  2412. if (!DeviceIoControl(Handle,
  2413. (Persistent ?
  2414. IOCTL_IPV6_PERSISTENT_UPDATE_ROUTE_TABLE :
  2415. IOCTL_IPV6_UPDATE_ROUTE_TABLE),
  2416. &Route, sizeof Route,
  2417. NULL, 0, &BytesReturned, NULL)) {
  2418. NlsPutMsg(STDOUT, IPV6_MESSAGE_124, GetLastError());
  2419. // printf("route update error: %x\n", GetLastError());
  2420. exit(1);
  2421. }
  2422. }
  2423. void
  2424. UpdateAddress(int argc, char *argv[])
  2425. {
  2426. IPV6_UPDATE_ADDRESS Update;
  2427. u_int BytesReturned;
  2428. int i;
  2429. int Origin;
  2430. Update.Type = ADE_UNICAST;
  2431. Update.PrefixConf = PREFIX_CONF_MANUAL;
  2432. Update.InterfaceIdConf = IID_CONF_MANUAL;
  2433. Update.ValidLifetime = INFINITE_LIFETIME;
  2434. Update.PreferredLifetime = INFINITE_LIFETIME;
  2435. if (argc < 1)
  2436. usage();
  2437. if ((strchr(argv[0], '/') == NULL) ||
  2438. ! GetNeighbor(argv[0],
  2439. &Update.This.IF,
  2440. &Update.This.Address))
  2441. usage();
  2442. for (i = 1; i < argc; i++) {
  2443. if (!strncmp(argv[i], "lifetime", strlen(argv[i])) &&
  2444. (i+1 < argc)) {
  2445. if (! GetLifetimes(argv[++i],
  2446. &Update.ValidLifetime,
  2447. &Update.PreferredLifetime))
  2448. usage();
  2449. }
  2450. else if (!strcmp(argv[i], "unicast"))
  2451. Update.Type = ADE_UNICAST;
  2452. else if (!strcmp(argv[i], "anycast"))
  2453. Update.Type = ADE_ANYCAST;
  2454. else if (!strcmp(argv[i], "prefixorigin") &&
  2455. (i+1 < argc)) {
  2456. if (! GetPrefixOrigin(argv[++i], &Origin))
  2457. usage();
  2458. Update.PrefixConf = Origin;
  2459. }
  2460. else if (!strcmp(argv[i], "ifidorigin") &&
  2461. (i+1 < argc)) {
  2462. if (! GetInterfaceIdOrigin(argv[++i], &Origin))
  2463. usage();
  2464. Update.InterfaceIdConf = Origin;
  2465. }
  2466. else
  2467. usage();
  2468. }
  2469. if (!DeviceIoControl(Handle,
  2470. (Persistent ?
  2471. IOCTL_IPV6_PERSISTENT_UPDATE_ADDRESS :
  2472. IOCTL_IPV6_UPDATE_ADDRESS),
  2473. &Update, sizeof Update,
  2474. NULL, 0, &BytesReturned, NULL)) {
  2475. NlsPutMsg(STDOUT, IPV6_MESSAGE_125, GetLastError());
  2476. // printf("address update error: %x\n", GetLastError());
  2477. exit(1);
  2478. }
  2479. }
  2480. void
  2481. ForEachBinding(void (*func)(IPV6_INFO_BINDING_CACHE *))
  2482. {
  2483. IPV6_QUERY_BINDING_CACHE Query, NextQuery;
  2484. IPV6_INFO_BINDING_CACHE BCE;
  2485. u_int BytesReturned;
  2486. NextQuery.HomeAddress = in6addr_any;
  2487. for (;;) {
  2488. Query = NextQuery;
  2489. if (!DeviceIoControl(Handle, IOCTL_IPV6_QUERY_BINDING_CACHE,
  2490. &Query, sizeof Query,
  2491. &BCE, sizeof BCE, &BytesReturned,
  2492. NULL)) {
  2493. NlsPutMsg(STDOUT, IPV6_MESSAGE_126,
  2494. FormatIPv6Address(&Query.HomeAddress));
  2495. // printf("bad home address %s\n",
  2496. // FormatIPv6Address(&Query.HomeAddress));
  2497. exit(1);
  2498. }
  2499. NextQuery = BCE.Query;
  2500. if (!IN6_ADDR_EQUAL(&Query.HomeAddress, &in6addr_any)) {
  2501. BCE.Query = Query;
  2502. (*func)(&BCE);
  2503. }
  2504. if (IN6_ADDR_EQUAL(&NextQuery.HomeAddress, &in6addr_any))
  2505. break;
  2506. }
  2507. }
  2508. void
  2509. PrintBindingCacheEntry(IPV6_INFO_BINDING_CACHE *BCE)
  2510. {
  2511. NlsPutMsg(STDOUT, IPV6_MESSAGE_127,
  2512. FormatIPv6Address(&BCE->HomeAddress));
  2513. // printf("home: %s\n", FormatIPv6Address(&BCE->HomeAddress));
  2514. NlsPutMsg(STDOUT, IPV6_MESSAGE_128,
  2515. FormatIPv6Address(&BCE->CareOfAddress));
  2516. // printf(" c/o: %s\n", FormatIPv6Address(&BCE->CareOfAddress));
  2517. NlsPutMsg(STDOUT, IPV6_MESSAGE_129,
  2518. BCE->BindingSeqNumber, BCE->BindingLifetime);
  2519. // printf(" seq: %u Lifetime: %us\n\n",
  2520. // BCE->BindingSeqNumber, BCE->BindingLifetime);
  2521. }
  2522. void
  2523. QueryBindingCache(int argc, char *argv[])
  2524. {
  2525. if (argc == 0) {
  2526. ForEachBinding(PrintBindingCacheEntry);
  2527. } else {
  2528. usage();
  2529. }
  2530. }
  2531. void
  2532. FlushNeighborCacheForInterface(IPV6_INFO_INTERFACE *IF)
  2533. {
  2534. IPV6_QUERY_NEIGHBOR_CACHE Query;
  2535. u_int BytesReturned;
  2536. Query.IF = IF->This;
  2537. Query.Address = in6addr_any;
  2538. if (!DeviceIoControl(Handle, IOCTL_IPV6_FLUSH_NEIGHBOR_CACHE,
  2539. &Query, sizeof Query,
  2540. NULL, 0, &BytesReturned, NULL)) {
  2541. NlsPutMsg(STDOUT, IPV6_MESSAGE_130, GetLastError());
  2542. // printf("flush neighbor cache error: %x\n", GetLastError());
  2543. exit(1);
  2544. }
  2545. }
  2546. void
  2547. FlushNeighborCache(int argc, char *argv[])
  2548. {
  2549. //
  2550. // Rather than put code in the kernel ioctl to iterate
  2551. // over the interfaces, we do it here in user space.
  2552. //
  2553. if (argc == 0) {
  2554. ForEachInterface(FlushNeighborCacheForInterface);
  2555. }
  2556. else {
  2557. IPV6_QUERY_NEIGHBOR_CACHE Query;
  2558. u_int BytesReturned;
  2559. Query.IF.Index = 0;
  2560. Query.Address = in6addr_any;
  2561. switch (argc) {
  2562. case 2:
  2563. if (! GetAddress(argv[1], &Query.Address))
  2564. usage();
  2565. // fall-through
  2566. case 1:
  2567. if (! GetInterface(argv[0], &Query.IF))
  2568. usage();
  2569. // fall-through
  2570. case 0:
  2571. break;
  2572. default:
  2573. usage();
  2574. }
  2575. if (!DeviceIoControl(Handle, IOCTL_IPV6_FLUSH_NEIGHBOR_CACHE,
  2576. &Query, sizeof Query,
  2577. NULL, 0, &BytesReturned, NULL)) {
  2578. NlsPutMsg(STDOUT, IPV6_MESSAGE_130, GetLastError());
  2579. // printf("flush neighbor cache error: %x\n", GetLastError());
  2580. exit(1);
  2581. }
  2582. }
  2583. }
  2584. void
  2585. FlushRouteCache(int argc, char *argv[])
  2586. {
  2587. IPV6_QUERY_ROUTE_CACHE Query;
  2588. u_int BytesReturned;
  2589. Query.IF.Index = (u_int)-1;
  2590. Query.Address = in6addr_any;
  2591. switch (argc) {
  2592. case 2:
  2593. if (! GetAddress(argv[1], &Query.Address))
  2594. usage();
  2595. // fall-through
  2596. case 1:
  2597. if (! GetInterface(argv[0], &Query.IF))
  2598. usage();
  2599. // fall-through
  2600. case 0:
  2601. break;
  2602. default:
  2603. usage();
  2604. }
  2605. if (!DeviceIoControl(Handle, IOCTL_IPV6_FLUSH_ROUTE_CACHE,
  2606. &Query, sizeof Query,
  2607. NULL, 0, &BytesReturned, NULL)) {
  2608. NlsPutMsg(STDOUT, IPV6_MESSAGE_131, GetLastError());
  2609. // printf("flush route cache error: %x\n", GetLastError());
  2610. exit(1);
  2611. }
  2612. }
  2613. void
  2614. ForEachSitePrefix(void (*func)(IPV6_INFO_SITE_PREFIX *))
  2615. {
  2616. IPV6_QUERY_SITE_PREFIX Query, NextQuery;
  2617. IPV6_INFO_SITE_PREFIX SPE;
  2618. u_int BytesReturned;
  2619. NextQuery.IF.Index = 0;
  2620. for (;;) {
  2621. Query = NextQuery;
  2622. if (!DeviceIoControl(Handle, IOCTL_IPV6_QUERY_SITE_PREFIX,
  2623. &Query, sizeof Query,
  2624. &SPE, sizeof SPE, &BytesReturned,
  2625. NULL)) {
  2626. NlsPutMsg(STDOUT, IPV6_MESSAGE_132, Query.IF.Index);
  2627. // printf("bad index %u\n", Query.IF.Index);
  2628. exit(1);
  2629. }
  2630. NextQuery = SPE.Query;
  2631. if (Query.IF.Index != 0) {
  2632. SPE.Query = Query;
  2633. (*func)(&SPE);
  2634. }
  2635. if (NextQuery.IF.Index == 0)
  2636. break;
  2637. }
  2638. }
  2639. void
  2640. PrintSitePrefix(IPV6_INFO_SITE_PREFIX *SPE)
  2641. {
  2642. NlsPutMsg(STDOUT, IPV6_MESSAGE_133,
  2643. FormatIPv6Address(&SPE->Query.Prefix),
  2644. SPE->Query.PrefixLength,
  2645. SPE->Query.IF.Index,
  2646. FormatLifetimes(SPE->ValidLifetime, SPE->ValidLifetime));
  2647. // printf("%s/%u -> %u (life %s)\n",
  2648. // FormatIPv6Address(&SPE->Query.Prefix),
  2649. // SPE->Query.PrefixLength,
  2650. // SPE->Query.IF.Index,
  2651. // FormatLifetimes(SPE->ValidLifetime, SPE->ValidLifetime));
  2652. }
  2653. void
  2654. QuerySitePrefixTable(int argc, char *argv[])
  2655. {
  2656. if (argc == 0) {
  2657. ForEachSitePrefix(PrintSitePrefix);
  2658. }
  2659. else {
  2660. usage();
  2661. }
  2662. }
  2663. void
  2664. UpdateSitePrefixTable(int argc, char *argv[])
  2665. {
  2666. IPV6_INFO_SITE_PREFIX SitePrefix;
  2667. u_int BytesReturned;
  2668. int i;
  2669. SitePrefix.ValidLifetime = INFINITE_LIFETIME;
  2670. if (argc < 2)
  2671. usage();
  2672. if (! GetInterface(argv[1], &SitePrefix.Query.IF))
  2673. usage();
  2674. if (! GetPrefix(argv[0],
  2675. &SitePrefix.Query.Prefix,
  2676. &SitePrefix.Query.PrefixLength))
  2677. usage();
  2678. for (i = 2; i < argc; i++) {
  2679. if (!strncmp(argv[i], "lifetime", strlen(argv[i])) &&
  2680. (i+1 < argc)) {
  2681. if (! GetLifetimes(argv[++i], &SitePrefix.ValidLifetime, NULL))
  2682. usage();
  2683. }
  2684. else
  2685. usage();
  2686. }
  2687. if (!DeviceIoControl(Handle, IOCTL_IPV6_UPDATE_SITE_PREFIX,
  2688. &SitePrefix, sizeof SitePrefix,
  2689. NULL, 0, &BytesReturned, NULL)) {
  2690. NlsPutMsg(STDOUT, IPV6_MESSAGE_134, GetLastError());
  2691. // printf("site prefix update error: %x\n", GetLastError());
  2692. exit(1);
  2693. }
  2694. }
  2695. void
  2696. QueryGlobalParameters(int argc, char *argv[])
  2697. {
  2698. IPV6_GLOBAL_PARAMETERS Params;
  2699. u_int BytesReturned;
  2700. if (argc != 0)
  2701. usage();
  2702. if (!DeviceIoControl(Handle,
  2703. (Persistent ?
  2704. IOCTL_IPV6_PERSISTENT_QUERY_GLOBAL_PARAMETERS :
  2705. IOCTL_IPV6_QUERY_GLOBAL_PARAMETERS),
  2706. NULL, 0,
  2707. &Params, sizeof Params, &BytesReturned, NULL) ||
  2708. (BytesReturned != sizeof Params)) {
  2709. NlsPutMsg(STDOUT, IPV6_MESSAGE_135, GetLastError());
  2710. // printf("query global params error: %x\n", GetLastError());
  2711. exit(1);
  2712. }
  2713. if (Params.DefaultCurHopLimit != (u_int) -1) {
  2714. NlsPutMsg(STDOUT, IPV6_MESSAGE_136, Params.DefaultCurHopLimit);
  2715. // printf("DefaultCurHopLimit = %u\n", Params.DefaultCurHopLimit);
  2716. }
  2717. if (Params.UseTemporaryAddresses != (u_int) -1) {
  2718. switch (Params.UseTemporaryAddresses) {
  2719. case USE_TEMP_NO:
  2720. NlsPutMsg(STDOUT, IPV6_MESSAGE_137);
  2721. // printf("UseTemporaryAddresses = no\n");
  2722. break;
  2723. case USE_TEMP_YES:
  2724. NlsPutMsg(STDOUT, IPV6_MESSAGE_138);
  2725. // printf("UseTemporaryAddresses = yes\n");
  2726. break;
  2727. case USE_TEMP_ALWAYS:
  2728. NlsPutMsg(STDOUT, IPV6_MESSAGE_139);
  2729. // printf("UseTemporaryAddresses = yes, new random interface id for every address\n");
  2730. break;
  2731. case USE_TEMP_COUNTER:
  2732. NlsPutMsg(STDOUT, IPV6_MESSAGE_140);
  2733. // printf("UseTemporaryAddresses = yes, incrementing interface ids\n");
  2734. break;
  2735. default:
  2736. NlsPutMsg(STDOUT, IPV6_MESSAGE_141, Params.UseTemporaryAddresses);
  2737. // printf("UseTemporaryAddresses = %u\n", Params.UseTemporaryAddresses);
  2738. break;
  2739. }
  2740. }
  2741. if (Params.MaxTempDADAttempts != (u_int) -1) {
  2742. NlsPutMsg(STDOUT, IPV6_MESSAGE_142, Params.MaxTempDADAttempts);
  2743. // printf("MaxTempDADAttempts = %u\n", Params.MaxTempDADAttempts);
  2744. }
  2745. if ((Params.MaxTempValidLifetime != (u_int) -1) ||
  2746. (Params.MaxTempPreferredLifetime != (u_int) -1)) {
  2747. NlsPutMsg(STDOUT, IPV6_MESSAGE_143,
  2748. FormatLifetimes(Params.MaxTempValidLifetime,
  2749. Params.MaxTempPreferredLifetime));
  2750. // printf("MaxTempLifetime = %s\n",
  2751. // FormatLifetimes(Params.MaxTempValidLifetime,
  2752. // Params.MaxTempPreferredLifetime));
  2753. }
  2754. if (Params.TempRegenerateTime != (u_int) -1) {
  2755. NlsPutMsg(STDOUT, IPV6_MESSAGE_144, Params.TempRegenerateTime);
  2756. // printf("TempRegenerateTime = %us\n", Params.TempRegenerateTime);
  2757. }
  2758. if (Params.MaxTempRandomTime != (u_int) -1) {
  2759. NlsPutMsg(STDOUT, IPV6_MESSAGE_145,
  2760. FormatLifetime(Params.MaxTempRandomTime));
  2761. // printf("MaxTempRandomTime = %s\n",
  2762. // FormatLifetime(Params.MaxTempRandomTime));
  2763. }
  2764. if (! Persistent) {
  2765. NlsPutMsg(STDOUT, IPV6_MESSAGE_146,
  2766. FormatLifetime(Params.TempRandomTime));
  2767. // printf("TempRandomTime = %s\n",
  2768. // FormatLifetime(Params.TempRandomTime));
  2769. }
  2770. if (Params.NeighborCacheLimit != (u_int) -1) {
  2771. NlsPutMsg(STDOUT, IPV6_MESSAGE_147, Params.NeighborCacheLimit);
  2772. // printf("NeighborCacheLimit = %u\n", Params.NeighborCacheLimit);
  2773. }
  2774. if (Params.RouteCacheLimit != (u_int) -1) {
  2775. NlsPutMsg(STDOUT, IPV6_MESSAGE_148, Params.RouteCacheLimit);
  2776. // printf("RouteCacheLimit = %u\n", Params.RouteCacheLimit);
  2777. }
  2778. if (Params.BindingCacheLimit != (u_int) -1) {
  2779. NlsPutMsg(STDOUT, IPV6_MESSAGE_BCL_DISPLAY, Params.BindingCacheLimit);
  2780. // printf("BindingCacheLimit = %u\n", Params.BindingCacheLimit);
  2781. }
  2782. if (Params.ReassemblyLimit != (u_int) -1) {
  2783. NlsPutMsg(STDOUT, IPV6_MESSAGE_REASS_LIMIT_DISPLAY, Params.ReassemblyLimit);
  2784. // printf("ReassemblyLimit = %u\n", Params.ReassemblyLimit);
  2785. }
  2786. if (Params.MobilitySecurity != -1) {
  2787. if (Params.MobilitySecurity) {
  2788. NlsPutMsg(STDOUT, IPV6_MESSAGE_MOBILITY_SECURITY_ON);
  2789. // printf("MobilitySecurity = on\n");
  2790. }
  2791. else {
  2792. NlsPutMsg(STDOUT, IPV6_MESSAGE_MOBILITY_SECURITY_OFF);
  2793. // printf("MobilitySecurity = off\n");
  2794. }
  2795. }
  2796. if (Params.MobileIPv6Mode != (u_int) -1) {
  2797. NlsPutMsg(STDOUT, MIPV6_MESSAGE_MODE);
  2798. // printf("MobileIPv6Mode =");
  2799. if (Params.MobileIPv6Mode & MOBILE_MOBILE_NODE) {
  2800. NlsPutMsg(STDOUT, MIPV6_MESSAGE_MODE_MN);
  2801. // printf(" MN");
  2802. }
  2803. if (Params.MobileIPv6Mode & MOBILE_HOME_AGENT) {
  2804. NlsPutMsg(STDOUT, MIPV6_MESSAGE_MODE_HA);
  2805. // printf(" HA");
  2806. }
  2807. if (Params.MobileIPv6Mode & MOBILE_CORRESPONDENT) {
  2808. NlsPutMsg(STDOUT, MIPV6_MESSAGE_MODE_CN);
  2809. // printf(" CN");
  2810. }
  2811. NlsPutMsg(STDOUT, IPV6_MESSAGE_36);
  2812. // printf("\n");
  2813. }
  2814. }
  2815. void
  2816. UpdateGlobalParameters(int argc, char *argv[])
  2817. {
  2818. IPV6_GLOBAL_PARAMETERS Params;
  2819. u_int BytesReturned;
  2820. int i;
  2821. IPV6_INIT_GLOBAL_PARAMETERS(&Params);
  2822. for (i = 0; i < argc; i++) {
  2823. if (!strcmp(argv[i], "DefaultCurHopLimit") && (i+1 < argc)) {
  2824. if (! GetNumber(argv[++i], &Params.DefaultCurHopLimit))
  2825. goto usage;
  2826. }
  2827. else if (!strcmp(argv[i], "UseTemporaryAddresses") && (i+1 < argc)) {
  2828. if (!strncmp(argv[++i], "no", strlen(argv[i])))
  2829. Params.UseTemporaryAddresses = USE_TEMP_NO;
  2830. else if (!strncmp(argv[i], "yes", strlen(argv[i])))
  2831. Params.UseTemporaryAddresses = USE_TEMP_YES;
  2832. else if (!strncmp(argv[i], "always", strlen(argv[i])))
  2833. Params.UseTemporaryAddresses = USE_TEMP_ALWAYS;
  2834. else if (!strncmp(argv[i], "counter", strlen(argv[i])))
  2835. Params.UseTemporaryAddresses = USE_TEMP_COUNTER;
  2836. else
  2837. goto usage;
  2838. }
  2839. else if (!strcmp(argv[i], "MaxTempDADAttempts") && (i+1 < argc)) {
  2840. if (! GetNumber(argv[++i], &Params.MaxTempDADAttempts))
  2841. goto usage;
  2842. }
  2843. else if (!strcmp(argv[i], "MaxTempLifetime") && (i+1 < argc)) {
  2844. if (! GetLifetimes(argv[++i],
  2845. &Params.MaxTempValidLifetime,
  2846. &Params.MaxTempPreferredLifetime))
  2847. goto usage;
  2848. }
  2849. else if (!strcmp(argv[i], "TempRegenerateTime") && (i+1 < argc)) {
  2850. if (! GetLifetime(argv[++i], &Params.TempRegenerateTime))
  2851. goto usage;
  2852. }
  2853. else if (!strcmp(argv[i], "MaxTempRandomTime") && (i+1 < argc)) {
  2854. if (! GetLifetime(argv[++i], &Params.MaxTempRandomTime))
  2855. goto usage;
  2856. }
  2857. else if (!strcmp(argv[i], "TempRandomTime") && (i+1 < argc)) {
  2858. if (! GetLifetime(argv[++i], &Params.TempRandomTime))
  2859. goto usage;
  2860. }
  2861. else if (!strcmp(argv[i], "NeighborCacheLimit") && (i+1 < argc)) {
  2862. if (! GetNumber(argv[++i], &Params.NeighborCacheLimit))
  2863. goto usage;
  2864. }
  2865. else if (!strcmp(argv[i], "RouteCacheLimit") && (i+1 < argc)) {
  2866. if (! GetNumber(argv[++i], &Params.RouteCacheLimit))
  2867. goto usage;
  2868. }
  2869. else if (!strcmp(argv[i], "BindingCacheLimit") && (i+1 < argc)) {
  2870. if (! GetNumber(argv[++i], &Params.BindingCacheLimit))
  2871. goto usage;
  2872. }
  2873. else if (!strcmp(argv[i], "ReassemblyLimit") && (i+1 < argc)) {
  2874. if (! GetNumber(argv[++i], &Params.ReassemblyLimit))
  2875. goto usage;
  2876. }
  2877. else if (!strcmp(argv[i], "MobilitySecurity") && (i+1 < argc)) {
  2878. if (!strncmp(argv[++i], "on", strlen(argv[i])))
  2879. Params.MobilitySecurity = TRUE;
  2880. else if (!strncmp(argv[i], "off", strlen(argv[i])))
  2881. Params.MobilitySecurity = FALSE;
  2882. else if (!strncmp(argv[i], "yes", strlen(argv[i])))
  2883. Params.MobilitySecurity = TRUE;
  2884. else if (!strncmp(argv[i], "no", strlen(argv[i])))
  2885. Params.MobilitySecurity = FALSE;
  2886. else
  2887. goto usage;
  2888. }
  2889. else if (!strcmp(argv[i], "MobileIPv6Mode")) {
  2890. Params.MobileIPv6Mode = 0;
  2891. while (++i < argc) {
  2892. if (!strncmp(argv[i], "CN", strlen(argv[i])))
  2893. Params.MobileIPv6Mode |= MOBILE_CORRESPONDENT;
  2894. else if (!strncmp(argv[i], "MN", strlen(argv[i])))
  2895. Params.MobileIPv6Mode |= MOBILE_MOBILE_NODE;
  2896. else if (!strncmp(argv[i], "HA", strlen(argv[i])))
  2897. Params.MobileIPv6Mode |= MOBILE_HOME_AGENT;
  2898. else
  2899. break;
  2900. }
  2901. i--;
  2902. //
  2903. // Until we have full mobility support, only allow CN.
  2904. //
  2905. if (Params.MobileIPv6Mode &~ MOBILE_CORRESPONDENT) {
  2906. // printf("MobileIPv6Modes MN and HA currently unsupported\n");
  2907. NlsPutMsg(STDOUT, MIPV6_MESSAGE_UNSUPPORTED_MODE);
  2908. exit(1);
  2909. }
  2910. //
  2911. // Disallow nonsensical combinations.
  2912. //
  2913. if ((Params.MobileIPv6Mode & MOBILE_MOBILE_NODE) &&
  2914. (Params.MobileIPv6Mode & MOBILE_HOME_AGENT)) {
  2915. // printf("invalid MobileIPv6Mode combination (HA and MN).\n");
  2916. NlsPutMsg(STDOUT, MIPV6_MESSAGE_INVALID_MODE_COMBINATION1);
  2917. exit(1);
  2918. }
  2919. if ((Params.MobileIPv6Mode & MOBILE_HOME_AGENT) &&
  2920. !(Params.MobileIPv6Mode & MOBILE_CORRESPONDENT)) {
  2921. // printf("invalid MobileIPv6Mode combination (HA and not CN).\n");
  2922. NlsPutMsg(STDOUT, MIPV6_MESSAGE_INVALID_MODE_COMBINATION2);
  2923. exit(1);
  2924. }
  2925. }
  2926. else {
  2927. usage:
  2928. NlsPutMsg(STDOUT, IPV6_MESSAGE_149);
  2929. // printf("usage: ipv6 gpu [parameter value] ...\n");
  2930. // printf(" ipv6 gpu DefaultCurHopLimit hops\n");
  2931. // printf(" ipv6 gpu UseTemporaryAddresses [yes|no|always|counter]\n");
  2932. // printf(" ipv6 gpu MaxTempDADAttempts number\n");
  2933. // printf(" ipv6 gpu MaxTempLifetime valid[/preferred]\n");
  2934. // printf(" ipv6 gpu TempRegenerateTime time\n");
  2935. // printf(" ipv6 gpu MaxTempRandomTime time\n");
  2936. // printf(" ipv6 gpu TempRandomTime time\n");
  2937. // printf(" ipv6 gpu NeighborCacheLimit number\n");
  2938. // printf(" ipv6 gpu RouteCacheLimit number\n");
  2939. // printf(" ipv6 gpu BindingCacheLimit number\n");
  2940. // printf(" ipv6 gpu ReassemblyLimit number\n");
  2941. // printf(" ipv6 gpu MobilitySecurity [on|off]\n");
  2942. // printf(" ipv6 gpu MobileIPv6Mode [CN|MN|HA]*\n");
  2943. // printf("Use ipv6 -p gpu ... to make a persistent change\n");
  2944. // printf("in the registry. Many global parameter changes\n");
  2945. // printf("only take effect after restarting the stack.\n");
  2946. // printf("MobileIPv6Modes MN and HA are currently unsupported.\n");
  2947. exit(1);
  2948. }
  2949. }
  2950. if (!DeviceIoControl(Handle,
  2951. (Persistent ?
  2952. IOCTL_IPV6_PERSISTENT_UPDATE_GLOBAL_PARAMETERS :
  2953. IOCTL_IPV6_UPDATE_GLOBAL_PARAMETERS),
  2954. &Params, sizeof Params,
  2955. NULL, 0,
  2956. &BytesReturned, NULL)) {
  2957. NlsPutMsg(STDOUT, IPV6_MESSAGE_150, GetLastError());
  2958. // printf("update global params error: %x\n", GetLastError());
  2959. exit(1);
  2960. }
  2961. }
  2962. void
  2963. ForEachPrefixPolicy(void (*func)(IPV6_INFO_PREFIX_POLICY *))
  2964. {
  2965. IPV6_QUERY_PREFIX_POLICY Query;
  2966. IPV6_INFO_PREFIX_POLICY PPE;
  2967. u_int BytesReturned;
  2968. Query.PrefixLength = (u_int) -1;
  2969. for (;;) {
  2970. if (!DeviceIoControl(Handle, IOCTL_IPV6_QUERY_PREFIX_POLICY,
  2971. &Query, sizeof Query,
  2972. &PPE, sizeof PPE, &BytesReturned,
  2973. NULL)) {
  2974. NlsPutMsg(STDOUT, IPV6_MESSAGE_160);
  2975. // printf("bad prefix\n");
  2976. exit(1);
  2977. }
  2978. if (Query.PrefixLength != (u_int) -1) {
  2979. if (BytesReturned != sizeof PPE) {
  2980. NlsPutMsg(STDOUT, IPV6_MESSAGE_160);
  2981. // printf("bad prefix\n");
  2982. exit(1);
  2983. }
  2984. (*func)(&PPE);
  2985. }
  2986. else {
  2987. if (BytesReturned != sizeof PPE.Next) {
  2988. NlsPutMsg(STDOUT, IPV6_MESSAGE_160);
  2989. // printf("bad prefix\n");
  2990. exit(1);
  2991. }
  2992. }
  2993. if (PPE.Next.PrefixLength == (u_int) -1)
  2994. break;
  2995. Query = PPE.Next;
  2996. }
  2997. }
  2998. void
  2999. ForEachPersistentPrefixPolicy(void (*func)(IPV6_INFO_PREFIX_POLICY *))
  3000. {
  3001. IPV6_PERSISTENT_QUERY_PREFIX_POLICY Query;
  3002. IPV6_INFO_PREFIX_POLICY PPE;
  3003. u_int BytesReturned;
  3004. for (Query.RegistryIndex = 0;; Query.RegistryIndex++) {
  3005. if (!DeviceIoControl(Handle,
  3006. IOCTL_IPV6_PERSISTENT_QUERY_PREFIX_POLICY,
  3007. &Query, sizeof Query,
  3008. &PPE, sizeof PPE, &BytesReturned,
  3009. NULL)) {
  3010. if (GetLastError() == ERROR_NO_MORE_ITEMS)
  3011. break;
  3012. NlsPutMsg(STDOUT, IPV6_MESSAGE_160);
  3013. // printf("bad prefix\n");
  3014. exit(1);
  3015. }
  3016. if (BytesReturned != sizeof PPE) {
  3017. NlsPutMsg(STDOUT, IPV6_MESSAGE_160);
  3018. // printf("bad prefix\n");
  3019. exit(1);
  3020. }
  3021. (*func)(&PPE);
  3022. }
  3023. }
  3024. void
  3025. PrintPrefixPolicyEntry(IPV6_INFO_PREFIX_POLICY *PPE)
  3026. {
  3027. NlsPutMsg(STDOUT, IPV6_MESSAGE_161,
  3028. FormatIPv6Address(&PPE->This.Prefix),
  3029. PPE->This.PrefixLength,
  3030. PPE->Precedence,
  3031. PPE->SrcLabel,
  3032. PPE->DstLabel);
  3033. // printf("%s/%u -> precedence %u srclabel %u dstlabel %u\n",
  3034. // FormatIPv6Address(&PPE->This.Prefix),
  3035. // PPE->This.PrefixLength,
  3036. // PPE->Precedence,
  3037. // PPE->SrcLabel,
  3038. // PPE->DstLabel);
  3039. }
  3040. void
  3041. QueryPrefixPolicy(int argc, char *argv[])
  3042. {
  3043. if (argc == 0) {
  3044. if (Persistent)
  3045. ForEachPersistentPrefixPolicy(PrintPrefixPolicyEntry);
  3046. else
  3047. ForEachPrefixPolicy(PrintPrefixPolicyEntry);
  3048. }
  3049. else {
  3050. usage();
  3051. }
  3052. }
  3053. void
  3054. UpdatePrefixPolicy(int argc, char *argv[])
  3055. {
  3056. IPV6_INFO_PREFIX_POLICY Info;
  3057. u_int BytesReturned;
  3058. int i;
  3059. if (argc < 1)
  3060. usage();
  3061. if (! GetPrefix(argv[0],
  3062. &Info.This.Prefix,
  3063. &Info.This.PrefixLength))
  3064. usage();
  3065. Info.Precedence = (u_int) -1;
  3066. Info.SrcLabel = (u_int) -1;
  3067. Info.DstLabel = (u_int) -1;
  3068. for (i = 1; i < argc; i++) {
  3069. if (!strncmp(argv[i], "precedence", strlen(argv[i])) &&
  3070. ((i + 1) < argc)) {
  3071. if (! GetNumber(argv[++i], &Info.Precedence))
  3072. usage();
  3073. }
  3074. else if ((!strncmp(argv[i], "srclabel", strlen(argv[i])) ||
  3075. !strcmp(argv[i], "sl") ||
  3076. !strcmp(argv[i], "label")) &&
  3077. ((i + 1) < argc)) {
  3078. if (! GetNumber(argv[++i], &Info.SrcLabel))
  3079. usage();
  3080. }
  3081. else if ((!strncmp(argv[i], "dstlabel", strlen(argv[i])) ||
  3082. !strcmp(argv[i], "dl")) &&
  3083. ((i + 1) < argc)) {
  3084. if (! GetNumber(argv[++i], &Info.DstLabel))
  3085. usage();
  3086. }
  3087. else
  3088. usage();
  3089. }
  3090. if ((Info.Precedence == (u_int) -1) ||
  3091. (Info.SrcLabel == (u_int) -1))
  3092. usage();
  3093. if (Info.DstLabel == (u_int) -1)
  3094. Info.DstLabel = Info.SrcLabel;
  3095. if (!DeviceIoControl(Handle,
  3096. (Persistent ?
  3097. IOCTL_IPV6_PERSISTENT_UPDATE_PREFIX_POLICY :
  3098. IOCTL_IPV6_UPDATE_PREFIX_POLICY),
  3099. &Info, sizeof Info,
  3100. NULL, 0, &BytesReturned, NULL)) {
  3101. NlsPutMsg(STDOUT, IPV6_MESSAGE_162, GetLastError());
  3102. // printf("prefix policy create error: %x\n", GetLastError());
  3103. exit(1);
  3104. }
  3105. }
  3106. void
  3107. DeletePrefixPolicy(int argc, char *argv[])
  3108. {
  3109. IPV6_QUERY_PREFIX_POLICY Query;
  3110. u_int BytesReturned;
  3111. if (argc == 1) {
  3112. if (! GetPrefix(argv[0],
  3113. &Query.Prefix,
  3114. &Query.PrefixLength))
  3115. usage();
  3116. }
  3117. else {
  3118. usage();
  3119. }
  3120. if (!DeviceIoControl(Handle,
  3121. (Persistent ?
  3122. IOCTL_IPV6_PERSISTENT_DELETE_PREFIX_POLICY :
  3123. IOCTL_IPV6_DELETE_PREFIX_POLICY),
  3124. &Query, sizeof Query,
  3125. NULL, 0, &BytesReturned, NULL)) {
  3126. NlsPutMsg(STDOUT, IPV6_MESSAGE_163, GetLastError());
  3127. // printf("prefix policy delete error: %x\n", GetLastError());
  3128. exit(1);
  3129. }
  3130. }
  3131. void
  3132. ResetManualConfig(int argc, char *argv[])
  3133. {
  3134. u_int BytesReturned;
  3135. if (argc != 0)
  3136. usage();
  3137. if (!DeviceIoControl(Handle,
  3138. (Persistent ?
  3139. IOCTL_IPV6_PERSISTENT_RESET :
  3140. IOCTL_IPV6_RESET),
  3141. NULL, 0,
  3142. NULL, 0, &BytesReturned, NULL)) {
  3143. NlsPutMsg(STDOUT, IPV6_MESSAGE_RESET, GetLastError());
  3144. // printf("reset error: %x\n", GetLastError());
  3145. exit(1);
  3146. }
  3147. }