Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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