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.

2500 lines
59 KiB

  1. #include "precomp.h"
  2. #pragma hdrstop
  3. #ifdef SN_UNICODE
  4. # define sn_strlen wcslen
  5. # define sn_strcpy wcscpy
  6. # define sn_sprintf wsprintf
  7. # define sn_strcmp wcscmp
  8. # define SN_EMPTYSTRING L""
  9. # define SN_L L
  10. #else
  11. # define sn_strlen strlen
  12. # define sn_strcpy strcpy
  13. # define sn_sprintf sprintf
  14. # define sn_strcmp strcmp
  15. # define SN_EMPTYSTRING ""
  16. # define SN_L
  17. #endif
  18. IPV4_ADDRESS g_ipGrpAddr,
  19. g_ipGrpMask;
  20. SCOPE_NAME g_snScopeName;
  21. enum RouterOps
  22. {
  23. ADD_BOUNDARY = 1,
  24. DELETE_BOUNDARY,
  25. ADD_SCOPE,
  26. DELETE_SCOPE,
  27. SET_SCOPE
  28. };
  29. typedef struct _SCOPE_ENTRY {
  30. IPV4_ADDRESS ipGroupAddress;
  31. IPV4_ADDRESS ipGroupMask;
  32. ULONG ulNumNames;
  33. BOOL bDivisible;
  34. LANGID idLanguage;
  35. SCOPE_NAME_BUFFER snScopeNameBuffer;
  36. DWORD dwNumInterfaces;
  37. } SCOPE_ENTRY, *PSCOPE_ENTRY;
  38. #define MIN_SCOPE_ADDR 0xef000000
  39. #define MAX_SCOPE_ADDR (0xefff0000 - 1)
  40. DWORD
  41. UpdateBoundaryBlock(
  42. IN DWORD dwAction,
  43. IN PBYTE pib,
  44. OUT PBYTE *ppibNew,
  45. IN OUT DWORD *pdwBlkSize,
  46. IN OUT DWORD *pdwCount,
  47. OUT BOOL *bChanged
  48. );
  49. PSCOPE_ENTRY
  50. FindScopeByPrefix(
  51. IN IPV4_ADDRESS ipGroupAddress,
  52. IN IPV4_ADDRESS ipGroupMask,
  53. IN PSCOPE_ENTRY pScopes,
  54. IN ULONG ulNumScopes
  55. )
  56. {
  57. DWORD dwInd;
  58. for (dwInd = 0; dwInd < ulNumScopes; dwInd++)
  59. {
  60. if ( pScopes[dwInd].ipGroupAddress == ipGroupAddress
  61. && pScopes[dwInd].ipGroupMask == ipGroupMask )
  62. {
  63. return &pScopes[dwInd];
  64. }
  65. }
  66. return NULL;
  67. }
  68. DWORD
  69. FindScopeByName(
  70. IN SCOPE_NAME snScopeName,
  71. IN PSCOPE_ENTRY pScopes,
  72. IN ULONG ulNumScopes,
  73. OUT PSCOPE_ENTRY *ppScope
  74. )
  75. {
  76. DWORD dwErr = NO_ERROR;
  77. ULONG i, j, dwCnt = 0;
  78. for (i = 0; i < ulNumScopes; i++)
  79. {
  80. if ( !sn_strcmp(snScopeName, pScopes[i].snScopeNameBuffer))
  81. {
  82. *ppScope = &pScopes[i];
  83. dwCnt++;
  84. }
  85. }
  86. switch (dwCnt)
  87. {
  88. case 0:
  89. *ppScope = NULL;
  90. return ERROR_NOT_FOUND;
  91. case 1:
  92. return NO_ERROR;
  93. default:
  94. return ERROR_MORE_DATA;
  95. }
  96. }
  97. DWORD
  98. MakeInfoFromScopes2(
  99. OUT PBYTE pBuffer,
  100. IN OUT ULONG *pulBufferLen,
  101. IN PSCOPE_ENTRY pScopes,
  102. IN ULONG ulNumScopes
  103. )
  104. /*++
  105. Description:
  106. Compose registry block from array of scopes.
  107. --*/
  108. {
  109. DWORD dwLen, i, dwSize, dwNumNames, j, dwLanguage, dwFlags;
  110. PLIST_ENTRY pleNode;
  111. if (ulNumScopes is 0) {
  112. *pulBufferLen = 0;
  113. return NO_ERROR;
  114. }
  115. // Compute size needed
  116. dwSize = sizeof(DWORD);
  117. for (i=0; i< ulNumScopes; i++)
  118. {
  119. dwSize += 2 * sizeof(IPV4_ADDRESS) + 2 * sizeof(DWORD);
  120. // Currently we only store at most one name.
  121. for (j=0; j<pScopes[i].ulNumNames; j++)
  122. {
  123. dwSize += (DWORD)(2*sizeof(DWORD)
  124. + sn_strlen(pScopes[i].snScopeNameBuffer) * sizeof(SN_CHAR));
  125. }
  126. }
  127. if (dwSize > *pulBufferLen)
  128. {
  129. *pulBufferLen = dwSize;
  130. return ERROR_INSUFFICIENT_BUFFER;
  131. }
  132. //
  133. // Save scope count in first DWORD
  134. //
  135. *((PDWORD) pBuffer) = ulNumScopes;
  136. pBuffer += sizeof(DWORD);
  137. //
  138. // Now step through and add each scope to the buffer
  139. //
  140. for (i=0; i< ulNumScopes; i++)
  141. {
  142. // Copy scope address, and mask
  143. dwLen = 2 * sizeof(IPV4_ADDRESS);
  144. CopyMemory(pBuffer, &pScopes[i], dwLen);
  145. pBuffer += dwLen;
  146. // Copy flags
  147. dwFlags = pScopes[i].bDivisible;
  148. CopyMemory(pBuffer, &dwFlags, sizeof(dwFlags));
  149. pBuffer += sizeof(dwFlags);
  150. // Copy # of names
  151. CopyMemory(pBuffer, &pScopes[i].ulNumNames, sizeof(DWORD));
  152. pBuffer += sizeof(DWORD);
  153. // Currently we only save at most one name
  154. for (j=0; j<pScopes[i].ulNumNames; j++)
  155. {
  156. // Save language
  157. dwLanguage = pScopes[i].idLanguage;
  158. CopyMemory(pBuffer, &dwLanguage, sizeof(dwLanguage));
  159. pBuffer += sizeof(dwLanguage);
  160. // Copy scope name (save length in words)
  161. dwLen = sn_strlen(pScopes[i].snScopeNameBuffer);
  162. CopyMemory(pBuffer, &dwLen, sizeof(DWORD));
  163. pBuffer += sizeof(DWORD);
  164. dwLen *= sizeof(SN_CHAR);
  165. if (dwLen)
  166. {
  167. CopyMemory(pBuffer, pScopes[i].snScopeNameBuffer, dwLen);
  168. pBuffer += dwLen;
  169. }
  170. }
  171. }
  172. return NO_ERROR;
  173. }
  174. DWORD
  175. MakeInfoFromScopes(
  176. OUT PBYTE *ppibNew,
  177. OUT DWORD *pdwSize,
  178. IN PSCOPE_ENTRY pScopes,
  179. IN ULONG ulNumScopes
  180. )
  181. /*++
  182. Description:
  183. Caller is responsible for freeing buffer returned.
  184. --*/
  185. {
  186. *pdwSize = 0;
  187. *ppibNew = NULL;
  188. if (MakeInfoFromScopes2(NULL, pdwSize, pScopes, ulNumScopes)
  189. is ERROR_INSUFFICIENT_BUFFER)
  190. {
  191. *ppibNew = MALLOC( *pdwSize );
  192. if ( *ppibNew == NULL )
  193. {
  194. DisplayMessage( g_hModule, MSG_IP_NOT_ENOUGH_MEMORY );
  195. return ERROR_NOT_ENOUGH_MEMORY;
  196. }
  197. }
  198. return MakeInfoFromScopes2(*ppibNew, pdwSize, pScopes, ulNumScopes);
  199. }
  200. PSCOPE_ENTRY
  201. GetScopesFromInfo(
  202. IN PBYTE pBuffer,
  203. OUT PULONG pulNumScopes
  204. )
  205. /*++
  206. Description:
  207. Convert a registry block into an array of scope information.
  208. Caller is responsible for freeing pointer returned.
  209. --*/
  210. {
  211. PSCOPE_ENTRY pScopes;
  212. DWORD dwLen, i, dwNumNames, j, dwLanguage, dwFlags;
  213. if (pBuffer is NULL)
  214. {
  215. *pulNumScopes = 0;
  216. return NULL;
  217. }
  218. //
  219. // Retrieve scope count from first DWORD
  220. //
  221. *pulNumScopes = *((PDWORD) pBuffer);
  222. pBuffer += sizeof(DWORD);
  223. //
  224. // Malloc enough space for pScopes
  225. //
  226. pScopes = MALLOC( (*pulNumScopes) * sizeof(SCOPE_ENTRY) );
  227. if (pScopes is NULL)
  228. {
  229. *pulNumScopes = 0;
  230. return NULL;
  231. }
  232. //
  233. // Now step through and add each scope to the array
  234. //
  235. for (i=0; i< *pulNumScopes; i++)
  236. {
  237. // Copy scope address, and mask
  238. dwLen = 2 * sizeof(IPV4_ADDRESS);
  239. CopyMemory(&pScopes[i], pBuffer, dwLen);
  240. pBuffer += dwLen;
  241. // Get flags
  242. CopyMemory(&dwFlags, pBuffer, sizeof(dwFlags));
  243. pScopes[i].bDivisible = dwFlags;
  244. pBuffer += sizeof(dwFlags);
  245. // Get # of names
  246. CopyMemory(&dwNumNames, pBuffer, sizeof(DWORD));
  247. pScopes[i].ulNumNames = dwNumNames;
  248. pBuffer += sizeof(DWORD);
  249. // Get names. Currently, we'll only keep the last name (if any)
  250. // and throw out the rest.
  251. for (j=0; j<dwNumNames; j++)
  252. {
  253. // Set language name
  254. CopyMemory(&dwLanguage, pBuffer, sizeof(dwLanguage));
  255. pBuffer += sizeof(dwLanguage);
  256. pScopes[i].idLanguage = (LANGID)dwLanguage;
  257. CopyMemory(&dwLen, pBuffer, sizeof(DWORD));
  258. pBuffer += sizeof(DWORD);
  259. CopyMemory( pScopes[i].snScopeNameBuffer,
  260. pBuffer,
  261. dwLen * sizeof(SN_CHAR) );
  262. pScopes[i].snScopeNameBuffer[ dwLen ] = '\0';
  263. pBuffer += dwLen * sizeof(SN_CHAR);
  264. pScopes[i].ulNumNames = 1;
  265. }
  266. pScopes[i].dwNumInterfaces = 0; // this value is ignored
  267. }
  268. return pScopes;
  269. }
  270. PSCOPE_ENTRY
  271. GetScopes(
  272. OUT PULONG pulNumScopes,
  273. OUT PBYTE *ppBuffer
  274. )
  275. /*++
  276. Description:
  277. Creates a SCOPE_ENTRY array by parsing the info block
  278. Caller is responsible for freeing both the pointer returned
  279. and the buffer passed back.
  280. Called by:
  281. ShowBoundaryInfoForInterface(), UpdateScopeBlock()
  282. --*/
  283. {
  284. DWORD i, dwLen, dwErr, dwBlkSize, dwCount;
  285. DWORD dwInd;
  286. PSCOPE_ENTRY pScopes;
  287. if ( IpmontrGetInfoBlockFromGlobalInfo( IP_MCAST_BOUNDARY_INFO,
  288. ppBuffer,
  289. &dwBlkSize,
  290. &dwCount ) isnot NO_ERROR)
  291. {
  292. *pulNumScopes = 0;
  293. return NULL;
  294. }
  295. pScopes = GetScopesFromInfo(*ppBuffer, pulNumScopes);
  296. return pScopes;
  297. }
  298. DWORD
  299. ScopeNameToPrefix(
  300. IN SCOPE_NAME snScopeName,
  301. OUT IPV4_ADDRESS *pipScopeAddr,
  302. OUT IPV4_ADDRESS *pipScopeMask
  303. )
  304. {
  305. DWORD dwErr = ERROR_NOT_FOUND;
  306. ULONG ulNumScopes;
  307. PBYTE pBuffer = NULL;
  308. PSCOPE_ENTRY pScopes, pScope;
  309. // If first character is a digit, then assume it's
  310. // an address, not a name.
  311. if (iswdigit(snScopeName[0]))
  312. {
  313. dwErr = GetIpAddress(snScopeName, pipScopeAddr);
  314. if (dwErr is NO_ERROR)
  315. {
  316. return NO_ERROR;
  317. }
  318. }
  319. pScopes = GetScopes( &ulNumScopes, &pBuffer );
  320. if (pScopes)
  321. {
  322. dwErr = FindScopeByName(snScopeName, pScopes, ulNumScopes, &pScope);
  323. if (dwErr is NO_ERROR)
  324. {
  325. *pipScopeAddr = pScope->ipGroupAddress;
  326. *pipScopeMask = pScope->ipGroupMask;
  327. dwErr = NO_ERROR;
  328. }
  329. FREE(pScopes);
  330. }
  331. if (pBuffer)
  332. FREE(pBuffer);
  333. return dwErr;
  334. }
  335. DWORD
  336. UpdateScope(
  337. IN PSCOPE_ENTRY pScopeToUpdate,
  338. IN PSCOPE_ENTRY pScopes,
  339. IN ULONG ulNumScopes,
  340. OUT PBYTE *ppibNew,
  341. OUT DWORD *pdwSizeNew
  342. )
  343. /*++
  344. Description:
  345. Caller is responsible for freeing buffer returned.
  346. --*/
  347. {
  348. // Update the scope name
  349. sn_strcpy(pScopeToUpdate->snScopeNameBuffer, g_snScopeName);
  350. pScopeToUpdate->ulNumNames = 1;
  351. pScopeToUpdate->idLanguage = GetUserDefaultLangID();
  352. // Now convert the array to a buffer
  353. return MakeInfoFromScopes( ppibNew, pdwSizeNew, pScopes, ulNumScopes);
  354. }
  355. DWORD
  356. DeleteBoundaryFromInterface(
  357. IN LPCWSTR pwszIfName,
  358. IN PSCOPE_ENTRY pScopeToDelete
  359. )
  360. {
  361. BOOL bChanged;
  362. DWORD dwErr, dwBlkSize, dwCount, dwIfType;
  363. PBYTE pibNew, pib;
  364. dwErr = IpmontrGetInfoBlockFromInterfaceInfo( pwszIfName,
  365. IP_MCAST_BOUNDARY_INFO,
  366. &pib,
  367. &dwBlkSize,
  368. &dwCount,
  369. &dwIfType );
  370. if (dwErr is ERROR_NOT_FOUND)
  371. return NO_ERROR;
  372. if (dwErr isnot NO_ERROR)
  373. return dwErr;
  374. dwErr = UpdateBoundaryBlock( DELETE_BOUNDARY,
  375. pib,
  376. &pibNew,
  377. &dwBlkSize,
  378. &dwCount,
  379. &bChanged );
  380. if (dwErr is NO_ERROR && bChanged)
  381. {
  382. dwErr = IpmontrSetInfoBlockInInterfaceInfo( pwszIfName,
  383. IP_MCAST_BOUNDARY_INFO,
  384. pibNew,
  385. dwBlkSize,
  386. dwCount );
  387. }
  388. if (pib)
  389. FREE(pib);
  390. if (pibNew)
  391. FREE(pibNew);
  392. return dwErr;
  393. }
  394. DWORD
  395. DeleteScopeBoundaries(
  396. IN PSCOPE_ENTRY pScopeToDelete
  397. )
  398. {
  399. DWORD dwErr, dwCount, dwTotal, i;
  400. PMPR_INTERFACE_0 pmi0;
  401. // Enumerate interfaces
  402. dwErr = IpmontrInterfaceEnum((PBYTE *) &pmi0, &dwCount, &dwTotal);
  403. if (dwErr isnot NO_ERROR)
  404. {
  405. DisplayError(g_hModule, dwErr);
  406. return dwErr;
  407. }
  408. // Delete scope boundaries for each interface
  409. for ( i = 0; i < dwCount && dwErr is NO_ERROR; i++)
  410. {
  411. dwErr = DeleteBoundaryFromInterface( pmi0[i].wszInterfaceName,
  412. pScopeToDelete );
  413. // Ignore ERROR_NO_SUCH_INTERFACE since it may be that IP
  414. // is not enabled on the interface, so we expect to get this
  415. // error sometimes.
  416. if (dwErr is ERROR_NO_SUCH_INTERFACE)
  417. {
  418. dwErr = NO_ERROR;
  419. }
  420. }
  421. return dwErr;
  422. }
  423. DWORD
  424. DeleteScope(
  425. IN PSCOPE_ENTRY pScopeToDelete,
  426. IN PSCOPE_ENTRY pScopes,
  427. IN ULONG *pulNumScopes,
  428. OUT PBYTE *ppibNew,
  429. OUT DWORD *pdwSizeNew
  430. )
  431. /*++
  432. Description:
  433. Creates a new info block which does not include the scope given
  434. by pScopeToDelete.
  435. Caller is responsible for freeing buffer returned.
  436. Called by:
  437. UpdateScopeBlock()
  438. --*/
  439. {
  440. DWORD dwErr;
  441. // Delete all boundaries for this scope
  442. dwErr = DeleteScopeBoundaries(pScopeToDelete);
  443. if (dwErr isnot NO_ERROR)
  444. return dwErr;
  445. // Delete the scope from the array
  446. MoveMemory( pScopeToDelete,
  447. pScopeToDelete+1,
  448. ((PBYTE)(pScopes + *pulNumScopes))
  449. - ((PBYTE)(pScopeToDelete + 1) ));
  450. (*pulNumScopes)--;
  451. // Now convert the array to a buffer
  452. return MakeInfoFromScopes( ppibNew, pdwSizeNew, pScopes, *pulNumScopes);
  453. }
  454. DWORD
  455. AddScope(
  456. IN OUT PSCOPE_ENTRY *ppScopes,
  457. IN ULONG *pulNumScopes,
  458. OUT PBYTE *ppibNew,
  459. OUT DWORD *pdwSizeNew
  460. )
  461. /*++
  462. Description:
  463. Creates a new info block which includes the scope given
  464. by g_snScopeName, g_dwDstAddr, and g_dwDstMask.
  465. Caller is responsible for freeing buffer returned.
  466. Called by:
  467. UpdateScopeBlock()
  468. --*/
  469. {
  470. PBYTE *pBuff;
  471. DWORD dwRes = NO_ERROR,
  472. dwInd,
  473. dwSize = 0,
  474. dwSizeReqd = 0;
  475. SCOPE_ENTRY *pScopes = *ppScopes;
  476. do
  477. {
  478. // Make room for the new scope
  479. if (*pulNumScopes > 0)
  480. pScopes = REALLOC( pScopes,
  481. (*pulNumScopes + 1) * sizeof(SCOPE_ENTRY) );
  482. else
  483. pScopes = MALLOC( sizeof(SCOPE_ENTRY) );
  484. if (!pScopes)
  485. return ERROR_NOT_ENOUGH_MEMORY;
  486. dwInd = (*pulNumScopes)++;
  487. // Fill in the new scope
  488. ZeroMemory(&pScopes[dwInd], sizeof(SCOPE_ENTRY));
  489. pScopes[dwInd].ipGroupAddress = g_ipGrpAddr;
  490. pScopes[dwInd].ipGroupMask = g_ipGrpMask;
  491. sn_strcpy(pScopes[dwInd].snScopeNameBuffer, g_snScopeName);
  492. pScopes[dwInd].ulNumNames = 1;
  493. pScopes[dwInd].idLanguage = GetUserDefaultLangID();
  494. // Now convert the array to a buffer
  495. dwRes = MakeInfoFromScopes( ppibNew, &dwSize, pScopes, *pulNumScopes);
  496. } while ( FALSE );
  497. *pdwSizeNew = dwSize;
  498. *ppScopes = pScopes;
  499. return dwRes;
  500. }
  501. BOOL
  502. IsContiguous(
  503. IN IPV4_ADDRESS dwMask
  504. )
  505. {
  506. register int i;
  507. dwMask = ntohl(dwMask);
  508. // Set i to index of lowest 1 bit, or 32 if none
  509. for (i=0; i<32 && !(dwMask & (1<<i)); i++);
  510. // Set i to index of lowest 0 bit greater than the 1 bit found,
  511. // or 32 if none
  512. for (; i<32 && (dwMask & (1<<i)); i++);
  513. // Mask is contiguous if we got up to 32 without finding such
  514. // a 0 bit.
  515. return (i is 32);
  516. }
  517. DWORD
  518. UpdateScopeBlock(
  519. DWORD dwAction,
  520. PBYTE pib,
  521. PBYTE *ppibNew,
  522. DWORD *pdwBlkSize,
  523. DWORD *pdwCount
  524. )
  525. /*++
  526. Description:
  527. Caller is responsible for freeing buffer returned.
  528. Called by:
  529. IpAddSetDelScope()
  530. --*/
  531. {
  532. DWORD dwRes = (DWORD) -1,
  533. dwInd = 0,
  534. dwSize = 0;
  535. ULONG ulNumScopes = 0;
  536. PSCOPE_ENTRY pScopes = NULL,
  537. pFoundScope = NULL;
  538. do
  539. {
  540. *ppibNew = NULL;
  541. *pdwBlkSize = 0;
  542. *pdwCount = 0;
  543. //
  544. // Verify scope info.
  545. //
  546. if ( ( g_ipGrpAddr & g_ipGrpMask ) != g_ipGrpAddr
  547. || ntohl(g_ipGrpAddr) < MIN_SCOPE_ADDR
  548. || ntohl(g_ipGrpAddr) > MAX_SCOPE_ADDR)
  549. {
  550. dwRes = ERROR_INVALID_PARAMETER;
  551. break;
  552. }
  553. // Make sure mask is contiguous
  554. if (!IsContiguous(g_ipGrpMask))
  555. {
  556. char buff[20], *lpstr;
  557. lpstr = inet_ntoa( *((struct in_addr *) &g_ipGrpMask));
  558. if (lpstr != NULL)
  559. {
  560. strcpy( buff, lpstr );
  561. DisplayMessage( g_hModule, MSG_IP_BAD_IP_MASK, buff );
  562. }
  563. break;
  564. }
  565. //
  566. // Find if specified scope is present
  567. //
  568. pScopes = GetScopesFromInfo( pib, &ulNumScopes );
  569. if ( pScopes )
  570. {
  571. pFoundScope = FindScopeByPrefix( g_ipGrpAddr,
  572. g_ipGrpMask,
  573. pScopes,
  574. ulNumScopes
  575. );
  576. }
  577. //
  578. // Update the scope infoblock.
  579. //
  580. switch ( dwAction )
  581. {
  582. case ADD_SCOPE:
  583. //
  584. // If scope is not present, add it. Else return error.
  585. //
  586. if ( !pFoundScope )
  587. {
  588. dwRes = AddScope( &pScopes, &ulNumScopes, ppibNew, &dwSize );
  589. if ( dwRes == NO_ERROR )
  590. {
  591. *pdwBlkSize = dwSize;
  592. *pdwCount = 1;
  593. }
  594. break;
  595. }
  596. // else fall through into SET_SCOPE.
  597. case SET_SCOPE:
  598. //
  599. // if scope present, update it.
  600. //
  601. if ( pFoundScope )
  602. {
  603. dwRes = UpdateScope( pFoundScope,
  604. pScopes,
  605. ulNumScopes,
  606. ppibNew,
  607. &dwSize );
  608. if ( dwRes == NO_ERROR )
  609. {
  610. *pdwBlkSize = dwSize;
  611. *pdwCount = 1;
  612. }
  613. }
  614. else
  615. {
  616. dwRes = ERROR_INVALID_PARAMETER;
  617. }
  618. break;
  619. case DELETE_SCOPE:
  620. //
  621. // Delete scope only if present.
  622. //
  623. if ( pFoundScope )
  624. {
  625. dwRes = DeleteScope( pFoundScope,
  626. pScopes,
  627. &ulNumScopes,
  628. ppibNew,
  629. &dwSize );
  630. if ( dwRes == NO_ERROR )
  631. {
  632. *pdwBlkSize = dwSize;
  633. *pdwCount = (dwSize>0)? 1 : 0;
  634. }
  635. }
  636. else
  637. {
  638. dwRes = ERROR_INVALID_PARAMETER;
  639. }
  640. break;
  641. }
  642. } while ( FALSE );
  643. if (pScopes)
  644. FREE( pScopes );
  645. return dwRes;
  646. }
  647. DWORD
  648. VerifyBoundaryPrefix(
  649. IPV4_ADDRESS ipAddr,
  650. IPV4_ADDRESS ipMask
  651. )
  652. {
  653. WCHAR wstr1[20], wstr2[20];
  654. //
  655. // Verify boundary info.
  656. //
  657. if (ntohl(ipAddr) < MIN_SCOPE_ADDR
  658. || ntohl(ipAddr) > MAX_SCOPE_ADDR)
  659. {
  660. MakeAddressStringW(wstr1, htonl(MIN_SCOPE_ADDR));
  661. MakeAddressStringW(wstr2, htonl(MAX_SCOPE_ADDR));
  662. DisplayMessage( g_hModule,
  663. EMSG_INVALID_ADDR,
  664. wstr1,
  665. wstr2 );
  666. return ERROR_INVALID_PARAMETER;
  667. }
  668. if ( ( ipAddr & ipMask ) != ipAddr )
  669. {
  670. DisplayMessage( g_hModule, EMSG_PREFIX_ERROR );
  671. return ERROR_INVALID_PARAMETER;
  672. }
  673. // Make sure mask is contiguous
  674. if (!IsContiguous(ipMask))
  675. {
  676. char buff[20], *lpstr;
  677. lpstr = inet_ntoa( *((struct in_addr *) &g_ipGrpMask));
  678. if (lpstr != NULL)
  679. {
  680. strcpy( buff, lpstr );
  681. DisplayMessage( g_hModule, MSG_IP_BAD_IP_MASK, buff );
  682. }
  683. return ERROR_INVALID_PARAMETER;
  684. }
  685. return NO_ERROR;
  686. }
  687. DWORD
  688. IpAddSetDelScope(
  689. DWORD dwAction,
  690. PWCHAR *ppwcArguments,
  691. DWORD dwCurrentIndex,
  692. DWORD dwArgCount
  693. )
  694. {
  695. DWORD dwErr;
  696. TAG_TYPE pttTags[] = {{TOKEN_GROUP_ADDRESS,FALSE,FALSE},
  697. {TOKEN_GROUP_MASK, FALSE,FALSE},
  698. {TOKEN_SCOPE_NAME, FALSE,FALSE}};
  699. SCOPE_NAME_BUFFER snScopeName;
  700. DWORD rgdwTagType[sizeof(pttTags)/sizeof(TAG_TYPE)];
  701. IPV4_ADDRESS ipGroup, ipMask;
  702. DWORD dwBlkSize, dwCount, i, dwNumParsed;
  703. PBYTE pib, pibNew = NULL;
  704. DWORD dwArgsReqd = (dwAction is DELETE_SCOPE)? 1 : 3;
  705. PWCHAR p;
  706. // Do generic processing
  707. dwErr = PreHandleCommand( ppwcArguments,
  708. dwCurrentIndex,
  709. dwArgCount,
  710. pttTags,
  711. sizeof(pttTags)/sizeof(TAG_TYPE),
  712. dwArgsReqd,
  713. sizeof(pttTags)/sizeof(TAG_TYPE),
  714. rgdwTagType );
  715. if (dwErr)
  716. {
  717. return dwErr;
  718. }
  719. g_ipGrpAddr = g_ipGrpMask = 0;
  720. for(i = 0; i < dwArgCount - dwCurrentIndex; i ++)
  721. {
  722. switch (rgdwTagType[i])
  723. {
  724. case 1: // GRPMASK
  725. {
  726. dwErr = GetIpMask(ppwcArguments[i + dwCurrentIndex],
  727. &g_ipGrpMask);
  728. if (dwErr is ERROR_INVALID_PARAMETER)
  729. {
  730. DisplayMessage( g_hModule, MSG_IP_BAD_IP_ADDR,
  731. ppwcArguments[i + dwCurrentIndex]);
  732. DispTokenErrMsg(g_hModule, MSG_IP_BAD_OPTION_VALUE,
  733. pttTags[rgdwTagType[i]].pwszTag,
  734. ppwcArguments[i + dwCurrentIndex]);
  735. return NO_ERROR;
  736. }
  737. break;
  738. }
  739. case 0: // GRPADDR
  740. {
  741. dwErr = GetIpPrefix(ppwcArguments[i + dwCurrentIndex],
  742. &g_ipGrpAddr,
  743. &g_ipGrpMask);
  744. if (!((dwErr is ERROR_INVALID_PARAMETER)
  745. && (dwAction is DELETE_SCOPE)))
  746. {
  747. break;
  748. }
  749. // FALLTHROUGH
  750. }
  751. case 2 : // SCOPENAME
  752. {
  753. // Strip leading and trailing whitespace
  754. for (p = ppwcArguments[i + dwCurrentIndex]; iswspace(*p); p++);
  755. while (iswspace( p[wcslen(p) - 1] ))
  756. {
  757. p[ wcslen(p)-1 ] = 0;
  758. }
  759. if (wcslen(p) > MAX_SCOPE_NAME_LEN)
  760. {
  761. DisplayMessage( g_hModule,
  762. EMSG_SCOPE_NAME_TOO_LONG,
  763. MAX_SCOPE_NAME_LEN );
  764. return NO_ERROR;
  765. }
  766. sn_strcpy( snScopeName, p);
  767. g_snScopeName = snScopeName;
  768. if (dwAction is DELETE_SCOPE)
  769. {
  770. dwErr = ScopeNameToPrefix(snScopeName,
  771. &g_ipGrpAddr,
  772. &g_ipGrpMask);
  773. if (dwErr is ERROR_MORE_DATA)
  774. {
  775. DisplayMessage( g_hModule, EMSG_AMBIGUOUS_SCOPE_NAME,
  776. ppwcArguments[i + dwCurrentIndex]);
  777. return NO_ERROR;
  778. }
  779. }
  780. break;
  781. }
  782. }
  783. }
  784. if (dwErr isnot NO_ERROR)
  785. {
  786. return dwErr;
  787. }
  788. if (!g_ipGrpAddr || !g_ipGrpMask)
  789. {
  790. return ERROR_INVALID_SYNTAX;
  791. }
  792. dwErr = VerifyBoundaryPrefix(g_ipGrpAddr, g_ipGrpMask);
  793. if (dwErr)
  794. {
  795. return NO_ERROR;
  796. }
  797. do {
  798. dwErr = IpmontrGetInfoBlockFromGlobalInfo( IP_MCAST_BOUNDARY_INFO,
  799. &pib,
  800. &dwBlkSize,
  801. &dwCount );
  802. if (dwErr is ERROR_NOT_FOUND)
  803. {
  804. //
  805. // No info of this type is currently present
  806. //
  807. dwErr = NO_ERROR;
  808. dwCount = 1;
  809. }
  810. if (dwErr isnot NO_ERROR)
  811. break;
  812. dwErr = UpdateScopeBlock( dwAction,
  813. pib,
  814. &pibNew,
  815. &dwBlkSize,
  816. &dwCount );
  817. if (dwErr isnot NO_ERROR)
  818. break;
  819. dwErr = IpmontrSetInfoBlockInGlobalInfo( IP_MCAST_BOUNDARY_INFO,
  820. pibNew,
  821. dwBlkSize,
  822. dwCount );
  823. } while (FALSE);
  824. if (pib)
  825. HeapFree(GetProcessHeap(), 0 , pib);
  826. if (pibNew)
  827. HeapFree(GetProcessHeap(), 0 , pibNew);
  828. return dwErr;
  829. }
  830. DWORD
  831. HandleIpAddScope(
  832. IN LPCWSTR pwszMachine,
  833. IN OUT LPWSTR *ppwcArguments,
  834. IN DWORD dwCurrentIndex,
  835. IN DWORD dwArgCount,
  836. IN DWORD dwFlags,
  837. IN LPCVOID pvData,
  838. OUT BOOL *pbDone
  839. )
  840. /*++
  841. Routine Description:
  842. Arguments:
  843. ppwcArguments - Argument array
  844. dwCurrentIndex - ppwcArguments[dwCurrentIndex] is the first arg
  845. dwArgCount - ppwcArguments[dwArgCount - 1] is the last arg
  846. Return Value:
  847. NO_ERROR
  848. --*/
  849. {
  850. return IpAddSetDelScope( ADD_SCOPE,
  851. ppwcArguments,
  852. dwCurrentIndex,
  853. dwArgCount );
  854. }
  855. DWORD
  856. HandleIpDelScope(
  857. IN LPCWSTR pwszMachine,
  858. IN OUT LPWSTR *ppwcArguments,
  859. IN DWORD dwCurrentIndex,
  860. IN DWORD dwArgCount,
  861. IN DWORD dwFlags,
  862. IN LPCVOID pvData,
  863. OUT BOOL *pbDone
  864. )
  865. /*++
  866. Routine Description:
  867. Arguments:
  868. ppwcArguments - Argument array
  869. dwCurrentIndex - ppwcArguments[dwCurrentIndex] is the first arg
  870. dwArgCount - ppwcArguments[dwArgCount - 1] is the last arg
  871. Return Value:
  872. NO_ERROR
  873. --*/
  874. {
  875. return IpAddSetDelScope( DELETE_SCOPE,
  876. ppwcArguments,
  877. dwCurrentIndex,
  878. dwArgCount );
  879. }
  880. DWORD
  881. HandleIpSetScope(
  882. IN LPCWSTR pwszMachine,
  883. IN OUT LPWSTR *ppwcArguments,
  884. IN DWORD dwCurrentIndex,
  885. IN DWORD dwArgCount,
  886. IN DWORD dwFlags,
  887. IN LPCVOID pvData,
  888. OUT BOOL *pbDone
  889. )
  890. /*++
  891. Routine Description:
  892. Arguments:
  893. ppwcArguments - Argument array
  894. dwCurrentIndex - ppwcArguments[dwCurrentIndex] is the first arg
  895. dwArgCount - ppwcArguments[dwArgCount - 1] is the last arg
  896. Return Value:
  897. NO_ERROR
  898. --*/
  899. {
  900. return IpAddSetDelScope( SET_SCOPE,
  901. ppwcArguments,
  902. dwCurrentIndex,
  903. dwArgCount );
  904. }
  905. DWORD
  906. ShowScopes(
  907. IN HANDLE hFile
  908. )
  909. {
  910. DWORD dwRes = (DWORD) -1,
  911. dwCnt = 0,
  912. dwInd = 0,
  913. dwGlobalSize = 0;
  914. ULONG ulNumScopes = 0;
  915. CHAR szAddr1[ ADDR_LENGTH ],
  916. szAddr2[ ADDR_LENGTH ];
  917. PSCOPE_ENTRY pScope,
  918. pScopes;
  919. HANDLE hTransport = (HANDLE) NULL;
  920. PBYTE pScopesBuffer;
  921. SCOPE_NAME_BUFFER snScopeNameBuffer;
  922. do
  923. {
  924. pScopes = GetScopes( &ulNumScopes, &pScopesBuffer );
  925. if (hFile is NULL)
  926. {
  927. if (ulNumScopes)
  928. {
  929. DisplayMessage( g_hModule, MSG_RTR_SCOPE_HDR );
  930. }
  931. else
  932. {
  933. DisplayMessage( g_hModule, MSG_IP_NO_ENTRIES );
  934. }
  935. }
  936. //
  937. // Enumerate the scopes
  938. //
  939. for ( dwCnt = 0; dwCnt < ulNumScopes; dwCnt++ )
  940. {
  941. pScope = &pScopes[dwCnt];
  942. strcpy(
  943. szAddr1,
  944. inet_ntoa( *((struct in_addr *) &pScope->ipGroupAddress) )
  945. );
  946. strcpy(
  947. szAddr2,
  948. inet_ntoa( *((struct in_addr *) &pScope->ipGroupMask) )
  949. );
  950. MakePrefixStringW(snScopeNameBuffer,
  951. pScope->ipGroupAddress,
  952. pScope->ipGroupMask);
  953. if (hFile)
  954. {
  955. PWCHAR pwszQuoted = MakeQuotedString( (pScope->ulNumNames)?
  956. pScope->snScopeNameBuffer : snScopeNameBuffer );
  957. DisplayMessageT( DMP_SCOPE_INFO,
  958. szAddr1,
  959. szAddr2,
  960. pwszQuoted );
  961. FreeQuotedString(pwszQuoted);
  962. }
  963. else
  964. {
  965. DisplayMessage( g_hModule,
  966. MSG_RTR_SCOPE_INFO,
  967. szAddr1,
  968. szAddr2,
  969. (pScope->ulNumNames)? pScope->snScopeNameBuffer
  970. : snScopeNameBuffer );
  971. }
  972. }
  973. dwRes = NO_ERROR;
  974. if (pScopes)
  975. FREE(pScopes);
  976. if (pScopesBuffer)
  977. FREE(pScopesBuffer);
  978. } while ( FALSE );
  979. return dwRes;
  980. }
  981. DWORD
  982. HandleIpShowScope(
  983. IN LPCWSTR pwszMachine,
  984. IN OUT LPWSTR *ppwcArguments,
  985. IN DWORD dwCurrentIndex,
  986. IN DWORD dwArgCount,
  987. IN DWORD dwFlags,
  988. IN LPCVOID pvData,
  989. OUT BOOL *pbDone
  990. )
  991. /*++
  992. Routine Description:
  993. Arguments:
  994. ppwcArguments - Argument array
  995. dwCurrentIndex - ppwcArguments[dwCurrentIndex] is the first arg
  996. dwArgCount - ppwcArguments[dwArgCount - 1] is the last arg
  997. Return Value:
  998. NO_ERROR
  999. --*/
  1000. {
  1001. return ShowScopes(0);
  1002. }
  1003. DWORD
  1004. DeleteBoundary(
  1005. IN DWORD dwDelInd,
  1006. IN PBYTE pib,
  1007. OUT PBYTE *ppibNew,
  1008. IN OUT DWORD *pdwCount
  1009. )
  1010. /*++
  1011. Description:
  1012. Creates a new info block header which does not include the
  1013. boundary with the specified index.
  1014. Caller is responsible for freeing buffer returned.
  1015. Called by:
  1016. UpdateBoundaryBlock()
  1017. --*/
  1018. {
  1019. DWORD dwInd = 0,
  1020. dwCnt = 0,
  1021. dwCnt0 = 0,
  1022. dwSize = 0,
  1023. dwRes = NO_ERROR;
  1024. LPBYTE pbDst = (LPBYTE) NULL,
  1025. pbSrc = (LPBYTE) NULL;
  1026. PRTR_INFO_BLOCK_HEADER pibh = (PRTR_INFO_BLOCK_HEADER) NULL;
  1027. PMIB_BOUNDARYROW pimbSrc = (PMIB_BOUNDARYROW) NULL;
  1028. PMIB_BOUNDARYROW pimbDst = (PMIB_BOUNDARYROW) NULL;
  1029. //
  1030. // Create new info block with boundary removed.
  1031. //
  1032. dwSize = (*pdwCount - 1) * sizeof( MIB_BOUNDARYROW );
  1033. if (dwSize is 0)
  1034. {
  1035. *ppibNew = NULL;
  1036. *pdwCount = 0;
  1037. return NO_ERROR;
  1038. }
  1039. *ppibNew = MALLOC( dwSize );
  1040. if ( *ppibNew == NULL )
  1041. {
  1042. DisplayMessage( g_hModule, MSG_IP_NOT_ENOUGH_MEMORY );
  1043. return ERROR_NOT_ENOUGH_MEMORY;
  1044. }
  1045. //
  1046. // Copy boundaries, skip boundary to be deleted
  1047. //
  1048. pimbDst = (PMIB_BOUNDARYROW) *ppibNew;
  1049. pimbSrc = (PMIB_BOUNDARYROW) pib;
  1050. for ( dwCnt = 0, dwCnt0 = 0;
  1051. dwCnt < *pdwCount;
  1052. dwCnt++ )
  1053. {
  1054. if ( dwCnt == dwDelInd )
  1055. {
  1056. continue;
  1057. }
  1058. pimbDst[ dwCnt0 ] = pimbSrc[ dwCnt ];
  1059. dwCnt0++;
  1060. }
  1061. (*pdwCount)--;
  1062. return NO_ERROR;
  1063. }
  1064. DWORD
  1065. AddBoundary (
  1066. IN PBYTE pib,
  1067. OUT PBYTE *ppibNew,
  1068. IN OUT DWORD *pdwCount
  1069. )
  1070. /*++
  1071. Description:
  1072. Creates a new info block which includes a boundary for the
  1073. scope identified by g_ipGrpAddr/g_ipGrpMask.
  1074. Caller is responsible for freeing buffer returned.
  1075. Called by:
  1076. UpdateBoundaryBlock()
  1077. --*/
  1078. {
  1079. DWORD dwRes = NO_ERROR,
  1080. dwInd = 0,
  1081. dwSize = 0;
  1082. LPBYTE pbDst = (LPBYTE) NULL,
  1083. pbSrc = (LPBYTE) NULL;
  1084. PMIB_BOUNDARYROW pimb = (PMIB_BOUNDARYROW ) NULL;
  1085. dwRes = VerifyBoundaryPrefix(g_ipGrpAddr, g_ipGrpMask);
  1086. if (dwRes)
  1087. {
  1088. return NO_ERROR;
  1089. }
  1090. do
  1091. {
  1092. *ppibNew = NULL;
  1093. //
  1094. // If this is the first boundary, create info block
  1095. // with an extra TocEntry.
  1096. //
  1097. dwSize = (*pdwCount + 1) * sizeof( MIB_BOUNDARYROW );
  1098. *ppibNew = MALLOC( dwSize );
  1099. if ( *ppibNew == NULL )
  1100. {
  1101. DisplayMessage(g_hModule, MSG_IP_NOT_ENOUGH_MEMORY );
  1102. dwRes = ERROR_NOT_ENOUGH_MEMORY;
  1103. break;
  1104. }
  1105. pbDst = *ppibNew;
  1106. CopyMemory( pbDst, pib, (*pdwCount) * sizeof(MIB_BOUNDARYROW) );
  1107. pbDst += (*pdwCount) * sizeof(MIB_BOUNDARYROW);
  1108. (*pdwCount)++;
  1109. pimb = (PMIB_BOUNDARYROW) pbDst;
  1110. pimb-> dwGroupAddress = g_ipGrpAddr;
  1111. pimb-> dwGroupMask = g_ipGrpMask;
  1112. pbDst += sizeof( MIB_BOUNDARYROW );
  1113. } while ( FALSE );
  1114. return dwRes;
  1115. }
  1116. BOOL
  1117. IsBoundaryPresent(
  1118. IN IPV4_ADDRESS ipGroupAddress,
  1119. IN IPV4_ADDRESS ipGroupMask,
  1120. IN PMIB_BOUNDARYROW pimb,
  1121. IN DWORD dwNumBoundaries,
  1122. OUT PDWORD pdwInd
  1123. )
  1124. /*++
  1125. Returns:
  1126. TRUE if present, and sets dwInd to index
  1127. FALSE if not present, and sets dwInd to -1
  1128. Called by:
  1129. UpdateBoundaryBlock()
  1130. --*/
  1131. {
  1132. DWORD dwInd = 0;
  1133. *pdwInd = (DWORD) -1;
  1134. for ( dwInd = 0; dwInd < dwNumBoundaries; dwInd++, pimb++ )
  1135. {
  1136. if ( pimb-> dwGroupAddress != ipGroupAddress
  1137. || pimb-> dwGroupMask != ipGroupMask )
  1138. {
  1139. continue;
  1140. }
  1141. *pdwInd = dwInd;
  1142. return TRUE;
  1143. }
  1144. return FALSE;
  1145. }
  1146. DWORD
  1147. UpdateBoundaryBlock(
  1148. IN DWORD dwAction,
  1149. IN PBYTE pib,
  1150. OUT PBYTE *ppibNew,
  1151. IN OUT DWORD *pdwBlkSize,
  1152. IN OUT DWORD *pdwCount,
  1153. OUT BOOL *pbChanged
  1154. )
  1155. /*++
  1156. Description:
  1157. Caller is responsible for freeing buffer returned.
  1158. Called by:
  1159. IpAddDelBoundary(), DeleteBoundaryFromInterface()
  1160. --*/
  1161. {
  1162. DWORD dwRes = NO_ERROR,
  1163. dwInd = 0,
  1164. dwInd0 = 0;
  1165. BOOL bBoFound = FALSE;
  1166. PMIB_BOUNDARYROW pimb = (PMIB_BOUNDARYROW) NULL;
  1167. *pbChanged = FALSE;
  1168. do
  1169. {
  1170. *ppibNew = NULL;
  1171. //
  1172. // Find if specified boundary is present
  1173. //
  1174. bBoFound = IsBoundaryPresent( g_ipGrpAddr,
  1175. g_ipGrpMask,
  1176. (PMIB_BOUNDARYROW)pib,
  1177. *pdwCount,
  1178. &dwInd0 );
  1179. //
  1180. // Update the boundary infoblock.
  1181. //
  1182. switch ( dwAction )
  1183. {
  1184. case ADD_BOUNDARY:
  1185. //
  1186. // If boundary is not present, add it. Else return error.
  1187. //
  1188. if ( !bBoFound )
  1189. {
  1190. dwRes = AddBoundary( pib, ppibNew, pdwCount );
  1191. *pdwBlkSize = sizeof(MIB_BOUNDARYROW);
  1192. *pbChanged = TRUE;
  1193. }
  1194. else
  1195. {
  1196. dwRes = ERROR_OBJECT_ALREADY_EXISTS;
  1197. }
  1198. break;
  1199. case DELETE_BOUNDARY:
  1200. //
  1201. // Delete boundary only if present.
  1202. //
  1203. if ( bBoFound )
  1204. {
  1205. dwRes = DeleteBoundary( dwInd0, pib, ppibNew, pdwCount );
  1206. *pbChanged = TRUE;
  1207. }
  1208. // If not present, return success but don't set the changed flag.
  1209. break;
  1210. }
  1211. } while ( FALSE );
  1212. return dwRes;
  1213. }
  1214. DWORD
  1215. IpAddDelBoundary(
  1216. DWORD dwAction,
  1217. PWCHAR *ppwcArguments,
  1218. DWORD dwCurrentIndex,
  1219. DWORD dwArgCount
  1220. )
  1221. {
  1222. DWORD dwErr;
  1223. TAG_TYPE pttTags[] = {{TOKEN_NAME, TRUE, FALSE},
  1224. {TOKEN_GROUP_ADDRESS, FALSE,FALSE},
  1225. {TOKEN_GROUP_MASK, FALSE,FALSE},
  1226. {TOKEN_SCOPE_NAME, FALSE,FALSE},
  1227. };
  1228. WCHAR rgwcIfName[MAX_INTERFACE_NAME_LEN + 1];
  1229. DWORD rgdwTagType[sizeof(pttTags)/sizeof(TAG_TYPE)];
  1230. IPV4_ADDRESS ipGroup, ipMask;
  1231. DWORD dwBlkSize, dwCount, dwIfType, i, dwNumParsed;
  1232. PBYTE pib, pibNew = NULL;
  1233. BOOL bChanged;
  1234. // Do generic processing
  1235. dwErr = PreHandleCommand( ppwcArguments,
  1236. dwCurrentIndex,
  1237. dwArgCount,
  1238. pttTags,
  1239. sizeof(pttTags)/sizeof(TAG_TYPE),
  1240. 2,
  1241. 3,
  1242. rgdwTagType );
  1243. if (dwErr)
  1244. {
  1245. return dwErr;
  1246. }
  1247. g_ipGrpAddr = g_ipGrpMask = 0;
  1248. for(i = 0; i < dwArgCount - dwCurrentIndex; i ++)
  1249. {
  1250. switch (rgdwTagType[i])
  1251. {
  1252. case 0 : // NAME
  1253. {
  1254. GetInterfaceName(ppwcArguments[i + dwCurrentIndex],
  1255. rgwcIfName,
  1256. sizeof(rgwcIfName),
  1257. &dwNumParsed);
  1258. break;
  1259. }
  1260. case 1: // GRPADDR
  1261. {
  1262. dwErr = GetIpPrefix(ppwcArguments[i + dwCurrentIndex],
  1263. &g_ipGrpAddr,
  1264. &g_ipGrpMask);
  1265. if (!((dwErr is ERROR_INVALID_PARAMETER)
  1266. && (dwAction is DELETE_BOUNDARY)))
  1267. {
  1268. break;
  1269. }
  1270. // FALLTHROUGH
  1271. }
  1272. case 3: // SCOPENAME
  1273. {
  1274. dwErr = ScopeNameToPrefix( ppwcArguments[i + dwCurrentIndex],
  1275. &g_ipGrpAddr,
  1276. &g_ipGrpMask );
  1277. if (dwErr is ERROR_MORE_DATA)
  1278. {
  1279. DisplayMessage( g_hModule, EMSG_AMBIGUOUS_SCOPE_NAME,
  1280. ppwcArguments[i + dwCurrentIndex]);
  1281. return NO_ERROR;
  1282. }
  1283. break;
  1284. }
  1285. case 2: // GRPMASK
  1286. {
  1287. dwErr = GetIpMask(ppwcArguments[i + dwCurrentIndex],
  1288. &g_ipGrpMask);
  1289. if (dwErr is ERROR_INVALID_PARAMETER)
  1290. {
  1291. DisplayMessage( g_hModule, MSG_IP_BAD_IP_ADDR,
  1292. ppwcArguments[i + dwCurrentIndex]);
  1293. DispTokenErrMsg(g_hModule, MSG_IP_BAD_OPTION_VALUE,
  1294. pttTags[rgdwTagType[i]].pwszTag,
  1295. ppwcArguments[i + dwCurrentIndex]);
  1296. return NO_ERROR;
  1297. }
  1298. break;
  1299. }
  1300. }
  1301. }
  1302. if (dwErr isnot NO_ERROR)
  1303. {
  1304. return dwErr;
  1305. }
  1306. if (!g_ipGrpAddr || !g_ipGrpMask)
  1307. {
  1308. return ERROR_INVALID_SYNTAX;
  1309. }
  1310. do {
  1311. dwErr = IpmontrGetInfoBlockFromInterfaceInfo( rgwcIfName,
  1312. IP_MCAST_BOUNDARY_INFO,
  1313. &pib,
  1314. &dwBlkSize,
  1315. &dwCount,
  1316. &dwIfType );
  1317. if (dwErr is ERROR_NOT_FOUND)
  1318. {
  1319. //
  1320. // No info of this type is currently present
  1321. //
  1322. dwErr = NO_ERROR;
  1323. dwCount = 0;
  1324. }
  1325. if (dwErr isnot NO_ERROR)
  1326. break;
  1327. dwErr = UpdateBoundaryBlock( dwAction,
  1328. pib,
  1329. &pibNew,
  1330. &dwBlkSize,
  1331. &dwCount,
  1332. &bChanged );
  1333. if (dwErr isnot NO_ERROR)
  1334. break;
  1335. if (bChanged)
  1336. {
  1337. dwErr = IpmontrSetInfoBlockInInterfaceInfo( rgwcIfName,
  1338. IP_MCAST_BOUNDARY_INFO,
  1339. pibNew,
  1340. dwBlkSize,
  1341. dwCount );
  1342. }
  1343. } while (FALSE);
  1344. if (pib)
  1345. FREE(pib);
  1346. if (pibNew)
  1347. FREE(pibNew);
  1348. return dwErr;
  1349. }
  1350. DWORD
  1351. HandleIpAddBoundary(
  1352. IN LPCWSTR pwszMachine,
  1353. IN OUT LPWSTR *ppwcArguments,
  1354. IN DWORD dwCurrentIndex,
  1355. IN DWORD dwArgCount,
  1356. IN DWORD dwFlags,
  1357. IN LPCVOID pvData,
  1358. OUT BOOL *pbDone
  1359. )
  1360. /*++
  1361. Routine Description:
  1362. Arguments:
  1363. ppwcArguments - Argument array
  1364. dwCurrentIndex - ppwcArguments[dwCurrentIndex] is the first arg
  1365. dwArgCount - ppwcArguments[dwArgCount - 1] is the last arg
  1366. Return Value:
  1367. NO_ERROR
  1368. --*/
  1369. {
  1370. return IpAddDelBoundary( ADD_BOUNDARY,
  1371. ppwcArguments,
  1372. dwCurrentIndex,
  1373. dwArgCount );
  1374. }
  1375. DWORD
  1376. HandleIpDelBoundary(
  1377. IN LPCWSTR pwszMachine,
  1378. IN OUT LPWSTR *ppwcArguments,
  1379. IN DWORD dwCurrentIndex,
  1380. IN DWORD dwArgCount,
  1381. IN DWORD dwFlags,
  1382. IN LPCVOID pvData,
  1383. OUT BOOL *pbDone
  1384. )
  1385. /*++
  1386. Routine Description:
  1387. Arguments:
  1388. ppwcArguments - Argument array
  1389. dwCurrentIndex - ppwcArguments[dwCurrentIndex] is the first arg
  1390. dwArgCount - ppwcArguments[dwArgCount - 1] is the last arg
  1391. Return Value:
  1392. NO_ERROR
  1393. --*/
  1394. {
  1395. return IpAddDelBoundary( DELETE_BOUNDARY,
  1396. ppwcArguments,
  1397. dwCurrentIndex,
  1398. dwArgCount );
  1399. }
  1400. DWORD
  1401. ShowBoundaryInfoForInterface(
  1402. IN HANDLE hFile,
  1403. IN LPCWSTR pwszIfName,
  1404. OUT PDWORD pdwNumRows
  1405. )
  1406. /*++
  1407. Called by:
  1408. ShowBoundaryInfo()
  1409. --*/
  1410. {
  1411. DWORD dwErr,
  1412. dwBlkSize,
  1413. dwCount,
  1414. dwIfType,
  1415. dwNumParsed,
  1416. dwInd = 0,
  1417. dwCnt = 0,
  1418. dwSize = 0,
  1419. dwGlobalSize = 0,
  1420. dwIfLen = 0;
  1421. WCHAR wszIfDesc[MAX_INTERFACE_NAME_LEN + 1];
  1422. ULONG ulNumScopes = 0;
  1423. CHAR szAddr1[ ADDR_LENGTH ],
  1424. szAddr2[ ADDR_LENGTH ];
  1425. HANDLE hIfTransport = (HANDLE) NULL,
  1426. hTransport = (HANDLE) NULL;
  1427. PRTR_INFO_BLOCK_HEADER pibhIfInfo = (PRTR_INFO_BLOCK_HEADER) NULL,
  1428. pibhGlobalInfo = (PRTR_INFO_BLOCK_HEADER) NULL;
  1429. PMIB_BOUNDARYROW pimb;
  1430. PSCOPE_ENTRY pScope,
  1431. pScopes;
  1432. PBYTE pScopesBuffer;
  1433. SCOPE_NAME_BUFFER snScopeNameBuffer;
  1434. do
  1435. {
  1436. dwErr = IpmontrGetInfoBlockFromInterfaceInfo( pwszIfName,
  1437. IP_MCAST_BOUNDARY_INFO,
  1438. (PBYTE*)&pimb,
  1439. &dwBlkSize,
  1440. &dwCount,
  1441. &dwIfType );
  1442. if (dwErr is ERROR_NOT_FOUND)
  1443. dwErr = NO_ERROR;
  1444. if (dwErr isnot NO_ERROR)
  1445. return dwErr;
  1446. if ( !dwCount )
  1447. break;
  1448. dwErr = GetInterfaceDescription(pwszIfName,
  1449. wszIfDesc,
  1450. &dwNumParsed);
  1451. if (!dwNumParsed)
  1452. {
  1453. wcscpy(wszIfDesc, pwszIfName);
  1454. }
  1455. dwIfLen = wcslen(wszIfDesc);
  1456. //
  1457. // Retrieve the list of scopes in pScopes[]
  1458. //
  1459. pScopes = GetScopes( &ulNumScopes, &pScopesBuffer );
  1460. //
  1461. // Enumerate the boundaries
  1462. //
  1463. for ( dwCnt = 0; dwCnt < dwCount; dwCnt++ )
  1464. {
  1465. pScope = FindScopeByPrefix( pimb[dwCnt].dwGroupAddress,
  1466. pimb[dwCnt].dwGroupMask,
  1467. pScopes,
  1468. ulNumScopes );
  1469. strcpy( szAddr1,
  1470. inet_ntoa( *((struct in_addr *) &pimb[dwCnt].dwGroupAddress)
  1471. )
  1472. );
  1473. strcpy( szAddr2,
  1474. inet_ntoa( *((struct in_addr *) &pimb[dwCnt].dwGroupMask) )
  1475. );
  1476. // Copy prefix to snScopeNameBuffer
  1477. MakePrefixStringW(snScopeNameBuffer,
  1478. pimb[dwCnt].dwGroupAddress,
  1479. pimb[dwCnt].dwGroupMask);
  1480. if (hFile)
  1481. {
  1482. PWCHAR pwszQuoted = MakeQuotedString(wszIfDesc);
  1483. DisplayMessageT( DMP_BOUNDARY_INFO,
  1484. pwszQuoted,
  1485. szAddr1,
  1486. szAddr2,
  1487. (pScope && pScope->ulNumNames)?
  1488. pScope->snScopeNameBuffer : snScopeNameBuffer );
  1489. FreeQuotedString(pwszQuoted);
  1490. }
  1491. else
  1492. {
  1493. if ( !*pdwNumRows )
  1494. {
  1495. DisplayMessage( g_hModule, MSG_RTR_BOUNDARY_HDR );
  1496. }
  1497. if (dwIfLen <= 15)
  1498. {
  1499. DisplayMessage( g_hModule,
  1500. MSG_RTR_BOUNDARY_INFO_2,
  1501. wszIfDesc,
  1502. szAddr1,
  1503. szAddr2,
  1504. (pScope && pScope->ulNumNames)?
  1505. pScope->snScopeNameBuffer : snScopeNameBuffer );
  1506. }
  1507. else
  1508. {
  1509. DisplayMessage( g_hModule,
  1510. MSG_RTR_BOUNDARY_INFO_0,
  1511. wszIfDesc
  1512. );
  1513. DisplayMessage( g_hModule,
  1514. MSG_RTR_BOUNDARY_INFO_1,
  1515. szAddr1,
  1516. szAddr2,
  1517. (pScope && pScope->ulNumNames)?
  1518. pScope->snScopeNameBuffer : snScopeNameBuffer );
  1519. }
  1520. }
  1521. (*pdwNumRows) ++;
  1522. }
  1523. dwErr = NO_ERROR;
  1524. if (pScopes)
  1525. FREE(pScopes);
  1526. if (pScopesBuffer)
  1527. FREE(pScopesBuffer);
  1528. } while ( FALSE );
  1529. if ( pimb ) { FREE(pimb); }
  1530. return dwErr;
  1531. }
  1532. DWORD
  1533. HandleIpShowBoundary(
  1534. IN LPCWSTR pwszMachine,
  1535. IN OUT LPWSTR *ppwcArguments,
  1536. IN DWORD dwCurrentIndex,
  1537. IN DWORD dwArgCount,
  1538. IN DWORD dwFlags,
  1539. IN LPCVOID pvData,
  1540. OUT BOOL *pbDone
  1541. )
  1542. /*++
  1543. Routine Description:
  1544. Arguments:
  1545. ppwcArguments - Argument array
  1546. dwCurrentIndex - ppwcArguments[dwCurrentIndex] is the first arg
  1547. dwArgCount - ppwcArguments[dwArgCount - 1] is the last arg
  1548. Return Value:
  1549. NO_ERROR
  1550. --*/
  1551. {
  1552. DWORD dwErr, dwTotal;
  1553. TAG_TYPE pttTags[] = {{TOKEN_NAME,FALSE,FALSE}};
  1554. WCHAR rgwcIfName[MAX_INTERFACE_NAME_LEN + 1];
  1555. DWORD rgdwTagType[sizeof(pttTags)/sizeof(TAG_TYPE)];
  1556. DWORD dwBlkSize, dwCount, dwIfType, i, dwNumParsed;
  1557. PBYTE pib, pibNew = NULL;
  1558. PMPR_INTERFACE_0 pmi0;
  1559. DWORD dwNumRows = 0;
  1560. // Do generic processing
  1561. dwErr = PreHandleCommand( ppwcArguments,
  1562. dwCurrentIndex,
  1563. dwArgCount,
  1564. pttTags,
  1565. sizeof(pttTags)/sizeof(TAG_TYPE),
  1566. 0,
  1567. 1,
  1568. rgdwTagType );
  1569. if (dwErr)
  1570. {
  1571. return dwErr;
  1572. }
  1573. // If interface specified, show boundaries for specified interface only.
  1574. if (dwArgCount > dwCurrentIndex) {
  1575. GetInterfaceName( ppwcArguments[dwCurrentIndex],
  1576. rgwcIfName,
  1577. sizeof(rgwcIfName),
  1578. &dwNumParsed );
  1579. dwErr = ShowBoundaryInfoForInterface( 0, rgwcIfName, &dwNumRows );
  1580. if (!dwNumRows)
  1581. {
  1582. DisplayMessage( g_hModule, MSG_IP_NO_ENTRIES );
  1583. }
  1584. return dwErr;
  1585. }
  1586. // No Interface specified. Enumerate interfaces and show
  1587. // boundaries for each interface.
  1588. //
  1589. // No interface name specified. List all interfaces under IP
  1590. //
  1591. dwErr = IpmontrInterfaceEnum((PBYTE *) &pmi0, &dwCount, &dwTotal);
  1592. if (dwErr isnot NO_ERROR)
  1593. {
  1594. DisplayError(g_hModule, dwErr);
  1595. return dwErr;
  1596. }
  1597. for ( i = 0; i < dwCount && dwErr is NO_ERROR; i++)
  1598. {
  1599. dwErr = ShowBoundaryInfoForInterface( 0,
  1600. pmi0[i].wszInterfaceName,
  1601. &dwNumRows );
  1602. if (dwErr is ERROR_NO_SUCH_INTERFACE)
  1603. {
  1604. dwErr = NO_ERROR;
  1605. }
  1606. }
  1607. if (!dwNumRows)
  1608. {
  1609. DisplayMessage( g_hModule, MSG_IP_NO_ENTRIES );
  1610. }
  1611. return dwErr;
  1612. }
  1613. //----------------------------------------------------------------------------
  1614. // PrintScope
  1615. //
  1616. //
  1617. //----------------------------------------------------------------------------
  1618. static VOID
  1619. PrintScope(
  1620. PMIB_OPAQUE_INFO prpcInfo,
  1621. PDWORD pdwLastAddr,
  1622. PDWORD pdwLastMask
  1623. )
  1624. {
  1625. TCHAR ptszAddr[ ADDR_LENGTH + 1 ],
  1626. ptszMask[ ADDR_LENGTH + 1 ],
  1627. ptszBuffer[ MAX_SCOPE_NAME_LEN + 40 ];
  1628. PMIB_IPMCAST_SCOPE pmims;
  1629. //
  1630. // get scope
  1631. //
  1632. pmims = (PMIB_IPMCAST_SCOPE) prpcInfo->rgbyData;
  1633. *pdwLastAddr = pmims-> dwGroupAddress;
  1634. MakeUnicodeIpAddr(ptszAddr,
  1635. inet_ntoa(*((struct in_addr *)(&pmims-> dwGroupAddress))));
  1636. *pdwLastMask = pmims-> dwGroupMask;
  1637. MakeUnicodeIpAddr(ptszMask,
  1638. inet_ntoa(*((struct in_addr *)(&pmims-> dwGroupMask))));
  1639. _stprintf(ptszBuffer, _T("%-15.15s %-15.15s %s"),
  1640. ptszAddr,
  1641. ptszMask,
  1642. pmims-> snNameBuffer
  1643. );
  1644. DisplayMessage( g_hModule,
  1645. MSG_MIB_SCOPE_INFO,
  1646. ptszBuffer
  1647. );
  1648. return;
  1649. }
  1650. //----------------------------------------------------------------------------
  1651. // PrintBoundary
  1652. //
  1653. //
  1654. //----------------------------------------------------------------------------
  1655. static VOID
  1656. PrintBoundary(
  1657. MIB_SERVER_HANDLE hMibServer,
  1658. PMIB_OPAQUE_INFO prpcInfo,
  1659. PDWORD pdwLastIfIndex,
  1660. PDWORD pdwLastAddr,
  1661. PDWORD pdwLastMask
  1662. )
  1663. {
  1664. WCHAR wszBuffer[MAX_INTERFACE_NAME_LEN+1];
  1665. TCHAR ptszAddr[ ADDR_LENGTH + 1 ],
  1666. ptszMask[ ADDR_LENGTH + 1 ];
  1667. PMIB_IPMCAST_BOUNDARY pmims;
  1668. //
  1669. // get boundary
  1670. //
  1671. pmims = (PMIB_IPMCAST_BOUNDARY) prpcInfo->rgbyData;
  1672. *pdwLastIfIndex = pmims-> dwIfIndex;
  1673. *pdwLastAddr = pmims-> dwGroupAddress;
  1674. MakeUnicodeIpAddr(ptszAddr,
  1675. inet_ntoa(*((struct in_addr *)(&pmims-> dwGroupAddress))));
  1676. *pdwLastMask = pmims-> dwGroupMask;
  1677. MakeUnicodeIpAddr(ptszMask,
  1678. inet_ntoa(*((struct in_addr *)(&pmims-> dwGroupMask))));
  1679. IpmontrGetFriendlyNameFromIfIndex( hMibServer,
  1680. pmims->dwIfIndex,
  1681. wszBuffer,
  1682. sizeof(wszBuffer) );
  1683. DisplayMessageToConsole( g_hModule, g_hConsole,
  1684. MSG_MIB_BOUNDARY_INFO,
  1685. ptszAddr,
  1686. ptszMask,
  1687. wszBuffer
  1688. );
  1689. return;
  1690. }
  1691. #if 0
  1692. //----------------------------------------------------------------------------
  1693. // GetPrintScopeInfo
  1694. //
  1695. //----------------------------------------------------------------------------
  1696. DWORD
  1697. GetPrintScopeInfo(
  1698. MIB_SERVER_HANDLE hMIBServer
  1699. )
  1700. {
  1701. DWORD dwErr, dwOutEntrySize = 0, dwQuerySize,
  1702. dwLastAddr = 0,
  1703. dwLastMask = 0, i;
  1704. PMIB_OPAQUE_INFO pRpcInfo = NULL;
  1705. PMIB_IPMCAST_SCOPE pmims = NULL;
  1706. PMIB_OPAQUE_QUERY pQuery;
  1707. do
  1708. {
  1709. //
  1710. // allocate and setup query structure
  1711. //
  1712. dwQuerySize = sizeof( MIB_OPAQUE_QUERY ) + sizeof(DWORD);
  1713. pQuery = (PMIB_OPAQUE_QUERY) HeapAlloc(
  1714. GetProcessHeap(), 0, dwQuerySize
  1715. );
  1716. if ( pQuery == NULL )
  1717. {
  1718. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  1719. DisplayMessage( g_hModule, ERROR_CONFIG, dwErr );
  1720. break;
  1721. }
  1722. pQuery->dwVarId = MCAST_SCOPE;
  1723. for( i = 0; i < 2; i++ )
  1724. {
  1725. pQuery->rgdwVarIndex[i] = 0;
  1726. }
  1727. //
  1728. // get first scope
  1729. //
  1730. dwErr = MibGetFirst(
  1731. PID_IP,
  1732. IPRTRMGR_PID,
  1733. (PVOID) pQuery,
  1734. dwQuerySize,
  1735. (PVOID *) &pRpcInfo,
  1736. &dwOutEntrySize
  1737. );
  1738. if ( dwErr != NO_ERROR )
  1739. {
  1740. DisplayError( g_hModule, dwErr );
  1741. break;
  1742. }
  1743. //
  1744. // if no scopes are present print a message to tell the user
  1745. //
  1746. pmims = (PMIB_IPMCAST_SCOPE)( pRpcInfo->rgbyData );
  1747. #if 0
  1748. if ( pTable->dwNumEntries is 0 )
  1749. {
  1750. //
  1751. // no scopes present.
  1752. //
  1753. DisplayMessage( g_hModule, MSG_MIB_NO_SCOPES );
  1754. break;
  1755. }
  1756. #endif
  1757. //
  1758. // print the scope
  1759. //
  1760. DisplayMessage( g_hModule, MSG_MIB_SCOPE_HDR );
  1761. PrintScope( pRpcInfo, &dwLastAddr, &dwLastMask );
  1762. MprAdminMIBBufferFree( pRpcInfo );
  1763. pRpcInfo = NULL;
  1764. dwOutEntrySize = 0;
  1765. //
  1766. // while there are more scopes
  1767. // get next scope
  1768. // print it.
  1769. //
  1770. pQuery->rgdwVarIndex[ 0 ] = dwLastAddr;
  1771. pQuery->rgdwVarIndex[ 1 ] = dwLastMask;
  1772. while ( ( dwErr = MibGetNext(
  1773. PID_IP, IPRTRMGR_PID, (PVOID) pQuery,
  1774. dwQuerySize, (PVOID *) &pRpcInfo, &dwOutEntrySize
  1775. ) ) == NO_ERROR )
  1776. {
  1777. //
  1778. // if no scopes are present quit
  1779. //
  1780. pmims = (PMIB_IPMCAST_SCOPE)( pRpcInfo->rgbyData );
  1781. #if 0
  1782. pTable = (PMIB_IPMCAST_SCOPE)( pRpcInfo->rgbyData );
  1783. if ( pTable->dwNumEntries is 0 )
  1784. {
  1785. break;
  1786. }
  1787. #endif
  1788. //
  1789. // print the scope
  1790. //
  1791. PrintScope( pRpcInfo, &dwLastAddr, &dwLastMask );
  1792. MprAdminMIBBufferFree( pRpcInfo );
  1793. pRpcInfo = NULL;
  1794. dwOutEntrySize = 0;
  1795. //
  1796. // set up the next query
  1797. //
  1798. pQuery->rgdwVarIndex[ 0 ] = dwLastAddr;
  1799. pQuery->rgdwVarIndex[ 1 ] = dwLastMask;
  1800. }
  1801. if ( dwErr != NO_ERROR )
  1802. {
  1803. DisplayMessage( g_hModule, ERROR_ADMIN, dwErr );
  1804. }
  1805. } while ( FALSE );
  1806. return dwErr;
  1807. }
  1808. #endif
  1809. //----------------------------------------------------------------------------
  1810. // GetPrintBoundaryInfo
  1811. //
  1812. //----------------------------------------------------------------------------
  1813. DWORD
  1814. GetPrintBoundaryInfo(
  1815. MIB_SERVER_HANDLE hMIBServer
  1816. )
  1817. {
  1818. DWORD dwErr, dwOutEntrySize = 0, dwQuerySize,
  1819. dwLastIfIndex = 0, dwLastAddr = 0,
  1820. dwLastMask = 0, i;
  1821. PMIB_OPAQUE_INFO pRpcInfo = NULL;
  1822. PMIB_IPMCAST_BOUNDARY pmims = NULL;
  1823. PMIB_OPAQUE_QUERY pQuery;
  1824. do
  1825. {
  1826. //
  1827. // allocate and setup query structure
  1828. //
  1829. dwQuerySize = sizeof( MIB_OPAQUE_QUERY ) + 2 * sizeof(DWORD);
  1830. pQuery = (PMIB_OPAQUE_QUERY) HeapAlloc(
  1831. GetProcessHeap(), 0, dwQuerySize
  1832. );
  1833. if ( pQuery == NULL )
  1834. {
  1835. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  1836. DisplayMessage( g_hModule, ERROR_CONFIG, dwErr );
  1837. break;
  1838. }
  1839. pQuery->dwVarId = MCAST_BOUNDARY;
  1840. for( i = 0; i < 2; i++ )
  1841. {
  1842. pQuery->rgdwVarIndex[i] = 0;
  1843. }
  1844. //
  1845. // get first boundary
  1846. //
  1847. dwErr = MibGetFirst(
  1848. PID_IP,
  1849. IPRTRMGR_PID,
  1850. (PVOID) pQuery,
  1851. dwQuerySize,
  1852. (PVOID *) &pRpcInfo,
  1853. &dwOutEntrySize
  1854. );
  1855. if ( dwErr != NO_ERROR )
  1856. {
  1857. DisplayError( g_hModule, dwErr );
  1858. break;
  1859. }
  1860. //
  1861. // if no boundaries are present print a message to tell the user
  1862. //
  1863. pmims = (PMIB_IPMCAST_BOUNDARY)( pRpcInfo->rgbyData );
  1864. #if 0
  1865. if ( pTable->dwNumEntries is 0 )
  1866. {
  1867. //
  1868. // no boundaries present.
  1869. //
  1870. DisplayMessage( g_hModule, MSG_MIB_NO_BOUNDARIES );
  1871. break;
  1872. }
  1873. #endif
  1874. //
  1875. // print the boundary
  1876. //
  1877. DisplayMessageToConsole( g_hModule, g_hConsole, MSG_MIB_BOUNDARY_HDR );
  1878. PrintBoundary( hMIBServer,
  1879. pRpcInfo, &dwLastIfIndex, &dwLastAddr, &dwLastMask );
  1880. MprAdminMIBBufferFree( pRpcInfo );
  1881. pRpcInfo = NULL;
  1882. dwOutEntrySize = 0;
  1883. //
  1884. // while there are more boundaries
  1885. // get next boundary
  1886. // print it.
  1887. //
  1888. pQuery->rgdwVarIndex[ 0 ] = dwLastIfIndex;
  1889. pQuery->rgdwVarIndex[ 1 ] = dwLastAddr;
  1890. pQuery->rgdwVarIndex[ 2 ] = dwLastMask;
  1891. while ( ( dwErr = MibGetNext(
  1892. PID_IP, IPRTRMGR_PID, (PVOID) pQuery,
  1893. dwQuerySize, (PVOID *) &pRpcInfo, &dwOutEntrySize
  1894. ) ) == NO_ERROR )
  1895. {
  1896. //
  1897. // if no boundaries are present quit
  1898. //
  1899. pmims = (PMIB_IPMCAST_BOUNDARY)( pRpcInfo->rgbyData );
  1900. #if 0
  1901. pTable = (PMIB_IPMCAST_BOUNDARY)( pRpcInfo->rgbyData );
  1902. if ( pTable->dwNumEntries is 0 )
  1903. {
  1904. break;
  1905. }
  1906. #endif
  1907. //
  1908. // print the boundary
  1909. //
  1910. PrintBoundary(
  1911. hMIBServer,
  1912. pRpcInfo, &dwLastIfIndex, &dwLastAddr, &dwLastMask
  1913. );
  1914. MprAdminMIBBufferFree( pRpcInfo );
  1915. pRpcInfo = NULL;
  1916. dwOutEntrySize = 0;
  1917. //
  1918. // set up the next query
  1919. //
  1920. pQuery->rgdwVarIndex[ 0 ] = dwLastIfIndex;
  1921. pQuery->rgdwVarIndex[ 1 ] = dwLastAddr;
  1922. pQuery->rgdwVarIndex[ 2 ] = dwLastMask;
  1923. }
  1924. if ( dwErr != NO_ERROR )
  1925. {
  1926. DisplayMessage( g_hModule, ERROR_ADMIN, dwErr );
  1927. }
  1928. } while ( FALSE );
  1929. return dwErr;
  1930. }