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.

3039 lines
93 KiB

  1. //=============================================================================
  2. // Copyright (c) 2001 Microsoft Corporation
  3. // Abstract:
  4. // This module implements IPv6 configuration commands.
  5. //=============================================================================
  6. #include "precomp.h"
  7. #pragma hdrstop
  8. typedef enum {
  9. ACTION_ADD,
  10. ACTION_SET
  11. } ACTION;
  12. DWORD
  13. GetTime(
  14. IN PWCHAR pwszLife)
  15. {
  16. PWCHAR pwcUnit;
  17. DWORD dwUnits, dwLife = 0;
  18. if (!_wcsnicmp(pwszLife, TOKEN_VALUE_INFINITE, wcslen(pwszLife))) {
  19. return INFINITE_LIFETIME;
  20. }
  21. while ((pwcUnit = wcspbrk(pwszLife, L"sSmMhHdD")) != NULL) {
  22. switch (*pwcUnit) {
  23. case L's':
  24. case L'S':
  25. dwUnits = SECONDS;
  26. break;
  27. case L'm':
  28. case L'M':
  29. dwUnits = MINUTES;
  30. break;
  31. case L'h':
  32. case L'H':
  33. dwUnits = HOURS;
  34. break;
  35. case L'd':
  36. case L'D':
  37. dwUnits = DAYS;
  38. break;
  39. }
  40. *pwcUnit = L'\0';
  41. dwLife += wcstoul(pwszLife, NULL, 10) * dwUnits;
  42. pwszLife = pwcUnit + 1;
  43. if (*pwszLife == L'\0')
  44. return dwLife;
  45. }
  46. return dwLife + wcstoul(pwszLife, NULL, 10);
  47. }
  48. /////////////////////////////////////////////////////////////////////////////
  49. // Commands related to addresses
  50. /////////////////////////////////////////////////////////////////////////////
  51. DWORD
  52. HandleAddSetAddress(
  53. IN OUT LPWSTR *ppwcArguments,
  54. IN DWORD dwCurrentIndex,
  55. IN DWORD dwArgCount,
  56. IN ACTION Action,
  57. OUT BOOL *pbDone
  58. )
  59. {
  60. DWORD dwErr, i;
  61. TAG_TYPE pttTags[] = {{TOKEN_INTERFACE, TRUE, FALSE},
  62. {TOKEN_ADDRESS, TRUE, FALSE},
  63. {TOKEN_TYPE, FALSE, FALSE},
  64. {TOKEN_VALIDLIFETIME, FALSE, FALSE},
  65. {TOKEN_PREFERREDLIFETIME, FALSE, FALSE},
  66. {TOKEN_STORE, FALSE, FALSE}};
  67. DWORD rgdwTagType[sizeof(pttTags)/sizeof(TAG_TYPE)];
  68. PWCHAR pwszIfFriendlyName = NULL;
  69. IN6_ADDR ipAddress;
  70. TOKEN_VALUE rgtvTypeEnum[] = {{ TOKEN_VALUE_UNICAST, ADE_UNICAST },
  71. { TOKEN_VALUE_ANYCAST, ADE_ANYCAST }};
  72. TOKEN_VALUE rgtvStoreEnum[] = {{ TOKEN_VALUE_ACTIVE, FALSE },
  73. { TOKEN_VALUE_PERSISTENT, TRUE }};
  74. DWORD dwType = ADE_UNICAST;
  75. DWORD dwValidLifetime = INFINITE_LIFETIME;
  76. DWORD dwPreferredLifetime = INFINITE_LIFETIME;
  77. BOOL bPersistent = TRUE;
  78. // Parse arguments
  79. dwErr = PreprocessCommand(g_hModule,
  80. ppwcArguments,
  81. dwCurrentIndex,
  82. dwArgCount,
  83. pttTags,
  84. sizeof(pttTags)/sizeof(TAG_TYPE),
  85. 0,
  86. sizeof(pttTags)/sizeof(TAG_TYPE),
  87. rgdwTagType );
  88. for (i=0; (dwErr == NO_ERROR) && (i<dwArgCount-dwCurrentIndex); i++) {
  89. switch(rgdwTagType[i]) {
  90. case 0: // INTERFACE
  91. pwszIfFriendlyName = ppwcArguments[i + dwCurrentIndex];
  92. break;
  93. case 1: // ADDRESS
  94. dwErr = GetIpv6Address(ppwcArguments[i + dwCurrentIndex],
  95. &ipAddress);
  96. break;
  97. case 2: // TYPE
  98. dwErr = MatchEnumTag(NULL,
  99. ppwcArguments[dwCurrentIndex + i],
  100. NUM_TOKENS_IN_TABLE(rgtvTypeEnum),
  101. rgtvTypeEnum,
  102. &dwType);
  103. if (dwErr isnot NO_ERROR) {
  104. dwErr = ERROR_INVALID_PARAMETER;
  105. break;
  106. }
  107. break;
  108. case 3: // VALIDLIFETIME
  109. dwValidLifetime = GetTime(ppwcArguments[dwCurrentIndex + i]);
  110. break;
  111. case 4: // PREFERREDLIFETIME
  112. dwPreferredLifetime = GetTime(ppwcArguments[dwCurrentIndex + i]);
  113. break;
  114. case 5: // STORE
  115. dwErr = MatchEnumTag(NULL,
  116. ppwcArguments[dwCurrentIndex + i],
  117. NUM_TOKENS_IN_TABLE(rgtvStoreEnum),
  118. rgtvStoreEnum,
  119. &bPersistent);
  120. if (dwErr isnot NO_ERROR) {
  121. dwErr = ERROR_INVALID_PARAMETER;
  122. break;
  123. }
  124. break;
  125. default:
  126. dwErr = ERROR_INVALID_SYNTAX;
  127. break;
  128. }
  129. }
  130. if (dwErr isnot NO_ERROR) {
  131. return dwErr;
  132. }
  133. // Now do the work
  134. return UpdateAddress(pwszIfFriendlyName, &ipAddress, dwType,
  135. dwValidLifetime, dwPreferredLifetime, bPersistent);
  136. }
  137. DWORD
  138. HandleAddAddress(
  139. IN LPCWSTR pwszMachine,
  140. IN OUT LPWSTR *ppwcArguments,
  141. IN DWORD dwCurrentIndex,
  142. IN DWORD dwArgCount,
  143. IN DWORD dwFlags,
  144. IN LPCVOID pvData,
  145. OUT BOOL *pbDone
  146. )
  147. {
  148. return HandleAddSetAddress(ppwcArguments, dwCurrentIndex, dwArgCount,
  149. ACTION_ADD, pbDone);
  150. }
  151. DWORD
  152. HandleSetAddress(
  153. IN LPCWSTR pwszMachine,
  154. IN OUT LPWSTR *ppwcArguments,
  155. IN DWORD dwCurrentIndex,
  156. IN DWORD dwArgCount,
  157. IN DWORD dwFlags,
  158. IN LPCVOID pvData,
  159. OUT BOOL *pbDone
  160. )
  161. {
  162. return HandleAddSetAddress(ppwcArguments, dwCurrentIndex, dwArgCount,
  163. ACTION_SET, pbDone);
  164. }
  165. DWORD
  166. HandleDelAddress(
  167. IN LPCWSTR pwszMachine,
  168. IN OUT LPWSTR *ppwcArguments,
  169. IN DWORD dwCurrentIndex,
  170. IN DWORD dwArgCount,
  171. IN DWORD dwFlags,
  172. IN LPCVOID pvData,
  173. OUT BOOL *pbDone
  174. )
  175. {
  176. DWORD dwErr, i;
  177. TAG_TYPE pttTags[] = {{TOKEN_INTERFACE, TRUE, FALSE},
  178. {TOKEN_ADDRESS, TRUE, FALSE},
  179. {TOKEN_STORE, FALSE, FALSE}};
  180. DWORD rgdwTagType[sizeof(pttTags)/sizeof(TAG_TYPE)];
  181. PWCHAR pwszIfFriendlyName = NULL;
  182. IN6_ADDR ipAddress;
  183. TOKEN_VALUE rgtvStoreEnum[] = {{ TOKEN_VALUE_ACTIVE, FALSE },
  184. { TOKEN_VALUE_PERSISTENT, TRUE }};
  185. DWORD dwType = ADE_UNICAST;
  186. BOOL bPersistent = TRUE;
  187. // Parse arguments
  188. dwErr = PreprocessCommand(g_hModule,
  189. ppwcArguments,
  190. dwCurrentIndex,
  191. dwArgCount,
  192. pttTags,
  193. sizeof(pttTags)/sizeof(TAG_TYPE),
  194. 0,
  195. sizeof(pttTags)/sizeof(TAG_TYPE),
  196. rgdwTagType );
  197. for (i=0; (dwErr == NO_ERROR) && (i<dwArgCount-dwCurrentIndex); i++) {
  198. switch(rgdwTagType[i]) {
  199. case 0: // INTERFACE
  200. pwszIfFriendlyName = ppwcArguments[i + dwCurrentIndex];
  201. break;
  202. case 1: // ADDRESS
  203. dwErr = GetIpv6Address(ppwcArguments[i + dwCurrentIndex],
  204. &ipAddress);
  205. break;
  206. case 2: // STORE
  207. dwErr = MatchEnumTag(NULL,
  208. ppwcArguments[dwCurrentIndex + i],
  209. NUM_TOKENS_IN_TABLE(rgtvStoreEnum),
  210. rgtvStoreEnum,
  211. &bPersistent);
  212. if (dwErr isnot NO_ERROR) {
  213. dwErr = ERROR_INVALID_PARAMETER;
  214. break;
  215. }
  216. break;
  217. default:
  218. dwErr = ERROR_INVALID_SYNTAX;
  219. break;
  220. }
  221. }
  222. if (dwErr isnot NO_ERROR) {
  223. return dwErr;
  224. }
  225. // Now do the work
  226. return UpdateAddress(pwszIfFriendlyName, &ipAddress, dwType,
  227. 0, 0, bPersistent);
  228. }
  229. DWORD
  230. HandleShowAddress(
  231. IN LPCWSTR pwszMachine,
  232. IN OUT LPWSTR *ppwcArguments,
  233. IN DWORD dwCurrentIndex,
  234. IN DWORD dwArgCount,
  235. IN DWORD dwFlags,
  236. IN LPCVOID pvData,
  237. OUT BOOL *pbDone
  238. )
  239. {
  240. DWORD dwErr;
  241. TAG_TYPE pttTags[] = {{TOKEN_INTERFACE, FALSE, FALSE},
  242. {TOKEN_LEVEL, FALSE, FALSE},
  243. {TOKEN_STORE, FALSE, FALSE}};
  244. DWORD rgdwTagType[sizeof(pttTags)/sizeof(TAG_TYPE)];
  245. PWCHAR pwszIfFriendlyName = NULL;
  246. DWORD i;
  247. BOOL bPersistent = FALSE;
  248. FORMAT Format = FORMAT_NORMAL;
  249. TOKEN_VALUE rgtvLevelEnum[] = {{ TOKEN_VALUE_NORMAL, FORMAT_NORMAL },
  250. { TOKEN_VALUE_VERBOSE, FORMAT_VERBOSE }};
  251. TOKEN_VALUE rgtvStoreEnum[] = {{ TOKEN_VALUE_ACTIVE, FALSE },
  252. { TOKEN_VALUE_PERSISTENT, TRUE }};
  253. // Parse arguments
  254. dwErr = PreprocessCommand(g_hModule,
  255. ppwcArguments,
  256. dwCurrentIndex,
  257. dwArgCount,
  258. pttTags,
  259. sizeof(pttTags)/sizeof(TAG_TYPE),
  260. 0,
  261. sizeof(pttTags)/sizeof(TAG_TYPE),
  262. rgdwTagType );
  263. for (i=0; (dwErr == NO_ERROR) && (i<dwArgCount-dwCurrentIndex); i++) {
  264. switch(rgdwTagType[i]) {
  265. case 0: // INTERFACE
  266. pwszIfFriendlyName = ppwcArguments[i + dwCurrentIndex];
  267. Format = FORMAT_VERBOSE;
  268. break;
  269. case 1: // LEVEL
  270. dwErr = MatchEnumTag(NULL,
  271. ppwcArguments[dwCurrentIndex + i],
  272. NUM_TOKENS_IN_TABLE(rgtvLevelEnum),
  273. rgtvLevelEnum,
  274. (DWORD*)&Format);
  275. if (dwErr isnot NO_ERROR) {
  276. dwErr = ERROR_INVALID_PARAMETER;
  277. break;
  278. }
  279. break;
  280. case 2: // STORE
  281. dwErr = MatchEnumTag(NULL,
  282. ppwcArguments[dwCurrentIndex + i],
  283. NUM_TOKENS_IN_TABLE(rgtvStoreEnum),
  284. rgtvStoreEnum,
  285. &bPersistent);
  286. if (dwErr isnot NO_ERROR) {
  287. dwErr = ERROR_INVALID_PARAMETER;
  288. break;
  289. }
  290. break;
  291. default:
  292. dwErr = ERROR_INVALID_SYNTAX;
  293. break;
  294. }
  295. }
  296. if (dwErr isnot NO_ERROR) {
  297. return dwErr;
  298. }
  299. // Now do the work
  300. return QueryAddressTable(pwszIfFriendlyName, Format, bPersistent);
  301. }
  302. DWORD
  303. HandleShowJoins(
  304. IN LPCWSTR pwszMachine,
  305. IN OUT LPWSTR *ppwcArguments,
  306. IN DWORD dwCurrentIndex,
  307. IN DWORD dwArgCount,
  308. IN DWORD dwFlags,
  309. IN LPCVOID pvData,
  310. OUT BOOL *pbDone
  311. )
  312. {
  313. DWORD dwErr;
  314. TAG_TYPE pttTags[] = {{TOKEN_INTERFACE, FALSE, FALSE},
  315. {TOKEN_LEVEL, FALSE, FALSE}};
  316. DWORD rgdwTagType[sizeof(pttTags)/sizeof(TAG_TYPE)];
  317. PWCHAR pwszIfFriendlyName = NULL;
  318. DWORD i;
  319. FORMAT Format = FORMAT_NORMAL;
  320. TOKEN_VALUE rgtvLevelEnum[] = {{ TOKEN_VALUE_NORMAL, FORMAT_NORMAL },
  321. { TOKEN_VALUE_VERBOSE, FORMAT_VERBOSE }};
  322. // Parse arguments
  323. dwErr = PreprocessCommand(g_hModule,
  324. ppwcArguments,
  325. dwCurrentIndex,
  326. dwArgCount,
  327. pttTags,
  328. sizeof(pttTags)/sizeof(TAG_TYPE),
  329. 0,
  330. sizeof(pttTags)/sizeof(TAG_TYPE),
  331. rgdwTagType );
  332. for (i=0; (dwErr == NO_ERROR) && (i<dwArgCount-dwCurrentIndex); i++) {
  333. switch(rgdwTagType[i]) {
  334. case 0: // INTERFACE
  335. pwszIfFriendlyName = ppwcArguments[i + dwCurrentIndex];
  336. break;
  337. case 1: // LEVEL
  338. dwErr = MatchEnumTag(NULL,
  339. ppwcArguments[dwCurrentIndex + i],
  340. NUM_TOKENS_IN_TABLE(rgtvLevelEnum),
  341. rgtvLevelEnum,
  342. (DWORD*)&Format);
  343. if (dwErr isnot NO_ERROR) {
  344. dwErr = ERROR_INVALID_PARAMETER;
  345. break;
  346. }
  347. break;
  348. default:
  349. dwErr = ERROR_INVALID_SYNTAX;
  350. break;
  351. }
  352. }
  353. if (dwErr isnot NO_ERROR) {
  354. return dwErr;
  355. }
  356. // Now do the work
  357. return QueryMulticastAddressTable(pwszIfFriendlyName, Format);
  358. }
  359. /////////////////////////////////////////////////////////////////////////////
  360. // Commands related to mobility
  361. /////////////////////////////////////////////////////////////////////////////
  362. TOKEN_VALUE rgtvSecurityEnum[] = {
  363. { TOKEN_VALUE_ENABLED, TRUE },
  364. { TOKEN_VALUE_DISABLED, FALSE },
  365. };
  366. DWORD
  367. HandleSetMobility(
  368. IN LPCWSTR pwszMachine,
  369. IN OUT LPWSTR *ppwcArguments,
  370. IN DWORD dwCurrentIndex,
  371. IN DWORD dwArgCount,
  372. IN DWORD dwFlags,
  373. IN LPCVOID pvData,
  374. OUT BOOL *pbDone
  375. )
  376. {
  377. DWORD dwErr;
  378. TAG_TYPE pttTags[] = {{TOKEN_SECURITY, FALSE, FALSE},
  379. {TOKEN_BINDINGCACHELIMIT, FALSE, FALSE},
  380. {TOKEN_STORE, FALSE, FALSE}};
  381. DWORD rgdwTagType[sizeof(pttTags)/sizeof(TAG_TYPE)];
  382. TOKEN_VALUE rgtvStoreEnum[] = {{ TOKEN_VALUE_ACTIVE, FALSE },
  383. { TOKEN_VALUE_PERSISTENT, TRUE }};
  384. DWORD i, dwEnableSecurity = -1, dwBindingCacheLimit = -1;
  385. BOOL bPersistent = TRUE;
  386. // Parse arguments
  387. dwErr = PreprocessCommand(g_hModule,
  388. ppwcArguments,
  389. dwCurrentIndex,
  390. dwArgCount,
  391. pttTags,
  392. sizeof(pttTags)/sizeof(TAG_TYPE),
  393. 1,
  394. sizeof(pttTags)/sizeof(TAG_TYPE),
  395. rgdwTagType );
  396. for (i=0; (dwErr == NO_ERROR) && (i<dwArgCount-dwCurrentIndex); i++) {
  397. switch(rgdwTagType[i]) {
  398. case 0: // SECURITY
  399. dwErr = MatchEnumTag(NULL,
  400. ppwcArguments[dwCurrentIndex + i],
  401. NUM_TOKENS_IN_TABLE(rgtvSecurityEnum),
  402. rgtvSecurityEnum,
  403. &dwEnableSecurity);
  404. if (dwErr isnot NO_ERROR) {
  405. dwErr = ERROR_INVALID_PARAMETER;
  406. break;
  407. }
  408. break;
  409. case 1: // BINDINGCACHELIMIT
  410. dwBindingCacheLimit = wcstoul(ppwcArguments[dwCurrentIndex + i],
  411. NULL, 10);
  412. break;
  413. case 2: // STORE
  414. dwErr = MatchEnumTag(NULL,
  415. ppwcArguments[dwCurrentIndex + i],
  416. NUM_TOKENS_IN_TABLE(rgtvStoreEnum),
  417. rgtvStoreEnum,
  418. &bPersistent);
  419. if (dwErr isnot NO_ERROR) {
  420. dwErr = ERROR_INVALID_PARAMETER;
  421. break;
  422. }
  423. break;
  424. default:
  425. dwErr = ERROR_INVALID_SYNTAX;
  426. break;
  427. }
  428. }
  429. if (dwErr isnot NO_ERROR) {
  430. return dwErr;
  431. }
  432. // Now do the work
  433. return UpdateMobilityParameters(dwEnableSecurity, dwBindingCacheLimit,
  434. bPersistent);
  435. }
  436. DWORD
  437. HandleShowMobility(
  438. IN LPCWSTR pwszMachine,
  439. IN OUT LPWSTR *ppwcArguments,
  440. IN DWORD dwCurrentIndex,
  441. IN DWORD dwArgCount,
  442. IN DWORD dwFlags,
  443. IN LPCVOID pvData,
  444. OUT BOOL *pbDone
  445. )
  446. {
  447. DWORD dwErr;
  448. TAG_TYPE pttTags[] = {{TOKEN_STORE, FALSE, FALSE}};
  449. DWORD rgdwTagType[sizeof(pttTags)/sizeof(TAG_TYPE)];
  450. DWORD i;
  451. BOOL bPersistent = FALSE;
  452. TOKEN_VALUE rgtvStoreEnum[] = {{ TOKEN_VALUE_ACTIVE, FALSE },
  453. { TOKEN_VALUE_PERSISTENT, TRUE }};
  454. // Parse arguments
  455. dwErr = PreprocessCommand(g_hModule,
  456. ppwcArguments,
  457. dwCurrentIndex,
  458. dwArgCount,
  459. pttTags,
  460. sizeof(pttTags)/sizeof(TAG_TYPE),
  461. 0,
  462. sizeof(pttTags)/sizeof(TAG_TYPE),
  463. rgdwTagType );
  464. for (i=0; (dwErr == NO_ERROR) && (i<dwArgCount-dwCurrentIndex); i++) {
  465. switch(rgdwTagType[i]) {
  466. case 0: // STORE
  467. dwErr = MatchEnumTag(NULL,
  468. ppwcArguments[dwCurrentIndex + i],
  469. NUM_TOKENS_IN_TABLE(rgtvStoreEnum),
  470. rgtvStoreEnum,
  471. &bPersistent);
  472. if (dwErr isnot NO_ERROR) {
  473. dwErr = ERROR_INVALID_PARAMETER;
  474. break;
  475. }
  476. break;
  477. default:
  478. dwErr = ERROR_INVALID_SYNTAX;
  479. break;
  480. }
  481. }
  482. if (dwErr isnot NO_ERROR) {
  483. return dwErr;
  484. }
  485. // Now do the work
  486. return QueryMobilityParameters(FORMAT_NORMAL, bPersistent);
  487. }
  488. DWORD
  489. HandleShowBindingCacheEntries(
  490. IN LPCWSTR pwszMachine,
  491. IN OUT LPWSTR *ppwcArguments,
  492. IN DWORD dwCurrentIndex,
  493. IN DWORD dwArgCount,
  494. IN DWORD dwFlags,
  495. IN LPCVOID pvData,
  496. OUT BOOL *pbDone
  497. )
  498. {
  499. return QueryBindingCache();
  500. }
  501. /////////////////////////////////////////////////////////////////////////////
  502. // Commands related to other global parameters
  503. /////////////////////////////////////////////////////////////////////////////
  504. DWORD
  505. HandleSetGlobal(
  506. IN LPCWSTR pwszMachine,
  507. IN OUT LPWSTR *ppwcArguments,
  508. IN DWORD dwCurrentIndex,
  509. IN DWORD dwArgCount,
  510. IN DWORD dwFlags,
  511. IN LPCVOID pvData,
  512. OUT BOOL *pbDone
  513. )
  514. {
  515. DWORD dwErr, i;
  516. TAG_TYPE pttTags[] = {{TOKEN_DEFAULTCURHOPLIMIT, FALSE, FALSE},
  517. {TOKEN_NEIGHBORCACHELIMIT, FALSE, FALSE},
  518. {TOKEN_DESTINATIONCACHELIMIT, FALSE, FALSE},
  519. {TOKEN_REASSEMBLYLIMIT, FALSE, FALSE},
  520. {TOKEN_STORE, FALSE, FALSE}};
  521. DWORD rgdwTagType[sizeof(pttTags)/sizeof(TAG_TYPE)];
  522. TOKEN_VALUE rgtvStoreEnum[] = {{ TOKEN_VALUE_ACTIVE, FALSE },
  523. { TOKEN_VALUE_PERSISTENT, TRUE }};
  524. DWORD dwDefaultCurHopLimit = -1;
  525. DWORD dwNeighborCacheLimit = -1;
  526. DWORD dwRouteCacheLimit = -1;
  527. DWORD dwReassemblyLimit = -1;
  528. BOOL bPersistent = TRUE;
  529. // Parse arguments
  530. dwErr = PreprocessCommand(g_hModule,
  531. ppwcArguments,
  532. dwCurrentIndex,
  533. dwArgCount,
  534. pttTags,
  535. sizeof(pttTags)/sizeof(TAG_TYPE),
  536. 1,
  537. sizeof(pttTags)/sizeof(TAG_TYPE),
  538. rgdwTagType );
  539. for (i=0; (dwErr == NO_ERROR) && (i<dwArgCount-dwCurrentIndex); i++) {
  540. switch(rgdwTagType[i]) {
  541. case 0: // DEFAULTCURHOPLIMIT
  542. dwDefaultCurHopLimit = wcstoul(ppwcArguments[dwCurrentIndex + i],
  543. NULL, 10);
  544. break;
  545. case 1: // NEIGHBORCACHELIMIT
  546. dwNeighborCacheLimit = wcstoul(ppwcArguments[dwCurrentIndex + i],
  547. NULL, 10);
  548. break;
  549. case 2: // DESTINATIONCACHELIMIT
  550. dwRouteCacheLimit = wcstoul(ppwcArguments[dwCurrentIndex + i],
  551. NULL, 10);
  552. break;
  553. case 3: // REASSEMBLYLIMIT
  554. dwReassemblyLimit = wcstoul(ppwcArguments[dwCurrentIndex + i],
  555. NULL, 10);
  556. break;
  557. case 4: // STORE
  558. dwErr = MatchEnumTag(NULL,
  559. ppwcArguments[dwCurrentIndex + i],
  560. NUM_TOKENS_IN_TABLE(rgtvStoreEnum),
  561. rgtvStoreEnum,
  562. &bPersistent);
  563. if (dwErr isnot NO_ERROR) {
  564. dwErr = ERROR_INVALID_PARAMETER;
  565. break;
  566. }
  567. break;
  568. default:
  569. dwErr = ERROR_INVALID_SYNTAX;
  570. break;
  571. }
  572. }
  573. if (dwErr isnot NO_ERROR) {
  574. return dwErr;
  575. }
  576. // Now do the work
  577. return UpdateGlobalParameters(dwDefaultCurHopLimit, dwNeighborCacheLimit,
  578. dwRouteCacheLimit, dwReassemblyLimit,
  579. bPersistent);
  580. }
  581. DWORD
  582. HandleShowGlobal(
  583. IN LPCWSTR pwszMachine,
  584. IN OUT LPWSTR *ppwcArguments,
  585. IN DWORD dwCurrentIndex,
  586. IN DWORD dwArgCount,
  587. IN DWORD dwFlags,
  588. IN LPCVOID pvData,
  589. OUT BOOL *pbDone
  590. )
  591. {
  592. DWORD dwErr;
  593. TAG_TYPE pttTags[] = {{TOKEN_STORE, FALSE, FALSE}};
  594. DWORD rgdwTagType[sizeof(pttTags)/sizeof(TAG_TYPE)];
  595. DWORD i;
  596. BOOL bPersistent = FALSE;
  597. TOKEN_VALUE rgtvStoreEnum[] = {{ TOKEN_VALUE_ACTIVE, FALSE },
  598. { TOKEN_VALUE_PERSISTENT, TRUE }};
  599. // Parse arguments
  600. dwErr = PreprocessCommand(g_hModule,
  601. ppwcArguments,
  602. dwCurrentIndex,
  603. dwArgCount,
  604. pttTags,
  605. sizeof(pttTags)/sizeof(TAG_TYPE),
  606. 0,
  607. sizeof(pttTags)/sizeof(TAG_TYPE),
  608. rgdwTagType );
  609. for (i=0; (dwErr == NO_ERROR) && (i<dwArgCount-dwCurrentIndex); i++) {
  610. switch(rgdwTagType[i]) {
  611. case 0: // STORE
  612. dwErr = MatchEnumTag(NULL,
  613. ppwcArguments[dwCurrentIndex + i],
  614. NUM_TOKENS_IN_TABLE(rgtvStoreEnum),
  615. rgtvStoreEnum,
  616. &bPersistent);
  617. if (dwErr isnot NO_ERROR) {
  618. dwErr = ERROR_INVALID_PARAMETER;
  619. break;
  620. }
  621. break;
  622. default:
  623. dwErr = ERROR_INVALID_SYNTAX;
  624. break;
  625. }
  626. }
  627. if (dwErr isnot NO_ERROR) {
  628. return dwErr;
  629. }
  630. // Now do the work
  631. return QueryGlobalParameters(FORMAT_NORMAL, bPersistent);
  632. }
  633. DWORD
  634. HandleSetPrivacy(
  635. IN LPCWSTR pwszMachine,
  636. IN OUT LPWSTR *ppwcArguments,
  637. IN DWORD dwCurrentIndex,
  638. IN DWORD dwArgCount,
  639. IN DWORD dwFlags,
  640. IN LPCVOID pvData,
  641. OUT BOOL *pbDone
  642. )
  643. {
  644. DWORD dwErr, i;
  645. TAG_TYPE pttTags[] = {{TOKEN_STATE, FALSE, FALSE},
  646. {TOKEN_MAXDADATTEMPTS, FALSE, FALSE},
  647. {TOKEN_MAXVALIDLIFETIME, FALSE, FALSE},
  648. {TOKEN_MAXPREFERREDLIFETIME, FALSE, FALSE},
  649. {TOKEN_REGENERATETIME, FALSE, FALSE},
  650. {TOKEN_MAXRANDOMTIME, FALSE, FALSE},
  651. {TOKEN_RANDOMTIME, FALSE, FALSE},
  652. {TOKEN_STORE, FALSE, FALSE}};
  653. DWORD rgdwTagType[sizeof(pttTags)/sizeof(TAG_TYPE)];
  654. TOKEN_VALUE rgtvStateEnum[] = {{ TOKEN_VALUE_DISABLED, USE_ANON_NO },
  655. { TOKEN_VALUE_ENABLED, USE_ANON_YES }};
  656. TOKEN_VALUE rgtvStoreEnum[] = {{ TOKEN_VALUE_ACTIVE, FALSE },
  657. { TOKEN_VALUE_PERSISTENT, TRUE }};
  658. DWORD dwState = -1;
  659. DWORD dwMaxDadAttempts = -1;
  660. DWORD dwMaxValidLifetime = -1;
  661. DWORD dwMaxPrefLifetime = -1;
  662. DWORD dwRegenerateTime = -1;
  663. DWORD dwMaxRandomTime = -1;
  664. DWORD dwRandomTime = -1;
  665. BOOL bPersistent = TRUE;
  666. // Parse arguments
  667. dwErr = PreprocessCommand(g_hModule,
  668. ppwcArguments,
  669. dwCurrentIndex,
  670. dwArgCount,
  671. pttTags,
  672. sizeof(pttTags)/sizeof(TAG_TYPE),
  673. 1,
  674. sizeof(pttTags)/sizeof(TAG_TYPE),
  675. rgdwTagType );
  676. for (i=0; (dwErr == NO_ERROR) && (i<dwArgCount-dwCurrentIndex); i++) {
  677. switch(rgdwTagType[i]) {
  678. case 0: // STATE
  679. dwErr = MatchEnumTag(NULL,
  680. ppwcArguments[dwCurrentIndex + i],
  681. NUM_TOKENS_IN_TABLE(rgtvStateEnum),
  682. rgtvStateEnum,
  683. &dwState);
  684. if (dwErr isnot NO_ERROR) {
  685. dwErr = ERROR_INVALID_PARAMETER;
  686. break;
  687. }
  688. break;
  689. case 1: // MAXDADATTEMPTS
  690. dwMaxDadAttempts = wcstoul(ppwcArguments[dwCurrentIndex + i],
  691. NULL, 10);
  692. break;
  693. case 2: // MAXVALIDLIFETIME
  694. dwMaxValidLifetime =
  695. GetTime(ppwcArguments[dwCurrentIndex + i]);
  696. break;
  697. case 3: // MAXPREFLIFETIME
  698. dwMaxPrefLifetime =
  699. GetTime(ppwcArguments[dwCurrentIndex + i]);
  700. break;
  701. case 4: // REGENERATETIME
  702. dwRegenerateTime =
  703. GetTime(ppwcArguments[dwCurrentIndex + i]);
  704. break;
  705. case 5: // MAXRANDOMTIME
  706. dwMaxRandomTime =
  707. GetTime(ppwcArguments[dwCurrentIndex + i]);
  708. break;
  709. case 6: // RANDOMTIME
  710. dwRandomTime =
  711. GetTime(ppwcArguments[dwCurrentIndex + i]);
  712. break;
  713. case 7: // STORE
  714. dwErr = MatchEnumTag(NULL,
  715. ppwcArguments[dwCurrentIndex + i],
  716. NUM_TOKENS_IN_TABLE(rgtvStoreEnum),
  717. rgtvStoreEnum,
  718. &bPersistent);
  719. if (dwErr isnot NO_ERROR) {
  720. dwErr = ERROR_INVALID_PARAMETER;
  721. break;
  722. }
  723. break;
  724. default:
  725. dwErr = ERROR_INVALID_SYNTAX;
  726. break;
  727. }
  728. }
  729. if (dwErr isnot NO_ERROR) {
  730. return dwErr;
  731. }
  732. // Now do the work
  733. return UpdatePrivacyParameters(dwState, dwMaxDadAttempts,
  734. dwMaxValidLifetime, dwMaxPrefLifetime,
  735. dwRegenerateTime, dwMaxRandomTime,
  736. dwRandomTime, bPersistent);
  737. }
  738. DWORD
  739. HandleShowPrivacy(
  740. IN LPCWSTR pwszMachine,
  741. IN OUT LPWSTR *ppwcArguments,
  742. IN DWORD dwCurrentIndex,
  743. IN DWORD dwArgCount,
  744. IN DWORD dwFlags,
  745. IN LPCVOID pvData,
  746. OUT BOOL *pbDone
  747. )
  748. {
  749. DWORD dwErr;
  750. TAG_TYPE pttTags[] = {{TOKEN_STORE, FALSE, FALSE}};
  751. DWORD rgdwTagType[sizeof(pttTags)/sizeof(TAG_TYPE)];
  752. DWORD i;
  753. BOOL bPersistent = FALSE;
  754. TOKEN_VALUE rgtvStoreEnum[] = {{ TOKEN_VALUE_ACTIVE, FALSE },
  755. { TOKEN_VALUE_PERSISTENT, TRUE }};
  756. // Parse arguments
  757. dwErr = PreprocessCommand(g_hModule,
  758. ppwcArguments,
  759. dwCurrentIndex,
  760. dwArgCount,
  761. pttTags,
  762. sizeof(pttTags)/sizeof(TAG_TYPE),
  763. 0,
  764. sizeof(pttTags)/sizeof(TAG_TYPE),
  765. rgdwTagType );
  766. for (i=0; (dwErr == NO_ERROR) && (i<dwArgCount-dwCurrentIndex); i++) {
  767. switch(rgdwTagType[i]) {
  768. case 0: // STORE
  769. dwErr = MatchEnumTag(NULL,
  770. ppwcArguments[dwCurrentIndex + i],
  771. NUM_TOKENS_IN_TABLE(rgtvStoreEnum),
  772. rgtvStoreEnum,
  773. &bPersistent);
  774. if (dwErr isnot NO_ERROR) {
  775. dwErr = ERROR_INVALID_PARAMETER;
  776. break;
  777. }
  778. break;
  779. default:
  780. dwErr = ERROR_INVALID_SYNTAX;
  781. break;
  782. }
  783. }
  784. if (dwErr isnot NO_ERROR) {
  785. return dwErr;
  786. }
  787. // Now do the work
  788. return QueryPrivacyParameters(FORMAT_NORMAL, bPersistent);
  789. }
  790. /////////////////////////////////////////////////////////////////////////////
  791. // Commands related to interfaces
  792. /////////////////////////////////////////////////////////////////////////////
  793. DWORD
  794. HandleAddV6V4Tunnel(
  795. IN LPCWSTR pwszMachine,
  796. IN OUT LPWSTR *ppwcArguments,
  797. IN DWORD dwCurrentIndex,
  798. IN DWORD dwArgCount,
  799. IN DWORD dwFlags,
  800. IN LPCVOID pvData,
  801. OUT BOOL *pbDone
  802. )
  803. {
  804. DWORD dwErr;
  805. TAG_TYPE pttTags[] = {{TOKEN_INTERFACE, TRUE, FALSE},
  806. {TOKEN_LOCALADDRESS, TRUE, FALSE},
  807. {TOKEN_REMOTEADDRESS, TRUE, FALSE},
  808. {TOKEN_NEIGHBORDISCOVERY, FALSE, FALSE},
  809. {TOKEN_STORE, FALSE, FALSE}};
  810. DWORD rgdwTagType[sizeof(pttTags)/sizeof(TAG_TYPE)];
  811. DWORD i, dwNeighborDiscovery = FALSE;
  812. IN_ADDR ipLocalAddr, ipRemoteAddr;
  813. PWCHAR pwszFriendlyName;
  814. TOKEN_VALUE rgtvNDEnum[] = {{ TOKEN_VALUE_DISABLED, FALSE },
  815. { TOKEN_VALUE_ENABLED, TRUE }};
  816. TOKEN_VALUE rgtvStoreEnum[] = {{ TOKEN_VALUE_ACTIVE, FALSE },
  817. { TOKEN_VALUE_PERSISTENT, TRUE }};
  818. BOOL bPersistent = TRUE;
  819. // Parse arguments
  820. dwErr = PreprocessCommand(g_hModule,
  821. ppwcArguments,
  822. dwCurrentIndex,
  823. dwArgCount,
  824. pttTags,
  825. sizeof(pttTags)/sizeof(TAG_TYPE),
  826. 0,
  827. sizeof(pttTags)/sizeof(TAG_TYPE),
  828. rgdwTagType );
  829. for (i=0; (dwErr == NO_ERROR) && (i<dwArgCount-dwCurrentIndex); i++) {
  830. switch(rgdwTagType[i]) {
  831. case 0: // INTERFACE
  832. pwszFriendlyName = ppwcArguments[i + dwCurrentIndex];
  833. break;
  834. case 1: // LOCALADDRESS
  835. dwErr = GetIpv4Address(ppwcArguments[i + dwCurrentIndex],
  836. &ipLocalAddr);
  837. break;
  838. case 2: // REMOTEADDRESS
  839. dwErr = GetIpv4Address(ppwcArguments[i + dwCurrentIndex],
  840. &ipRemoteAddr);
  841. break;
  842. case 3: // NEIGHBORDISCOVERY
  843. dwErr = MatchEnumTag(NULL,
  844. ppwcArguments[dwCurrentIndex + i],
  845. NUM_TOKENS_IN_TABLE(rgtvNDEnum),
  846. rgtvNDEnum,
  847. &dwNeighborDiscovery);
  848. if (dwErr isnot NO_ERROR) {
  849. dwErr = ERROR_INVALID_PARAMETER;
  850. break;
  851. }
  852. break;
  853. case 4: // STORE
  854. dwErr = MatchEnumTag(NULL,
  855. ppwcArguments[dwCurrentIndex + i],
  856. NUM_TOKENS_IN_TABLE(rgtvStoreEnum),
  857. rgtvStoreEnum,
  858. &bPersistent);
  859. if (dwErr isnot NO_ERROR) {
  860. dwErr = ERROR_INVALID_PARAMETER;
  861. break;
  862. }
  863. break;
  864. default:
  865. dwErr = ERROR_INVALID_SYNTAX;
  866. break;
  867. }
  868. }
  869. if (dwErr isnot NO_ERROR) {
  870. return dwErr;
  871. }
  872. // Now do the work
  873. dwErr = AddTunnelInterface(pwszFriendlyName, &ipLocalAddr, &ipRemoteAddr,
  874. IPV6_IF_TYPE_TUNNEL_V6V4, dwNeighborDiscovery,
  875. bPersistent);
  876. if (dwErr == ERROR_INVALID_HANDLE) {
  877. DisplayMessage(g_hModule, EMSG_INVALID_ADDRESS);
  878. dwErr = ERROR_SUPPRESS_OUTPUT;
  879. }
  880. return dwErr;
  881. }
  882. DWORD
  883. HandleAdd6over4Tunnel(
  884. IN LPCWSTR pwszMachine,
  885. IN OUT LPWSTR *ppwcArguments,
  886. IN DWORD dwCurrentIndex,
  887. IN DWORD dwArgCount,
  888. IN DWORD dwFlags,
  889. IN LPCVOID pvData,
  890. OUT BOOL *pbDone
  891. )
  892. {
  893. DWORD dwErr;
  894. TAG_TYPE pttTags[] = {{TOKEN_INTERFACE, TRUE, FALSE},
  895. {TOKEN_LOCALADDRESS, TRUE, FALSE},
  896. {TOKEN_STORE, FALSE, FALSE}};
  897. DWORD rgdwTagType[sizeof(pttTags)/sizeof(TAG_TYPE)];
  898. TOKEN_VALUE rgtvStoreEnum[] = {{ TOKEN_VALUE_ACTIVE, FALSE },
  899. { TOKEN_VALUE_PERSISTENT, TRUE }};
  900. DWORD i, dwEnableSecurity;
  901. PWCHAR pwszFriendlyName;
  902. IN_ADDR ipLocalAddr;
  903. BOOL bPersistent = TRUE;
  904. // Parse arguments
  905. dwErr = PreprocessCommand(g_hModule,
  906. ppwcArguments,
  907. dwCurrentIndex,
  908. dwArgCount,
  909. pttTags,
  910. sizeof(pttTags)/sizeof(TAG_TYPE),
  911. 0,
  912. sizeof(pttTags)/sizeof(TAG_TYPE),
  913. rgdwTagType );
  914. for (i=0; (dwErr == NO_ERROR) && (i<dwArgCount-dwCurrentIndex); i++) {
  915. switch(rgdwTagType[i]) {
  916. case 0: // INTERFACE
  917. pwszFriendlyName = ppwcArguments[i + dwCurrentIndex];
  918. break;
  919. case 1: // LOCALADDRESS
  920. dwErr = GetIpv4Address(ppwcArguments[i + dwCurrentIndex],
  921. &ipLocalAddr);
  922. break;
  923. case 2: // STORE
  924. dwErr = MatchEnumTag(NULL,
  925. ppwcArguments[dwCurrentIndex + i],
  926. NUM_TOKENS_IN_TABLE(rgtvStoreEnum),
  927. rgtvStoreEnum,
  928. &bPersistent);
  929. if (dwErr isnot NO_ERROR) {
  930. dwErr = ERROR_INVALID_PARAMETER;
  931. break;
  932. }
  933. break;
  934. default:
  935. dwErr = ERROR_INVALID_SYNTAX;
  936. break;
  937. }
  938. }
  939. if (dwErr isnot NO_ERROR) {
  940. return dwErr;
  941. }
  942. // Now do the work
  943. dwErr = AddTunnelInterface(pwszFriendlyName, &ipLocalAddr, NULL,
  944. IPV6_IF_TYPE_TUNNEL_6OVER4,
  945. TRUE,
  946. bPersistent);
  947. if (dwErr == ERROR_INVALID_HANDLE) {
  948. DisplayMessage(g_hModule, EMSG_INVALID_ADDRESS);
  949. dwErr = ERROR_SUPPRESS_OUTPUT;
  950. }
  951. return dwErr;
  952. }
  953. DWORD
  954. HandleSetInterface(
  955. IN LPCWSTR pwszMachine,
  956. IN OUT LPWSTR *ppwcArguments,
  957. IN DWORD dwCurrentIndex,
  958. IN DWORD dwArgCount,
  959. IN DWORD dwFlags,
  960. IN LPCVOID pvData,
  961. OUT BOOL *pbDone
  962. )
  963. {
  964. DWORD dwErr;
  965. TAG_TYPE pttTags[] = {{TOKEN_INTERFACE, TRUE, FALSE},
  966. {TOKEN_FORWARDING, FALSE, FALSE},
  967. {TOKEN_ADVERTISE, FALSE, FALSE},
  968. {TOKEN_MTU, FALSE, FALSE},
  969. {TOKEN_SITEID, FALSE, FALSE},
  970. {TOKEN_METRIC, FALSE, FALSE},
  971. {TOKEN_STORE, FALSE, FALSE}};
  972. DWORD rgdwTagType[sizeof(pttTags)/sizeof(TAG_TYPE)];
  973. TOKEN_VALUE rgtvEnum[] = {{ TOKEN_VALUE_DISABLED, FALSE },
  974. { TOKEN_VALUE_ENABLED, TRUE }};
  975. TOKEN_VALUE rgtvStoreEnum[] = {{ TOKEN_VALUE_ACTIVE, FALSE },
  976. { TOKEN_VALUE_PERSISTENT, TRUE }};
  977. PWCHAR pwszIfFriendlyName = NULL;
  978. DWORD i, dwMtu = 0, dwSiteId = 0, dwMetric = -1;
  979. DWORD dwAdvertise = -1, dwForwarding = -1;
  980. BOOL bPersistent = TRUE;
  981. // Parse arguments
  982. dwErr = PreprocessCommand(g_hModule,
  983. ppwcArguments,
  984. dwCurrentIndex,
  985. dwArgCount,
  986. pttTags,
  987. sizeof(pttTags)/sizeof(TAG_TYPE),
  988. 0,
  989. sizeof(pttTags)/sizeof(TAG_TYPE),
  990. rgdwTagType );
  991. for (i=0; (dwErr == NO_ERROR) && (i<dwArgCount-dwCurrentIndex); i++) {
  992. switch(rgdwTagType[i]) {
  993. case 0: // INTERFACE
  994. pwszIfFriendlyName = ppwcArguments[i + dwCurrentIndex];
  995. break;
  996. case 1: // FORWARDING
  997. dwErr = MatchEnumTag(NULL,
  998. ppwcArguments[dwCurrentIndex + i],
  999. NUM_TOKENS_IN_TABLE(rgtvEnum),
  1000. rgtvEnum,
  1001. &dwForwarding);
  1002. if (dwErr isnot NO_ERROR) {
  1003. dwErr = ERROR_INVALID_PARAMETER;
  1004. break;
  1005. }
  1006. break;
  1007. case 2: // ADVERTISE
  1008. dwErr = MatchEnumTag(NULL,
  1009. ppwcArguments[dwCurrentIndex + i],
  1010. NUM_TOKENS_IN_TABLE(rgtvEnum),
  1011. rgtvEnum,
  1012. &dwAdvertise);
  1013. if (dwErr isnot NO_ERROR) {
  1014. dwErr = ERROR_INVALID_PARAMETER;
  1015. break;
  1016. }
  1017. break;
  1018. case 3: // MTU
  1019. dwMtu = wcstoul(ppwcArguments[dwCurrentIndex + i], NULL, 10);
  1020. break;
  1021. case 4: // SITEID
  1022. dwSiteId = wcstoul(ppwcArguments[dwCurrentIndex + i], NULL, 10);
  1023. break;
  1024. case 5: // METRIC
  1025. dwMetric = wcstoul(ppwcArguments[dwCurrentIndex + i], NULL, 10);
  1026. break;
  1027. case 6: // STORE
  1028. dwErr = MatchEnumTag(NULL,
  1029. ppwcArguments[dwCurrentIndex + i],
  1030. NUM_TOKENS_IN_TABLE(rgtvStoreEnum),
  1031. rgtvStoreEnum,
  1032. &bPersistent);
  1033. if (dwErr isnot NO_ERROR) {
  1034. dwErr = ERROR_INVALID_PARAMETER;
  1035. break;
  1036. }
  1037. break;
  1038. default:
  1039. dwErr = ERROR_INVALID_SYNTAX;
  1040. break;
  1041. }
  1042. }
  1043. if (dwErr isnot NO_ERROR) {
  1044. return dwErr;
  1045. }
  1046. // Now do the work
  1047. return UpdateInterface(pwszIfFriendlyName, dwForwarding, dwAdvertise,
  1048. dwMtu, dwSiteId, dwMetric, bPersistent);
  1049. }
  1050. DWORD
  1051. HandleDelInterface(
  1052. IN LPCWSTR pwszMachine,
  1053. IN OUT LPWSTR *ppwcArguments,
  1054. IN DWORD dwCurrentIndex,
  1055. IN DWORD dwArgCount,
  1056. IN DWORD dwFlags,
  1057. IN LPCVOID pvData,
  1058. OUT BOOL *pbDone
  1059. )
  1060. {
  1061. DWORD dwErr;
  1062. TAG_TYPE pttTags[] = {{TOKEN_INTERFACE, TRUE, FALSE},
  1063. {TOKEN_STORE, FALSE, FALSE}};
  1064. DWORD rgdwTagType[sizeof(pttTags)/sizeof(TAG_TYPE)];
  1065. PWCHAR pwszIfFriendlyName = NULL;
  1066. TOKEN_VALUE rgtvStoreEnum[] = {{ TOKEN_VALUE_ACTIVE, FALSE },
  1067. { TOKEN_VALUE_PERSISTENT, TRUE }};
  1068. DWORD i;
  1069. BOOL bPersistent = TRUE;
  1070. // Parse arguments
  1071. dwErr = PreprocessCommand(g_hModule,
  1072. ppwcArguments,
  1073. dwCurrentIndex,
  1074. dwArgCount,
  1075. pttTags,
  1076. sizeof(pttTags)/sizeof(TAG_TYPE),
  1077. 0,
  1078. sizeof(pttTags)/sizeof(TAG_TYPE),
  1079. rgdwTagType );
  1080. for (i=0; (dwErr == NO_ERROR) && (i<dwArgCount-dwCurrentIndex); i++) {
  1081. switch(rgdwTagType[i]) {
  1082. case 0: // INTERFACE
  1083. pwszIfFriendlyName = ppwcArguments[i + dwCurrentIndex];
  1084. break;
  1085. case 1: // STORE
  1086. dwErr = MatchEnumTag(NULL,
  1087. ppwcArguments[dwCurrentIndex + i],
  1088. NUM_TOKENS_IN_TABLE(rgtvStoreEnum),
  1089. rgtvStoreEnum,
  1090. &bPersistent);
  1091. if (dwErr isnot NO_ERROR) {
  1092. dwErr = ERROR_INVALID_PARAMETER;
  1093. break;
  1094. }
  1095. break;
  1096. default:
  1097. dwErr = ERROR_INVALID_SYNTAX;
  1098. break;
  1099. }
  1100. }
  1101. if (dwErr isnot NO_ERROR) {
  1102. return dwErr;
  1103. }
  1104. // Now do the work
  1105. return DeleteInterface(pwszIfFriendlyName, bPersistent);
  1106. }
  1107. DWORD
  1108. HandleShowInterface(
  1109. IN LPCWSTR pwszMachine,
  1110. IN OUT LPWSTR *ppwcArguments,
  1111. IN DWORD dwCurrentIndex,
  1112. IN DWORD dwArgCount,
  1113. IN DWORD dwFlags,
  1114. IN LPCVOID pvData,
  1115. OUT BOOL *pbDone
  1116. )
  1117. {
  1118. DWORD dwErr;
  1119. TAG_TYPE pttTags[] = {{TOKEN_INTERFACE, FALSE, FALSE},
  1120. {TOKEN_LEVEL, FALSE, FALSE},
  1121. {TOKEN_STORE, FALSE, FALSE}};
  1122. DWORD rgdwTagType[sizeof(pttTags)/sizeof(TAG_TYPE)];
  1123. PWCHAR pwszIfFriendlyName = NULL;
  1124. DWORD i;
  1125. FORMAT Format = FORMAT_NORMAL;
  1126. TOKEN_VALUE rgtvLevelEnum[] = {{ TOKEN_VALUE_NORMAL, FORMAT_NORMAL },
  1127. { TOKEN_VALUE_VERBOSE, FORMAT_VERBOSE }};
  1128. TOKEN_VALUE rgtvStoreEnum[] = {{ TOKEN_VALUE_ACTIVE, FALSE },
  1129. { TOKEN_VALUE_PERSISTENT, TRUE }};
  1130. BOOL bPersistent = FALSE;
  1131. // Parse arguments
  1132. dwErr = PreprocessCommand(g_hModule,
  1133. ppwcArguments,
  1134. dwCurrentIndex,
  1135. dwArgCount,
  1136. pttTags,
  1137. sizeof(pttTags)/sizeof(TAG_TYPE),
  1138. 0,
  1139. sizeof(pttTags)/sizeof(TAG_TYPE),
  1140. rgdwTagType );
  1141. for (i=0; (dwErr == NO_ERROR) && (i<dwArgCount-dwCurrentIndex); i++) {
  1142. switch(rgdwTagType[i]) {
  1143. case 0: // INTERFACE
  1144. pwszIfFriendlyName = ppwcArguments[i + dwCurrentIndex];
  1145. Format = FORMAT_VERBOSE;
  1146. break;
  1147. case 1: // LEVEL
  1148. dwErr = MatchEnumTag(NULL,
  1149. ppwcArguments[dwCurrentIndex + i],
  1150. NUM_TOKENS_IN_TABLE(rgtvLevelEnum),
  1151. rgtvLevelEnum,
  1152. (DWORD*)&Format);
  1153. if (dwErr isnot NO_ERROR) {
  1154. dwErr = ERROR_INVALID_PARAMETER;
  1155. break;
  1156. }
  1157. break;
  1158. case 2: // STORE
  1159. dwErr = MatchEnumTag(NULL,
  1160. ppwcArguments[dwCurrentIndex + i],
  1161. NUM_TOKENS_IN_TABLE(rgtvStoreEnum),
  1162. rgtvStoreEnum,
  1163. &bPersistent);
  1164. if (dwErr isnot NO_ERROR) {
  1165. dwErr = ERROR_INVALID_PARAMETER;
  1166. break;
  1167. }
  1168. break;
  1169. default:
  1170. dwErr = ERROR_INVALID_SYNTAX;
  1171. break;
  1172. }
  1173. }
  1174. if (dwErr isnot NO_ERROR) {
  1175. return dwErr;
  1176. }
  1177. // Now do the work
  1178. return QueryInterface(pwszIfFriendlyName, Format, bPersistent);
  1179. }
  1180. DWORD
  1181. HandleRenew(
  1182. IN LPCWSTR pwszMachine,
  1183. IN OUT LPWSTR *ppwcArguments,
  1184. IN DWORD dwCurrentIndex,
  1185. IN DWORD dwArgCount,
  1186. IN DWORD dwFlags,
  1187. IN LPCVOID pvData,
  1188. OUT BOOL *pbDone
  1189. )
  1190. {
  1191. DWORD dwErr;
  1192. TAG_TYPE pttTags[] = {{TOKEN_INTERFACE, FALSE, FALSE}};
  1193. DWORD rgdwTagType[sizeof(pttTags)/sizeof(TAG_TYPE)];
  1194. PWCHAR pwszIfFriendlyName = NULL;
  1195. DWORD i;
  1196. // Parse arguments
  1197. dwErr = PreprocessCommand(g_hModule,
  1198. ppwcArguments,
  1199. dwCurrentIndex,
  1200. dwArgCount,
  1201. pttTags,
  1202. sizeof(pttTags)/sizeof(TAG_TYPE),
  1203. 0,
  1204. sizeof(pttTags)/sizeof(TAG_TYPE),
  1205. rgdwTagType );
  1206. for (i=0; (dwErr == NO_ERROR) && (i<dwArgCount-dwCurrentIndex); i++) {
  1207. switch(rgdwTagType[i]) {
  1208. case 0: // INTERFACE
  1209. pwszIfFriendlyName = ppwcArguments[i + dwCurrentIndex];
  1210. break;
  1211. default:
  1212. dwErr = ERROR_INVALID_SYNTAX;
  1213. break;
  1214. }
  1215. }
  1216. if (dwErr isnot NO_ERROR) {
  1217. return dwErr;
  1218. }
  1219. // Now do the work
  1220. return RenewInterface(pwszIfFriendlyName);
  1221. }
  1222. /////////////////////////////////////////////////////////////////////////////
  1223. // Commands related to the neighbor cache
  1224. /////////////////////////////////////////////////////////////////////////////
  1225. DWORD
  1226. HandleDelNeighbors(
  1227. IN LPCWSTR pwszMachine,
  1228. IN OUT LPWSTR *ppwcArguments,
  1229. IN DWORD dwCurrentIndex,
  1230. IN DWORD dwArgCount,
  1231. IN DWORD dwFlags,
  1232. IN LPCVOID pvData,
  1233. OUT BOOL *pbDone
  1234. )
  1235. {
  1236. DWORD dwErr;
  1237. TAG_TYPE pttTags[] = {{TOKEN_INTERFACE, FALSE, FALSE},
  1238. {TOKEN_ADDRESS, FALSE, FALSE}};
  1239. DWORD rgdwTagType[sizeof(pttTags)/sizeof(TAG_TYPE)];
  1240. PWCHAR pwszIfFriendlyName = NULL;
  1241. DWORD i;
  1242. IN6_ADDR ipAddress, *pipAddress = NULL;
  1243. // Parse arguments
  1244. dwErr = PreprocessCommand(g_hModule,
  1245. ppwcArguments,
  1246. dwCurrentIndex,
  1247. dwArgCount,
  1248. pttTags,
  1249. sizeof(pttTags)/sizeof(TAG_TYPE),
  1250. 0,
  1251. sizeof(pttTags)/sizeof(TAG_TYPE),
  1252. rgdwTagType );
  1253. for (i=0; (dwErr == NO_ERROR) && (i<dwArgCount-dwCurrentIndex); i++) {
  1254. switch(rgdwTagType[i]) {
  1255. case 0: // INTERFACE
  1256. pwszIfFriendlyName = ppwcArguments[i + dwCurrentIndex];
  1257. break;
  1258. case 1: // ADDRESS
  1259. dwErr = GetIpv6Address(ppwcArguments[i + dwCurrentIndex],
  1260. &ipAddress);
  1261. pipAddress = &ipAddress;
  1262. break;
  1263. default:
  1264. dwErr = ERROR_INVALID_SYNTAX;
  1265. break;
  1266. }
  1267. }
  1268. if (dwErr isnot NO_ERROR) {
  1269. return dwErr;
  1270. }
  1271. // Now do the work
  1272. return FlushNeighborCache(pwszIfFriendlyName, pipAddress);
  1273. }
  1274. DWORD
  1275. HandleShowNeighbors(
  1276. IN LPCWSTR pwszMachine,
  1277. IN OUT LPWSTR *ppwcArguments,
  1278. IN DWORD dwCurrentIndex,
  1279. IN DWORD dwArgCount,
  1280. IN DWORD dwFlags,
  1281. IN LPCVOID pvData,
  1282. OUT BOOL *pbDone
  1283. )
  1284. {
  1285. DWORD dwErr;
  1286. TAG_TYPE pttTags[] = {{TOKEN_INTERFACE, FALSE, FALSE},
  1287. {TOKEN_ADDRESS, FALSE, FALSE}};
  1288. DWORD rgdwTagType[sizeof(pttTags)/sizeof(TAG_TYPE)];
  1289. PWCHAR pwszIfFriendlyName = NULL;
  1290. DWORD i;
  1291. IN6_ADDR ipAddress, *pipAddress = NULL;
  1292. // Parse arguments
  1293. dwErr = PreprocessCommand(g_hModule,
  1294. ppwcArguments,
  1295. dwCurrentIndex,
  1296. dwArgCount,
  1297. pttTags,
  1298. sizeof(pttTags)/sizeof(TAG_TYPE),
  1299. 0,
  1300. sizeof(pttTags)/sizeof(TAG_TYPE),
  1301. rgdwTagType );
  1302. for (i=0; (dwErr == NO_ERROR) && (i<dwArgCount-dwCurrentIndex); i++) {
  1303. switch(rgdwTagType[i]) {
  1304. case 0: // INTERFACE
  1305. pwszIfFriendlyName = ppwcArguments[i + dwCurrentIndex];
  1306. break;
  1307. case 1: // ADDRESS
  1308. dwErr = GetIpv6Address(ppwcArguments[i + dwCurrentIndex],
  1309. &ipAddress);
  1310. pipAddress = &ipAddress;
  1311. break;
  1312. default:
  1313. dwErr = ERROR_INVALID_SYNTAX;
  1314. break;
  1315. }
  1316. }
  1317. if (dwErr isnot NO_ERROR) {
  1318. return dwErr;
  1319. }
  1320. // Now do the work
  1321. return QueryNeighborCache(pwszIfFriendlyName, pipAddress);
  1322. }
  1323. /////////////////////////////////////////////////////////////////////////////
  1324. // Commands related to the prefix policies
  1325. /////////////////////////////////////////////////////////////////////////////
  1326. DWORD
  1327. HandleAddSetPrefixPolicy(
  1328. IN OUT LPWSTR *ppwcArguments,
  1329. IN DWORD dwCurrentIndex,
  1330. IN DWORD dwArgCount,
  1331. IN ACTION Action,
  1332. OUT BOOL *pbDone
  1333. )
  1334. {
  1335. DWORD dwErr;
  1336. TAG_TYPE pttTags[] = {{TOKEN_PREFIX, TRUE, FALSE},
  1337. {TOKEN_PRECEDENCE, TRUE, FALSE},
  1338. {TOKEN_LABEL, TRUE, FALSE},
  1339. {TOKEN_STORE, FALSE, FALSE}};
  1340. DWORD rgdwTagType[sizeof(pttTags)/sizeof(TAG_TYPE)];
  1341. TOKEN_VALUE rgtvStoreEnum[] = {{ TOKEN_VALUE_ACTIVE, FALSE },
  1342. { TOKEN_VALUE_PERSISTENT, TRUE }};
  1343. DWORD i, dwPrefixLength, dwPrecedence = -1, dwLabel = -1;
  1344. IN6_ADDR ipAddress;
  1345. BOOL bPersistent = TRUE;
  1346. // Parse arguments
  1347. dwErr = PreprocessCommand(g_hModule,
  1348. ppwcArguments,
  1349. dwCurrentIndex,
  1350. dwArgCount,
  1351. pttTags,
  1352. sizeof(pttTags)/sizeof(TAG_TYPE),
  1353. 0,
  1354. sizeof(pttTags)/sizeof(TAG_TYPE),
  1355. rgdwTagType );
  1356. for (i=0; (dwErr == NO_ERROR) && (i<dwArgCount-dwCurrentIndex); i++) {
  1357. switch(rgdwTagType[i]) {
  1358. case 0: // PREFIX
  1359. dwErr = GetIpv6Prefix(ppwcArguments[i + dwCurrentIndex],
  1360. &ipAddress, &dwPrefixLength);
  1361. break;
  1362. case 1: // PRECEDENCE
  1363. dwPrecedence = wcstoul(ppwcArguments[dwCurrentIndex + i], NULL, 10);
  1364. break;
  1365. case 2: // LABEL
  1366. dwLabel = wcstoul(ppwcArguments[dwCurrentIndex + i], NULL, 10);
  1367. break;
  1368. case 3: // STORE
  1369. dwErr = MatchEnumTag(NULL,
  1370. ppwcArguments[dwCurrentIndex + i],
  1371. NUM_TOKENS_IN_TABLE(rgtvStoreEnum),
  1372. rgtvStoreEnum,
  1373. &bPersistent);
  1374. if (dwErr isnot NO_ERROR) {
  1375. dwErr = ERROR_INVALID_PARAMETER;
  1376. break;
  1377. }
  1378. break;
  1379. default:
  1380. dwErr = ERROR_INVALID_SYNTAX;
  1381. break;
  1382. }
  1383. }
  1384. if (dwErr isnot NO_ERROR) {
  1385. return dwErr;
  1386. }
  1387. // Now do the work
  1388. return UpdatePrefixPolicy(&ipAddress, dwPrefixLength, dwPrecedence,
  1389. dwLabel, bPersistent);
  1390. }
  1391. DWORD
  1392. HandleAddPrefixPolicy(
  1393. IN LPCWSTR pwszMachine,
  1394. IN OUT LPWSTR *ppwcArguments,
  1395. IN DWORD dwCurrentIndex,
  1396. IN DWORD dwArgCount,
  1397. IN DWORD dwFlags,
  1398. IN LPCVOID pvData,
  1399. OUT BOOL *pbDone
  1400. )
  1401. {
  1402. return HandleAddSetPrefixPolicy(ppwcArguments, dwCurrentIndex, dwArgCount,
  1403. ACTION_ADD, pbDone);
  1404. }
  1405. DWORD
  1406. HandleSetPrefixPolicy(
  1407. IN LPCWSTR pwszMachine,
  1408. IN OUT LPWSTR *ppwcArguments,
  1409. IN DWORD dwCurrentIndex,
  1410. IN DWORD dwArgCount,
  1411. IN DWORD dwFlags,
  1412. IN LPCVOID pvData,
  1413. OUT BOOL *pbDone
  1414. )
  1415. {
  1416. return HandleAddSetPrefixPolicy(ppwcArguments, dwCurrentIndex, dwArgCount,
  1417. ACTION_SET, pbDone);
  1418. }
  1419. DWORD
  1420. HandleDelPrefixPolicy(
  1421. IN LPCWSTR pwszMachine,
  1422. IN OUT LPWSTR *ppwcArguments,
  1423. IN DWORD dwCurrentIndex,
  1424. IN DWORD dwArgCount,
  1425. IN DWORD dwFlags,
  1426. IN LPCVOID pvData,
  1427. OUT BOOL *pbDone
  1428. )
  1429. {
  1430. DWORD dwErr;
  1431. TAG_TYPE pttTags[] = {{TOKEN_PREFIX, TRUE, FALSE},
  1432. {TOKEN_STORE, FALSE, FALSE}};
  1433. DWORD rgdwTagType[sizeof(pttTags)/sizeof(TAG_TYPE)];
  1434. TOKEN_VALUE rgtvStoreEnum[] = {{ TOKEN_VALUE_ACTIVE, FALSE },
  1435. { TOKEN_VALUE_PERSISTENT, TRUE }};
  1436. DWORD i, dwPrefixLength;
  1437. IN6_ADDR ipAddress;
  1438. BOOL bPersistent = TRUE;
  1439. // Parse arguments
  1440. dwErr = PreprocessCommand(g_hModule,
  1441. ppwcArguments,
  1442. dwCurrentIndex,
  1443. dwArgCount,
  1444. pttTags,
  1445. sizeof(pttTags)/sizeof(TAG_TYPE),
  1446. 0,
  1447. sizeof(pttTags)/sizeof(TAG_TYPE),
  1448. rgdwTagType );
  1449. for (i=0; (dwErr == NO_ERROR) && (i<dwArgCount-dwCurrentIndex); i++) {
  1450. switch(rgdwTagType[i]) {
  1451. case 0: // PREFIX
  1452. dwErr = GetIpv6Prefix(ppwcArguments[i + dwCurrentIndex],
  1453. &ipAddress, &dwPrefixLength);
  1454. break;
  1455. case 1: // STORE
  1456. dwErr = MatchEnumTag(NULL,
  1457. ppwcArguments[dwCurrentIndex + i],
  1458. NUM_TOKENS_IN_TABLE(rgtvStoreEnum),
  1459. rgtvStoreEnum,
  1460. &bPersistent);
  1461. if (dwErr isnot NO_ERROR) {
  1462. dwErr = ERROR_INVALID_PARAMETER;
  1463. break;
  1464. }
  1465. break;
  1466. default:
  1467. dwErr = ERROR_INVALID_SYNTAX;
  1468. break;
  1469. }
  1470. }
  1471. if (dwErr isnot NO_ERROR) {
  1472. return dwErr;
  1473. }
  1474. // Now do the work
  1475. return DeletePrefixPolicy(&ipAddress, dwPrefixLength, bPersistent);
  1476. }
  1477. DWORD
  1478. HandleShowPrefixPolicy(
  1479. IN LPCWSTR pwszMachine,
  1480. IN OUT LPWSTR *ppwcArguments,
  1481. IN DWORD dwCurrentIndex,
  1482. IN DWORD dwArgCount,
  1483. IN DWORD dwFlags,
  1484. IN LPCVOID pvData,
  1485. OUT BOOL *pbDone
  1486. )
  1487. {
  1488. DWORD dwErr;
  1489. TAG_TYPE pttTags[] = {{TOKEN_STORE, FALSE, FALSE}};
  1490. DWORD rgdwTagType[sizeof(pttTags)/sizeof(TAG_TYPE)];
  1491. DWORD i;
  1492. BOOL bPersistent = FALSE;
  1493. TOKEN_VALUE rgtvStoreEnum[] = {{ TOKEN_VALUE_ACTIVE, FALSE },
  1494. { TOKEN_VALUE_PERSISTENT, TRUE }};
  1495. // Parse arguments
  1496. dwErr = PreprocessCommand(g_hModule,
  1497. ppwcArguments,
  1498. dwCurrentIndex,
  1499. dwArgCount,
  1500. pttTags,
  1501. sizeof(pttTags)/sizeof(TAG_TYPE),
  1502. 0,
  1503. sizeof(pttTags)/sizeof(TAG_TYPE),
  1504. rgdwTagType );
  1505. for (i=0; (dwErr == NO_ERROR) && (i<dwArgCount-dwCurrentIndex); i++) {
  1506. switch(rgdwTagType[i]) {
  1507. case 0: // STORE
  1508. dwErr = MatchEnumTag(NULL,
  1509. ppwcArguments[dwCurrentIndex + i],
  1510. NUM_TOKENS_IN_TABLE(rgtvStoreEnum),
  1511. rgtvStoreEnum,
  1512. &bPersistent);
  1513. if (dwErr isnot NO_ERROR) {
  1514. dwErr = ERROR_INVALID_PARAMETER;
  1515. break;
  1516. }
  1517. break;
  1518. default:
  1519. dwErr = ERROR_INVALID_SYNTAX;
  1520. break;
  1521. }
  1522. }
  1523. if (dwErr isnot NO_ERROR) {
  1524. return dwErr;
  1525. }
  1526. // Now do the work
  1527. return QueryPrefixPolicy(FORMAT_NORMAL, bPersistent);
  1528. }
  1529. /////////////////////////////////////////////////////////////////////////////
  1530. // Commands related to routes
  1531. /////////////////////////////////////////////////////////////////////////////
  1532. DWORD
  1533. HandleAddSetRoute(
  1534. IN OUT LPWSTR *ppwcArguments,
  1535. IN DWORD dwCurrentIndex,
  1536. IN DWORD dwArgCount,
  1537. IN ACTION Action,
  1538. OUT BOOL *pbDone
  1539. )
  1540. {
  1541. DWORD dwErr, i;
  1542. TAG_TYPE pttTags[] = {{TOKEN_PREFIX, TRUE, FALSE},
  1543. {TOKEN_INTERFACE, TRUE, FALSE},
  1544. {TOKEN_NEXTHOP, FALSE, FALSE},
  1545. {TOKEN_SITEPREFIXLENGTH, FALSE, FALSE},
  1546. {TOKEN_METRIC, FALSE, FALSE},
  1547. {TOKEN_PUBLISH, FALSE, FALSE},
  1548. {TOKEN_VALIDLIFETIME, FALSE, FALSE},
  1549. {TOKEN_PREFERREDLIFETIME, FALSE, FALSE},
  1550. {TOKEN_STORE, FALSE, FALSE}};
  1551. DWORD rgdwTagType[sizeof(pttTags)/sizeof(TAG_TYPE)];
  1552. TOKEN_VALUE rgtvPublishEnum[] = {
  1553. {TOKEN_VALUE_NO, PUBLISH_NO },
  1554. {TOKEN_VALUE_AGE, PUBLISH_AGE },
  1555. {TOKEN_VALUE_YES, PUBLISH_IMMORTAL }};
  1556. TOKEN_VALUE rgtvStoreEnum[] = {{ TOKEN_VALUE_ACTIVE, FALSE },
  1557. { TOKEN_VALUE_PERSISTENT, TRUE }};
  1558. DWORD dwPrefixLength, dwMetric = ROUTE_PREF_HIGHEST;
  1559. DWORD dwSitePrefixLength = 0;
  1560. IN6_ADDR ipPrefix, ipNextHop, *pipNextHop = NULL;
  1561. PWCHAR pwszIfFriendlyName;
  1562. PUBLISH Publish = PUBLISH_NO;
  1563. DWORD dwValidLifetime = INFINITE_LIFETIME;
  1564. DWORD dwPreferredLifetime = INFINITE_LIFETIME;
  1565. BOOL bPersistent = TRUE;
  1566. // Parse arguments
  1567. dwErr = PreprocessCommand(g_hModule,
  1568. ppwcArguments,
  1569. dwCurrentIndex,
  1570. dwArgCount,
  1571. pttTags,
  1572. sizeof(pttTags)/sizeof(TAG_TYPE),
  1573. 0,
  1574. sizeof(pttTags)/sizeof(TAG_TYPE),
  1575. rgdwTagType );
  1576. for (i=0; (dwErr == NO_ERROR) && (i<dwArgCount-dwCurrentIndex); i++) {
  1577. switch(rgdwTagType[i]) {
  1578. case 0: // PREFIX
  1579. dwErr = GetIpv6Prefix(ppwcArguments[i + dwCurrentIndex],
  1580. &ipPrefix, &dwPrefixLength);
  1581. break;
  1582. case 1: // INTERFACE
  1583. pwszIfFriendlyName = ppwcArguments[dwCurrentIndex + i];
  1584. break;
  1585. case 2: // NEXTHOP
  1586. pipNextHop = &ipNextHop;
  1587. dwErr = GetIpv6Address(ppwcArguments[i + dwCurrentIndex],
  1588. &ipNextHop);
  1589. break;
  1590. case 3: // SITEPREFIXLENGTH
  1591. dwSitePrefixLength = wcstoul(ppwcArguments[dwCurrentIndex + i],
  1592. NULL, 10);
  1593. break;
  1594. case 4: // METRIC
  1595. dwMetric = wcstoul(ppwcArguments[dwCurrentIndex + i], NULL, 10);
  1596. break;
  1597. case 5: // PUBLISH
  1598. dwErr = MatchEnumTag(NULL,
  1599. ppwcArguments[dwCurrentIndex + i],
  1600. NUM_TOKENS_IN_TABLE(rgtvPublishEnum),
  1601. rgtvPublishEnum,
  1602. (DWORD*)&Publish);
  1603. if (dwErr isnot NO_ERROR) {
  1604. dwErr = ERROR_INVALID_PARAMETER;
  1605. break;
  1606. }
  1607. break;
  1608. case 6: // VALIDLIFETIME
  1609. dwValidLifetime = GetTime(ppwcArguments[dwCurrentIndex + i]);
  1610. break;
  1611. case 7: // PREFERREDLIFETIME
  1612. dwPreferredLifetime = GetTime(ppwcArguments[dwCurrentIndex + i]);
  1613. break;
  1614. case 8: // STORE
  1615. dwErr = MatchEnumTag(NULL,
  1616. ppwcArguments[dwCurrentIndex + i],
  1617. NUM_TOKENS_IN_TABLE(rgtvStoreEnum),
  1618. rgtvStoreEnum,
  1619. &bPersistent);
  1620. if (dwErr isnot NO_ERROR) {
  1621. dwErr = ERROR_INVALID_PARAMETER;
  1622. break;
  1623. }
  1624. break;
  1625. default:
  1626. dwErr = ERROR_INVALID_SYNTAX;
  1627. break;
  1628. }
  1629. }
  1630. if (dwErr isnot NO_ERROR) {
  1631. return dwErr;
  1632. }
  1633. // Now do the work
  1634. if ((dwPreferredLifetime == INFINITE_LIFETIME) &&
  1635. (dwValidLifetime != INFINITE_LIFETIME)) {
  1636. dwPreferredLifetime = dwValidLifetime;
  1637. }
  1638. // Disallow persistent aging routes with non-infinite valid lifetimes,
  1639. // since every reboot they would come back, and then go away after
  1640. // the lifetime expires. This would be very confusing, and so we
  1641. // just disallow it.
  1642. if ((Publish != PUBLISH_IMMORTAL) &&
  1643. (dwValidLifetime != INFINITE_LIFETIME) &&
  1644. (bPersistent == TRUE)) {
  1645. return ERROR_INVALID_PARAMETER;
  1646. // DisplayMessage(g_hModule, EMSG_CANT_PERSIST_AGING_ROUTES);
  1647. // return ERROR_SUPPRESS_OUTPUT;
  1648. }
  1649. return UpdateRouteTable(&ipPrefix, dwPrefixLength, pwszIfFriendlyName,
  1650. pipNextHop, dwMetric, Publish, dwSitePrefixLength,
  1651. dwValidLifetime, dwPreferredLifetime, bPersistent);
  1652. }
  1653. DWORD
  1654. HandleAddRoute(
  1655. IN LPCWSTR pwszMachine,
  1656. IN OUT LPWSTR *ppwcArguments,
  1657. IN DWORD dwCurrentIndex,
  1658. IN DWORD dwArgCount,
  1659. IN DWORD dwFlags,
  1660. IN LPCVOID pvData,
  1661. OUT BOOL *pbDone
  1662. )
  1663. {
  1664. return HandleAddSetRoute(ppwcArguments, dwCurrentIndex, dwArgCount,
  1665. ACTION_ADD, pbDone);
  1666. }
  1667. DWORD
  1668. HandleSetRoute(
  1669. IN LPCWSTR pwszMachine,
  1670. IN OUT LPWSTR *ppwcArguments,
  1671. IN DWORD dwCurrentIndex,
  1672. IN DWORD dwArgCount,
  1673. IN DWORD dwFlags,
  1674. IN LPCVOID pvData,
  1675. OUT BOOL *pbDone
  1676. )
  1677. {
  1678. return HandleAddSetRoute(ppwcArguments, dwCurrentIndex, dwArgCount,
  1679. ACTION_SET, pbDone);
  1680. }
  1681. DWORD
  1682. HandleDelRoute(
  1683. IN LPCWSTR pwszMachine,
  1684. IN OUT LPWSTR *ppwcArguments,
  1685. IN DWORD dwCurrentIndex,
  1686. IN DWORD dwArgCount,
  1687. IN DWORD dwFlags,
  1688. IN LPCVOID pvData,
  1689. OUT BOOL *pbDone
  1690. )
  1691. {
  1692. DWORD dwErr, i;
  1693. TAG_TYPE pttTags[] = {{TOKEN_PREFIX, TRUE, FALSE},
  1694. {TOKEN_INTERFACE, TRUE, FALSE},
  1695. {TOKEN_NEXTHOP, FALSE, FALSE},
  1696. {TOKEN_STORE, FALSE, FALSE}};
  1697. DWORD rgdwTagType[sizeof(pttTags)/sizeof(TAG_TYPE)];
  1698. TOKEN_VALUE rgtvStoreEnum[] = {{ TOKEN_VALUE_ACTIVE, FALSE },
  1699. { TOKEN_VALUE_PERSISTENT, TRUE }};
  1700. DWORD dwPrefixLength, dwMetric = ROUTE_PREF_HIGHEST;
  1701. DWORD dwSitePrefixLength = 0;
  1702. IN6_ADDR ipPrefix, ipNextHop, *pipNextHop = NULL;
  1703. PWCHAR pwszIfFriendlyName;
  1704. PUBLISH Publish = PUBLISH_NO;
  1705. BOOL bPersistent = TRUE;
  1706. // Parse arguments
  1707. dwErr = PreprocessCommand(g_hModule,
  1708. ppwcArguments,
  1709. dwCurrentIndex,
  1710. dwArgCount,
  1711. pttTags,
  1712. sizeof(pttTags)/sizeof(TAG_TYPE),
  1713. 0,
  1714. sizeof(pttTags)/sizeof(TAG_TYPE),
  1715. rgdwTagType );
  1716. for (i=0; (dwErr == NO_ERROR) && (i<dwArgCount-dwCurrentIndex); i++) {
  1717. switch(rgdwTagType[i]) {
  1718. case 0: // PREFIX
  1719. dwErr = GetIpv6Prefix(ppwcArguments[i + dwCurrentIndex],
  1720. &ipPrefix, &dwPrefixLength);
  1721. break;
  1722. case 1: // INTERFACE
  1723. pwszIfFriendlyName = ppwcArguments[dwCurrentIndex + i];
  1724. break;
  1725. case 2: // NEXTHOP
  1726. pipNextHop = &ipNextHop;
  1727. dwErr = GetIpv6Address(ppwcArguments[i + dwCurrentIndex],
  1728. &ipNextHop);
  1729. break;
  1730. case 3: // STORE
  1731. dwErr = MatchEnumTag(NULL,
  1732. ppwcArguments[dwCurrentIndex + i],
  1733. NUM_TOKENS_IN_TABLE(rgtvStoreEnum),
  1734. rgtvStoreEnum,
  1735. &bPersistent);
  1736. if (dwErr isnot NO_ERROR) {
  1737. dwErr = ERROR_INVALID_PARAMETER;
  1738. break;
  1739. }
  1740. break;
  1741. default:
  1742. dwErr = ERROR_INVALID_SYNTAX;
  1743. break;
  1744. }
  1745. }
  1746. if (dwErr isnot NO_ERROR) {
  1747. return dwErr;
  1748. }
  1749. // Now do the work
  1750. return UpdateRouteTable(&ipPrefix, dwPrefixLength, pwszIfFriendlyName,
  1751. pipNextHop, dwMetric, Publish, dwSitePrefixLength,
  1752. 0, 0, bPersistent);
  1753. }
  1754. DWORD
  1755. HandleShowRoutes(
  1756. IN LPCWSTR pwszMachine,
  1757. IN OUT LPWSTR *ppwcArguments,
  1758. IN DWORD dwCurrentIndex,
  1759. IN DWORD dwArgCount,
  1760. IN DWORD dwFlags,
  1761. IN LPCVOID pvData,
  1762. OUT BOOL *pbDone
  1763. )
  1764. {
  1765. DWORD dwErr;
  1766. TAG_TYPE pttTags[] = {{TOKEN_LEVEL, FALSE, FALSE},
  1767. {TOKEN_STORE, FALSE, FALSE}};
  1768. DWORD rgdwTagType[sizeof(pttTags)/sizeof(TAG_TYPE)];
  1769. DWORD i;
  1770. IN6_ADDR ipAddress, *pipAddress = NULL;
  1771. TOKEN_VALUE rgtvLevelEnum[] = {{ TOKEN_VALUE_NORMAL, FORMAT_NORMAL },
  1772. { TOKEN_VALUE_VERBOSE, FORMAT_VERBOSE }};
  1773. TOKEN_VALUE rgtvStoreEnum[] = {{ TOKEN_VALUE_ACTIVE, FALSE },
  1774. { TOKEN_VALUE_PERSISTENT, TRUE }};
  1775. FORMAT Format = FORMAT_NORMAL;
  1776. BOOL bPersistent = FALSE;
  1777. // Parse arguments
  1778. dwErr = PreprocessCommand(g_hModule,
  1779. ppwcArguments,
  1780. dwCurrentIndex,
  1781. dwArgCount,
  1782. pttTags,
  1783. sizeof(pttTags)/sizeof(TAG_TYPE),
  1784. 0,
  1785. sizeof(pttTags)/sizeof(TAG_TYPE),
  1786. rgdwTagType );
  1787. for (i=0; (dwErr == NO_ERROR) && (i<dwArgCount-dwCurrentIndex); i++) {
  1788. switch(rgdwTagType[i]) {
  1789. case 0: // LEVEL
  1790. dwErr = MatchEnumTag(NULL,
  1791. ppwcArguments[dwCurrentIndex + i],
  1792. NUM_TOKENS_IN_TABLE(rgtvLevelEnum),
  1793. rgtvLevelEnum,
  1794. (DWORD*)&Format);
  1795. if (dwErr isnot NO_ERROR) {
  1796. dwErr = ERROR_INVALID_PARAMETER;
  1797. break;
  1798. }
  1799. break;
  1800. case 1: // STORE
  1801. dwErr = MatchEnumTag(NULL,
  1802. ppwcArguments[dwCurrentIndex + i],
  1803. NUM_TOKENS_IN_TABLE(rgtvStoreEnum),
  1804. rgtvStoreEnum,
  1805. &bPersistent);
  1806. if (dwErr isnot NO_ERROR) {
  1807. dwErr = ERROR_INVALID_PARAMETER;
  1808. break;
  1809. }
  1810. break;
  1811. default:
  1812. dwErr = ERROR_INVALID_SYNTAX;
  1813. break;
  1814. }
  1815. }
  1816. if (dwErr isnot NO_ERROR) {
  1817. return dwErr;
  1818. }
  1819. // Now do the work
  1820. return QueryRouteTable(Format, bPersistent);
  1821. }
  1822. /////////////////////////////////////////////////////////////////////////////
  1823. // Commands related to the destination cache
  1824. /////////////////////////////////////////////////////////////////////////////
  1825. DWORD
  1826. HandleDelDestinationCache(
  1827. IN LPCWSTR pwszMachine,
  1828. IN OUT LPWSTR *ppwcArguments,
  1829. IN DWORD dwCurrentIndex,
  1830. IN DWORD dwArgCount,
  1831. IN DWORD dwFlags,
  1832. IN LPCVOID pvData,
  1833. OUT BOOL *pbDone
  1834. )
  1835. {
  1836. DWORD dwErr;
  1837. TAG_TYPE pttTags[] = {{TOKEN_INTERFACE, FALSE, FALSE},
  1838. {TOKEN_ADDRESS, FALSE, FALSE}};
  1839. DWORD rgdwTagType[sizeof(pttTags)/sizeof(TAG_TYPE)];
  1840. PWCHAR pwszIfFriendlyName = NULL;
  1841. DWORD i;
  1842. IN6_ADDR ipAddress, *pipAddress = NULL;
  1843. // Parse arguments
  1844. dwErr = PreprocessCommand(g_hModule,
  1845. ppwcArguments,
  1846. dwCurrentIndex,
  1847. dwArgCount,
  1848. pttTags,
  1849. sizeof(pttTags)/sizeof(TAG_TYPE),
  1850. 0,
  1851. sizeof(pttTags)/sizeof(TAG_TYPE),
  1852. rgdwTagType );
  1853. for (i=0; (dwErr == NO_ERROR) && (i<dwArgCount-dwCurrentIndex); i++) {
  1854. switch(rgdwTagType[i]) {
  1855. case 0: // INTERFACE
  1856. pwszIfFriendlyName = ppwcArguments[i + dwCurrentIndex];
  1857. break;
  1858. case 1: // ADDRESS
  1859. dwErr = GetIpv6Address(ppwcArguments[i + dwCurrentIndex],
  1860. &ipAddress);
  1861. pipAddress = &ipAddress;
  1862. break;
  1863. default:
  1864. dwErr = ERROR_INVALID_SYNTAX;
  1865. break;
  1866. }
  1867. }
  1868. if (dwErr isnot NO_ERROR) {
  1869. return dwErr;
  1870. }
  1871. // Now do the work
  1872. return FlushRouteCache(pwszIfFriendlyName, pipAddress);
  1873. }
  1874. DWORD
  1875. HandleShowDestinationCache(
  1876. IN LPCWSTR pwszMachine,
  1877. IN OUT LPWSTR *ppwcArguments,
  1878. IN DWORD dwCurrentIndex,
  1879. IN DWORD dwArgCount,
  1880. IN DWORD dwFlags,
  1881. IN LPCVOID pvData,
  1882. OUT BOOL *pbDone
  1883. )
  1884. {
  1885. DWORD dwErr;
  1886. TAG_TYPE pttTags[] = {{TOKEN_INTERFACE, FALSE, FALSE},
  1887. {TOKEN_ADDRESS, FALSE, FALSE},
  1888. {TOKEN_LEVEL, FALSE, FALSE}};
  1889. DWORD rgdwTagType[sizeof(pttTags)/sizeof(TAG_TYPE)];
  1890. PWCHAR pwszIfFriendlyName = NULL;
  1891. DWORD i;
  1892. IN6_ADDR ipAddress, *pipAddress = NULL;
  1893. FORMAT Format = FORMAT_NORMAL;
  1894. TOKEN_VALUE rgtvLevelEnum[] = {{ TOKEN_VALUE_NORMAL, FORMAT_NORMAL },
  1895. { TOKEN_VALUE_VERBOSE, FORMAT_VERBOSE }};
  1896. // Parse arguments
  1897. dwErr = PreprocessCommand(g_hModule,
  1898. ppwcArguments,
  1899. dwCurrentIndex,
  1900. dwArgCount,
  1901. pttTags,
  1902. sizeof(pttTags)/sizeof(TAG_TYPE),
  1903. 0,
  1904. sizeof(pttTags)/sizeof(TAG_TYPE),
  1905. rgdwTagType );
  1906. for (i=0; (dwErr == NO_ERROR) && (i<dwArgCount-dwCurrentIndex); i++) {
  1907. switch(rgdwTagType[i]) {
  1908. case 0: // INTERFACE
  1909. pwszIfFriendlyName = ppwcArguments[i + dwCurrentIndex];
  1910. break;
  1911. case 1: // ADDRESS
  1912. dwErr = GetIpv6Address(ppwcArguments[i + dwCurrentIndex],
  1913. &ipAddress);
  1914. pipAddress = &ipAddress;
  1915. Format = FORMAT_VERBOSE;
  1916. break;
  1917. case 2: // LEVEL
  1918. dwErr = MatchEnumTag(NULL,
  1919. ppwcArguments[dwCurrentIndex + i],
  1920. NUM_TOKENS_IN_TABLE(rgtvLevelEnum),
  1921. rgtvLevelEnum,
  1922. (DWORD*)&Format);
  1923. if (dwErr isnot NO_ERROR) {
  1924. dwErr = ERROR_INVALID_PARAMETER;
  1925. break;
  1926. }
  1927. break;
  1928. default:
  1929. dwErr = ERROR_INVALID_SYNTAX;
  1930. break;
  1931. }
  1932. }
  1933. if (dwErr isnot NO_ERROR) {
  1934. return dwErr;
  1935. }
  1936. // Now do the work
  1937. return QueryRouteCache(pwszIfFriendlyName, pipAddress, Format);
  1938. }
  1939. /////////////////////////////////////////////////////////////////////////////
  1940. // Commands related to the site prefix table
  1941. /////////////////////////////////////////////////////////////////////////////
  1942. DWORD
  1943. HandleShowSitePrefixes(
  1944. IN LPCWSTR pwszMachine,
  1945. IN OUT LPWSTR *ppwcArguments,
  1946. IN DWORD dwCurrentIndex,
  1947. IN DWORD dwArgCount,
  1948. IN DWORD dwFlags,
  1949. IN LPCVOID pvData,
  1950. OUT BOOL *pbDone
  1951. )
  1952. {
  1953. return QuerySitePrefixTable(FORMAT_NORMAL);
  1954. }
  1955. /////////////////////////////////////////////////////////////////////////////
  1956. // Commands related to installation
  1957. /////////////////////////////////////////////////////////////////////////////
  1958. DWORD
  1959. HandleInstall(
  1960. IN LPCWSTR pwszMachine,
  1961. IN OUT LPWSTR *ppwcArguments,
  1962. IN DWORD dwCurrentIndex,
  1963. IN DWORD dwArgCount,
  1964. IN DWORD dwFlags,
  1965. IN LPCVOID pvData,
  1966. OUT BOOL *pbDone
  1967. )
  1968. {
  1969. return AddOrRemoveIpv6(TRUE);
  1970. }
  1971. DWORD
  1972. HandleReset(
  1973. IN LPCWSTR pwszMachine,
  1974. IN OUT LPWSTR *ppwcArguments,
  1975. IN DWORD dwCurrentIndex,
  1976. IN DWORD dwArgCount,
  1977. IN DWORD dwFlags,
  1978. IN LPCVOID pvData,
  1979. OUT BOOL *pbDone
  1980. )
  1981. {
  1982. DWORD dwErr;
  1983. #if TEREDO
  1984. dwErr = ResetTeredo();
  1985. if (dwErr != NO_ERROR) {
  1986. return dwErr;
  1987. }
  1988. #endif // TEREDO
  1989. return ResetIpv6Config(TRUE);
  1990. }
  1991. DWORD
  1992. HandleUninstall(
  1993. IN LPCWSTR pwszMachine,
  1994. IN OUT LPWSTR *ppwcArguments,
  1995. IN DWORD dwCurrentIndex,
  1996. IN DWORD dwArgCount,
  1997. IN DWORD dwFlags,
  1998. IN LPCVOID pvData,
  1999. OUT BOOL *pbDone
  2000. )
  2001. {
  2002. return AddOrRemoveIpv6(FALSE);
  2003. }
  2004. /////////////////////////////////////////////////////////////////////////////
  2005. // Commands related to deprecated functionality
  2006. /////////////////////////////////////////////////////////////////////////////
  2007. #define KEY_ENABLE_6OVER4 L"Enable6over4"
  2008. #define KEY_ENABLE_V4COMPAT L"EnableV4Compat"
  2009. #define BM_ENABLE_6OVER4 0x01
  2010. #define BM_ENABLE_V4COMPAT 0x02
  2011. DWORD
  2012. HandleSetState(
  2013. IN LPCWSTR pwszMachine,
  2014. IN OUT LPWSTR *ppwcArguments,
  2015. IN DWORD dwCurrentIndex,
  2016. IN DWORD dwArgCount,
  2017. IN DWORD dwFlags,
  2018. IN LPCVOID pvData,
  2019. OUT BOOL *pbDone
  2020. )
  2021. {
  2022. DWORD dwErr = NO_ERROR;
  2023. HKEY hGlobal;
  2024. STATE stEnable6over4;
  2025. STATE stEnableV4Compat;
  2026. DWORD dwBitVector = 0;
  2027. TAG_TYPE pttTags[] = {{TOKEN_6OVER4, FALSE, FALSE},
  2028. {TOKEN_V4COMPAT, FALSE, FALSE}};
  2029. DWORD rgdwTagType[sizeof(pttTags)/sizeof(TAG_TYPE)];
  2030. DWORD dwNumArg;
  2031. DWORD i;
  2032. // Parse arguments
  2033. dwErr = PreprocessCommand(g_hModule,
  2034. ppwcArguments,
  2035. dwCurrentIndex,
  2036. dwArgCount,
  2037. pttTags,
  2038. sizeof(pttTags)/sizeof(TAG_TYPE),
  2039. 1,
  2040. sizeof(pttTags)/sizeof(TAG_TYPE),
  2041. rgdwTagType );
  2042. if (dwErr isnot NO_ERROR) {
  2043. return dwErr;
  2044. }
  2045. for (i=0; i<dwArgCount-dwCurrentIndex; i++) {
  2046. switch(rgdwTagType[i]) {
  2047. case 0: // 6OVER4
  2048. dwErr = MatchEnumTag(NULL,
  2049. ppwcArguments[dwCurrentIndex + i],
  2050. NUM_TOKENS_IN_TABLE(rgtvEnums),
  2051. rgtvEnums,
  2052. (PDWORD)&stEnable6over4);
  2053. if (dwErr isnot NO_ERROR) {
  2054. dwErr = ERROR_INVALID_PARAMETER;
  2055. break;
  2056. }
  2057. dwBitVector |= BM_ENABLE_6OVER4;
  2058. break;
  2059. case 1: // V4COMPAT
  2060. dwErr = MatchEnumTag(NULL,
  2061. ppwcArguments[dwCurrentIndex + i],
  2062. NUM_TOKENS_IN_TABLE(rgtvEnums),
  2063. rgtvEnums,
  2064. (PDWORD)&stEnableV4Compat);
  2065. if (dwErr isnot NO_ERROR) {
  2066. dwErr = ERROR_INVALID_PARAMETER;
  2067. break;
  2068. }
  2069. dwBitVector |= BM_ENABLE_V4COMPAT;
  2070. break;
  2071. default:
  2072. dwErr = ERROR_INVALID_SYNTAX;
  2073. break;
  2074. }
  2075. if (dwErr isnot NO_ERROR) {
  2076. return dwErr;
  2077. }
  2078. }
  2079. // Now do the sets
  2080. dwErr = RegCreateKeyEx(HKEY_LOCAL_MACHINE, KEY_GLOBAL, 0,
  2081. NULL, 0, KEY_ALL_ACCESS, NULL, &hGlobal, NULL);
  2082. if (dwErr != NO_ERROR) {
  2083. return dwErr;
  2084. }
  2085. if (dwBitVector & BM_ENABLE_6OVER4) {
  2086. dwErr = SetInteger(hGlobal, KEY_ENABLE_6OVER4, stEnable6over4);
  2087. if (dwErr != NO_ERROR)
  2088. return dwErr;
  2089. }
  2090. if (dwBitVector & BM_ENABLE_V4COMPAT) {
  2091. dwErr = SetInteger(hGlobal, KEY_ENABLE_V4COMPAT, stEnableV4Compat);
  2092. if (dwErr != NO_ERROR)
  2093. return dwErr;
  2094. }
  2095. RegCloseKey(hGlobal);
  2096. Ip6to4PokeService();
  2097. return ERROR_OKAY;
  2098. }
  2099. DWORD
  2100. ShowIpv6StateConfig(
  2101. IN BOOL Dumping
  2102. )
  2103. {
  2104. DWORD dwErr = NO_ERROR;
  2105. HKEY hGlobal;
  2106. STATE stEnable6over4;
  2107. STATE stEnableV4Compat;
  2108. dwErr = RegOpenKeyEx(HKEY_LOCAL_MACHINE, KEY_GLOBAL, 0, KEY_QUERY_VALUE,
  2109. &hGlobal);
  2110. if (dwErr != NO_ERROR) {
  2111. hGlobal = INVALID_HANDLE_VALUE;
  2112. dwErr = NO_ERROR;
  2113. }
  2114. stEnable6over4 = GetInteger(hGlobal, KEY_ENABLE_6OVER4, VAL_DEFAULT);
  2115. stEnableV4Compat = GetInteger(hGlobal, KEY_ENABLE_V4COMPAT, VAL_DEFAULT);
  2116. RegCloseKey(hGlobal);
  2117. if (Dumping) {
  2118. if ((stEnable6over4 != VAL_DEFAULT) ||
  2119. (stEnableV4Compat != VAL_DEFAULT)) {
  2120. DisplayMessageT(DMP_IP6TO4_SET_STATE);
  2121. if (stEnable6over4 != VAL_DEFAULT) {
  2122. DisplayMessageT(DMP_STRING_ARG, TOKEN_6OVER4,
  2123. pwszStateString[stEnable6over4]);
  2124. }
  2125. if (stEnableV4Compat != VAL_DEFAULT) {
  2126. DisplayMessageT(DMP_STRING_ARG, TOKEN_V4COMPAT,
  2127. pwszStateString[stEnableV4Compat]);
  2128. }
  2129. DisplayMessage(g_hModule, MSG_NEWLINE);
  2130. }
  2131. } else {
  2132. DisplayMessage(g_hModule, MSG_6OVER4_STATE,
  2133. pwszStateString[stEnable6over4]);
  2134. // DisplayMessage(g_hModule, MSG_V4COMPAT_STATE,
  2135. // pwszStateString[stEnableV4Compat]);
  2136. }
  2137. return dwErr;
  2138. }
  2139. DWORD
  2140. HandleShowState(
  2141. IN LPCWSTR pwszMachine,
  2142. IN OUT LPWSTR *ppwcArguments,
  2143. IN DWORD dwCurrentIndex,
  2144. IN DWORD dwArgCount,
  2145. IN DWORD dwFlags,
  2146. IN LPCVOID pvData,
  2147. OUT BOOL *pbDone
  2148. )
  2149. {
  2150. return ShowIpv6StateConfig(FALSE);
  2151. }
  2152. #define KEY_DNS_SERVER_LIST L"NameServer"
  2153. DWORD
  2154. GetDnsServerList(
  2155. IN PWCHAR pwszIfFriendlyName,
  2156. IN PIP_ADAPTER_ADDRESSES pAdapterInfo,
  2157. OUT IN6_ADDR **ppipDnsList,
  2158. OUT DWORD *pdwNumEntries
  2159. )
  2160. /*++
  2161. Routine Description:
  2162. Reads the list of DNS servers from the registry and returns them in
  2163. an array which includes space for at least one more server. The
  2164. caller is responsible for freeing this space with FREE().
  2165. --*/
  2166. {
  2167. HKEY hInterfaces = INVALID_HANDLE_VALUE, hIf = INVALID_HANDLE_VALUE;
  2168. DWORD dwErr = NO_ERROR, Count = 0;
  2169. WCHAR Servers[800], *p, *pend;
  2170. DWORD i;
  2171. IN6_ADDR *pipDnsList = NULL;
  2172. SOCKADDR_IN6 saddr;
  2173. DWORD Length;
  2174. PCHAR pszAdapterName;
  2175. dwErr = MapFriendlyNameToAdapterName(NULL, pwszIfFriendlyName,
  2176. pAdapterInfo, &pszAdapterName);
  2177. if (dwErr != NO_ERROR) {
  2178. goto Cleanup;
  2179. }
  2180. Servers[0] = L'\0';
  2181. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, KEY_IPV6_INTERFACES, 0, GENERIC_READ,
  2182. &hInterfaces) != NO_ERROR) {
  2183. goto HaveString;
  2184. }
  2185. if (RegOpenKeyExA(hInterfaces, pszAdapterName, 0, GENERIC_READ, &hIf)
  2186. == NO_ERROR) {
  2187. GetString(hIf, KEY_DNS_SERVER_LIST, Servers, 800);
  2188. }
  2189. HaveString:
  2190. // Count one server for each delimiter, plus one at the end, plus
  2191. // one more which the caller might want to add to the array which
  2192. // we allocate.
  2193. for (p = Servers; *p; p++) {
  2194. if (*p == ' ' || *p == ',' || *p == ';') {
  2195. Count++;
  2196. }
  2197. }
  2198. Count += 2;
  2199. //
  2200. // Now allocate an array of IN6_ADDR structures, and copy all the
  2201. // addresses into it.
  2202. //
  2203. pipDnsList = MALLOC(sizeof(IN6_ADDR) * Count);
  2204. if (pipDnsList == NULL) {
  2205. dwErr = GetLastError();
  2206. goto Cleanup;
  2207. }
  2208. Count = 0;
  2209. for (p = wcstok(Servers, L" ,;"); p; p = wcstok(NULL, L" ,;")) {
  2210. Length = sizeof(saddr);
  2211. if (WSAStringToAddressW(p, AF_INET6, NULL, (LPSOCKADDR)&saddr,
  2212. &Length) == NO_ERROR) {
  2213. pipDnsList[Count++] = saddr.sin6_addr;
  2214. }
  2215. }
  2216. Cleanup:
  2217. if (hIf != INVALID_HANDLE_VALUE) {
  2218. RegCloseKey(hIf);
  2219. }
  2220. if (hInterfaces != INVALID_HANDLE_VALUE) {
  2221. RegCloseKey(hInterfaces);
  2222. }
  2223. *pdwNumEntries = Count;
  2224. *ppipDnsList = pipDnsList;
  2225. return dwErr;
  2226. }
  2227. DWORD
  2228. SetDnsServerList(
  2229. IN PWCHAR pwszIfFriendlyName,
  2230. IN PIP_ADAPTER_ADDRESSES pAdapterInfo,
  2231. IN IN6_ADDR *pipDnsList,
  2232. IN DWORD dwNumEntries
  2233. )
  2234. /*++
  2235. Routine Description:
  2236. Writes the list of DNS servers to the registry, overwriting any
  2237. previously list.
  2238. --*/
  2239. {
  2240. DWORD dwErr;
  2241. WCHAR Servers[800], *p = Servers;
  2242. ULONG LengthLeft = 800, Length;
  2243. DWORD i;
  2244. SOCKADDR_IN6 saddr;
  2245. HKEY hInterfaces, hIf;
  2246. PCHAR pszAdapterName;
  2247. dwErr = MapFriendlyNameToAdapterName(NULL, pwszIfFriendlyName,
  2248. pAdapterInfo, &pszAdapterName);
  2249. if (dwErr != NO_ERROR) {
  2250. return dwErr;
  2251. }
  2252. dwErr = RegCreateKeyEx(HKEY_LOCAL_MACHINE, KEY_IPV6_INTERFACES, 0,
  2253. NULL, 0, KEY_ALL_ACCESS, NULL, &hInterfaces, NULL);
  2254. if (dwErr != NO_ERROR) {
  2255. return dwErr;
  2256. }
  2257. dwErr = RegCreateKeyExA(hInterfaces, pszAdapterName, 0,
  2258. NULL, 0, KEY_ALL_ACCESS, NULL, &hIf, NULL);
  2259. if (dwErr != NO_ERROR) {
  2260. RegCloseKey(hInterfaces);
  2261. return dwErr;
  2262. }
  2263. // Compose the string value, making sure to prevent a buffer overrun.
  2264. Servers[0] = L'\0';
  2265. ZeroMemory(&saddr, sizeof(saddr));
  2266. saddr.sin6_family = AF_INET6;
  2267. for (i = 0; i < dwNumEntries; i++) {
  2268. saddr.sin6_addr = pipDnsList[i];
  2269. Length = LengthLeft;
  2270. if (WSAAddressToStringW((LPSOCKADDR)&saddr, sizeof(saddr), NULL,
  2271. p, &Length) != NO_ERROR) {
  2272. continue;
  2273. }
  2274. // Update string taking into account that Length includes the NULL
  2275. // byte.
  2276. LengthLeft -= Length;
  2277. p += (Length-1);
  2278. *p++ = L' ';
  2279. }
  2280. if (p > Servers) {
  2281. // Null out final delimiter.
  2282. p--;
  2283. *p = '\0';
  2284. }
  2285. dwErr = SetString(hIf, KEY_DNS_SERVER_LIST, Servers);
  2286. RegCloseKey(hIf);
  2287. RegCloseKey(hInterfaces);
  2288. return dwErr;
  2289. }
  2290. DWORD
  2291. HandleAddDns(
  2292. IN LPCWSTR pwszMachine,
  2293. IN OUT LPWSTR *ppwcArguments,
  2294. IN DWORD dwCurrentIndex,
  2295. IN DWORD dwArgCount,
  2296. IN DWORD dwFlags,
  2297. IN LPCVOID pvData,
  2298. OUT BOOL *pbDone
  2299. )
  2300. {
  2301. DWORD dwErr = NO_ERROR;
  2302. TAG_TYPE pttTags[] = {{TOKEN_INTERFACE, NS_REQ_PRESENT, FALSE},
  2303. {TOKEN_ADDRESS, NS_REQ_PRESENT, FALSE},
  2304. {TOKEN_INDEX, NS_REQ_ZERO, FALSE}};
  2305. DWORD rgdwTagType[sizeof(pttTags)/sizeof(TAG_TYPE)];
  2306. DWORD i;
  2307. PWCHAR pwszIfFriendlyName = NULL;
  2308. IN6_ADDR ipAddress;
  2309. DWORD dwIndex = -1;
  2310. HKEY hInterfaces, hIf;
  2311. IN6_ADDR *ipDnsList;
  2312. DWORD dwNumEntries;
  2313. PIP_ADAPTER_ADDRESSES pAdapterInfo = NULL;
  2314. // Parse arguments
  2315. dwErr = PreprocessCommand(g_hModule,
  2316. ppwcArguments,
  2317. dwCurrentIndex,
  2318. dwArgCount,
  2319. pttTags,
  2320. sizeof(pttTags)/sizeof(TAG_TYPE),
  2321. 0,
  2322. sizeof(pttTags)/sizeof(TAG_TYPE),
  2323. rgdwTagType );
  2324. if (dwErr isnot NO_ERROR) {
  2325. return dwErr;
  2326. }
  2327. for (i=0; i<dwArgCount-dwCurrentIndex; i++) {
  2328. switch(rgdwTagType[i]) {
  2329. case 0: // INTERFACE
  2330. pwszIfFriendlyName = ppwcArguments[i + dwCurrentIndex];
  2331. break;
  2332. case 1: // ADDRESS
  2333. dwErr = GetIpv6Address(ppwcArguments[i + dwCurrentIndex],
  2334. &ipAddress);
  2335. break;
  2336. case 2: // INDEX
  2337. dwIndex = wcstoul(ppwcArguments[dwCurrentIndex + i], NULL, 10);
  2338. break;
  2339. default:
  2340. dwErr = ERROR_INVALID_SYNTAX;
  2341. break;
  2342. }
  2343. if (dwErr isnot NO_ERROR) {
  2344. return dwErr;
  2345. }
  2346. }
  2347. dwErr = MyGetAdaptersInfo(&pAdapterInfo);
  2348. if (dwErr != NO_ERROR) {
  2349. goto Cleanup;
  2350. }
  2351. dwErr = GetDnsServerList(pwszIfFriendlyName, pAdapterInfo, &ipDnsList,
  2352. &dwNumEntries);
  2353. if (dwErr != NO_ERROR) {
  2354. goto Cleanup;
  2355. }
  2356. if ((dwIndex == -1) || (dwIndex-1 == dwNumEntries)) {
  2357. // Append server.
  2358. ipDnsList[dwNumEntries++] = ipAddress;
  2359. } else if ((dwIndex == 0) || (dwIndex > dwNumEntries)) {
  2360. dwErr = ERROR_INVALID_PARAMETER;
  2361. goto Cleanup;
  2362. } else {
  2363. dwIndex--;
  2364. // Insert server at location 'dwIndex'.
  2365. for (i = dwNumEntries; i > dwIndex; i--) {
  2366. ipDnsList[i] = ipDnsList[i-1];
  2367. }
  2368. ipDnsList[dwIndex] = ipAddress;
  2369. dwNumEntries++;
  2370. }
  2371. dwErr = SetDnsServerList(pwszIfFriendlyName, pAdapterInfo, ipDnsList,
  2372. dwNumEntries);
  2373. Cleanup:
  2374. if (ipDnsList != NULL) {
  2375. FREE(ipDnsList);
  2376. }
  2377. if (pAdapterInfo != NULL) {
  2378. FREE(pAdapterInfo);
  2379. }
  2380. if (dwErr == NO_ERROR) {
  2381. dwErr = ERROR_OKAY;
  2382. }
  2383. return dwErr;
  2384. }
  2385. DWORD
  2386. HandleDelDns(
  2387. IN LPCWSTR pwszMachine,
  2388. IN OUT LPWSTR *ppwcArguments,
  2389. IN DWORD dwCurrentIndex,
  2390. IN DWORD dwArgCount,
  2391. IN DWORD dwFlags,
  2392. IN LPCVOID pvData,
  2393. OUT BOOL *pbDone
  2394. )
  2395. {
  2396. DWORD dwErr = NO_ERROR;
  2397. TAG_TYPE pttTags[] = {{TOKEN_INTERFACE, NS_REQ_PRESENT, FALSE},
  2398. {TOKEN_ADDRESS, NS_REQ_PRESENT, FALSE}};
  2399. DWORD rgdwTagType[sizeof(pttTags)/sizeof(TAG_TYPE)];
  2400. DWORD i;
  2401. PWCHAR pwszIfFriendlyName = NULL;
  2402. IN6_ADDR ipAddress;
  2403. IN6_ADDR *ipDnsList;
  2404. BOOL bAll = FALSE;
  2405. DWORD dwNumEntries;
  2406. PIP_ADAPTER_ADDRESSES pAdapterInfo = NULL;
  2407. // Parse arguments
  2408. dwErr = PreprocessCommand(g_hModule,
  2409. ppwcArguments,
  2410. dwCurrentIndex,
  2411. dwArgCount,
  2412. pttTags,
  2413. sizeof(pttTags)/sizeof(TAG_TYPE),
  2414. 0,
  2415. sizeof(pttTags)/sizeof(TAG_TYPE),
  2416. rgdwTagType );
  2417. if (dwErr isnot NO_ERROR) {
  2418. return dwErr;
  2419. }
  2420. for (i=0; i<dwArgCount-dwCurrentIndex; i++) {
  2421. switch(rgdwTagType[i]) {
  2422. case 0: // INTERFACE
  2423. pwszIfFriendlyName = ppwcArguments[i + dwCurrentIndex];
  2424. break;
  2425. case 1: // ADDRESS
  2426. {
  2427. DWORD dwRes;
  2428. TOKEN_VALUE rgEnums[] = {{TOKEN_VALUE_ALL, 1}};
  2429. dwErr = MatchEnumTag(g_hModule,
  2430. ppwcArguments[i + dwCurrentIndex],
  2431. NUM_TOKENS_IN_TABLE(rgEnums),
  2432. rgEnums,
  2433. &dwRes);
  2434. if (NO_ERROR == dwErr) {
  2435. bAll = TRUE;
  2436. } else {
  2437. dwErr = GetIpv6Address(ppwcArguments[i + dwCurrentIndex],
  2438. &ipAddress);
  2439. }
  2440. break;
  2441. }
  2442. default:
  2443. dwErr = ERROR_INVALID_SYNTAX;
  2444. break;
  2445. }
  2446. if (dwErr isnot NO_ERROR) {
  2447. return dwErr;
  2448. }
  2449. }
  2450. dwErr = MyGetAdaptersInfo(&pAdapterInfo);
  2451. if (dwErr != NO_ERROR) {
  2452. goto Cleanup;
  2453. }
  2454. dwErr = GetDnsServerList(pwszIfFriendlyName, pAdapterInfo, &ipDnsList,
  2455. &dwNumEntries);
  2456. if (dwErr != NO_ERROR) {
  2457. goto Cleanup;
  2458. }
  2459. if (bAll) {
  2460. // Delete all entries.
  2461. dwNumEntries = 0;
  2462. } else {
  2463. // Find and delete the specified entry.
  2464. for (i = 0; i < dwNumEntries; i++) {
  2465. if (!memcmp(&ipAddress, &ipDnsList[i], sizeof(ipAddress))) {
  2466. break;
  2467. }
  2468. }
  2469. if (i == dwNumEntries) {
  2470. goto Cleanup;
  2471. }
  2472. for (; i + 1 < dwNumEntries; i++) {
  2473. ipDnsList[i] = ipDnsList[i+1];
  2474. }
  2475. dwNumEntries--;
  2476. }
  2477. dwErr = SetDnsServerList(pwszIfFriendlyName, pAdapterInfo, ipDnsList,
  2478. dwNumEntries);
  2479. Cleanup:
  2480. if (ipDnsList != NULL) {
  2481. FREE(ipDnsList);
  2482. }
  2483. if (pAdapterInfo != NULL) {
  2484. FREE(pAdapterInfo);
  2485. }
  2486. if (dwErr == NO_ERROR) {
  2487. dwErr = ERROR_OKAY;
  2488. }
  2489. return dwErr;
  2490. }
  2491. DWORD
  2492. ShowIfDnsServers(
  2493. IN BOOL bDump,
  2494. IN PIP_ADAPTER_ADDRESSES pAdapterInfo,
  2495. IN PWCHAR pwszIfFriendlyName,
  2496. IN OUT BOOL *pbHeaderDone
  2497. )
  2498. {
  2499. DWORD i, dwErr;
  2500. WCHAR buff[NI_MAXHOST];
  2501. SOCKADDR_IN6 saddr;
  2502. DWORD Length, dwNumEntries;
  2503. IN6_ADDR *ipDnsList;
  2504. dwErr = GetDnsServerList(pwszIfFriendlyName, pAdapterInfo, &ipDnsList,
  2505. &dwNumEntries);
  2506. if (dwErr != NO_ERROR) {
  2507. goto Error;
  2508. }
  2509. if (!bDump && (dwNumEntries > 0)) {
  2510. // DisplayMessage(g_hModule, MSG_DNS_SERVER_HEADER, pwszIfFriendlyName);
  2511. *pbHeaderDone = TRUE;
  2512. }
  2513. ZeroMemory(&saddr, sizeof(saddr));
  2514. saddr.sin6_family = AF_INET6;
  2515. for (i = 0; i < dwNumEntries; i++) {
  2516. saddr.sin6_addr = ipDnsList[i];
  2517. Length = sizeof(saddr);
  2518. if (WSAAddressToStringW((LPSOCKADDR)&saddr, sizeof(saddr), NULL,
  2519. buff, &Length) != NO_ERROR) {
  2520. continue;
  2521. }
  2522. if (bDump) {
  2523. DisplayMessageT(DMP_IPV6_ADD_DNS);
  2524. DisplayMessageT(DMP_QUOTED_STRING_ARG, TOKEN_INTERFACE,
  2525. pwszIfFriendlyName);
  2526. DisplayMessageT(DMP_STRING_ARG, TOKEN_ADDRESS, buff);
  2527. DisplayMessage(g_hModule, MSG_NEWLINE);
  2528. } else {
  2529. // DisplayMessage(g_hModule, MSG_DNS_SERVER, i+1, buff);
  2530. }
  2531. }
  2532. Error:
  2533. if (ipDnsList != NULL) {
  2534. FREE(ipDnsList);
  2535. }
  2536. return dwErr;
  2537. }
  2538. DWORD
  2539. ShowDnsServers(
  2540. IN BOOL bDump,
  2541. IN PWCHAR pwszIfFriendlyName
  2542. )
  2543. {
  2544. PIP_ADAPTER_ADDRESSES pIf, pAdapterInfo = NULL;
  2545. DWORD dwErr;
  2546. BOOL bHeaderDone = FALSE;
  2547. dwErr = MyGetAdaptersInfo(&pAdapterInfo);
  2548. if (dwErr != NO_ERROR) {
  2549. return dwErr;
  2550. }
  2551. if (pwszIfFriendlyName == NULL) {
  2552. for (pIf = pAdapterInfo; (dwErr == NO_ERROR) && pIf; pIf = pIf->Next) {
  2553. if (pIf->Ipv6IfIndex == 0) {
  2554. continue;
  2555. }
  2556. dwErr = ShowIfDnsServers(bDump, pAdapterInfo, pIf->FriendlyName,
  2557. &bHeaderDone);
  2558. }
  2559. } else {
  2560. dwErr = ShowIfDnsServers(bDump, pAdapterInfo, pwszIfFriendlyName,
  2561. &bHeaderDone);
  2562. }
  2563. if (!bDump) {
  2564. if (!bHeaderDone) {
  2565. DisplayMessage(g_hModule, MSG_IP_NO_ENTRIES);
  2566. }
  2567. if (dwErr == NO_ERROR) {
  2568. dwErr = ERROR_SUPPRESS_OUTPUT;
  2569. }
  2570. }
  2571. FREE(pAdapterInfo);
  2572. return dwErr;
  2573. }
  2574. DWORD
  2575. HandleShowDns(
  2576. IN LPCWSTR pwszMachine,
  2577. IN OUT LPWSTR *ppwcArguments,
  2578. IN DWORD dwCurrentIndex,
  2579. IN DWORD dwArgCount,
  2580. IN DWORD dwFlags,
  2581. IN LPCVOID pvData,
  2582. OUT BOOL *pbDone
  2583. )
  2584. {
  2585. DWORD dwErr = NO_ERROR;
  2586. TAG_TYPE pttTags[] = {{TOKEN_INTERFACE, NS_REQ_ZERO, FALSE}};
  2587. DWORD rgdwTagType[sizeof(pttTags)/sizeof(TAG_TYPE)];
  2588. DWORD i;
  2589. PWCHAR pwszIfFriendlyName = NULL;
  2590. // Parse arguments
  2591. dwErr = PreprocessCommand(g_hModule,
  2592. ppwcArguments,
  2593. dwCurrentIndex,
  2594. dwArgCount,
  2595. pttTags,
  2596. sizeof(pttTags)/sizeof(TAG_TYPE),
  2597. 0,
  2598. sizeof(pttTags)/sizeof(TAG_TYPE),
  2599. rgdwTagType );
  2600. if (dwErr isnot NO_ERROR) {
  2601. return dwErr;
  2602. }
  2603. for (i=0; i<dwArgCount-dwCurrentIndex; i++) {
  2604. switch(rgdwTagType[i]) {
  2605. case 0: // INTERFACE
  2606. pwszIfFriendlyName = ppwcArguments[i + dwCurrentIndex];
  2607. break;
  2608. default:
  2609. dwErr = ERROR_INVALID_SYNTAX;
  2610. break;
  2611. }
  2612. if (dwErr isnot NO_ERROR) {
  2613. return dwErr;
  2614. }
  2615. }
  2616. dwErr = ShowDnsServers(FALSE, pwszIfFriendlyName);
  2617. if (dwErr == NO_ERROR) {
  2618. dwErr = ERROR_OKAY;
  2619. }
  2620. return dwErr;
  2621. }