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

3733 lines
102 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_10, GetLastError());
  658. // NlsPutMsg(STDOUT, IPV6_MESSAGE_INCONSISTENT_ADDRESS);
  659. // printf("inconsistent address info length\n");
  660. exit(1);
  661. }
  662. (*func)(IF, &ADE);
  663. }
  664. else {
  665. if (BytesReturned != sizeof ADE.Next) {
  666. NlsPutMsg(STDOUT, IPV6_MESSAGE_10, GetLastError());
  667. // NlsPutMsg(STDOUT, IPV6_MESSAGE_INCONSISTENT_ADDRESS);
  668. // printf("inconsistent address info length\n");
  669. exit(1);
  670. }
  671. }
  672. if (IN6_ADDR_EQUAL(&ADE.Next.Address, &in6addr_any))
  673. break;
  674. Query = ADE.Next;
  675. }
  676. }
  677. void
  678. ForEachPersistentAddress(IPV6_INFO_INTERFACE *IF,
  679. void (*func)(IPV6_INFO_INTERFACE *IF, IPV6_UPDATE_ADDRESS *))
  680. {
  681. IPV6_PERSISTENT_QUERY_ADDRESS Query;
  682. IPV6_UPDATE_ADDRESS ADE;
  683. u_int BytesReturned;
  684. Query.IF.RegistryIndex = (u_int) -1;
  685. Query.IF.Guid = IF->This.Guid;
  686. for (Query.RegistryIndex = 0;; Query.RegistryIndex++) {
  687. if (!DeviceIoControl(Handle,
  688. IOCTL_IPV6_PERSISTENT_QUERY_ADDRESS,
  689. &Query, sizeof Query,
  690. &ADE, sizeof ADE, &BytesReturned,
  691. NULL) ||
  692. (BytesReturned != sizeof ADE)) {
  693. if (GetLastError() == ERROR_NO_MORE_ITEMS)
  694. break;
  695. NlsPutMsg(STDOUT, IPV6_MESSAGE_22, FormatIPv6Address(&Query.Address));
  696. // printf("bad address %s\n", FormatIPv6Address(&Query.Address));
  697. exit(1);
  698. }
  699. (*func)(IF, &ADE);
  700. }
  701. }
  702. const char *
  703. FormatDADState(u_int DADState)
  704. {
  705. static char buffer[128];
  706. switch (DADState) {
  707. case DAD_STATE_INVALID:
  708. return "invalid";
  709. case DAD_STATE_DUPLICATE:
  710. return "duplicate";
  711. case DAD_STATE_TENTATIVE:
  712. return "tentative";
  713. case DAD_STATE_DEPRECATED:
  714. return "deprecated";
  715. case DAD_STATE_PREFERRED:
  716. return "preferred";
  717. default:
  718. sprintf(buffer, "DAD state %u>", DADState);
  719. return buffer;
  720. }
  721. }
  722. const char *
  723. FormatScopeAdj(u_int Scope)
  724. {
  725. static char buffer[128];
  726. switch (Scope) {
  727. case ADE_INTERFACE_LOCAL:
  728. return "interface-local";
  729. case ADE_LINK_LOCAL:
  730. return "link-local";
  731. case ADE_SUBNET_LOCAL:
  732. return "subnet-local";
  733. case ADE_ADMIN_LOCAL:
  734. return "admin-local";
  735. case ADE_SITE_LOCAL:
  736. return "site-local";
  737. case ADE_ORG_LOCAL:
  738. return "org-local";
  739. case ADE_GLOBAL:
  740. return "global";
  741. default:
  742. sprintf(buffer, "scope %u", Scope);
  743. return buffer;
  744. }
  745. }
  746. const char *
  747. FormatScopeNoun(u_int Scope)
  748. {
  749. static char buffer[128];
  750. switch (Scope) {
  751. case ADE_INTERFACE_LOCAL:
  752. return "if";
  753. case ADE_LINK_LOCAL:
  754. return "link";
  755. case ADE_SUBNET_LOCAL:
  756. return "subnet";
  757. case ADE_ADMIN_LOCAL:
  758. return "admin";
  759. case ADE_SITE_LOCAL:
  760. return "site";
  761. case ADE_ORG_LOCAL:
  762. return "org";
  763. case ADE_GLOBAL:
  764. return "global";
  765. default:
  766. sprintf(buffer, "zone%u", Scope);
  767. return buffer;
  768. }
  769. }
  770. void
  771. PrintAddrOrigin(u_int PrefixConf, u_int InterfaceIdConf)
  772. {
  773. if ((PrefixConf == PREFIX_CONF_MANUAL) &&
  774. (InterfaceIdConf == IID_CONF_MANUAL)) {
  775. NlsPutMsg(STDOUT, IPV6_MESSAGE_25);
  776. // printf(" (manual)");
  777. } else if ((PrefixConf == PREFIX_CONF_RA) &&
  778. (InterfaceIdConf == IID_CONF_LL_ADDRESS)) {
  779. NlsPutMsg(STDOUT, IPV6_MESSAGE_26);
  780. // printf(" (public)");
  781. } else if ((PrefixConf == PREFIX_CONF_RA) &&
  782. (InterfaceIdConf == IID_CONF_RANDOM)) {
  783. NlsPutMsg(STDOUT, IPV6_MESSAGE_27);
  784. // printf(" (anonymous)");
  785. } else if ((PrefixConf == PREFIX_CONF_DHCP) &&
  786. (InterfaceIdConf == IID_CONF_DHCP)) {
  787. NlsPutMsg(STDOUT, IPV6_MESSAGE_28);
  788. // printf(" (dhcp)");
  789. }
  790. if (Verbose) {
  791. //
  792. // Show prefix origin / interface id origin
  793. //
  794. NlsPutMsg(STDOUT, IPV6_MESSAGE_29);
  795. // printf(" (");
  796. if (PrefixConf >= MAX_PREFIX_CONF)
  797. NlsPutMsg(STDOUT, IPV6_MESSAGE_30, PrefixConf);
  798. // printf("unknown prefix origin %u", PrefixConf);
  799. else
  800. printf(PrefixConfStr[PrefixConf]);
  801. NlsPutMsg(STDOUT, IPV6_MESSAGE_32);
  802. // printf("/");
  803. if (InterfaceIdConf >= MAX_IID_CONF)
  804. NlsPutMsg(STDOUT, IPV6_MESSAGE_33, InterfaceIdConf);
  805. // printf("unknown ifid origin %u", InterfaceIdConf);
  806. else
  807. printf(InterfaceIdConfStr[InterfaceIdConf]);
  808. NlsPutMsg(STDOUT, IPV6_MESSAGE_35);
  809. // printf(")");
  810. }
  811. }
  812. void
  813. PrintAddress(IPV6_INFO_INTERFACE *IF, IPV6_INFO_ADDRESS *ADE)
  814. {
  815. if (!Verbose) {
  816. //
  817. // Suppress invalid addresses.
  818. //
  819. if ((ADE->Type == ADE_UNICAST) &&
  820. (ADE->DADState == DAD_STATE_INVALID))
  821. return;
  822. }
  823. switch (ADE->Type) {
  824. case ADE_UNICAST:
  825. NlsPutMsg(STDOUT, IPV6_MESSAGE_23,
  826. FormatDADState(ADE->DADState),
  827. FormatScopeAdj(ADE->Scope),
  828. FormatIPv6Address(&ADE->This.Address));
  829. // printf(" %s %s %s, ",
  830. // FormatDADState(ADE->DADState),
  831. // FormatScopeAdj(ADE->Scope),
  832. // FormatIPv6Address(&ADE->This.Address));
  833. NlsPutMsg(STDOUT, IPV6_MESSAGE_24,
  834. FormatLifetimes(ADE->ValidLifetime, ADE->PreferredLifetime));
  835. // printf("life %s",
  836. // FormatLifetimes(ADE->ValidLifetime, ADE->PreferredLifetime));
  837. PrintAddrOrigin(ADE->PrefixConf, ADE->InterfaceIdConf);
  838. NlsPutMsg(STDOUT, IPV6_MESSAGE_36);
  839. // printf("\n");
  840. break;
  841. case ADE_ANYCAST:
  842. NlsPutMsg(STDOUT, IPV6_MESSAGE_37,
  843. FormatScopeAdj(ADE->Scope),
  844. FormatIPv6Address(&ADE->This.Address));
  845. // printf(" anycast %s %s\n",
  846. // FormatScopeAdj(ADE->Scope),
  847. // FormatIPv6Address(&ADE->This.Address));
  848. break;
  849. case ADE_MULTICAST:
  850. NlsPutMsg(STDOUT, IPV6_MESSAGE_38,
  851. FormatScopeAdj(ADE->Scope),
  852. FormatIPv6Address(&ADE->This.Address),
  853. ADE->MCastRefCount);
  854. // printf(" multicast %s %s, %u refs",
  855. // FormatScopeAdj(ADE->Scope),
  856. // FormatIPv6Address(&ADE->This.Address),
  857. // ADE->MCastRefCount);
  858. if (!(ADE->MCastFlags & 0x01))
  859. NlsPutMsg(STDOUT, IPV6_MESSAGE_39);
  860. // printf(", not reportable");
  861. if (ADE->MCastFlags & 0x02)
  862. NlsPutMsg(STDOUT, IPV6_MESSAGE_40);
  863. // printf(", last reporter");
  864. if (ADE->MCastTimer != 0)
  865. NlsPutMsg(STDOUT, IPV6_MESSAGE_41, ADE->MCastTimer);
  866. // printf(", %u seconds until report", ADE->MCastTimer);
  867. NlsPutMsg(STDOUT, IPV6_MESSAGE_36);
  868. // printf("\n");
  869. break;
  870. default:
  871. NlsPutMsg(STDOUT, IPV6_MESSAGE_42,
  872. FormatScopeAdj(ADE->Scope), ADE->Type);
  873. // printf(" unknown %s address type %u\n",
  874. // FormatScopeAdj(ADE->Scope), ADE->Type);
  875. break;
  876. }
  877. }
  878. u_int
  879. AddressScope(IPv6Addr *Address)
  880. {
  881. if (IN6_IS_ADDR_LINKLOCAL(Address))
  882. return ADE_LINK_LOCAL;
  883. else if (IN6_IS_ADDR_SITELOCAL(Address))
  884. return ADE_SITE_LOCAL;
  885. else if (IN6_IS_ADDR_LOOPBACK(Address))
  886. return ADE_LINK_LOCAL;
  887. else
  888. return ADE_GLOBAL;
  889. }
  890. void
  891. PrintPersistentAddress(IPV6_INFO_INTERFACE *IF, IPV6_UPDATE_ADDRESS *ADE)
  892. {
  893. NlsPutMsg(STDOUT, IPV6_MESSAGE_23,
  894. ((ADE->Type == ADE_ANYCAST) ?
  895. "anycast" :
  896. FormatDADState((ADE->PreferredLifetime == 0) ?
  897. DAD_STATE_DEPRECATED : DAD_STATE_PREFERRED)),
  898. FormatScopeAdj(AddressScope(&ADE->This.Address)),
  899. FormatIPv6Address(&ADE->This.Address));
  900. // printf(" %s %s %s, ",
  901. NlsPutMsg(STDOUT, IPV6_MESSAGE_24,
  902. FormatLifetimes(ADE->ValidLifetime, ADE->PreferredLifetime));
  903. // printf("life %s",
  904. PrintAddrOrigin(ADE->PrefixConf, ADE->InterfaceIdConf);
  905. NlsPutMsg(STDOUT, IPV6_MESSAGE_36);
  906. // printf("\n");
  907. }
  908. IPV6_INFO_INTERFACE *
  909. GetInterfaceInfo(IPV6_QUERY_INTERFACE *Query)
  910. {
  911. IPV6_INFO_INTERFACE *IF;
  912. u_int InfoSize, BytesReturned;
  913. InfoSize = sizeof *IF + 2 * MAX_LINK_LAYER_ADDRESS_LENGTH;
  914. IF = malloc(InfoSize);
  915. if (IF == NULL) {
  916. NlsPutMsg(STDOUT, IPV6_MESSAGE_43);
  917. // printf("malloc failed\n");
  918. exit(1);
  919. }
  920. if (!DeviceIoControl(Handle,
  921. IOCTL_IPV6_QUERY_INTERFACE,
  922. Query, sizeof *Query,
  923. IF, InfoSize, &BytesReturned,
  924. NULL)) {
  925. NlsPutMsg(STDOUT, IPV6_MESSAGE_44, Query->Index);
  926. // printf("bad index %u\n", Query->Index);
  927. exit(1);
  928. }
  929. if ((BytesReturned < sizeof *IF) ||
  930. (IF->Length < sizeof *IF) ||
  931. (BytesReturned != IF->Length +
  932. ((IF->LocalLinkLayerAddress != 0) ?
  933. IF->LinkLayerAddressLength : 0) +
  934. ((IF->RemoteLinkLayerAddress != 0) ?
  935. IF->LinkLayerAddressLength : 0))) {
  936. NlsPutMsg(STDOUT, IPV6_MESSAGE_45);
  937. // printf("inconsistent interface info length\n");
  938. exit(1);
  939. }
  940. return IF;
  941. }
  942. IPV6_INFO_INTERFACE *
  943. GetPersistentInterfaceInfo(IPV6_PERSISTENT_QUERY_INTERFACE *Query)
  944. {
  945. IPV6_INFO_INTERFACE *IF;
  946. u_int InfoSize, BytesReturned;
  947. InfoSize = sizeof *IF + 2 * MAX_LINK_LAYER_ADDRESS_LENGTH;
  948. IF = malloc(InfoSize);
  949. if (IF == NULL) {
  950. NlsPutMsg(STDOUT, IPV6_MESSAGE_43);
  951. // printf("malloc failed\n");
  952. exit(1);
  953. }
  954. if (!DeviceIoControl(Handle,
  955. IOCTL_IPV6_PERSISTENT_QUERY_INTERFACE,
  956. Query, sizeof *Query,
  957. IF, InfoSize, &BytesReturned,
  958. NULL)) {
  959. NlsPutMsg(STDOUT, IPV6_MESSAGE_44, Query->RegistryIndex);
  960. // printf("bad index %u\n", Query->RegistryIndex);
  961. exit(1);
  962. }
  963. if ((BytesReturned < sizeof *IF) ||
  964. (IF->Length < sizeof *IF) ||
  965. (BytesReturned != IF->Length +
  966. ((IF->LocalLinkLayerAddress != 0) ?
  967. IF->LinkLayerAddressLength : 0) +
  968. ((IF->RemoteLinkLayerAddress != 0) ?
  969. IF->LinkLayerAddressLength : 0))) {
  970. NlsPutMsg(STDOUT, IPV6_MESSAGE_45);
  971. // printf("inconsistent interface info length\n");
  972. exit(1);
  973. }
  974. return IF;
  975. }
  976. void
  977. ForEachInterface(void (*func)(IPV6_INFO_INTERFACE *))
  978. {
  979. IPV6_QUERY_INTERFACE Query;
  980. IPV6_INFO_INTERFACE *IF;
  981. u_int InfoSize, BytesReturned;
  982. InfoSize = sizeof *IF + 2 * MAX_LINK_LAYER_ADDRESS_LENGTH;
  983. IF = malloc(InfoSize);
  984. if (IF == NULL) {
  985. NlsPutMsg(STDOUT, IPV6_MESSAGE_43);
  986. // printf("malloc failed\n");
  987. exit(1);
  988. }
  989. Query.Index = (u_int) -1;
  990. for (;;) {
  991. if (!DeviceIoControl(Handle, IOCTL_IPV6_QUERY_INTERFACE,
  992. &Query, sizeof Query,
  993. IF, InfoSize, &BytesReturned,
  994. NULL)) {
  995. NlsPutMsg(STDOUT, IPV6_MESSAGE_46, Query.Index);
  996. // printf("bad index %u\n", Query.Index);
  997. exit(1);
  998. }
  999. if (Query.Index != (u_int) -1) {
  1000. if ((BytesReturned < sizeof *IF) ||
  1001. (IF->Length < sizeof *IF) ||
  1002. (BytesReturned != IF->Length +
  1003. ((IF->LocalLinkLayerAddress != 0) ?
  1004. IF->LinkLayerAddressLength : 0) +
  1005. ((IF->RemoteLinkLayerAddress != 0) ?
  1006. IF->LinkLayerAddressLength : 0))) {
  1007. NlsPutMsg(STDOUT, IPV6_MESSAGE_45);
  1008. // printf("inconsistent interface info length\n");
  1009. exit(1);
  1010. }
  1011. (*func)(IF);
  1012. }
  1013. else {
  1014. if (BytesReturned != sizeof IF->Next) {
  1015. NlsPutMsg(STDOUT, IPV6_MESSAGE_45);
  1016. // printf("inconsistent interface info length\n");
  1017. exit(1);
  1018. }
  1019. }
  1020. if (IF->Next.Index == (u_int) -1)
  1021. break;
  1022. Query = IF->Next;
  1023. }
  1024. free(IF);
  1025. }
  1026. void
  1027. ForEachPersistentInterface(void (*func)(IPV6_INFO_INTERFACE *))
  1028. {
  1029. IPV6_PERSISTENT_QUERY_INTERFACE Query;
  1030. IPV6_INFO_INTERFACE *IF;
  1031. u_int InfoSize, BytesReturned;
  1032. InfoSize = sizeof *IF + 2 * MAX_LINK_LAYER_ADDRESS_LENGTH;
  1033. IF = malloc(InfoSize);
  1034. if (IF == NULL) {
  1035. NlsPutMsg(STDOUT, IPV6_MESSAGE_43);
  1036. // printf("malloc failed\n");
  1037. exit(1);
  1038. }
  1039. for (Query.RegistryIndex = 0;; Query.RegistryIndex++) {
  1040. if (!DeviceIoControl(Handle,
  1041. IOCTL_IPV6_PERSISTENT_QUERY_INTERFACE,
  1042. &Query, sizeof Query,
  1043. IF, InfoSize, &BytesReturned,
  1044. NULL)) {
  1045. if (GetLastError() == ERROR_NO_MORE_ITEMS)
  1046. break;
  1047. NlsPutMsg(STDOUT, IPV6_MESSAGE_46, Query.RegistryIndex);
  1048. // printf("bad index %u\n", Query.RegistryIndex);
  1049. exit(1);
  1050. }
  1051. if ((BytesReturned < sizeof *IF) ||
  1052. (IF->Length < sizeof *IF) ||
  1053. (BytesReturned != IF->Length +
  1054. ((IF->LocalLinkLayerAddress != 0) ?
  1055. IF->LinkLayerAddressLength : 0) +
  1056. ((IF->RemoteLinkLayerAddress != 0) ?
  1057. IF->LinkLayerAddressLength : 0))) {
  1058. NlsPutMsg(STDOUT, IPV6_MESSAGE_45);
  1059. // printf("inconsistent interface info length\n");
  1060. exit(1);
  1061. }
  1062. (*func)(IF);
  1063. }
  1064. free(IF);
  1065. }
  1066. #ifndef IP_TYPES_INCLUDED
  1067. //
  1068. // The real version of this structure in iptypes.h
  1069. // has more fields, but these are all we need here.
  1070. //
  1071. #define MAX_ADAPTER_DESCRIPTION_LENGTH 128 // arb.
  1072. #define MAX_ADAPTER_NAME_LENGTH 256 // arb.
  1073. #define MAX_ADAPTER_ADDRESS_LENGTH 8 // arb.
  1074. typedef struct _IP_ADAPTER_INFO {
  1075. struct _IP_ADAPTER_INFO* Next;
  1076. DWORD ComboIndex;
  1077. char AdapterName[MAX_ADAPTER_NAME_LENGTH + 4];
  1078. char Description[MAX_ADAPTER_DESCRIPTION_LENGTH + 4];
  1079. UINT AddressLength;
  1080. BYTE Address[MAX_ADAPTER_ADDRESS_LENGTH];
  1081. DWORD Index;
  1082. } IP_ADAPTER_INFO;
  1083. #endif // IP_TYPES_INCLUDED
  1084. DWORD (WINAPI *pGetAdaptersInfo)(IP_ADAPTER_INFO *pAdapterInfo, ULONG *pOutBufLen);
  1085. IP_ADAPTER_INFO *pAdapterInfo;
  1086. HRESULT (WINAPI *pHrLanConnectionNameFromGuidOrPath)(
  1087. const GUID *pGuid,
  1088. LPCWSTR pszwPath,
  1089. LPWSTR pszwName,
  1090. LPDWORD pcchMax);
  1091. #define IPHLPAPI_LIBRARY_NAME "iphlpapi.dll"
  1092. #define NETMAN_LIBRARY_NAME "netman.dll"
  1093. void
  1094. InitializeAdaptersInfo(void)
  1095. {
  1096. HMODULE hModule;
  1097. CHAR SystemDir[MAX_PATH + 1];
  1098. CHAR Path[MAX_PATH + sizeof(IPHLPAPI_LIBRARY_NAME) + 2];
  1099. pAdapterInfo = NULL;
  1100. if (GetSystemDirectory(SystemDir, MAX_PATH) == 0) {
  1101. return;
  1102. }
  1103. //
  1104. // Check if the GetAdaptersInfo API is available on this system.
  1105. //
  1106. lstrcpy(Path, SystemDir);
  1107. lstrcat(Path, "\\" IPHLPAPI_LIBRARY_NAME);
  1108. hModule = LoadLibrary(Path);
  1109. if (hModule != NULL) {
  1110. pGetAdaptersInfo = (DWORD (WINAPI *)(IP_ADAPTER_INFO *, ULONG *))
  1111. GetProcAddress(hModule, "GetAdaptersInfo");
  1112. //
  1113. // We don't release hModule, to keep the module loaded.
  1114. //
  1115. if (pGetAdaptersInfo != NULL) {
  1116. ULONG BufLen = 0;
  1117. DWORD error;
  1118. //
  1119. // If this returns something other than buffer-overflow,
  1120. // it probably means that GetAdaptersInfo is not supported.
  1121. //
  1122. error = (*pGetAdaptersInfo)(NULL, &BufLen);
  1123. if (error == ERROR_BUFFER_OVERFLOW) {
  1124. pAdapterInfo = (IP_ADAPTER_INFO *) malloc(BufLen);
  1125. if (pAdapterInfo != NULL) {
  1126. error = (*pGetAdaptersInfo)(pAdapterInfo, &BufLen);
  1127. if (error != 0) {
  1128. free(pAdapterInfo);
  1129. pAdapterInfo = NULL;
  1130. }
  1131. }
  1132. }
  1133. }
  1134. }
  1135. //
  1136. // Only bother with HrLanConnectionNameFromGuidOrPath
  1137. // if we could get pAdapterInfo.
  1138. //
  1139. if (pAdapterInfo != NULL) {
  1140. lstrcpy(Path, SystemDir);
  1141. lstrcat(Path, "\\" NETMAN_LIBRARY_NAME);
  1142. hModule = LoadLibrary(Path);
  1143. if (hModule != NULL) {
  1144. pHrLanConnectionNameFromGuidOrPath =
  1145. (HRESULT (WINAPI *)(const GUID *, LPCWSTR, LPWSTR, LPDWORD))
  1146. GetProcAddress(hModule, "HrLanConnectionNameFromGuidOrPath");
  1147. //
  1148. // We don't release hModule, to keep the module loaded.
  1149. //
  1150. }
  1151. if (pHrLanConnectionNameFromGuidOrPath == NULL) {
  1152. free(pAdapterInfo);
  1153. pAdapterInfo = NULL;
  1154. }
  1155. }
  1156. }
  1157. #define MAX_FRIENDLY_NAME_LENGTH 2000
  1158. LPSTR
  1159. MapAdapterNameToFriendly(LPSTR AdapterName)
  1160. {
  1161. WCHAR wszAdapterName[MAX_ADAPTER_NAME_LENGTH];
  1162. WCHAR wszFriendlyName[MAX_FRIENDLY_NAME_LENGTH];
  1163. DWORD cchFriendlyName = MAX_FRIENDLY_NAME_LENGTH;
  1164. static CHAR FriendlyName[MAX_FRIENDLY_NAME_LENGTH];
  1165. MultiByteToWideChar(CP_ACP, 0, AdapterName, -1,
  1166. wszAdapterName, MAX_ADAPTER_NAME_LENGTH);
  1167. if((*pHrLanConnectionNameFromGuidOrPath)(
  1168. NULL, wszAdapterName, wszFriendlyName, &cchFriendlyName))
  1169. return NULL;
  1170. WideCharToMultiByte(CP_ACP, 0, wszFriendlyName, -1,
  1171. FriendlyName, MAX_FRIENDLY_NAME_LENGTH,
  1172. NULL, NULL);
  1173. return FriendlyName;
  1174. }
  1175. LPSTR
  1176. MapAdapterAddressToFriendly(u_char *Address, u_int AddressLength)
  1177. {
  1178. IP_ADAPTER_INFO *pAdapter;
  1179. for (pAdapter = pAdapterInfo;
  1180. pAdapter != NULL;
  1181. pAdapter = pAdapter->Next) {
  1182. if ((AddressLength == pAdapter->AddressLength) &&
  1183. ! memcmp(Address, pAdapter->Address, AddressLength))
  1184. return MapAdapterNameToFriendly(pAdapter->AdapterName);
  1185. }
  1186. return NULL;
  1187. }
  1188. int
  1189. ShouldPrintZones(IPV6_INFO_INTERFACE *IF)
  1190. {
  1191. u_int Scope;
  1192. for (Scope = ADE_SMALLEST_SCOPE; Scope <= ADE_LINK_LOCAL; Scope++)
  1193. if (IF->ZoneIndices[Scope] != IF->This.Index)
  1194. return TRUE;
  1195. for (; Scope <= ADE_LARGEST_SCOPE; Scope++)
  1196. if (IF->ZoneIndices[Scope] != 1)
  1197. return TRUE;
  1198. return FALSE;
  1199. }
  1200. void
  1201. PrintInterface(IPV6_INFO_INTERFACE *IF)
  1202. {
  1203. LPSTR FriendlyName;
  1204. u_int Scope;
  1205. if (IF->LocalLinkLayerAddress == 0)
  1206. FriendlyName = NULL;
  1207. else
  1208. FriendlyName = MapAdapterAddressToFriendly(
  1209. (u_char *)IF + IF->LocalLinkLayerAddress,
  1210. IF->LinkLayerAddressLength);
  1211. NlsPutMsg(STDOUT, IPV6_MESSAGE_47, IF->This.Index);
  1212. // printf("Interface %u:", IF->This.Index);
  1213. switch (IF->Type) {
  1214. case IPV6_IF_TYPE_LOOPBACK:
  1215. NlsPutMsg(STDOUT, IPV6_MESSAGE_48);
  1216. // printf(" Loopback Pseudo-Interface");
  1217. break;
  1218. case IPV6_IF_TYPE_ETHERNET:
  1219. NlsPutMsg(STDOUT, IPV6_MESSAGE_49);
  1220. // printf(" Ethernet");
  1221. break;
  1222. case IPV6_IF_TYPE_FDDI:
  1223. NlsPutMsg(STDOUT, IPV6_MESSAGE_50);
  1224. // printf(" FDDI");
  1225. break;
  1226. case IPV6_IF_TYPE_TUNNEL_AUTO:
  1227. NlsPutMsg(STDOUT, IPV6_MESSAGE_51);
  1228. // printf(" Automatic Tunneling Pseudo-Interface");
  1229. break;
  1230. case IPV6_IF_TYPE_TUNNEL_6OVER4:
  1231. NlsPutMsg(STDOUT, IPV6_MESSAGE_52);
  1232. // printf(" 6-over-4 Virtual Interface");
  1233. break;
  1234. case IPV6_IF_TYPE_TUNNEL_V6V4:
  1235. NlsPutMsg(STDOUT, IPV6_MESSAGE_53);
  1236. // printf(" Configured Tunnel Interface");
  1237. break;
  1238. case IPV6_IF_TYPE_TUNNEL_6TO4:
  1239. NlsPutMsg(STDOUT, IPV6_6TO4_INTERFACE);
  1240. // printf(" 6to4 Tunneling Pseudo-Interface");
  1241. break;
  1242. case IPV6_IF_TYPE_TUNNEL_TEREDO:
  1243. // NlsPutMsg(STDOUT, IPV6_TEREDO_INTERFACE);
  1244. printf(" Teredo Tunneling Pseudo-Interface");
  1245. break;
  1246. }
  1247. if (FriendlyName != NULL)
  1248. NlsPutMsg(STDOUT, IPV6_MESSAGE_54, FriendlyName);
  1249. // printf(": %s", FriendlyName);
  1250. NlsPutMsg(STDOUT, IPV6_MESSAGE_36);
  1251. // printf("\n");
  1252. printf("%s\n", FormatGuid(&IF->This.Guid));
  1253. // NlsPutMsg(STDOUT, IPV6_MESSAGE_GUID, FormatGuid(&IF->This.Guid));
  1254. // printf(" Guid %s\n", FormatGuid(&IF->This.Guid));
  1255. if (Verbose || ShouldPrintZones(IF)) {
  1256. NlsPutMsg(STDOUT, IPV6_MESSAGE_55);
  1257. // printf(" zones:");
  1258. for (Scope = ADE_LINK_LOCAL; Scope < ADE_GLOBAL; Scope++) {
  1259. u_int Expected;
  1260. if ((Scope == ADE_LINK_LOCAL) ||
  1261. (Scope == ADE_SITE_LOCAL))
  1262. Expected = 0; // Always print link & site.
  1263. else
  1264. Expected = IF->ZoneIndices[Scope + 1];
  1265. if (IF->ZoneIndices[Scope] != Expected)
  1266. NlsPutMsg(STDOUT, IPV6_MESSAGE_56,
  1267. FormatScopeNoun(Scope),
  1268. IF->ZoneIndices[Scope]);
  1269. // printf(" %s %u",
  1270. // FormatScopeNoun(Scope),
  1271. // IF->ZoneIndices[Scope]);
  1272. }
  1273. NlsPutMsg(STDOUT, IPV6_MESSAGE_36);
  1274. // printf("\n");
  1275. }
  1276. switch (IF->MediaStatus) {
  1277. case IPV6_IF_MEDIA_STATUS_DISCONNECTED:
  1278. NlsPutMsg(STDOUT, IPV6_MESSAGE_57);
  1279. // printf(" cable unplugged\n");
  1280. break;
  1281. case IPV6_IF_MEDIA_STATUS_RECONNECTED:
  1282. NlsPutMsg(STDOUT, IPV6_MESSAGE_58);
  1283. // printf(" cable reconnected\n");
  1284. break;
  1285. case IPV6_IF_MEDIA_STATUS_CONNECTED:
  1286. break;
  1287. }
  1288. if (IF->NeighborDiscovers)
  1289. NlsPutMsg(STDOUT, IPV6_MESSAGE_59);
  1290. // printf(" uses Neighbor Discovery\n");
  1291. else
  1292. NlsPutMsg(STDOUT, IPV6_MESSAGE_60);
  1293. // printf(" does not use Neighbor Discovery\n");
  1294. if (IF->RouterDiscovers)
  1295. NlsPutMsg(STDOUT, IPV6_MESSAGE_USES_RD);
  1296. else
  1297. NlsPutMsg(STDOUT, IPV6_MESSAGE_DOESNT_USE_RD);
  1298. if (IF->Advertises)
  1299. NlsPutMsg(STDOUT, IPV6_MESSAGE_61);
  1300. // printf(" sends Router Advertisements\n");
  1301. if (IF->Forwards)
  1302. NlsPutMsg(STDOUT, IPV6_MESSAGE_62);
  1303. // printf(" forwards packets\n");
  1304. if (IF->PeriodicMLD)
  1305. NlsPutMsg(STDOUT, IPV6_MESSAGE_63);
  1306. // printf(" periodically sends MLD Reports\n");
  1307. if (IF->Preference != 0)
  1308. NlsPutMsg(STDOUT, IPV6_MESSAGE_64, IF->Preference);
  1309. // printf(" routing preference %u\n", IF->Preference);
  1310. if (IF->Type == IPV6_IF_TYPE_TUNNEL_AUTO) {
  1311. if (IF->LocalLinkLayerAddress != 0) {
  1312. NlsPutMsg(STDOUT, IPV6_MESSAGE_TOKEN_ADDRESS,
  1313. FormatLinkLayerAddress(IF->LinkLayerAddressLength,
  1314. (u_char *)IF + IF->LocalLinkLayerAddress));
  1315. // printf(" EUI-64 embedded IPv4 address: %s\n",
  1316. }
  1317. if (IF->RemoteLinkLayerAddress != 0) {
  1318. NlsPutMsg(STDOUT, IPV6_MESSAGE_ROUTER_LL_ADDRESS,
  1319. FormatLinkLayerAddress(IF->LinkLayerAddressLength,
  1320. (u_char *)IF + IF->RemoteLinkLayerAddress));
  1321. // printf(" router link-layer address: %s\n",
  1322. }
  1323. }
  1324. else {
  1325. if (IF->LocalLinkLayerAddress != 0) {
  1326. NlsPutMsg(STDOUT, IPV6_MESSAGE_65,
  1327. FormatLinkLayerAddress(IF->LinkLayerAddressLength,
  1328. (u_char *)IF + IF->LocalLinkLayerAddress));
  1329. // printf(" link-layer address: %s\n",
  1330. }
  1331. if (IF->RemoteLinkLayerAddress != 0) {
  1332. NlsPutMsg(STDOUT, IPV6_MESSAGE_66,
  1333. FormatLinkLayerAddress(IF->LinkLayerAddressLength,
  1334. (u_char *)IF + IF->RemoteLinkLayerAddress));
  1335. // printf(" remote link-layer address: %s\n",
  1336. }
  1337. }
  1338. ForEachAddress(IF, PrintAddress);
  1339. NlsPutMsg(STDOUT, IPV6_MESSAGE_67, IF->LinkMTU, IF->TrueLinkMTU);
  1340. // printf(" link MTU %u (true link MTU %u)\n",
  1341. // IF->LinkMTU, IF->TrueLinkMTU);
  1342. NlsPutMsg(STDOUT, IPV6_MESSAGE_68, IF->CurHopLimit);
  1343. // printf(" current hop limit %u\n", IF->CurHopLimit);
  1344. NlsPutMsg(STDOUT, IPV6_MESSAGE_69,
  1345. IF->ReachableTime, IF->BaseReachableTime);
  1346. // printf(" reachable time %ums (base %ums)\n",
  1347. // IF->ReachableTime, IF->BaseReachableTime);
  1348. NlsPutMsg(STDOUT, IPV6_MESSAGE_70, IF->RetransTimer);
  1349. // printf(" retransmission interval %ums\n", IF->RetransTimer);
  1350. NlsPutMsg(STDOUT, IPV6_MESSAGE_71, IF->DupAddrDetectTransmits);
  1351. // printf(" DAD transmits %u\n", IF->DupAddrDetectTransmits);
  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. printf("%s\n", FormatGuid(&IF->This.Guid));
  1392. // NlsPutMsg(STDOUT, IPV6_MESSAGE_GUID, FormatGuid(&IF->This.Guid));
  1393. // printf(" Guid %s\n", FormatGuid(&IF->This.Guid));
  1394. if (IF->NeighborDiscovers == TRUE)
  1395. NlsPutMsg(STDOUT, IPV6_MESSAGE_59);
  1396. // printf(" uses Neighbor Discovery\n");
  1397. else if (IF->NeighborDiscovers == FALSE)
  1398. NlsPutMsg(STDOUT, IPV6_MESSAGE_60);
  1399. // printf(" does not use Neighbor Discovery\n");
  1400. if (IF->RouterDiscovers == TRUE)
  1401. NlsPutMsg(STDOUT, IPV6_MESSAGE_USES_RD);
  1402. else if (IF->RouterDiscovers == FALSE)
  1403. NlsPutMsg(STDOUT, IPV6_MESSAGE_DOESNT_USE_RD);
  1404. if (IF->Advertises == TRUE)
  1405. NlsPutMsg(STDOUT, IPV6_MESSAGE_61);
  1406. // printf(" sends Router Advertisements\n");
  1407. // else if (IF->Advertises == FALSE)
  1408. // NlsPutMsg(STDOUT, IPV6_MESSAGE_DOESNT_SEND_RAs);
  1409. // printf(" does not send Router Advertisements\n");
  1410. if (IF->Forwards == TRUE)
  1411. NlsPutMsg(STDOUT, IPV6_MESSAGE_62);
  1412. // printf(" forwards packets\n");
  1413. // else if (IF->Forwards == FALSE)
  1414. // NlsPutMsg(STDOUT, IPV6_MESSAGE_DOESNT_FORWARD);
  1415. // printf(" does not forward packets\n");
  1416. if (IF->PeriodicMLD == TRUE)
  1417. NlsPutMsg(STDOUT, IPV6_MESSAGE_63);
  1418. // printf(" periodically sends MLD Reports\n");
  1419. // else if (IF->PeriodicMLD == FALSE)
  1420. // NlsPutMsg(STDOUT, IPV6_MESSAGE_DOESNT_SEND_PERIODIC_MLD);
  1421. // printf(" does not periodically send MLD Reports\n");
  1422. if (IF->Preference != (u_int)-1)
  1423. NlsPutMsg(STDOUT, IPV6_MESSAGE_64, IF->Preference);
  1424. // printf(" routing preference %u\n", IF->Preference);
  1425. if (IF->Type == IPV6_IF_TYPE_TUNNEL_AUTO) {
  1426. if (IF->LocalLinkLayerAddress != 0) {
  1427. NlsPutMsg(STDOUT, IPV6_MESSAGE_TOKEN_ADDRESS,
  1428. FormatLinkLayerAddress(IF->LinkLayerAddressLength,
  1429. (u_char *)IF + IF->LocalLinkLayerAddress));
  1430. // printf(" EUI-64 embedded IPv4 address: %s\n",
  1431. }
  1432. if (IF->RemoteLinkLayerAddress != 0) {
  1433. NlsPutMsg(STDOUT, IPV6_MESSAGE_ROUTER_LL_ADDRESS,
  1434. FormatLinkLayerAddress(IF->LinkLayerAddressLength,
  1435. (u_char *)IF + IF->RemoteLinkLayerAddress));
  1436. // printf(" router link-layer address: %s\n",
  1437. }
  1438. }
  1439. else {
  1440. if (IF->LocalLinkLayerAddress != 0) {
  1441. NlsPutMsg(STDOUT, IPV6_MESSAGE_65,
  1442. FormatLinkLayerAddress(IF->LinkLayerAddressLength,
  1443. (u_char *)IF + IF->LocalLinkLayerAddress));
  1444. // printf(" link-layer address: %s\n",
  1445. }
  1446. if (IF->RemoteLinkLayerAddress != 0) {
  1447. NlsPutMsg(STDOUT, IPV6_MESSAGE_66,
  1448. FormatLinkLayerAddress(IF->LinkLayerAddressLength,
  1449. (u_char *)IF + IF->RemoteLinkLayerAddress));
  1450. // printf(" remote link-layer address: %s\n",
  1451. }
  1452. }
  1453. ForEachPersistentAddress(IF, PrintPersistentAddress);
  1454. // if (IF->LinkMTU != 0) {
  1455. // NlsPutMsg(STDOUT, IPV6_MESSAGE_LINK_MTU, IF->LinkMTU);
  1456. // printf(" link MTU %u\n",
  1457. // }
  1458. if (IF->CurHopLimit != (u_int)-1) {
  1459. NlsPutMsg(STDOUT, IPV6_MESSAGE_68, IF->CurHopLimit);
  1460. // printf(" current hop limit %u\n", IF->CurHopLimit);
  1461. }
  1462. // if (IF->BaseReachableTime != 0) {
  1463. // NlsPutMsg(STDOUT, IPV6_MESSAGE_BASE_REACHABLE_TIME,
  1464. // IF->BaseReachableTime);
  1465. // printf(" base reachable time %ums\n",
  1466. // }
  1467. if (IF->RetransTimer != 0) {
  1468. NlsPutMsg(STDOUT, IPV6_MESSAGE_70, IF->RetransTimer);
  1469. // printf(" retransmission interval %ums\n", IF->RetransTimer);
  1470. }
  1471. if (IF->DupAddrDetectTransmits != (u_int)-1) {
  1472. NlsPutMsg(STDOUT, IPV6_MESSAGE_71, IF->DupAddrDetectTransmits);
  1473. // printf(" DAD transmits %u\n", IF->DupAddrDetectTransmits);
  1474. }
  1475. }
  1476. IPV6_INFO_NEIGHBOR_CACHE *
  1477. GetNeighborCacheEntry(IPV6_QUERY_NEIGHBOR_CACHE *Query)
  1478. {
  1479. IPV6_INFO_NEIGHBOR_CACHE *NCE;
  1480. u_int InfoSize, BytesReturned;
  1481. InfoSize = sizeof *NCE + MAX_LINK_LAYER_ADDRESS_LENGTH;
  1482. NCE = (IPV6_INFO_NEIGHBOR_CACHE *) malloc(InfoSize);
  1483. if (NCE == NULL) {
  1484. NlsPutMsg(STDOUT, IPV6_MESSAGE_36);
  1485. // printf("malloc failed\n");
  1486. exit(1);
  1487. }
  1488. if (!DeviceIoControl(Handle, IOCTL_IPV6_QUERY_NEIGHBOR_CACHE,
  1489. Query, sizeof *Query,
  1490. NCE, InfoSize, &BytesReturned,
  1491. NULL)) {
  1492. NlsPutMsg(STDOUT, IPV6_MESSAGE_72, FormatIPv6Address(&Query->Address));
  1493. // printf("bad address %s\n", FormatIPv6Address(&Query->Address));
  1494. exit(1);
  1495. }
  1496. if ((BytesReturned < sizeof *NCE) ||
  1497. (BytesReturned != sizeof *NCE + NCE->LinkLayerAddressLength)) {
  1498. NlsPutMsg(STDOUT, IPV6_MESSAGE_73);
  1499. // printf("inconsistent neighbor cache info length\n");
  1500. exit(1);
  1501. }
  1502. NCE->Query = *Query;
  1503. return NCE;
  1504. }
  1505. void
  1506. ForEachNeighborCacheEntry(IPV6_QUERY_INTERFACE *IF,
  1507. void (*func)(IPV6_INFO_NEIGHBOR_CACHE *))
  1508. {
  1509. IPV6_QUERY_NEIGHBOR_CACHE Query, NextQuery;
  1510. IPV6_INFO_NEIGHBOR_CACHE *NCE;
  1511. u_int InfoSize, BytesReturned;
  1512. InfoSize = sizeof *NCE + MAX_LINK_LAYER_ADDRESS_LENGTH;
  1513. NCE = (IPV6_INFO_NEIGHBOR_CACHE *) malloc(InfoSize);
  1514. if (NCE == NULL) {
  1515. NlsPutMsg(STDOUT, IPV6_MESSAGE_36);
  1516. // printf("malloc failed\n");
  1517. exit(1);
  1518. }
  1519. NextQuery.IF = *IF;
  1520. NextQuery.Address = in6addr_any;
  1521. for (;;) {
  1522. Query = NextQuery;
  1523. if (!DeviceIoControl(Handle, IOCTL_IPV6_QUERY_NEIGHBOR_CACHE,
  1524. &Query, sizeof Query,
  1525. NCE, InfoSize, &BytesReturned,
  1526. NULL)) {
  1527. NlsPutMsg(STDOUT, IPV6_MESSAGE_72,
  1528. FormatIPv6Address(&Query.Address));
  1529. // printf("bad address %s\n", FormatIPv6Address(&Query.Address));
  1530. exit(1);
  1531. }
  1532. NextQuery = NCE->Query;
  1533. if (!IN6_ADDR_EQUAL(&Query.Address, &in6addr_any)) {
  1534. if ((BytesReturned < sizeof *NCE) ||
  1535. (BytesReturned != sizeof *NCE + NCE->LinkLayerAddressLength)) {
  1536. NlsPutMsg(STDOUT, IPV6_MESSAGE_73);
  1537. // printf("inconsistent neighbor cache info length\n");
  1538. exit(1);
  1539. }
  1540. NCE->Query = Query;
  1541. (*func)(NCE);
  1542. }
  1543. if (IN6_ADDR_EQUAL(&NextQuery.Address, &in6addr_any))
  1544. break;
  1545. }
  1546. free(NCE);
  1547. }
  1548. void
  1549. PrintNeighborCacheEntry(IPV6_INFO_NEIGHBOR_CACHE *NCE)
  1550. {
  1551. NlsPutMsg(STDOUT, IPV6_MESSAGE_74, NCE->Query.IF.Index,
  1552. FormatIPv6Address(&NCE->Query.Address));
  1553. // printf("%u: %18s", NCE->Query.IF.Index,
  1554. // FormatIPv6Address(&NCE->Query.Address));
  1555. if (NCE->NDState != 0)
  1556. NlsPutMsg(STDOUT, IPV6_MESSAGE_75,
  1557. FormatLinkLayerAddress(
  1558. NCE->LinkLayerAddressLength, (u_char *)(NCE + 1)));
  1559. // printf(" %-17s", FormatLinkLayerAddress(NCE->LinkLayerAddressLength,
  1560. // (u_char *)(NCE + 1)));
  1561. else
  1562. NlsPutMsg(STDOUT, IPV6_MESSAGE_75, "");
  1563. // printf(" %-17s", "");
  1564. switch (NCE->NDState) {
  1565. case ND_STATE_INCOMPLETE:
  1566. NlsPutMsg(STDOUT, IPV6_MESSAGE_76);
  1567. // printf(" incomplete");
  1568. break;
  1569. case ND_STATE_PROBE:
  1570. NlsPutMsg(STDOUT, IPV6_MESSAGE_77);
  1571. // printf(" probe");
  1572. break;
  1573. case ND_STATE_DELAY:
  1574. NlsPutMsg(STDOUT, IPV6_MESSAGE_78);
  1575. // printf(" delay");
  1576. break;
  1577. case ND_STATE_STALE:
  1578. NlsPutMsg(STDOUT, IPV6_MESSAGE_79);
  1579. // printf(" stale");
  1580. break;
  1581. case ND_STATE_REACHABLE:
  1582. NlsPutMsg(STDOUT, IPV6_MESSAGE_80, NCE->ReachableTimer);
  1583. // printf(" reachable (%ums)", NCE->ReachableTimer);
  1584. break;
  1585. case ND_STATE_PERMANENT:
  1586. NlsPutMsg(STDOUT, IPV6_MESSAGE_81);
  1587. // printf(" permanent");
  1588. break;
  1589. default:
  1590. NlsPutMsg(STDOUT, IPV6_MESSAGE_82, NCE->NDState);
  1591. // printf(" unknown ND state %u", NCE->NDState);
  1592. break;
  1593. }
  1594. if (NCE->IsRouter)
  1595. NlsPutMsg(STDOUT, IPV6_MESSAGE_83);
  1596. // printf(" (router)");
  1597. if (NCE->IsUnreachable)
  1598. NlsPutMsg(STDOUT, IPV6_MESSAGE_84);
  1599. // printf(" (unreachable)");
  1600. NlsPutMsg(STDOUT, IPV6_MESSAGE_36);
  1601. // printf("\n");
  1602. }
  1603. void
  1604. QueryInterface(int argc, char *argv[])
  1605. {
  1606. InitializeAdaptersInfo();
  1607. if (argc == 0) {
  1608. if (Persistent)
  1609. ForEachPersistentInterface(PrintPersistentInterface);
  1610. else
  1611. ForEachInterface(PrintInterface);
  1612. }
  1613. else if (argc == 1) {
  1614. IPV6_INFO_INTERFACE *IF;
  1615. if (Persistent) {
  1616. IPV6_PERSISTENT_QUERY_INTERFACE Query;
  1617. Query.RegistryIndex = (u_int)-1;
  1618. if (! GetGuid(argv[0], &Query.Guid))
  1619. usage();
  1620. IF = GetPersistentInterfaceInfo(&Query);
  1621. PrintPersistentInterface(IF);
  1622. free(IF);
  1623. }
  1624. else {
  1625. IPV6_QUERY_INTERFACE Query;
  1626. if (! GetInterface(argv[0], &Query))
  1627. usage();
  1628. IF = GetInterfaceInfo(&Query);
  1629. PrintInterface(IF);
  1630. free(IF);
  1631. }
  1632. }
  1633. else {
  1634. usage();
  1635. }
  1636. }
  1637. void
  1638. RenewViaReconnect(IPV6_INFO_INTERFACE *IF)
  1639. {
  1640. u_int BytesReturned;
  1641. if (!DeviceIoControl(Handle, IOCTL_IPV6_RENEW_INTERFACE,
  1642. &IF->This, sizeof IF->This,
  1643. NULL, 0, &BytesReturned, NULL)) {
  1644. NlsPutMsg(STDOUT, IPV6_MESSAGE_RESET, GetLastError());
  1645. // NlsPutMsg(STDOUT, IPV6_MESSAGE_RENEW_INTERFACE, GetLastError());
  1646. // printf("renew interface error: %x\n", GetLastError());
  1647. exit(1);
  1648. }
  1649. }
  1650. VOID
  1651. Poke6to4Service()
  1652. {
  1653. SC_HANDLE Service, SCManager;
  1654. SERVICE_STATUS Status;
  1655. SCManager = OpenSCManager(NULL, NULL, GENERIC_READ);
  1656. if (SCManager == NULL) {
  1657. return;
  1658. }
  1659. Service = OpenService(SCManager, "6to4", SERVICE_ALL_ACCESS);
  1660. if (Service != NULL) {
  1661. //
  1662. // Tell the 6to4 service to re-read its configuration information.
  1663. //
  1664. (VOID) ControlService(Service, SERVICE_CONTROL_PARAMCHANGE, &Status);
  1665. CloseServiceHandle(Service);
  1666. }
  1667. CloseServiceHandle(SCManager);
  1668. }
  1669. void
  1670. RenewInterface(int argc, char *argv[])
  1671. {
  1672. BOOL PokeService = FALSE;
  1673. if (argc == 0) {
  1674. ForEachInterface(RenewViaReconnect);
  1675. PokeService = TRUE;
  1676. }
  1677. else if (argc == 1) {
  1678. IPV6_QUERY_INTERFACE Query;
  1679. IPV6_INFO_INTERFACE *IF;
  1680. if (! GetInterface(argv[0], &Query))
  1681. usage();
  1682. IF = GetInterfaceInfo(&Query);
  1683. RenewViaReconnect(IF);
  1684. //
  1685. // Poke the 6to4 service if it manages the interface being renewed.
  1686. //
  1687. PokeService = (IF->Type == IPV6_IF_TYPE_TUNNEL_6TO4) ||
  1688. (IF->Type == IPV6_IF_TYPE_TUNNEL_TEREDO) ||
  1689. (IF->Type == IPV6_IF_TYPE_TUNNEL_AUTO);
  1690. free(IF);
  1691. }
  1692. else {
  1693. usage();
  1694. }
  1695. if (PokeService) {
  1696. Poke6to4Service();
  1697. }
  1698. }
  1699. int
  1700. GetV4Address(char *astr, struct in_addr *address)
  1701. {
  1702. struct addrinfo hints;
  1703. struct addrinfo *result;
  1704. memset(&hints, 0, sizeof hints);
  1705. hints.ai_family = PF_INET;
  1706. if (getaddrinfo(astr, NULL, &hints, &result))
  1707. return FALSE;
  1708. *address = ((struct sockaddr_in *)result->ai_addr)->sin_addr;
  1709. freeaddrinfo(result);
  1710. return TRUE;
  1711. }
  1712. void
  1713. CreateInterface(int argc, char *argv[])
  1714. {
  1715. struct {
  1716. IPV6_INFO_INTERFACE Info;
  1717. struct in_addr SrcAddr;
  1718. struct in_addr DstAddr;
  1719. } Create;
  1720. IPV6_QUERY_INTERFACE Result;
  1721. u_int BytesReturned;
  1722. u_int FlagsOn, FlagsOff;
  1723. int i;
  1724. IPV6_INIT_INFO_INTERFACE(&Create.Info);
  1725. if (argc < 1)
  1726. usage();
  1727. if (!strcmp(argv[0], "v6v4")) {
  1728. i = 3;
  1729. if (argc < i)
  1730. usage();
  1731. if (! GetV4Address(argv[1], &Create.SrcAddr))
  1732. usage();
  1733. if (! GetV4Address(argv[2], &Create.DstAddr))
  1734. usage();
  1735. Create.Info.Type = IPV6_IF_TYPE_TUNNEL_V6V4;
  1736. Create.Info.LinkLayerAddressLength = sizeof(struct in_addr);
  1737. Create.Info.LocalLinkLayerAddress = (u_int)
  1738. ((char *)&Create.SrcAddr - (char *)&Create.Info);
  1739. Create.Info.RemoteLinkLayerAddress = (u_int)
  1740. ((char *)&Create.DstAddr - (char *)&Create.Info);
  1741. }
  1742. else if (!strcmp(argv[0], "6over4")) {
  1743. i = 2;
  1744. if (argc < i)
  1745. usage();
  1746. if (! GetV4Address(argv[1], &Create.SrcAddr))
  1747. usage();
  1748. Create.Info.Type = IPV6_IF_TYPE_TUNNEL_6OVER4;
  1749. Create.Info.LinkLayerAddressLength = sizeof(struct in_addr);
  1750. Create.Info.LocalLinkLayerAddress = (u_int)
  1751. ((char *)&Create.SrcAddr - (char *)&Create.Info);
  1752. }
  1753. else
  1754. usage();
  1755. for (; i < argc; i++) {
  1756. if (!strcmp(argv[i], "nd")) {
  1757. Create.Info.NeighborDiscovers = TRUE;
  1758. Create.Info.RouterDiscovers = TRUE;
  1759. }
  1760. else if (!strcmp(argv[i], "pmld")) {
  1761. Create.Info.PeriodicMLD = TRUE;
  1762. }
  1763. else if (!strcmp(argv[i], "nond")) {
  1764. Create.Info.NeighborDiscovers = FALSE;
  1765. Create.Info.RouterDiscovers = FALSE;
  1766. }
  1767. else
  1768. usage();
  1769. }
  1770. if (!DeviceIoControl(Handle,
  1771. (Persistent ?
  1772. IOCTL_IPV6_PERSISTENT_CREATE_INTERFACE :
  1773. IOCTL_IPV6_CREATE_INTERFACE),
  1774. &Create, sizeof Create,
  1775. &Result, sizeof Result, &BytesReturned, NULL) ||
  1776. (BytesReturned != sizeof Result)) {
  1777. NlsPutMsg(STDOUT, IPV6_MESSAGE_85, GetLastError());
  1778. // printf("control interface error: %x\n", GetLastError());
  1779. exit(1);
  1780. }
  1781. NlsPutMsg(STDOUT, IPV6_MESSAGE_86, Result.Index);
  1782. // printf("Created interface %u.\n", Result.Index);
  1783. }
  1784. void
  1785. UpdateInterface(int argc, char *argv[])
  1786. {
  1787. IPV6_INFO_INTERFACE Update;
  1788. u_int BytesReturned;
  1789. int i;
  1790. IPV6_INIT_INFO_INTERFACE(&Update);
  1791. if (argc < 1)
  1792. usage();
  1793. if (! GetInterface(argv[0], &Update.This))
  1794. usage();
  1795. for (i = 1; i < argc; i++) {
  1796. if (!strncmp(argv[i], "advertises", strlen(argv[i])))
  1797. Update.Advertises = TRUE;
  1798. else if (!strncmp(argv[i], "-advertises", strlen(argv[i])))
  1799. Update.Advertises = FALSE;
  1800. else if (!strncmp(argv[i], "forwards", strlen(argv[i])))
  1801. Update.Forwards = TRUE;
  1802. else if (!strncmp(argv[i], "-forwards", strlen(argv[i])))
  1803. Update.Forwards = FALSE;
  1804. else if (!strcmp(argv[i], "mtu") && (i+1 < argc)) {
  1805. if (! GetNumber(argv[i+1], &Update.LinkMTU))
  1806. usage();
  1807. i++;
  1808. }
  1809. else if (!strncmp(argv[i], "preference", strlen(argv[i])) &&
  1810. (i+1 < argc)) {
  1811. if (! GetNumber(argv[++i], &Update.Preference))
  1812. usage();
  1813. }
  1814. else if (!strncmp(argv[i], "basereachabletime", strlen(argv[i])) &&
  1815. (i+1 < argc)) {
  1816. if (! GetNumber(argv[++i], &Update.BaseReachableTime))
  1817. usage();
  1818. }
  1819. else if (!strncmp(argv[i], "retranstimer", strlen(argv[i])) &&
  1820. (i+1 < argc)) {
  1821. if (! GetNumber(argv[++i], &Update.RetransTimer))
  1822. usage();
  1823. }
  1824. else if (!strncmp(argv[i], "dupaddrdetecttransmits", strlen(argv[i])) &&
  1825. (i+1 < argc)) {
  1826. if (! GetNumber(argv[++i], &Update.DupAddrDetectTransmits))
  1827. usage();
  1828. }
  1829. else if (!strncmp(argv[i], "curhoplimit", strlen(argv[i])) &&
  1830. (i+1 < argc)) {
  1831. if (! GetNumber(argv[++i], &Update.CurHopLimit))
  1832. usage();
  1833. }
  1834. else if (!strcmp(argv[i], "link") && (i+1 < argc)) {
  1835. if (! GetNumber(argv[i+1], &Update.ZoneIndices[ADE_LINK_LOCAL]))
  1836. usage();
  1837. i++;
  1838. }
  1839. else if (!strcmp(argv[i], "subnet") && (i+1 < argc)) {
  1840. if (! GetNumber(argv[i+1], &Update.ZoneIndices[ADE_SUBNET_LOCAL]))
  1841. usage();
  1842. i++;
  1843. }
  1844. else if (!strcmp(argv[i], "admin") && (i+1 < argc)) {
  1845. if (! GetNumber(argv[i+1], &Update.ZoneIndices[ADE_ADMIN_LOCAL]))
  1846. usage();
  1847. i++;
  1848. }
  1849. else if (!strcmp(argv[i], "site") && (i+1 < argc)) {
  1850. if (! GetNumber(argv[i+1], &Update.ZoneIndices[ADE_SITE_LOCAL]))
  1851. usage();
  1852. i++;
  1853. }
  1854. else if (!strcmp(argv[i], "org") && (i+1 < argc)) {
  1855. if (! GetNumber(argv[i+1], &Update.ZoneIndices[ADE_ORG_LOCAL]))
  1856. usage();
  1857. i++;
  1858. }
  1859. else
  1860. usage();
  1861. }
  1862. if (!DeviceIoControl(Handle,
  1863. (Persistent ?
  1864. IOCTL_IPV6_PERSISTENT_UPDATE_INTERFACE :
  1865. IOCTL_IPV6_UPDATE_INTERFACE),
  1866. &Update, sizeof Update,
  1867. NULL, 0, &BytesReturned, NULL)) {
  1868. NlsPutMsg(STDOUT, IPV6_MESSAGE_85, GetLastError());
  1869. // printf("control interface error: %x\n", GetLastError());
  1870. exit(1);
  1871. }
  1872. }
  1873. void
  1874. UpdateRouterLinkAddress(int argc, char *argv[])
  1875. {
  1876. char Buffer[sizeof(IPV6_UPDATE_ROUTER_LL_ADDRESS) + 2 * sizeof(IN_ADDR)];
  1877. IPV6_UPDATE_ROUTER_LL_ADDRESS *Update =
  1878. (IPV6_UPDATE_ROUTER_LL_ADDRESS *)Buffer;
  1879. IN_ADDR *Addr = (IN_ADDR *)(Update + 1);
  1880. u_int BytesReturned;
  1881. SOCKET s;
  1882. SOCKADDR_IN sinRemote, sinLocal;
  1883. if (argc != 2)
  1884. usage();
  1885. if (! GetInterface(argv[0], &Update->IF))
  1886. usage();
  1887. if (! GetV4Address(argv[1], &Addr[1]))
  1888. usage();
  1889. s = socket(AF_INET, SOCK_DGRAM, 0);
  1890. if (s == INVALID_SOCKET) {
  1891. NlsPutMsg(STDOUT, IPV6_MESSAGE_85, WSAGetLastError());
  1892. exit(1);
  1893. }
  1894. sinRemote.sin_family = AF_INET;
  1895. sinRemote.sin_addr = Addr[1];
  1896. if (WSAIoctl(s, SIO_ROUTING_INTERFACE_QUERY,
  1897. &sinRemote, sizeof sinRemote,
  1898. &sinLocal, sizeof sinLocal,
  1899. &BytesReturned, NULL, NULL) == SOCKET_ERROR) {
  1900. NlsPutMsg(STDOUT, IPV6_MESSAGE_85, WSAGetLastError());
  1901. exit(1);
  1902. }
  1903. closesocket(s);
  1904. Addr[0] = sinLocal.sin_addr;
  1905. if (Addr[0].s_addr == htonl(INADDR_LOOPBACK)) {
  1906. //
  1907. // We're the router.
  1908. //
  1909. Addr[0] = Addr[1];
  1910. }
  1911. if (!DeviceIoControl(Handle, IOCTL_IPV6_UPDATE_ROUTER_LL_ADDRESS,
  1912. Buffer, sizeof Buffer,
  1913. NULL, 0, &BytesReturned, NULL)) {
  1914. NlsPutMsg(STDOUT, IPV6_MESSAGE_85, GetLastError());
  1915. // printf("control interface error: %x\n", GetLastError());
  1916. exit(1);
  1917. }
  1918. }
  1919. void
  1920. DeleteInterface(int argc, char *argv[])
  1921. {
  1922. IPV6_QUERY_INTERFACE Query;
  1923. u_int BytesReturned;
  1924. if (argc != 1)
  1925. usage();
  1926. if (! GetInterface(argv[0], &Query))
  1927. usage();
  1928. if (!DeviceIoControl(Handle,
  1929. (Persistent ?
  1930. IOCTL_IPV6_PERSISTENT_DELETE_INTERFACE :
  1931. IOCTL_IPV6_DELETE_INTERFACE),
  1932. &Query, sizeof Query,
  1933. NULL, 0, &BytesReturned, NULL)) {
  1934. NlsPutMsg(STDOUT, IPV6_MESSAGE_87, GetLastError());
  1935. // printf("delete interface error: %x\n", GetLastError());
  1936. exit(1);
  1937. }
  1938. }
  1939. void
  1940. PrintNeighborCache(IPV6_INFO_INTERFACE *IF)
  1941. {
  1942. ForEachNeighborCacheEntry(&IF->This, PrintNeighborCacheEntry);
  1943. }
  1944. void
  1945. QueryNeighborCache(int argc, char *argv[])
  1946. {
  1947. if (argc == 0) {
  1948. ForEachInterface(PrintNeighborCache);
  1949. }
  1950. else if (argc == 1) {
  1951. IPV6_QUERY_INTERFACE Query;
  1952. if (! GetInterface(argv[0], &Query))
  1953. usage();
  1954. ForEachNeighborCacheEntry(&Query, PrintNeighborCacheEntry);
  1955. }
  1956. else if (argc == 2) {
  1957. IPV6_QUERY_NEIGHBOR_CACHE Query;
  1958. IPV6_INFO_NEIGHBOR_CACHE *NCE;
  1959. if (! GetInterface(argv[0], &Query.IF))
  1960. usage();
  1961. if (! GetAddress(argv[1], &Query.Address))
  1962. usage();
  1963. NCE = GetNeighborCacheEntry(&Query);
  1964. PrintNeighborCacheEntry(NCE);
  1965. free(NCE);
  1966. }
  1967. else {
  1968. usage();
  1969. }
  1970. }
  1971. IPV6_INFO_ROUTE_CACHE *
  1972. GetRouteCacheEntry(IPV6_QUERY_ROUTE_CACHE *Query)
  1973. {
  1974. IPV6_INFO_ROUTE_CACHE *RCE;
  1975. u_int BytesReturned;
  1976. RCE = (IPV6_INFO_ROUTE_CACHE *) malloc(sizeof *RCE);
  1977. if (RCE == NULL) {
  1978. NlsPutMsg(STDOUT, IPV6_MESSAGE_36);
  1979. // printf("malloc failed\n");
  1980. exit(1);
  1981. }
  1982. if (!DeviceIoControl(Handle, IOCTL_IPV6_QUERY_ROUTE_CACHE,
  1983. Query, sizeof *Query,
  1984. RCE, sizeof *RCE, &BytesReturned,
  1985. NULL)) {
  1986. NlsPutMsg(STDOUT, IPV6_MESSAGE_88);
  1987. // printf("bad index or address\n");
  1988. exit(1);
  1989. }
  1990. RCE->Query = *Query;
  1991. return RCE;
  1992. }
  1993. void
  1994. ForEachDestination(void (*func)(IPV6_INFO_ROUTE_CACHE *))
  1995. {
  1996. IPV6_QUERY_ROUTE_CACHE Query, NextQuery;
  1997. IPV6_INFO_ROUTE_CACHE RCE;
  1998. u_int BytesReturned;
  1999. NextQuery.IF.Index = 0;
  2000. for (;;) {
  2001. Query = NextQuery;
  2002. if (!DeviceIoControl(Handle, IOCTL_IPV6_QUERY_ROUTE_CACHE,
  2003. &Query, sizeof Query,
  2004. &RCE, sizeof RCE, &BytesReturned,
  2005. NULL)) {
  2006. NlsPutMsg(STDOUT, IPV6_MESSAGE_89, Query.IF.Index);
  2007. // printf("bad index %u\n", Query.IF.Index);
  2008. exit(1);
  2009. }
  2010. NextQuery = RCE.Query;
  2011. if (Query.IF.Index != 0) {
  2012. RCE.Query = Query;
  2013. (*func)(&RCE);
  2014. }
  2015. if (NextQuery.IF.Index == 0)
  2016. break;
  2017. }
  2018. }
  2019. void
  2020. PrintRouteCacheEntry(IPV6_INFO_ROUTE_CACHE *RCE)
  2021. {
  2022. NlsPutMsg(STDOUT, IPV6_MESSAGE_90, FormatIPv6Address(&RCE->Query.Address));
  2023. // printf("%s via ", FormatIPv6Address(&RCE->Query.Address));
  2024. NlsPutMsg(STDOUT, IPV6_MESSAGE_91, RCE->NextHopInterface,
  2025. FormatIPv6Address(&RCE->NextHopAddress));
  2026. // printf("%u/%s", RCE->NextHopInterface,
  2027. // FormatIPv6Address(&RCE->NextHopAddress));
  2028. if (! RCE->Valid)
  2029. NlsPutMsg(STDOUT, IPV6_MESSAGE_92);
  2030. // printf(" (stale)");
  2031. switch (RCE->Type) {
  2032. case RCE_TYPE_COMPUTED:
  2033. break;
  2034. case RCE_TYPE_REDIRECT:
  2035. NlsPutMsg(STDOUT, IPV6_MESSAGE_93);
  2036. // printf(" (redirect)");
  2037. break;
  2038. default:
  2039. NlsPutMsg(STDOUT, IPV6_MESSAGE_94, RCE->Type);
  2040. // printf(" (unknown type %u)", RCE->Type);
  2041. break;
  2042. }
  2043. switch (RCE->Flags) {
  2044. case RCE_FLAG_CONSTRAINED:
  2045. NlsPutMsg(STDOUT, IPV6_MESSAGE_95);
  2046. // printf(" (interface-specific)\n");
  2047. break;
  2048. case RCE_FLAG_CONSTRAINED_SCOPEID:
  2049. NlsPutMsg(STDOUT, IPV6_MESSAGE_96);
  2050. // printf(" (zone-specific)\n");
  2051. break;
  2052. case 0:
  2053. NlsPutMsg(STDOUT, IPV6_MESSAGE_36);
  2054. // printf("\n");
  2055. break;
  2056. default:
  2057. NlsPutMsg(STDOUT, IPV6_MESSAGE_97, RCE->Flags);
  2058. // printf(" (flags 0x%x)\n", RCE->Flags);
  2059. }
  2060. NlsPutMsg(STDOUT, IPV6_MESSAGE_98,
  2061. RCE->Query.IF.Index, FormatIPv6Address(&RCE->SourceAddress));
  2062. // printf(" src %u/%s\n",
  2063. // RCE->Query.IF.Index,
  2064. // FormatIPv6Address(&RCE->SourceAddress));
  2065. if (RCE->PathMTU == 0)
  2066. NlsPutMsg(STDOUT, IPV6_MESSAGE_99, IPv6_MINIMUM_MTU);
  2067. // printf(" PMTU %u-", IPv6_MINIMUM_MTU);
  2068. else
  2069. NlsPutMsg(STDOUT, IPV6_MESSAGE_100, RCE->PathMTU);
  2070. // printf(" PMTU %u", RCE->PathMTU);
  2071. if (RCE->PMTUProbeTimer != INFINITE_LIFETIME)
  2072. NlsPutMsg(STDOUT, IPV6_MESSAGE_101, RCE->PMTUProbeTimer/1000);
  2073. // printf(" (%u seconds until PMTU probe)\n", RCE->PMTUProbeTimer/1000);
  2074. else
  2075. NlsPutMsg(STDOUT, IPV6_MESSAGE_36);
  2076. // printf("\n");
  2077. if ((RCE->ICMPLastError != 0) &&
  2078. (RCE->ICMPLastError < 10*60*1000))
  2079. NlsPutMsg(STDOUT, IPV6_MESSAGE_102, RCE->ICMPLastError/1000);
  2080. // printf(" %d seconds since ICMP error\n", RCE->ICMPLastError/1000);
  2081. if ((RCE->BindingSeqNumber != 0) ||
  2082. (RCE->BindingLifetime != 0) ||
  2083. ! IN6_ADDR_EQUAL(&RCE->CareOfAddress, &in6addr_any))
  2084. NlsPutMsg(STDOUT, IPV6_MESSAGE_103,
  2085. FormatIPv6Address(&RCE->CareOfAddress),
  2086. RCE->BindingSeqNumber,
  2087. RCE->BindingLifetime);
  2088. // printf(" careof %s seq %u life %us\n",
  2089. // FormatIPv6Address(&RCE->CareOfAddress),
  2090. // RCE->BindingSeqNumber,
  2091. // RCE->BindingLifetime);
  2092. }
  2093. void
  2094. QueryRouteCache(int argc, char *argv[])
  2095. {
  2096. if (argc == 0) {
  2097. ForEachDestination(PrintRouteCacheEntry);
  2098. }
  2099. else if (argc == 2) {
  2100. IPV6_QUERY_ROUTE_CACHE Query;
  2101. IPV6_INFO_ROUTE_CACHE *RCE;
  2102. if (! GetInterface(argv[0], &Query.IF))
  2103. usage();
  2104. if (! GetAddress(argv[1], &Query.Address))
  2105. usage();
  2106. RCE = GetRouteCacheEntry(&Query);
  2107. PrintRouteCacheEntry(RCE);
  2108. free(RCE);
  2109. }
  2110. else {
  2111. usage();
  2112. }
  2113. }
  2114. void
  2115. ForEachRoute(void (*func)(IPV6_INFO_ROUTE_TABLE *))
  2116. {
  2117. IPV6_QUERY_ROUTE_TABLE Query, NextQuery;
  2118. IPV6_INFO_ROUTE_TABLE RTE;
  2119. u_int BytesReturned;
  2120. NextQuery.Neighbor.IF.Index = 0;
  2121. for (;;) {
  2122. Query = NextQuery;
  2123. if (!DeviceIoControl(Handle, IOCTL_IPV6_QUERY_ROUTE_TABLE,
  2124. &Query, sizeof Query,
  2125. &RTE, sizeof RTE, &BytesReturned,
  2126. NULL)) {
  2127. NlsPutMsg(STDOUT, IPV6_MESSAGE_104, Query.Neighbor.IF.Index);
  2128. // printf("bad index %u\n", Query.Neighbor.IF.Index);
  2129. exit(1);
  2130. }
  2131. NextQuery = RTE.Next;
  2132. if (Query.Neighbor.IF.Index != 0) {
  2133. RTE.This = Query;
  2134. (*func)(&RTE);
  2135. }
  2136. if (NextQuery.Neighbor.IF.Index == 0)
  2137. break;
  2138. }
  2139. }
  2140. void
  2141. ForEachPersistentRoute(IPV6_INFO_INTERFACE *IF,
  2142. void (*func)(IPV6_INFO_ROUTE_TABLE *))
  2143. {
  2144. IPV6_PERSISTENT_QUERY_ROUTE_TABLE Query;
  2145. IPV6_INFO_ROUTE_TABLE RTE;
  2146. u_int BytesReturned;
  2147. Query.IF.RegistryIndex = (u_int) -1;
  2148. Query.IF.Guid = IF->This.Guid;
  2149. for (Query.RegistryIndex = 0;; Query.RegistryIndex++) {
  2150. if (!DeviceIoControl(Handle,
  2151. IOCTL_IPV6_PERSISTENT_QUERY_ROUTE_TABLE,
  2152. &Query, sizeof Query,
  2153. &RTE, sizeof RTE, &BytesReturned,
  2154. NULL) ||
  2155. (BytesReturned != sizeof RTE)) {
  2156. if (GetLastError() == ERROR_NO_MORE_ITEMS)
  2157. break;
  2158. NlsPutMsg(STDOUT, IPV6_MESSAGE_104, Query.RegistryIndex);
  2159. // printf("bad index %u\n", Query.RegistryIndex);
  2160. exit(1);
  2161. }
  2162. (*func)(&RTE);
  2163. }
  2164. }
  2165. void
  2166. PrintRouteTableEntry(IPV6_INFO_ROUTE_TABLE *RTE)
  2167. {
  2168. IPV6_INFO_INTERFACE *IF;
  2169. if (!Verbose) {
  2170. //
  2171. // Suppress system routes (used for loopback).
  2172. //
  2173. if (RTE->Type == RTE_TYPE_SYSTEM)
  2174. return;
  2175. }
  2176. NlsPutMsg(STDOUT, IPV6_MESSAGE_105,
  2177. FormatIPv6Address(&RTE->This.Prefix),
  2178. RTE->This.PrefixLength,
  2179. RTE->This.Neighbor.IF.Index);
  2180. // printf("%s/%u -> %u",
  2181. if (! IN6_ADDR_EQUAL(&RTE->This.Neighbor.Address, &in6addr_any))
  2182. NlsPutMsg(STDOUT, IPV6_MESSAGE_106,
  2183. FormatIPv6Address(&RTE->This.Neighbor.Address));
  2184. // printf("/%s", FormatIPv6Address(&RTE->This.Neighbor.Address));
  2185. IF = GetInterfaceInfo(&RTE->This.Neighbor.IF);
  2186. if (IF != NULL) {
  2187. if (IF->Preference != 0) {
  2188. NlsPutMsg(STDOUT, IPV6_MESSAGE_107,
  2189. IF->Preference, RTE->Preference,
  2190. IF->Preference + RTE->Preference);
  2191. // printf(" pref %uif+%u=%u ",
  2192. // IF->Preference, RTE->Preference,
  2193. // IF->Preference + RTE->Preference);
  2194. }
  2195. else {
  2196. NlsPutMsg(STDOUT, IPV6_MESSAGE_108, RTE->Preference);
  2197. // printf(" pref %u ", RTE->Preference);
  2198. }
  2199. free(IF);
  2200. }
  2201. else {
  2202. NlsPutMsg(STDOUT, IPV6_MESSAGE_108, RTE->Preference);
  2203. // printf(" pref %u ", RTE->Preference);
  2204. }
  2205. NlsPutMsg(STDOUT, IPV6_MESSAGE_109,
  2206. FormatLifetimes(RTE->ValidLifetime, RTE->PreferredLifetime));
  2207. // printf("life %s",
  2208. // FormatLifetimes(RTE->ValidLifetime, RTE->PreferredLifetime));
  2209. if (RTE->Publish)
  2210. NlsPutMsg(STDOUT, IPV6_MESSAGE_110);
  2211. // printf(", publish");
  2212. if (RTE->Immortal)
  2213. NlsPutMsg(STDOUT, IPV6_MESSAGE_111);
  2214. // printf(", no aging");
  2215. if (RTE->SitePrefixLength != 0)
  2216. NlsPutMsg(STDOUT, IPV6_MESSAGE_112, RTE->SitePrefixLength);
  2217. // printf(", spl %u", RTE->SitePrefixLength);
  2218. NlsPutMsg(STDOUT, IPV6_MESSAGE_113);
  2219. // printf(" (");
  2220. switch (RTE->Type) {
  2221. case RTE_TYPE_SYSTEM:
  2222. NlsPutMsg(STDOUT, IPV6_MESSAGE_114);
  2223. // printf("system");
  2224. break;
  2225. case RTE_TYPE_MANUAL:
  2226. NlsPutMsg(STDOUT, IPV6_MESSAGE_115);
  2227. // printf("manual");
  2228. break;
  2229. case RTE_TYPE_AUTOCONF:
  2230. NlsPutMsg(STDOUT, IPV6_MESSAGE_116);
  2231. // printf("autoconf");
  2232. break;
  2233. case RTE_TYPE_RIP:
  2234. NlsPutMsg(STDOUT, IPV6_MESSAGE_117);
  2235. // printf("RIP");
  2236. break;
  2237. case RTE_TYPE_OSPF:
  2238. NlsPutMsg(STDOUT, IPV6_MESSAGE_118);
  2239. // printf("OSPF");
  2240. break;
  2241. case RTE_TYPE_BGP:
  2242. NlsPutMsg(STDOUT, IPV6_MESSAGE_119);
  2243. // printf("BGP");
  2244. break;
  2245. case RTE_TYPE_IDRP:
  2246. NlsPutMsg(STDOUT, IPV6_MESSAGE_120);
  2247. // printf("IDRP");
  2248. break;
  2249. case RTE_TYPE_IGRP:
  2250. NlsPutMsg(STDOUT, IPV6_MESSAGE_121);
  2251. // printf("IGRP");
  2252. break;
  2253. default:
  2254. NlsPutMsg(STDOUT, IPV6_MESSAGE_122, RTE->Type);
  2255. // printf("type %u", RTE->Type);
  2256. break;
  2257. }
  2258. NlsPutMsg(STDOUT, IPV6_MESSAGE_123);
  2259. // printf(")\n");
  2260. }
  2261. void
  2262. PrintPersistentRouteTableEntry(IPV6_INFO_ROUTE_TABLE *RTE)
  2263. {
  2264. IPV6_INFO_INTERFACE *IF;
  2265. printf("%s/%u -> %s",
  2266. // NlsPutMsg(STDOUT, IPV6_MESSAGE_PRINT_PERSISTENT_ROUTE,
  2267. FormatIPv6Address(&RTE->This.Prefix),
  2268. RTE->This.PrefixLength,
  2269. FormatGuid(&RTE->This.Neighbor.IF.Guid));
  2270. if (! IN6_ADDR_EQUAL(&RTE->This.Neighbor.Address, &in6addr_any))
  2271. NlsPutMsg(STDOUT, IPV6_MESSAGE_106,
  2272. FormatIPv6Address(&RTE->This.Neighbor.Address));
  2273. // printf("/%s", FormatIPv6Address(&RTE->This.Neighbor.Address));
  2274. NlsPutMsg(STDOUT, IPV6_MESSAGE_108, RTE->Preference);
  2275. // printf(" pref %u ", RTE->Preference);
  2276. NlsPutMsg(STDOUT, IPV6_MESSAGE_109,
  2277. FormatLifetimes(RTE->ValidLifetime, RTE->PreferredLifetime));
  2278. // printf("life %s",
  2279. // FormatLifetimes(RTE->ValidLifetime, RTE->PreferredLifetime));
  2280. if (RTE->Publish)
  2281. NlsPutMsg(STDOUT, IPV6_MESSAGE_110);
  2282. // printf(", publish");
  2283. if (RTE->Immortal)
  2284. NlsPutMsg(STDOUT, IPV6_MESSAGE_111);
  2285. // printf(", no aging");
  2286. if (RTE->SitePrefixLength != 0)
  2287. NlsPutMsg(STDOUT, IPV6_MESSAGE_112, RTE->SitePrefixLength);
  2288. // printf(", spl %u", RTE->SitePrefixLength);
  2289. NlsPutMsg(STDOUT, IPV6_MESSAGE_36);
  2290. // printf("\n");
  2291. }
  2292. void
  2293. PrintPersistentRoutesOnInterface(IPV6_INFO_INTERFACE *IF)
  2294. {
  2295. ForEachPersistentRoute(IF, PrintPersistentRouteTableEntry);
  2296. }
  2297. void
  2298. QueryRouteTable(int argc, char *argv[])
  2299. {
  2300. if (argc == 0) {
  2301. if (Persistent)
  2302. ForEachPersistentInterface(PrintPersistentRoutesOnInterface);
  2303. else
  2304. ForEachRoute(PrintRouteTableEntry);
  2305. }
  2306. else {
  2307. usage();
  2308. }
  2309. }
  2310. void
  2311. UpdateRouteTable(int argc, char *argv[])
  2312. {
  2313. IPV6_INFO_ROUTE_TABLE Route;
  2314. u_int BytesReturned;
  2315. int i;
  2316. Route.SitePrefixLength = 0;
  2317. Route.ValidLifetime = INFINITE_LIFETIME;
  2318. Route.PreferredLifetime = INFINITE_LIFETIME;
  2319. Route.Preference = ROUTE_PREF_HIGHEST;
  2320. Route.Type = RTE_TYPE_MANUAL;
  2321. Route.Publish = FALSE;
  2322. Route.Immortal = -1;
  2323. if (argc < 2)
  2324. usage();
  2325. if (! GetNeighbor(argv[1],
  2326. &Route.This.Neighbor.IF,
  2327. &Route.This.Neighbor.Address))
  2328. usage();
  2329. if (! GetPrefix(argv[0],
  2330. &Route.This.Prefix,
  2331. &Route.This.PrefixLength))
  2332. usage();
  2333. for (i = 2; i < argc; i++) {
  2334. if (!strncmp(argv[i], "lifetime", strlen(argv[i])) &&
  2335. (i+1 < argc)) {
  2336. if (! GetLifetimes(argv[++i],
  2337. &Route.ValidLifetime,
  2338. &Route.PreferredLifetime))
  2339. usage();
  2340. }
  2341. else if (!strncmp(argv[i], "preference", strlen(argv[i])) &&
  2342. (i+1 < argc)) {
  2343. i++;
  2344. if (!strncmp(argv[i], "low", strlen(argv[i])))
  2345. Route.Preference = ROUTE_PREF_LOW;
  2346. else if (!strncmp(argv[i], "medium", strlen(argv[i])))
  2347. Route.Preference = ROUTE_PREF_MEDIUM;
  2348. else if (!strncmp(argv[i], "high", strlen(argv[i])))
  2349. Route.Preference = ROUTE_PREF_HIGH;
  2350. else if (!strncmp(argv[i], "onlink", strlen(argv[i])))
  2351. Route.Preference = ROUTE_PREF_ON_LINK;
  2352. else if (!strncmp(argv[i], "loopback", strlen(argv[i])))
  2353. Route.Preference = ROUTE_PREF_LOOPBACK;
  2354. else if (! GetNumber(argv[i], &Route.Preference))
  2355. usage();
  2356. }
  2357. else if (!strcmp(argv[i], "spl") && (i+1 < argc)) {
  2358. if (! GetNumber(argv[++i], &Route.SitePrefixLength))
  2359. usage();
  2360. }
  2361. else if (!strncmp(argv[i], "advertise", strlen(argv[i])) ||
  2362. !strncmp(argv[i], "publish", strlen(argv[i]))) {
  2363. Route.Publish = TRUE;
  2364. }
  2365. else if (!strncmp(argv[i], "immortal", strlen(argv[i])) ||
  2366. !strncmp(argv[i], "noaging", strlen(argv[i])) ||
  2367. !strcmp(argv[i], "noage")) {
  2368. Route.Immortal = TRUE;
  2369. }
  2370. else if (!strncmp(argv[i], "aging", strlen(argv[i])) ||
  2371. !strcmp(argv[i], "age")) {
  2372. Route.Immortal = FALSE;
  2373. }
  2374. else if (!strcmp(argv[i], "system")) {
  2375. Route.Type = RTE_TYPE_SYSTEM;
  2376. }
  2377. else if (!strcmp(argv[i], "manual")) {
  2378. Route.Type = RTE_TYPE_MANUAL;
  2379. }
  2380. else if (!strcmp(argv[i], "autoconf")) {
  2381. Route.Type = RTE_TYPE_AUTOCONF;
  2382. }
  2383. else if (!strcmp(argv[i], "rip")) {
  2384. Route.Type = RTE_TYPE_RIP;
  2385. }
  2386. else if (!strcmp(argv[i], "ospf")) {
  2387. Route.Type = RTE_TYPE_OSPF;
  2388. }
  2389. else if (!strcmp(argv[i], "bgp")) {
  2390. Route.Type = RTE_TYPE_BGP;
  2391. }
  2392. else if (!strcmp(argv[i], "idrp")) {
  2393. Route.Type = RTE_TYPE_IDRP;
  2394. }
  2395. else if (!strcmp(argv[i], "igrp")) {
  2396. Route.Type = RTE_TYPE_IGRP;
  2397. }
  2398. else
  2399. usage();
  2400. }
  2401. if (Route.Immortal == -1)
  2402. Route.Immortal = Route.Publish;
  2403. if (!DeviceIoControl(Handle,
  2404. (Persistent ?
  2405. IOCTL_IPV6_PERSISTENT_UPDATE_ROUTE_TABLE :
  2406. IOCTL_IPV6_UPDATE_ROUTE_TABLE),
  2407. &Route, sizeof Route,
  2408. NULL, 0, &BytesReturned, NULL)) {
  2409. NlsPutMsg(STDOUT, IPV6_MESSAGE_124, GetLastError());
  2410. // printf("route update error: %x\n", GetLastError());
  2411. exit(1);
  2412. }
  2413. }
  2414. void
  2415. UpdateAddress(int argc, char *argv[])
  2416. {
  2417. IPV6_UPDATE_ADDRESS Update;
  2418. u_int BytesReturned;
  2419. int i;
  2420. int Origin;
  2421. Update.Type = ADE_UNICAST;
  2422. Update.PrefixConf = PREFIX_CONF_MANUAL;
  2423. Update.InterfaceIdConf = IID_CONF_MANUAL;
  2424. Update.ValidLifetime = INFINITE_LIFETIME;
  2425. Update.PreferredLifetime = INFINITE_LIFETIME;
  2426. if (argc < 1)
  2427. usage();
  2428. if ((strchr(argv[0], '/') == NULL) ||
  2429. ! GetNeighbor(argv[0],
  2430. &Update.This.IF,
  2431. &Update.This.Address))
  2432. usage();
  2433. for (i = 1; i < argc; i++) {
  2434. if (!strncmp(argv[i], "lifetime", strlen(argv[i])) &&
  2435. (i+1 < argc)) {
  2436. if (! GetLifetimes(argv[++i],
  2437. &Update.ValidLifetime,
  2438. &Update.PreferredLifetime))
  2439. usage();
  2440. }
  2441. else if (!strcmp(argv[i], "unicast"))
  2442. Update.Type = ADE_UNICAST;
  2443. else if (!strcmp(argv[i], "anycast"))
  2444. Update.Type = ADE_ANYCAST;
  2445. else if (!strcmp(argv[i], "prefixorigin") &&
  2446. (i+1 < argc)) {
  2447. if (! GetPrefixOrigin(argv[++i], &Origin))
  2448. usage();
  2449. Update.PrefixConf = Origin;
  2450. }
  2451. else if (!strcmp(argv[i], "ifidorigin") &&
  2452. (i+1 < argc)) {
  2453. if (! GetInterfaceIdOrigin(argv[++i], &Origin))
  2454. usage();
  2455. Update.InterfaceIdConf = Origin;
  2456. }
  2457. else
  2458. usage();
  2459. }
  2460. if (!DeviceIoControl(Handle,
  2461. (Persistent ?
  2462. IOCTL_IPV6_PERSISTENT_UPDATE_ADDRESS :
  2463. IOCTL_IPV6_UPDATE_ADDRESS),
  2464. &Update, sizeof Update,
  2465. NULL, 0, &BytesReturned, NULL)) {
  2466. NlsPutMsg(STDOUT, IPV6_MESSAGE_125, GetLastError());
  2467. // printf("address update error: %x\n", GetLastError());
  2468. exit(1);
  2469. }
  2470. }
  2471. void
  2472. ForEachBinding(void (*func)(IPV6_INFO_BINDING_CACHE *))
  2473. {
  2474. IPV6_QUERY_BINDING_CACHE Query, NextQuery;
  2475. IPV6_INFO_BINDING_CACHE BCE;
  2476. u_int BytesReturned;
  2477. NextQuery.HomeAddress = in6addr_any;
  2478. for (;;) {
  2479. Query = NextQuery;
  2480. if (!DeviceIoControl(Handle, IOCTL_IPV6_QUERY_BINDING_CACHE,
  2481. &Query, sizeof Query,
  2482. &BCE, sizeof BCE, &BytesReturned,
  2483. NULL)) {
  2484. NlsPutMsg(STDOUT, IPV6_MESSAGE_126,
  2485. FormatIPv6Address(&Query.HomeAddress));
  2486. // printf("bad home address %s\n",
  2487. // FormatIPv6Address(&Query.HomeAddress));
  2488. exit(1);
  2489. }
  2490. NextQuery = BCE.Query;
  2491. if (!IN6_ADDR_EQUAL(&Query.HomeAddress, &in6addr_any)) {
  2492. BCE.Query = Query;
  2493. (*func)(&BCE);
  2494. }
  2495. if (IN6_ADDR_EQUAL(&NextQuery.HomeAddress, &in6addr_any))
  2496. break;
  2497. }
  2498. }
  2499. void
  2500. PrintBindingCacheEntry(IPV6_INFO_BINDING_CACHE *BCE)
  2501. {
  2502. NlsPutMsg(STDOUT, IPV6_MESSAGE_127,
  2503. FormatIPv6Address(&BCE->HomeAddress));
  2504. // printf("home: %s\n", FormatIPv6Address(&BCE->HomeAddress));
  2505. NlsPutMsg(STDOUT, IPV6_MESSAGE_128,
  2506. FormatIPv6Address(&BCE->CareOfAddress));
  2507. // printf(" c/o: %s\n", FormatIPv6Address(&BCE->CareOfAddress));
  2508. NlsPutMsg(STDOUT, IPV6_MESSAGE_129,
  2509. BCE->BindingSeqNumber, BCE->BindingLifetime);
  2510. // printf(" seq: %u Lifetime: %us\n\n",
  2511. // BCE->BindingSeqNumber, BCE->BindingLifetime);
  2512. }
  2513. void
  2514. QueryBindingCache(int argc, char *argv[])
  2515. {
  2516. if (argc == 0) {
  2517. ForEachBinding(PrintBindingCacheEntry);
  2518. } else {
  2519. usage();
  2520. }
  2521. }
  2522. void
  2523. FlushNeighborCacheForInterface(IPV6_INFO_INTERFACE *IF)
  2524. {
  2525. IPV6_QUERY_NEIGHBOR_CACHE Query;
  2526. u_int BytesReturned;
  2527. Query.IF = IF->This;
  2528. Query.Address = in6addr_any;
  2529. if (!DeviceIoControl(Handle, IOCTL_IPV6_FLUSH_NEIGHBOR_CACHE,
  2530. &Query, sizeof Query,
  2531. NULL, 0, &BytesReturned, NULL)) {
  2532. NlsPutMsg(STDOUT, IPV6_MESSAGE_130, GetLastError());
  2533. // printf("flush neighbor cache error: %x\n", GetLastError());
  2534. exit(1);
  2535. }
  2536. }
  2537. void
  2538. FlushNeighborCache(int argc, char *argv[])
  2539. {
  2540. //
  2541. // Rather than put code in the kernel ioctl to iterate
  2542. // over the interfaces, we do it here in user space.
  2543. //
  2544. if (argc == 0) {
  2545. ForEachInterface(FlushNeighborCacheForInterface);
  2546. }
  2547. else {
  2548. IPV6_QUERY_NEIGHBOR_CACHE Query;
  2549. u_int BytesReturned;
  2550. Query.IF.Index = 0;
  2551. Query.Address = in6addr_any;
  2552. switch (argc) {
  2553. case 2:
  2554. if (! GetAddress(argv[1], &Query.Address))
  2555. usage();
  2556. // fall-through
  2557. case 1:
  2558. if (! GetInterface(argv[0], &Query.IF))
  2559. usage();
  2560. // fall-through
  2561. case 0:
  2562. break;
  2563. default:
  2564. usage();
  2565. }
  2566. if (!DeviceIoControl(Handle, IOCTL_IPV6_FLUSH_NEIGHBOR_CACHE,
  2567. &Query, sizeof Query,
  2568. NULL, 0, &BytesReturned, NULL)) {
  2569. NlsPutMsg(STDOUT, IPV6_MESSAGE_130, GetLastError());
  2570. // printf("flush neighbor cache error: %x\n", GetLastError());
  2571. exit(1);
  2572. }
  2573. }
  2574. }
  2575. void
  2576. FlushRouteCache(int argc, char *argv[])
  2577. {
  2578. IPV6_QUERY_ROUTE_CACHE Query;
  2579. u_int BytesReturned;
  2580. Query.IF.Index = (u_int)-1;
  2581. Query.Address = in6addr_any;
  2582. switch (argc) {
  2583. case 2:
  2584. if (! GetAddress(argv[1], &Query.Address))
  2585. usage();
  2586. // fall-through
  2587. case 1:
  2588. if (! GetInterface(argv[0], &Query.IF))
  2589. usage();
  2590. // fall-through
  2591. case 0:
  2592. break;
  2593. default:
  2594. usage();
  2595. }
  2596. if (!DeviceIoControl(Handle, IOCTL_IPV6_FLUSH_ROUTE_CACHE,
  2597. &Query, sizeof Query,
  2598. NULL, 0, &BytesReturned, NULL)) {
  2599. NlsPutMsg(STDOUT, IPV6_MESSAGE_131, GetLastError());
  2600. // printf("flush route cache error: %x\n", GetLastError());
  2601. exit(1);
  2602. }
  2603. }
  2604. void
  2605. ForEachSitePrefix(void (*func)(IPV6_INFO_SITE_PREFIX *))
  2606. {
  2607. IPV6_QUERY_SITE_PREFIX Query, NextQuery;
  2608. IPV6_INFO_SITE_PREFIX SPE;
  2609. u_int BytesReturned;
  2610. NextQuery.IF.Index = 0;
  2611. for (;;) {
  2612. Query = NextQuery;
  2613. if (!DeviceIoControl(Handle, IOCTL_IPV6_QUERY_SITE_PREFIX,
  2614. &Query, sizeof Query,
  2615. &SPE, sizeof SPE, &BytesReturned,
  2616. NULL)) {
  2617. NlsPutMsg(STDOUT, IPV6_MESSAGE_132, Query.IF.Index);
  2618. // printf("bad index %u\n", Query.IF.Index);
  2619. exit(1);
  2620. }
  2621. NextQuery = SPE.Query;
  2622. if (Query.IF.Index != 0) {
  2623. SPE.Query = Query;
  2624. (*func)(&SPE);
  2625. }
  2626. if (NextQuery.IF.Index == 0)
  2627. break;
  2628. }
  2629. }
  2630. void
  2631. PrintSitePrefix(IPV6_INFO_SITE_PREFIX *SPE)
  2632. {
  2633. NlsPutMsg(STDOUT, IPV6_MESSAGE_133,
  2634. FormatIPv6Address(&SPE->Query.Prefix),
  2635. SPE->Query.PrefixLength,
  2636. SPE->Query.IF.Index,
  2637. FormatLifetimes(SPE->ValidLifetime, SPE->ValidLifetime));
  2638. // printf("%s/%u -> %u (life %s)\n",
  2639. // FormatIPv6Address(&SPE->Query.Prefix),
  2640. // SPE->Query.PrefixLength,
  2641. // SPE->Query.IF.Index,
  2642. // FormatLifetimes(SPE->ValidLifetime, SPE->ValidLifetime));
  2643. }
  2644. void
  2645. QuerySitePrefixTable(int argc, char *argv[])
  2646. {
  2647. if (argc == 0) {
  2648. ForEachSitePrefix(PrintSitePrefix);
  2649. }
  2650. else {
  2651. usage();
  2652. }
  2653. }
  2654. void
  2655. UpdateSitePrefixTable(int argc, char *argv[])
  2656. {
  2657. IPV6_INFO_SITE_PREFIX SitePrefix;
  2658. u_int BytesReturned;
  2659. int i;
  2660. SitePrefix.ValidLifetime = INFINITE_LIFETIME;
  2661. if (argc < 2)
  2662. usage();
  2663. if (! GetInterface(argv[1], &SitePrefix.Query.IF))
  2664. usage();
  2665. if (! GetPrefix(argv[0],
  2666. &SitePrefix.Query.Prefix,
  2667. &SitePrefix.Query.PrefixLength))
  2668. usage();
  2669. for (i = 2; i < argc; i++) {
  2670. if (!strncmp(argv[i], "lifetime", strlen(argv[i])) &&
  2671. (i+1 < argc)) {
  2672. if (! GetLifetimes(argv[++i], &SitePrefix.ValidLifetime, NULL))
  2673. usage();
  2674. }
  2675. else
  2676. usage();
  2677. }
  2678. if (!DeviceIoControl(Handle, IOCTL_IPV6_UPDATE_SITE_PREFIX,
  2679. &SitePrefix, sizeof SitePrefix,
  2680. NULL, 0, &BytesReturned, NULL)) {
  2681. NlsPutMsg(STDOUT, IPV6_MESSAGE_134, GetLastError());
  2682. // printf("site prefix update error: %x\n", GetLastError());
  2683. exit(1);
  2684. }
  2685. }
  2686. void
  2687. QueryGlobalParameters(int argc, char *argv[])
  2688. {
  2689. IPV6_GLOBAL_PARAMETERS Params;
  2690. u_int BytesReturned;
  2691. if (argc != 0)
  2692. usage();
  2693. if (!DeviceIoControl(Handle,
  2694. (Persistent ?
  2695. IOCTL_IPV6_PERSISTENT_QUERY_GLOBAL_PARAMETERS :
  2696. IOCTL_IPV6_QUERY_GLOBAL_PARAMETERS),
  2697. NULL, 0,
  2698. &Params, sizeof Params, &BytesReturned, NULL) ||
  2699. (BytesReturned != sizeof Params)) {
  2700. NlsPutMsg(STDOUT, IPV6_MESSAGE_135, GetLastError());
  2701. // printf("query global params error: %x\n", GetLastError());
  2702. exit(1);
  2703. }
  2704. if (Params.DefaultCurHopLimit != (u_int) -1) {
  2705. NlsPutMsg(STDOUT, IPV6_MESSAGE_136, Params.DefaultCurHopLimit);
  2706. // printf("DefaultCurHopLimit = %u\n", Params.DefaultCurHopLimit);
  2707. }
  2708. if (Params.UseAnonymousAddresses != (u_int) -1) {
  2709. switch (Params.UseAnonymousAddresses) {
  2710. case USE_ANON_NO:
  2711. NlsPutMsg(STDOUT, IPV6_MESSAGE_137);
  2712. // printf("UseAnonymousAddresses = no\n");
  2713. break;
  2714. case USE_ANON_YES:
  2715. NlsPutMsg(STDOUT, IPV6_MESSAGE_138);
  2716. // printf("UseAnonymousAddresses = yes\n");
  2717. break;
  2718. case USE_ANON_ALWAYS:
  2719. NlsPutMsg(STDOUT, IPV6_MESSAGE_139);
  2720. // printf("UseAnonymousAddresses = yes, new random interface id for every address\n");
  2721. break;
  2722. case USE_ANON_COUNTER:
  2723. NlsPutMsg(STDOUT, IPV6_MESSAGE_140);
  2724. // printf("UseAnonymousAddresses = yes, incrementing interface ids\n");
  2725. break;
  2726. default:
  2727. NlsPutMsg(STDOUT, IPV6_MESSAGE_141, Params.UseAnonymousAddresses);
  2728. // printf("UseAnonymousAddresses = %u\n", Params.UseAnonymousAddresses);
  2729. break;
  2730. }
  2731. }
  2732. if (Params.MaxAnonDADAttempts != (u_int) -1) {
  2733. NlsPutMsg(STDOUT, IPV6_MESSAGE_142, Params.MaxAnonDADAttempts);
  2734. // printf("MaxAnonDADAttempts = %u\n", Params.MaxAnonDADAttempts);
  2735. }
  2736. if ((Params.MaxAnonValidLifetime != (u_int) -1) ||
  2737. (Params.MaxAnonPreferredLifetime != (u_int) -1)) {
  2738. NlsPutMsg(STDOUT, IPV6_MESSAGE_143,
  2739. FormatLifetimes(Params.MaxAnonValidLifetime,
  2740. Params.MaxAnonPreferredLifetime));
  2741. // printf("MaxAnonLifetime = %s\n",
  2742. // FormatLifetimes(Params.MaxAnonValidLifetime,
  2743. // Params.MaxAnonPreferredLifetime));
  2744. }
  2745. if (Params.AnonRegenerateTime != (u_int) -1) {
  2746. NlsPutMsg(STDOUT, IPV6_MESSAGE_144, Params.AnonRegenerateTime);
  2747. // printf("AnonRegenerateTime = %us\n", Params.AnonRegenerateTime);
  2748. }
  2749. if (Params.MaxAnonRandomTime != (u_int) -1) {
  2750. NlsPutMsg(STDOUT, IPV6_MESSAGE_145,
  2751. FormatLifetime(Params.MaxAnonRandomTime));
  2752. // printf("MaxAnonRandomTime = %s\n",
  2753. // FormatLifetime(Params.MaxAnonRandomTime));
  2754. }
  2755. if (! Persistent) {
  2756. NlsPutMsg(STDOUT, IPV6_MESSAGE_146,
  2757. FormatLifetime(Params.AnonRandomTime));
  2758. // printf("AnonRandomTime = %s\n",
  2759. // FormatLifetime(Params.AnonRandomTime));
  2760. }
  2761. if (Params.NeighborCacheLimit != (u_int) -1) {
  2762. NlsPutMsg(STDOUT, IPV6_MESSAGE_147, Params.NeighborCacheLimit);
  2763. // printf("NeighborCacheLimit = %u\n", Params.NeighborCacheLimit);
  2764. }
  2765. if (Params.RouteCacheLimit != (u_int) -1) {
  2766. NlsPutMsg(STDOUT, IPV6_MESSAGE_148, Params.RouteCacheLimit);
  2767. // printf("RouteCacheLimit = %u\n", Params.RouteCacheLimit);
  2768. }
  2769. if (Params.BindingCacheLimit != (u_int) -1) {
  2770. NlsPutMsg(STDOUT, IPV6_MESSAGE_BCL_DISPLAY, Params.BindingCacheLimit);
  2771. // printf("BindingCacheLimit = %u\n", Params.BindingCacheLimit);
  2772. }
  2773. if (Params.ReassemblyLimit != (u_int) -1) {
  2774. NlsPutMsg(STDOUT, IPV6_MESSAGE_REASS_LIMIT_DISPLAY, Params.ReassemblyLimit);
  2775. // printf("ReassemblyLimit = %u\n", Params.ReassemblyLimit);
  2776. }
  2777. if (Params.MobilitySecurity != -1) {
  2778. if (Params.MobilitySecurity) {
  2779. NlsPutMsg(STDOUT, IPV6_MESSAGE_MOBILITY_SECURITY_ON);
  2780. // printf("MobilitySecurity = on\n");
  2781. }
  2782. else {
  2783. NlsPutMsg(STDOUT, IPV6_MESSAGE_MOBILITY_SECURITY_OFF);
  2784. // printf("MobilitySecurity = off\n");
  2785. }
  2786. }
  2787. }
  2788. void
  2789. UpdateGlobalParameters(int argc, char *argv[])
  2790. {
  2791. IPV6_GLOBAL_PARAMETERS Params;
  2792. u_int BytesReturned;
  2793. int i;
  2794. IPV6_INIT_GLOBAL_PARAMETERS(&Params);
  2795. for (i = 0; i < argc; i++) {
  2796. if (!strcmp(argv[i], "DefaultCurHopLimit") && (i+1 < argc)) {
  2797. if (! GetNumber(argv[++i], &Params.DefaultCurHopLimit))
  2798. goto usage;
  2799. }
  2800. else if (!strcmp(argv[i], "UseAnonymousAddresses") && (i+1 < argc)) {
  2801. if (!strncmp(argv[++i], "no", strlen(argv[i])))
  2802. Params.UseAnonymousAddresses = USE_ANON_NO;
  2803. else if (!strncmp(argv[i], "yes", strlen(argv[i])))
  2804. Params.UseAnonymousAddresses = USE_ANON_YES;
  2805. else if (!strncmp(argv[i], "always", strlen(argv[i])))
  2806. Params.UseAnonymousAddresses = USE_ANON_ALWAYS;
  2807. else if (!strncmp(argv[i], "counter", strlen(argv[i])))
  2808. Params.UseAnonymousAddresses = USE_ANON_COUNTER;
  2809. else
  2810. goto usage;
  2811. }
  2812. else if (!strcmp(argv[i], "MaxAnonDADAttempts") && (i+1 < argc)) {
  2813. if (! GetNumber(argv[++i], &Params.MaxAnonDADAttempts))
  2814. goto usage;
  2815. }
  2816. else if (!strcmp(argv[i], "MaxAnonLifetime") && (i+1 < argc)) {
  2817. if (! GetLifetimes(argv[++i],
  2818. &Params.MaxAnonValidLifetime,
  2819. &Params.MaxAnonPreferredLifetime))
  2820. goto usage;
  2821. }
  2822. else if (!strcmp(argv[i], "AnonRegenerateTime") && (i+1 < argc)) {
  2823. if (! GetLifetime(argv[++i], &Params.AnonRegenerateTime))
  2824. goto usage;
  2825. }
  2826. else if (!strcmp(argv[i], "MaxAnonRandomTime") && (i+1 < argc)) {
  2827. if (! GetLifetime(argv[++i], &Params.MaxAnonRandomTime))
  2828. goto usage;
  2829. }
  2830. else if (!strcmp(argv[i], "AnonRandomTime") && (i+1 < argc)) {
  2831. if (! GetLifetime(argv[++i], &Params.AnonRandomTime))
  2832. goto usage;
  2833. }
  2834. else if (!strcmp(argv[i], "NeighborCacheLimit") && (i+1 < argc)) {
  2835. if (! GetNumber(argv[++i], &Params.NeighborCacheLimit))
  2836. goto usage;
  2837. }
  2838. else if (!strcmp(argv[i], "RouteCacheLimit") && (i+1 < argc)) {
  2839. if (! GetNumber(argv[++i], &Params.RouteCacheLimit))
  2840. goto usage;
  2841. }
  2842. else if (!strcmp(argv[i], "BindingCacheLimit") && (i+1 < argc)) {
  2843. if (! GetNumber(argv[++i], &Params.BindingCacheLimit))
  2844. goto usage;
  2845. }
  2846. else if (!strcmp(argv[i], "ReassemblyLimit") && (i+1 < argc)) {
  2847. if (! GetNumber(argv[++i], &Params.ReassemblyLimit))
  2848. goto usage;
  2849. }
  2850. else if (!strcmp(argv[i], "MobilitySecurity") && (i+1 < argc)) {
  2851. if (!strncmp(argv[++i], "on", strlen(argv[i])))
  2852. Params.MobilitySecurity = TRUE;
  2853. else if (!strncmp(argv[i], "off", strlen(argv[i])))
  2854. Params.MobilitySecurity = FALSE;
  2855. else if (!strncmp(argv[i], "yes", strlen(argv[i])))
  2856. Params.MobilitySecurity = TRUE;
  2857. else if (!strncmp(argv[i], "no", strlen(argv[i])))
  2858. Params.MobilitySecurity = FALSE;
  2859. else
  2860. goto usage;
  2861. }
  2862. else {
  2863. usage:
  2864. NlsPutMsg(STDOUT, IPV6_MESSAGE_149);
  2865. // printf("usage: ipv6 gpu [parameter value] ...\n");
  2866. // printf(" ipv6 gpu DefaultCurHopLimit hops\n");
  2867. // printf(" ipv6 gpu UseAnonymousAddresses [yes|no|always|counter]\n");
  2868. // printf(" ipv6 gpu MaxAnonDADAttempts number\n");
  2869. // printf(" ipv6 gpu MaxAnonLifetime valid[/preferred]\n");
  2870. // printf(" ipv6 gpu AnonRegenerateTime time\n");
  2871. // printf(" ipv6 gpu MaxAnonRandomTime time\n");
  2872. // printf(" ipv6 gpu AnonRandomTime time\n");
  2873. // printf(" ipv6 gpu NeighborCacheLimit number\n");
  2874. // printf(" ipv6 gpu RouteCacheLimit number\n");
  2875. // printf(" ipv6 gpu BindingCacheLimit number\n");
  2876. // printf(" ipv6 gpu ReassemblyLimit number\n");
  2877. // printf(" ipv6 gpu MobilitySecurity [on|off]\n");
  2878. // printf("Use ipv6 -p gpu ... to make a persistent change\n");
  2879. // printf("in the registry. Many global parameter changes\n");
  2880. // printf("only take effect after restarting the stack.\n");
  2881. }
  2882. }
  2883. if (!DeviceIoControl(Handle,
  2884. (Persistent ?
  2885. IOCTL_IPV6_PERSISTENT_UPDATE_GLOBAL_PARAMETERS :
  2886. IOCTL_IPV6_UPDATE_GLOBAL_PARAMETERS),
  2887. &Params, sizeof Params,
  2888. NULL, 0,
  2889. &BytesReturned, NULL)) {
  2890. NlsPutMsg(STDOUT, IPV6_MESSAGE_150, GetLastError());
  2891. // printf("update global params error: %x\n", GetLastError());
  2892. exit(1);
  2893. }
  2894. }
  2895. void
  2896. ForEachPrefixPolicy(void (*func)(IPV6_INFO_PREFIX_POLICY *))
  2897. {
  2898. IPV6_QUERY_PREFIX_POLICY Query;
  2899. IPV6_INFO_PREFIX_POLICY PPE;
  2900. u_int BytesReturned;
  2901. Query.PrefixLength = (u_int) -1;
  2902. for (;;) {
  2903. if (!DeviceIoControl(Handle, IOCTL_IPV6_QUERY_PREFIX_POLICY,
  2904. &Query, sizeof Query,
  2905. &PPE, sizeof PPE, &BytesReturned,
  2906. NULL)) {
  2907. NlsPutMsg(STDOUT, IPV6_MESSAGE_160);
  2908. // printf("bad prefix\n");
  2909. exit(1);
  2910. }
  2911. if (Query.PrefixLength != (u_int) -1) {
  2912. if (BytesReturned != sizeof PPE) {
  2913. NlsPutMsg(STDOUT, IPV6_MESSAGE_160);
  2914. // printf("bad prefix\n");
  2915. exit(1);
  2916. }
  2917. (*func)(&PPE);
  2918. }
  2919. else {
  2920. if (BytesReturned != sizeof PPE.Next) {
  2921. NlsPutMsg(STDOUT, IPV6_MESSAGE_160);
  2922. // printf("bad prefix\n");
  2923. exit(1);
  2924. }
  2925. }
  2926. if (PPE.Next.PrefixLength == (u_int) -1)
  2927. break;
  2928. Query = PPE.Next;
  2929. }
  2930. }
  2931. void
  2932. ForEachPersistentPrefixPolicy(void (*func)(IPV6_INFO_PREFIX_POLICY *))
  2933. {
  2934. IPV6_PERSISTENT_QUERY_PREFIX_POLICY Query;
  2935. IPV6_INFO_PREFIX_POLICY PPE;
  2936. u_int BytesReturned;
  2937. for (Query.RegistryIndex = 0;; Query.RegistryIndex++) {
  2938. if (!DeviceIoControl(Handle,
  2939. IOCTL_IPV6_PERSISTENT_QUERY_PREFIX_POLICY,
  2940. &Query, sizeof Query,
  2941. &PPE, sizeof PPE, &BytesReturned,
  2942. NULL)) {
  2943. if (GetLastError() == ERROR_NO_MORE_ITEMS)
  2944. break;
  2945. NlsPutMsg(STDOUT, IPV6_MESSAGE_160);
  2946. // printf("bad prefix\n");
  2947. exit(1);
  2948. }
  2949. if (BytesReturned != sizeof PPE) {
  2950. NlsPutMsg(STDOUT, IPV6_MESSAGE_160);
  2951. // printf("bad prefix\n");
  2952. exit(1);
  2953. }
  2954. (*func)(&PPE);
  2955. }
  2956. }
  2957. void
  2958. PrintPrefixPolicyEntry(IPV6_INFO_PREFIX_POLICY *PPE)
  2959. {
  2960. NlsPutMsg(STDOUT, IPV6_MESSAGE_161,
  2961. FormatIPv6Address(&PPE->This.Prefix),
  2962. PPE->This.PrefixLength,
  2963. PPE->Precedence,
  2964. PPE->SrcLabel,
  2965. PPE->DstLabel);
  2966. // printf("%s/%u -> precedence %u srclabel %u dstlabel %u\n",
  2967. // FormatIPv6Address(&PPE->This.Prefix),
  2968. // PPE->This.PrefixLength,
  2969. // PPE->Precedence,
  2970. // PPE->SrcLabel,
  2971. // PPE->DstLabel);
  2972. }
  2973. void
  2974. QueryPrefixPolicy(int argc, char *argv[])
  2975. {
  2976. if (argc == 0) {
  2977. if (Persistent)
  2978. ForEachPersistentPrefixPolicy(PrintPrefixPolicyEntry);
  2979. else
  2980. ForEachPrefixPolicy(PrintPrefixPolicyEntry);
  2981. }
  2982. else {
  2983. usage();
  2984. }
  2985. }
  2986. void
  2987. UpdatePrefixPolicy(int argc, char *argv[])
  2988. {
  2989. IPV6_INFO_PREFIX_POLICY Info;
  2990. u_int BytesReturned;
  2991. int i;
  2992. if (argc < 1)
  2993. usage();
  2994. if (! GetPrefix(argv[0],
  2995. &Info.This.Prefix,
  2996. &Info.This.PrefixLength))
  2997. usage();
  2998. Info.Precedence = (u_int) -1;
  2999. Info.SrcLabel = (u_int) -1;
  3000. Info.DstLabel = (u_int) -1;
  3001. for (i = 1; i < argc; i++) {
  3002. if (!strncmp(argv[i], "precedence", strlen(argv[i])) &&
  3003. ((i + 1) < argc)) {
  3004. if (! GetNumber(argv[++i], &Info.Precedence))
  3005. usage();
  3006. }
  3007. else if ((!strncmp(argv[i], "srclabel", strlen(argv[i])) ||
  3008. !strcmp(argv[i], "sl") ||
  3009. !strcmp(argv[i], "label")) &&
  3010. ((i + 1) < argc)) {
  3011. if (! GetNumber(argv[++i], &Info.SrcLabel))
  3012. usage();
  3013. }
  3014. else if ((!strncmp(argv[i], "dstlabel", strlen(argv[i])) ||
  3015. !strcmp(argv[i], "dl")) &&
  3016. ((i + 1) < argc)) {
  3017. if (! GetNumber(argv[++i], &Info.DstLabel))
  3018. usage();
  3019. }
  3020. else
  3021. usage();
  3022. }
  3023. if ((Info.Precedence == (u_int) -1) ||
  3024. (Info.SrcLabel == (u_int) -1))
  3025. usage();
  3026. if (Info.DstLabel == (u_int) -1)
  3027. Info.DstLabel = Info.SrcLabel;
  3028. if (!DeviceIoControl(Handle,
  3029. (Persistent ?
  3030. IOCTL_IPV6_PERSISTENT_UPDATE_PREFIX_POLICY :
  3031. IOCTL_IPV6_UPDATE_PREFIX_POLICY),
  3032. &Info, sizeof Info,
  3033. NULL, 0, &BytesReturned, NULL)) {
  3034. NlsPutMsg(STDOUT, IPV6_MESSAGE_162, GetLastError());
  3035. // printf("prefix policy create error: %x\n", GetLastError());
  3036. exit(1);
  3037. }
  3038. }
  3039. void
  3040. DeletePrefixPolicy(int argc, char *argv[])
  3041. {
  3042. IPV6_QUERY_PREFIX_POLICY Query;
  3043. u_int BytesReturned;
  3044. if (argc == 1) {
  3045. if (! GetPrefix(argv[0],
  3046. &Query.Prefix,
  3047. &Query.PrefixLength))
  3048. usage();
  3049. }
  3050. else {
  3051. usage();
  3052. }
  3053. if (!DeviceIoControl(Handle,
  3054. (Persistent ?
  3055. IOCTL_IPV6_PERSISTENT_DELETE_PREFIX_POLICY :
  3056. IOCTL_IPV6_DELETE_PREFIX_POLICY),
  3057. &Query, sizeof Query,
  3058. NULL, 0, &BytesReturned, NULL)) {
  3059. NlsPutMsg(STDOUT, IPV6_MESSAGE_163, GetLastError());
  3060. // printf("prefix policy delete error: %x\n", GetLastError());
  3061. exit(1);
  3062. }
  3063. }
  3064. void
  3065. ResetManualConfig(int argc, char *argv[])
  3066. {
  3067. u_int BytesReturned;
  3068. if (argc != 0)
  3069. usage();
  3070. if (!DeviceIoControl(Handle,
  3071. (Persistent ?
  3072. IOCTL_IPV6_PERSISTENT_RESET :
  3073. IOCTL_IPV6_RESET),
  3074. NULL, 0,
  3075. NULL, 0, &BytesReturned, NULL)) {
  3076. NlsPutMsg(STDOUT, IPV6_MESSAGE_RESET, GetLastError());
  3077. // printf("reset error: %x\n", GetLastError());
  3078. exit(1);
  3079. }
  3080. }