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.

2366 lines
53 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. txspecific.c
  5. Abstract:
  6. This module contains all of the code to drive the
  7. specific transport filter list management of IPSecSPD
  8. Service.
  9. Author:
  10. abhisheV 29-October-1999
  11. Environment
  12. User Level: Win32
  13. Revision History:
  14. --*/
  15. #include "precomp.h"
  16. DWORD
  17. ApplyTxTransform(
  18. PINITXFILTER pFilter,
  19. MATCHING_ADDR * pMatchingAddresses,
  20. DWORD dwAddrCnt,
  21. PINITXSFILTER * ppSpecificFilters
  22. )
  23. /*++
  24. Routine Description:
  25. This function expands a generic transport filter into its
  26. corresponding specific filters.
  27. Arguments:
  28. pFilter - Generic filter to expand.
  29. pMatchingAddresses - List of local ip addresses whose interface
  30. type matches that of the filter.
  31. dwAddrCnt - Number of local ip addresses in the list.
  32. ppSpecificFilters - List of specific filters expanded for the
  33. given generic filter.
  34. Return Value:
  35. ERROR_SUCCESS - Success.
  36. Win32 Error - Failure.
  37. --*/
  38. {
  39. DWORD dwError = 0;
  40. PINITXSFILTER pSpecificFilters = NULL;
  41. PINITXSFILTER pOutboundSpecificFilters = NULL;
  42. PINITXSFILTER pInboundSpecificFilters = NULL;
  43. PADDR pOutSrcAddrList = NULL;
  44. DWORD dwOutSrcAddrCnt = 0;
  45. PADDR pInSrcAddrList = NULL;
  46. DWORD dwInSrcAddrCnt = 0;
  47. PADDR pOutDesAddrList = NULL;
  48. DWORD dwOutDesAddrCnt = 0;
  49. PADDR pInDesAddrList = NULL;
  50. DWORD dwInDesAddrCnt = 0;
  51. //
  52. // Form the outbound and inbound source and destination
  53. // address lists.
  54. //
  55. dwError = FormTxOutboundInboundAddresses(
  56. pFilter,
  57. pMatchingAddresses,
  58. dwAddrCnt,
  59. &pOutSrcAddrList,
  60. &dwOutSrcAddrCnt,
  61. &pInSrcAddrList,
  62. &dwInSrcAddrCnt,
  63. &pOutDesAddrList,
  64. &dwOutDesAddrCnt,
  65. &pInDesAddrList,
  66. &dwInDesAddrCnt
  67. );
  68. BAIL_ON_WIN32_ERROR(dwError);
  69. //
  70. // Form outbound specific filters.
  71. //
  72. dwError = FormSpecificTxFilters(
  73. pFilter,
  74. pOutSrcAddrList,
  75. dwOutSrcAddrCnt,
  76. pOutDesAddrList,
  77. dwOutDesAddrCnt,
  78. FILTER_DIRECTION_OUTBOUND,
  79. &pOutboundSpecificFilters
  80. );
  81. BAIL_ON_WIN32_ERROR(dwError);
  82. //
  83. // Form inbound specific filters.
  84. //
  85. dwError = FormSpecificTxFilters(
  86. pFilter,
  87. pInSrcAddrList,
  88. dwInSrcAddrCnt,
  89. pInDesAddrList,
  90. dwInDesAddrCnt,
  91. FILTER_DIRECTION_INBOUND,
  92. &pInboundSpecificFilters
  93. );
  94. BAIL_ON_WIN32_ERROR(dwError);
  95. pSpecificFilters = pOutboundSpecificFilters;
  96. AddToSpecificTxList(
  97. &pSpecificFilters,
  98. pInboundSpecificFilters
  99. );
  100. *ppSpecificFilters = pSpecificFilters;
  101. cleanup:
  102. if (pOutSrcAddrList) {
  103. FreeSPDMemory(pOutSrcAddrList);
  104. }
  105. if (pInSrcAddrList) {
  106. FreeSPDMemory(pInSrcAddrList);
  107. }
  108. if (pOutDesAddrList) {
  109. FreeSPDMemory(pOutDesAddrList);
  110. }
  111. if (pInDesAddrList) {
  112. FreeSPDMemory(pInDesAddrList);
  113. }
  114. return (dwError);
  115. error:
  116. if (pOutboundSpecificFilters) {
  117. FreeIniTxSFilterList(pOutboundSpecificFilters);
  118. }
  119. if (pInboundSpecificFilters) {
  120. FreeIniTxSFilterList(pInboundSpecificFilters);
  121. }
  122. *ppSpecificFilters = NULL;
  123. goto cleanup;
  124. }
  125. DWORD
  126. FormTxOutboundInboundAddresses(
  127. PINITXFILTER pFilter,
  128. MATCHING_ADDR * pMatchingAddresses,
  129. DWORD dwAddrCnt,
  130. PADDR * ppOutSrcAddrList,
  131. PDWORD pdwOutSrcAddrCnt,
  132. PADDR * ppInSrcAddrList,
  133. PDWORD pdwInSrcAddrCnt,
  134. PADDR * ppOutDesAddrList,
  135. PDWORD pdwOutDesAddrCnt,
  136. PADDR * ppInDesAddrList,
  137. PDWORD pdwInDesAddrCnt
  138. )
  139. /*++
  140. Routine Description:
  141. This function forms the outbound and inbound source and
  142. destination address sets for a generic filter.
  143. Arguments:
  144. pFilter - Generic filter under consideration.
  145. pMatchingAddresses - List of local ip addresses whose interface
  146. type matches that of the filter.
  147. dwAddrCnt - Number of local ip addresses in the list.
  148. ppOutSrcAddrList - List of outbound source addresses.
  149. pdwOutSrcAddrCnt - Number of addresses in the outbound
  150. source address list.
  151. ppInSrcAddrList - List of inbound source addresses.
  152. pdwInSrcAddrCnt - Number of addresses in the inbound
  153. source address list.
  154. ppOutDesAddrList - List of outbound destination addresses.
  155. pdwOutDesAddrCnt - Number of addresses in the outbound
  156. destination address list.
  157. ppInDesAddrList - List of inbound destination addresses.
  158. pdwInDesAddrCnt - Number of addresses in the inbound
  159. destination address list.
  160. Return Value:
  161. ERROR_SUCCESS - Success.
  162. Win32 Error - Failure.
  163. --*/
  164. {
  165. DWORD dwError = 0;
  166. PADDR pSrcAddrList = NULL;
  167. DWORD dwSrcAddrCnt = 0;
  168. PADDR pDesAddrList = NULL;
  169. DWORD dwDesAddrCnt = 0;
  170. PADDR pOutSrcAddrList = NULL;
  171. DWORD dwOutSrcAddrCnt = 0;
  172. PADDR pInSrcAddrList = NULL;
  173. DWORD dwInSrcAddrCnt = 0;
  174. PADDR pOutDesAddrList = NULL;
  175. DWORD dwOutDesAddrCnt = 0;
  176. PADDR pInDesAddrList = NULL;
  177. DWORD dwInDesAddrCnt = 0;
  178. //
  179. // Replace wild card information to generate the new source
  180. // address list.
  181. //
  182. dwError = FormAddressList(
  183. pFilter->SrcAddr,
  184. pMatchingAddresses,
  185. dwAddrCnt,
  186. &pSrcAddrList,
  187. &dwSrcAddrCnt
  188. );
  189. BAIL_ON_WIN32_ERROR(dwError);
  190. //
  191. // Replace wild card information to generate the new destination
  192. // address list.
  193. //
  194. dwError = FormAddressList(
  195. pFilter->DesAddr,
  196. pMatchingAddresses,
  197. dwAddrCnt,
  198. &pDesAddrList,
  199. &dwDesAddrCnt
  200. );
  201. BAIL_ON_WIN32_ERROR(dwError);
  202. //
  203. // Separate the source address list into outbound and inbound
  204. // source address sets based on the local machine's ip addresses.
  205. //
  206. dwError = SeparateAddrList(
  207. pFilter->SrcAddr.AddrType,
  208. pSrcAddrList,
  209. dwSrcAddrCnt,
  210. pMatchingAddresses,
  211. dwAddrCnt,
  212. &pOutSrcAddrList,
  213. &dwOutSrcAddrCnt,
  214. &pInSrcAddrList,
  215. &dwInSrcAddrCnt
  216. );
  217. BAIL_ON_WIN32_ERROR(dwError);
  218. //
  219. // Separate the destination address list into outbound and inbound
  220. // destination address sets based on the local machine's ip
  221. // addresses.
  222. //
  223. dwError = SeparateAddrList(
  224. pFilter->DesAddr.AddrType,
  225. pDesAddrList,
  226. dwDesAddrCnt,
  227. pMatchingAddresses,
  228. dwAddrCnt,
  229. &pInDesAddrList,
  230. &dwInDesAddrCnt,
  231. &pOutDesAddrList,
  232. &dwOutDesAddrCnt
  233. );
  234. BAIL_ON_WIN32_ERROR(dwError);
  235. *ppOutSrcAddrList = pOutSrcAddrList;
  236. *pdwOutSrcAddrCnt = dwOutSrcAddrCnt;
  237. *ppInSrcAddrList = pInSrcAddrList;
  238. *pdwInSrcAddrCnt = dwInSrcAddrCnt;
  239. *ppOutDesAddrList = pOutDesAddrList;
  240. *pdwOutDesAddrCnt = dwOutDesAddrCnt;
  241. *ppInDesAddrList = pInDesAddrList;
  242. *pdwInDesAddrCnt = dwInDesAddrCnt;
  243. cleanup:
  244. if (pSrcAddrList) {
  245. FreeSPDMemory(pSrcAddrList);
  246. }
  247. if (pDesAddrList) {
  248. FreeSPDMemory(pDesAddrList);
  249. }
  250. return (dwError);
  251. error:
  252. if (pOutSrcAddrList) {
  253. FreeSPDMemory(pOutSrcAddrList);
  254. }
  255. if (pInSrcAddrList) {
  256. FreeSPDMemory(pInSrcAddrList);
  257. }
  258. if (pOutDesAddrList) {
  259. FreeSPDMemory(pOutDesAddrList);
  260. }
  261. if (pInDesAddrList) {
  262. FreeSPDMemory(pInDesAddrList);
  263. }
  264. *ppOutSrcAddrList = NULL;
  265. *pdwOutSrcAddrCnt = 0;
  266. *ppInSrcAddrList = NULL;
  267. *pdwInSrcAddrCnt = 0;
  268. *ppOutDesAddrList = NULL;
  269. *pdwOutDesAddrCnt = 0;
  270. *ppInDesAddrList = NULL;
  271. *pdwInDesAddrCnt = 0;
  272. goto cleanup;
  273. }
  274. DWORD
  275. FormAddressList(
  276. ADDR InAddr,
  277. MATCHING_ADDR * pMatchingAddresses,
  278. DWORD dwAddrCnt,
  279. PADDR * ppOutAddr,
  280. PDWORD pdwOutAddrCnt
  281. )
  282. /*++
  283. Routine Description:
  284. This function forms the address list for a generic
  285. address.
  286. Arguments:
  287. InAddr - Generic address to expand.
  288. pMatchingAddresses - List of local ip addresses whose interface
  289. type matches that of the filter.
  290. dwAddrCnt - Number of local ip addresses in the list.
  291. ppOutAddr - Expanded address list for the generic address.
  292. pdwOutAddrCnt - Number of addresses in the expanded list.
  293. Return Value:
  294. ERROR_SUCCESS - Success.
  295. Win32 Error - Failure.
  296. --*/
  297. {
  298. DWORD dwError = 0;
  299. PADDR pOutAddr = NULL;
  300. DWORD dwOutAddrCnt = 0;
  301. DWORD i = 0, j = 0;
  302. switch(InAddr.AddrType) {
  303. case IP_ADDR_UNIQUE:
  304. if (InAddr.uIpAddr == IP_ADDRESS_ME) {
  305. dwError = AllocateSPDMemory(
  306. sizeof(ADDR) * dwAddrCnt,
  307. &pOutAddr
  308. );
  309. BAIL_ON_WIN32_ERROR(dwError);
  310. for (i = 0; i < dwAddrCnt; i++) {
  311. pOutAddr[i].AddrType = InAddr.AddrType;
  312. pOutAddr[i].uIpAddr = pMatchingAddresses[i].uIpAddr;
  313. pOutAddr[i].uSubNetMask = InAddr.uSubNetMask;
  314. memcpy(
  315. &pOutAddr[i].gInterfaceID,
  316. &InAddr.gInterfaceID,
  317. sizeof(GUID)
  318. );
  319. }
  320. dwOutAddrCnt = dwAddrCnt;
  321. }
  322. else {
  323. dwError = AllocateSPDMemory(
  324. sizeof(ADDR),
  325. &pOutAddr
  326. );
  327. BAIL_ON_WIN32_ERROR(dwError);
  328. memcpy(pOutAddr, &InAddr, sizeof(ADDR));
  329. dwOutAddrCnt = 1;
  330. }
  331. break;
  332. case IP_ADDR_SUBNET:
  333. dwError = AllocateSPDMemory(
  334. sizeof(ADDR),
  335. &pOutAddr
  336. );
  337. BAIL_ON_WIN32_ERROR(dwError);
  338. memcpy(pOutAddr, &InAddr, sizeof(ADDR));
  339. dwOutAddrCnt = 1;
  340. break;
  341. case IP_ADDR_INTERFACE:
  342. for (i = 0; i < dwAddrCnt; i++) {
  343. if (!memcmp(
  344. &pMatchingAddresses[i].gInterfaceID,
  345. &InAddr.gInterfaceID,
  346. sizeof(GUID))) {
  347. dwOutAddrCnt++;
  348. }
  349. }
  350. if (dwOutAddrCnt) {
  351. dwError = AllocateSPDMemory(
  352. sizeof(ADDR) * dwOutAddrCnt,
  353. &pOutAddr
  354. );
  355. BAIL_ON_WIN32_ERROR(dwError);
  356. for (i = 0; i < dwAddrCnt; i++) {
  357. if (!memcmp(
  358. &pMatchingAddresses[i].gInterfaceID,
  359. &InAddr.gInterfaceID,
  360. sizeof(GUID))) {
  361. pOutAddr[j].AddrType = InAddr.AddrType;
  362. pOutAddr[j].uIpAddr = pMatchingAddresses[i].uIpAddr;
  363. pOutAddr[j].uSubNetMask = InAddr.uSubNetMask;
  364. memcpy(
  365. &pOutAddr[j].gInterfaceID,
  366. &InAddr.gInterfaceID,
  367. sizeof(GUID)
  368. );
  369. j++;
  370. }
  371. }
  372. }
  373. break;
  374. }
  375. *ppOutAddr = pOutAddr;
  376. *pdwOutAddrCnt = dwOutAddrCnt;
  377. return (dwError);
  378. error:
  379. *ppOutAddr = NULL;
  380. *pdwOutAddrCnt = 0;
  381. return (dwError);
  382. }
  383. DWORD
  384. SeparateAddrList(
  385. ADDR_TYPE AddrType,
  386. PADDR pAddrList,
  387. DWORD dwAddrCnt,
  388. MATCHING_ADDR * pMatchingAddresses,
  389. DWORD dwLocalAddrCnt,
  390. PADDR * ppOutAddrList,
  391. PDWORD pdwOutAddrCnt,
  392. PADDR * ppInAddrList,
  393. PDWORD pdwInAddrCnt
  394. )
  395. /*++
  396. Routine Description:
  397. This function separates the address list into
  398. two mutually exclusive outbound and inbound
  399. address sets.
  400. Arguments:
  401. AddrType - Type of address under consideration.
  402. pAddrList - List of addresses to separate.
  403. dwAddrCnt - Number of addresses in the list.
  404. pMatchingAddresses - List of local ip addresses whose interface
  405. type matches that of the filter.
  406. dwLocalAddrCnt - Number of local ip addresses in the list.
  407. ppOutAddrList - List of outbound addresses.
  408. pdwOutAddrCnt - Number of addresses in the outbound
  409. address list.
  410. ppInAddrList - List of inbound addresses.
  411. pdwInAddrCnt - Number of addresses in the inbound
  412. address list.
  413. Return Value:
  414. ERROR_SUCCESS - Success.
  415. Win32 Error - Failure.
  416. --*/
  417. {
  418. DWORD dwError = 0;
  419. switch(AddrType) {
  420. case IP_ADDR_UNIQUE:
  421. dwError = SeparateUniqueAddresses(
  422. pAddrList,
  423. dwAddrCnt,
  424. pMatchingAddresses,
  425. dwLocalAddrCnt,
  426. ppOutAddrList,
  427. pdwOutAddrCnt,
  428. ppInAddrList,
  429. pdwInAddrCnt
  430. );
  431. BAIL_ON_WIN32_ERROR(dwError);
  432. break;
  433. case IP_ADDR_SUBNET:
  434. dwError = SeparateSubNetAddresses(
  435. pAddrList,
  436. dwAddrCnt,
  437. pMatchingAddresses,
  438. dwLocalAddrCnt,
  439. ppOutAddrList,
  440. pdwOutAddrCnt,
  441. ppInAddrList,
  442. pdwInAddrCnt
  443. );
  444. BAIL_ON_WIN32_ERROR(dwError);
  445. break;
  446. case IP_ADDR_INTERFACE:
  447. dwError = SeparateInterfaceAddresses(
  448. pAddrList,
  449. dwAddrCnt,
  450. pMatchingAddresses,
  451. dwLocalAddrCnt,
  452. ppOutAddrList,
  453. pdwOutAddrCnt,
  454. ppInAddrList,
  455. pdwInAddrCnt
  456. );
  457. BAIL_ON_WIN32_ERROR(dwError);
  458. break;
  459. }
  460. error:
  461. return (dwError);
  462. }
  463. DWORD
  464. FormSpecificTxFilters(
  465. PINITXFILTER pFilter,
  466. PADDR pSrcAddrList,
  467. DWORD dwSrcAddrCnt,
  468. PADDR pDesAddrList,
  469. DWORD dwDesAddrCnt,
  470. DWORD dwDirection,
  471. PINITXSFILTER * ppSpecificFilters
  472. )
  473. /*++
  474. Routine Description:
  475. This function forms the specific transport filters
  476. for the given generic filter and the source and
  477. destination address sets.
  478. Arguments:
  479. pFilter - Generic filter for which specific filters
  480. are to be created.
  481. pSrcAddrList - List of source addresses.
  482. dwSrcAddrCnt - Number of addresses in the source
  483. address list.
  484. pDesAddrList - List of destination addresses.
  485. dwDesAddrCnt - Number of addresses in the destination
  486. address list.
  487. ppSpecificFilters - Specific filters created for the given
  488. generic filter and the given addresses.
  489. Return Value:
  490. ERROR_SUCCESS - Success.
  491. Win32 Error - Failure.
  492. --*/
  493. {
  494. DWORD dwError = 0;
  495. PINITXSFILTER pSpecificFilters = NULL;
  496. DWORD i = 0, j = 0;
  497. PINITXSFILTER pSpecificFilter = NULL;
  498. for (i = 0; i < dwSrcAddrCnt; i++) {
  499. for (j = 0; j < dwDesAddrCnt; j++) {
  500. dwError = CreateSpecificTxFilter(
  501. pFilter,
  502. pSrcAddrList[i],
  503. pDesAddrList[j],
  504. &pSpecificFilter
  505. );
  506. BAIL_ON_WIN32_ERROR(dwError);
  507. //
  508. // Set the direction of the filter.
  509. //
  510. pSpecificFilter->dwDirection = dwDirection;
  511. AssignTxFilterWeight(pSpecificFilter);
  512. AddToSpecificTxList(
  513. &pSpecificFilters,
  514. pSpecificFilter
  515. );
  516. }
  517. }
  518. *ppSpecificFilters = pSpecificFilters;
  519. return (dwError);
  520. error:
  521. if (pSpecificFilters) {
  522. FreeIniTxSFilterList(pSpecificFilters);
  523. }
  524. *ppSpecificFilters = NULL;
  525. return (dwError);
  526. }
  527. DWORD
  528. SeparateUniqueAddresses(
  529. PADDR pAddrList,
  530. DWORD dwAddrCnt,
  531. MATCHING_ADDR * pMatchingAddresses,
  532. DWORD dwLocalAddrCnt,
  533. PADDR * ppIsMeAddrList,
  534. PDWORD pdwIsMeAddrCnt,
  535. PADDR * ppIsNotMeAddrList,
  536. PDWORD pdwIsNotMeAddrCnt
  537. )
  538. /*++
  539. Routine Description:
  540. This function separates a list of unique ip addresses into
  541. two mutually exclusive local and non-local address sets.
  542. Arguments:
  543. pAddrList - List of unique ip addresses to separate.
  544. dwAddrCnt - Number of unique ip addresses in the list.
  545. pMatchingAddresses - List of local ip addresses whose interface
  546. type matches that of the filter.
  547. dwAddrCnt - Number of local ip addresses in the list.
  548. ppIsMeAddrList - List of machine's ip addresses separated from
  549. the given list.
  550. pdwIsMeAddrCnt - Number of machine's ip addresses in the list.
  551. ppIsNotMeAddrList - List of not machine's ip addresses separated from
  552. the given list.
  553. pdwIsNotMeAddrCnt - Number of not machine's ip addresses in the list.
  554. Return Value:
  555. ERROR_SUCCESS - Success.
  556. Win32 Error - Failure.
  557. --*/
  558. {
  559. DWORD dwError = 0;
  560. PADDR pIsMeAddrList = NULL;
  561. DWORD dwIsMeAddrCnt = 0;
  562. PADDR pIsNotMeAddrList = NULL;
  563. DWORD dwIsNotMeAddrCnt = 0;
  564. DWORD i = 0, j = 0, k = 0;
  565. BOOL bEqual = FALSE;
  566. BOOL bIsClassD = FALSE;
  567. for (i = 0; i < dwAddrCnt; i++) {
  568. bIsClassD = IN_CLASSD(ntohl(pAddrList[i].uIpAddr));
  569. switch (bIsClassD) {
  570. case TRUE:
  571. dwIsMeAddrCnt++;
  572. dwIsNotMeAddrCnt++;
  573. break;
  574. case FALSE:
  575. //
  576. // Check if the address is one of the matching interfaces' address.
  577. //
  578. bEqual = InterfaceAddrIsLocal(
  579. pAddrList[i].uIpAddr,
  580. pAddrList[i].uSubNetMask,
  581. pMatchingAddresses,
  582. dwLocalAddrCnt
  583. );
  584. if (bEqual) {
  585. dwIsMeAddrCnt++;
  586. }
  587. else {
  588. //
  589. // Check if the address is one of the machine's ip address.
  590. //
  591. bEqual = IsMyAddress(
  592. pAddrList[i].uIpAddr,
  593. pAddrList[i].uSubNetMask,
  594. gpInterfaceList
  595. );
  596. if (!bEqual) {
  597. dwIsNotMeAddrCnt++;
  598. }
  599. }
  600. break;
  601. }
  602. }
  603. if (dwIsMeAddrCnt) {
  604. dwError = AllocateSPDMemory(
  605. sizeof(ADDR) * dwIsMeAddrCnt,
  606. &pIsMeAddrList
  607. );
  608. BAIL_ON_WIN32_ERROR(dwError);
  609. }
  610. if (dwIsNotMeAddrCnt) {
  611. dwError = AllocateSPDMemory(
  612. sizeof(ADDR) * dwIsNotMeAddrCnt,
  613. &pIsNotMeAddrList
  614. );
  615. BAIL_ON_WIN32_ERROR(dwError);
  616. }
  617. for (i = 0; i < dwAddrCnt; i++) {
  618. bIsClassD = IN_CLASSD(ntohl(pAddrList[i].uIpAddr));
  619. switch (bIsClassD) {
  620. case TRUE:
  621. memcpy(
  622. &(pIsMeAddrList[j]),
  623. &(pAddrList[i]),
  624. sizeof(ADDR)
  625. );
  626. j++;
  627. memcpy(
  628. &pIsNotMeAddrList[k],
  629. &pAddrList[i],
  630. sizeof(ADDR)
  631. );
  632. k++;
  633. break;
  634. case FALSE:
  635. bEqual = InterfaceAddrIsLocal(
  636. pAddrList[i].uIpAddr,
  637. pAddrList[i].uSubNetMask,
  638. pMatchingAddresses,
  639. dwLocalAddrCnt
  640. );
  641. if (bEqual) {
  642. memcpy(
  643. &(pIsMeAddrList[j]),
  644. &(pAddrList[i]),
  645. sizeof(ADDR)
  646. );
  647. j++;
  648. }
  649. else {
  650. bEqual = IsMyAddress(
  651. pAddrList[i].uIpAddr,
  652. pAddrList[i].uSubNetMask,
  653. gpInterfaceList
  654. );
  655. if (!bEqual) {
  656. memcpy(
  657. &pIsNotMeAddrList[k],
  658. &pAddrList[i],
  659. sizeof(ADDR)
  660. );
  661. k++;
  662. }
  663. }
  664. break;
  665. }
  666. }
  667. *ppIsMeAddrList = pIsMeAddrList;
  668. *pdwIsMeAddrCnt = dwIsMeAddrCnt;
  669. *ppIsNotMeAddrList = pIsNotMeAddrList;
  670. *pdwIsNotMeAddrCnt = dwIsNotMeAddrCnt;
  671. return (dwError);
  672. error:
  673. if (pIsMeAddrList) {
  674. FreeSPDMemory(pIsMeAddrList);
  675. }
  676. if (pIsNotMeAddrList) {
  677. FreeSPDMemory(pIsNotMeAddrList);
  678. }
  679. *ppIsMeAddrList = NULL;
  680. *pdwIsMeAddrCnt = 0;
  681. *ppIsNotMeAddrList = NULL;
  682. *pdwIsNotMeAddrCnt = 0;
  683. return (dwError);
  684. }
  685. DWORD
  686. SeparateSubNetAddresses(
  687. PADDR pAddrList,
  688. DWORD dwAddrCnt,
  689. MATCHING_ADDR * pMatchingAddresses,
  690. DWORD dwLocalAddrCnt,
  691. PADDR * ppIsMeAddrList,
  692. PDWORD pdwIsMeAddrCnt,
  693. PADDR * ppIsNotMeAddrList,
  694. PDWORD pdwIsNotMeAddrCnt
  695. )
  696. /*++
  697. Routine Description:
  698. This function separates a list of subnet addresses into
  699. two non-mutually exclusive local and non-local address sets.
  700. Arguments:
  701. pAddrList - List of subnet addresses to separate.
  702. dwAddrCnt - Number of subnet addresses in the list.
  703. pMatchingAddresses - List of local ip addresses whose interface
  704. type matches that of the filter.
  705. dwAddrCnt - Number of local ip addresses in the list.
  706. ppIsMeAddrList - List of subnet addresses that contain atleast
  707. one of the machine's ip address.
  708. pdwIsMeAddrCnt - Number of subnet addresses containing atleast
  709. one of the machine's ip address.
  710. ppIsNotMeAddrList - List of subnet addresses as in the input list.
  711. pdwIsNotMeAddrCnt - Number of subnet addresses as in the input list.
  712. Return Value:
  713. ERROR_SUCCESS - Success.
  714. Win32 Error - Failure.
  715. --*/
  716. {
  717. DWORD dwError = 0;
  718. PADDR pIsMeAddrList = NULL;
  719. DWORD dwIsMeAddrCnt = 0;
  720. PADDR pIsNotMeAddrList = NULL;
  721. DWORD dwIsNotMeAddrCnt = 0;
  722. DWORD i = 0, j = 0, k = 0;
  723. BOOL bEqual = FALSE;
  724. BOOL bIsClassD = FALSE;
  725. for (i = 0; i < dwAddrCnt; i++) {
  726. bIsClassD = IN_CLASSD(ntohl(pAddrList[i].uIpAddr));
  727. switch (bIsClassD) {
  728. case TRUE:
  729. dwIsMeAddrCnt++;
  730. break;
  731. case FALSE:
  732. //
  733. // Check if one of the matching interfaces' address belongs to
  734. // the subnet.
  735. //
  736. bEqual = InterfaceAddrIsLocal(
  737. pAddrList[i].uIpAddr,
  738. pAddrList[i].uSubNetMask,
  739. pMatchingAddresses,
  740. dwLocalAddrCnt
  741. );
  742. if (bEqual) {
  743. dwIsMeAddrCnt++;
  744. }
  745. break;
  746. }
  747. //
  748. // The subnet will have addresses that don't belong to the local
  749. // machine.
  750. //
  751. dwIsNotMeAddrCnt++;
  752. }
  753. if (dwIsMeAddrCnt) {
  754. dwError = AllocateSPDMemory(
  755. sizeof(ADDR) * dwIsMeAddrCnt,
  756. &pIsMeAddrList
  757. );
  758. BAIL_ON_WIN32_ERROR(dwError);
  759. }
  760. if (dwIsNotMeAddrCnt) {
  761. dwError = AllocateSPDMemory(
  762. sizeof(ADDR) * dwIsNotMeAddrCnt,
  763. &pIsNotMeAddrList
  764. );
  765. BAIL_ON_WIN32_ERROR(dwError);
  766. }
  767. for (i = 0; i < dwAddrCnt; i++) {
  768. bIsClassD = IN_CLASSD(ntohl(pAddrList[i].uIpAddr));
  769. switch (bIsClassD) {
  770. case TRUE:
  771. memcpy(
  772. &(pIsMeAddrList[j]),
  773. &(pAddrList[i]),
  774. sizeof(ADDR)
  775. );
  776. j++;
  777. break;
  778. case FALSE:
  779. bEqual = InterfaceAddrIsLocal(
  780. pAddrList[i].uIpAddr,
  781. pAddrList[i].uSubNetMask,
  782. pMatchingAddresses,
  783. dwLocalAddrCnt
  784. );
  785. if (bEqual) {
  786. memcpy(
  787. &(pIsMeAddrList[j]),
  788. &(pAddrList[i]),
  789. sizeof(ADDR)
  790. );
  791. j++;
  792. }
  793. break;
  794. }
  795. memcpy(
  796. &pIsNotMeAddrList[k],
  797. &pAddrList[i],
  798. sizeof(ADDR)
  799. );
  800. k++;
  801. }
  802. *ppIsMeAddrList = pIsMeAddrList;
  803. *pdwIsMeAddrCnt = dwIsMeAddrCnt;
  804. *ppIsNotMeAddrList = pIsNotMeAddrList;
  805. *pdwIsNotMeAddrCnt = dwIsNotMeAddrCnt;
  806. return (dwError);
  807. error:
  808. if (pIsMeAddrList) {
  809. FreeSPDMemory(pIsMeAddrList);
  810. }
  811. if (pIsNotMeAddrList) {
  812. FreeSPDMemory(pIsNotMeAddrList);
  813. }
  814. *ppIsMeAddrList = NULL;
  815. *pdwIsMeAddrCnt = 0;
  816. *ppIsNotMeAddrList = NULL;
  817. *pdwIsNotMeAddrCnt = 0;
  818. return (dwError);
  819. }
  820. DWORD
  821. CreateSpecificTxFilter(
  822. PINITXFILTER pGenericFilter,
  823. ADDR SrcAddr,
  824. ADDR DesAddr,
  825. PINITXSFILTER * ppSpecificFilter
  826. )
  827. {
  828. DWORD dwError = 0;
  829. PINITXSFILTER pSpecificFilter = NULL;
  830. dwError = AllocateSPDMemory(
  831. sizeof(INITXSFILTER),
  832. &pSpecificFilter
  833. );
  834. BAIL_ON_WIN32_ERROR(dwError);
  835. pSpecificFilter->cRef = 0;
  836. CopyGuid(pGenericFilter->gFilterID, &(pSpecificFilter->gParentID));
  837. dwError = AllocateSPDString(
  838. pGenericFilter->pszFilterName,
  839. &(pSpecificFilter->pszFilterName)
  840. );
  841. BAIL_ON_WIN32_ERROR(dwError);
  842. pSpecificFilter->InterfaceType = pGenericFilter->InterfaceType;
  843. pSpecificFilter->dwFlags = pGenericFilter->dwFlags;
  844. CopyAddresses(SrcAddr, &(pSpecificFilter->SrcAddr));
  845. CopyAddresses(DesAddr, &(pSpecificFilter->DesAddr));
  846. CopyPorts(pGenericFilter->SrcPort, &(pSpecificFilter->SrcPort));
  847. CopyPorts(pGenericFilter->DesPort, &(pSpecificFilter->DesPort));
  848. CopyProtocols(pGenericFilter->Protocol, &(pSpecificFilter->Protocol));
  849. pSpecificFilter->InboundFilterFlag = pGenericFilter->InboundFilterFlag;
  850. pSpecificFilter->OutboundFilterFlag = pGenericFilter->OutboundFilterFlag;
  851. //
  852. // Direction must be set in the calling routine.
  853. //
  854. pSpecificFilter->dwDirection = 0;
  855. //
  856. // Weight must be set in the calling routine.
  857. //
  858. pSpecificFilter->dwWeight = 0;
  859. CopyGuid(pGenericFilter->gPolicyID, &(pSpecificFilter->gPolicyID));
  860. pSpecificFilter->pIniQMPolicy = NULL;
  861. pSpecificFilter->pNext = NULL;
  862. *ppSpecificFilter = pSpecificFilter;
  863. return (dwError);
  864. error:
  865. if (pSpecificFilter) {
  866. FreeIniTxSFilter(pSpecificFilter);
  867. }
  868. *ppSpecificFilter = NULL;
  869. return (dwError);
  870. }
  871. VOID
  872. AssignTxFilterWeight(
  873. PINITXSFILTER pSpecificFilter
  874. )
  875. /*++
  876. Routine Description:
  877. Computes and assigns the weight to a specific transport filter.
  878. The transport filter weight consists of the following:
  879. 31 16 12 8 0
  880. +-----------+--------+-----------+--------+
  881. |AddrMaskWgt|Reserved|ProtocolWgt|PortWgts|
  882. +-----------+--------+-----------+--------+
  883. Arguments:
  884. pSpecificFilter - Specific transport filter to which the weight
  885. is to be assigned.
  886. Return Value:
  887. None.
  888. --*/
  889. {
  890. DWORD dwWeight = 0;
  891. ULONG SrcMask = 0;
  892. ULONG DesMask = 0;
  893. DWORD dwMaskWeight = 0;
  894. DWORD i = 0;
  895. //
  896. // Weight Rule:
  897. // A field with a more specific value gets a higher weight than
  898. // the same field with a lesser specific value.
  899. //
  900. //
  901. // If the protocol is specific then assign the specific protocol
  902. // weight else the weight is zero.
  903. // All the specific filters that have a specific protocol and
  904. // differ only in the protocol field will have the same weight.
  905. //
  906. if (pSpecificFilter->Protocol.dwProtocol != 0) {
  907. dwWeight |= WEIGHT_SPECIFIC_PROTOCOL;
  908. }
  909. //
  910. // If the source port is specific then assign the specific source
  911. // port weight else the weight is zero.
  912. // All the specific filters that have a specific source port and
  913. // differ only in the source port field will have the same weight.
  914. //
  915. if (pSpecificFilter->SrcPort.wPort != 0) {
  916. dwWeight |= WEIGHT_SPECIFIC_SOURCE_PORT;
  917. }
  918. //
  919. // If the destination port is specific then assign the specific
  920. // destination port weight else the weight is zero.
  921. // All the specific filters that have a specific destination port
  922. // and differ only in the destination port field will have the
  923. // same weight.
  924. //
  925. if (pSpecificFilter->DesPort.wPort != 0) {
  926. dwWeight |= WEIGHT_SPECIFIC_DESTINATION_PORT;
  927. }
  928. //
  929. // IP addresses get the weight values based on their mask values.
  930. // In the address case, the weight is computed as a sum of the
  931. // bit positions starting from the position that contains the
  932. // first least significant non-zero bit to the most significant
  933. // bit position of the mask.
  934. // All unique ip addresses have a mask of 0xFFFFFFFF and thus get
  935. // the same weight, which is 1 + 2 + .... + 32.
  936. // A subnet address has a mask with atleast the least significant
  937. // bit zero and thus gets weight in the range (2 + .. + 32) to 0.
  938. //
  939. DesMask = ntohl(pSpecificFilter->DesAddr.uSubNetMask);
  940. for (i = 0; i < sizeof(ULONG) * 8; i++) {
  941. //
  942. // If the bit position contains a non-zero bit, add the bit
  943. // position to the sum.
  944. //
  945. if ((DesMask & 0x1) == 0x1) {
  946. dwMaskWeight += (i+1);
  947. }
  948. //
  949. // Move to the next bit position.
  950. //
  951. DesMask = DesMask >> 1;
  952. }
  953. SrcMask = ntohl(pSpecificFilter->SrcAddr.uSubNetMask);
  954. for (i = 0; i < sizeof(ULONG) * 8; i++) {
  955. //
  956. // If the bit position contains a non-zero bit, add the bit
  957. // position to the sum.
  958. //
  959. if ((SrcMask & 0x1) == 0x1) {
  960. dwMaskWeight += (i+1);
  961. }
  962. //
  963. // Move to the next bit position.
  964. //
  965. SrcMask = SrcMask >> 1;
  966. }
  967. //
  968. // Move the mask weight to the set of bits in the overall weight
  969. // that it occupies.
  970. //
  971. dwMaskWeight = dwMaskWeight << 16;
  972. dwWeight += dwMaskWeight;
  973. pSpecificFilter->dwWeight = dwWeight;
  974. }
  975. VOID
  976. AddToSpecificTxList(
  977. PINITXSFILTER * ppSpecificTxFilterList,
  978. PINITXSFILTER pSpecificTxFilters
  979. )
  980. {
  981. PINITXSFILTER pListOne = NULL;
  982. PINITXSFILTER pListTwo = NULL;
  983. PINITXSFILTER pListMerge = NULL;
  984. PINITXSFILTER pLast = NULL;
  985. if (!(*ppSpecificTxFilterList) && !pSpecificTxFilters) {
  986. return;
  987. }
  988. if (!(*ppSpecificTxFilterList)) {
  989. *ppSpecificTxFilterList = pSpecificTxFilters;
  990. return;
  991. }
  992. if (!pSpecificTxFilters) {
  993. return;
  994. }
  995. pListOne = *ppSpecificTxFilterList;
  996. pListTwo = pSpecificTxFilters;
  997. while (pListOne && pListTwo) {
  998. if ((pListOne->dwWeight) > (pListTwo->dwWeight)) {
  999. if (!pListMerge) {
  1000. pListMerge = pListOne;
  1001. pLast = pListOne;
  1002. pListOne = pListOne->pNext;
  1003. }
  1004. else {
  1005. pLast->pNext = pListOne;
  1006. pListOne = pListOne->pNext;
  1007. pLast = pLast->pNext;
  1008. }
  1009. }
  1010. else {
  1011. if (!pListMerge) {
  1012. pListMerge = pListTwo;
  1013. pLast = pListTwo;
  1014. pListTwo = pListTwo->pNext;
  1015. }
  1016. else {
  1017. pLast->pNext = pListTwo;
  1018. pListTwo = pListTwo->pNext;
  1019. pLast = pLast->pNext;
  1020. }
  1021. }
  1022. }
  1023. if (pListOne) {
  1024. pLast->pNext = pListOne;
  1025. }
  1026. else {
  1027. pLast->pNext = pListTwo;
  1028. }
  1029. *ppSpecificTxFilterList = pListMerge;
  1030. return;
  1031. }
  1032. VOID
  1033. FreeIniTxSFilterList(
  1034. PINITXSFILTER pIniTxSFilterList
  1035. )
  1036. {
  1037. PINITXSFILTER pFilter = NULL;
  1038. PINITXSFILTER pTempFilter = NULL;
  1039. pFilter = pIniTxSFilterList;
  1040. while (pFilter) {
  1041. pTempFilter = pFilter;
  1042. pFilter = pFilter->pNext;
  1043. FreeIniTxSFilter(pTempFilter);
  1044. }
  1045. }
  1046. VOID
  1047. FreeIniTxSFilter(
  1048. PINITXSFILTER pIniTxSFilter
  1049. )
  1050. {
  1051. if (pIniTxSFilter) {
  1052. if (pIniTxSFilter->pszFilterName) {
  1053. FreeSPDString(pIniTxSFilter->pszFilterName);
  1054. }
  1055. //
  1056. // Must not ever free pIniTxSFilter->pIniQMPolicy.
  1057. //
  1058. FreeSPDMemory(pIniTxSFilter);
  1059. }
  1060. }
  1061. VOID
  1062. LinkTxSpecificFilters(
  1063. PINIQMPOLICY pIniQMPolicy,
  1064. PINITXSFILTER pIniTxSFilters
  1065. )
  1066. {
  1067. PINITXSFILTER pTemp = NULL;
  1068. pTemp = pIniTxSFilters;
  1069. while (pTemp) {
  1070. pTemp->pIniQMPolicy = pIniQMPolicy;
  1071. pTemp = pTemp->pNext;
  1072. }
  1073. return;
  1074. }
  1075. VOID
  1076. RemoveIniTxSFilter(
  1077. PINITXSFILTER pIniTxSFilter
  1078. )
  1079. {
  1080. PINITXSFILTER * ppTemp = NULL;
  1081. ppTemp = &gpIniTxSFilter;
  1082. while (*ppTemp) {
  1083. if (*ppTemp == pIniTxSFilter) {
  1084. break;
  1085. }
  1086. ppTemp = &((*ppTemp)->pNext);
  1087. }
  1088. if (*ppTemp) {
  1089. *ppTemp = pIniTxSFilter->pNext;
  1090. }
  1091. return;
  1092. }
  1093. DWORD
  1094. EnumSpecificTxFilters(
  1095. PINITXSFILTER pIniTxSFilterList,
  1096. DWORD dwResumeHandle,
  1097. DWORD dwPreferredNumEntries,
  1098. PTRANSPORT_FILTER * ppTxFilters,
  1099. PDWORD pdwNumTxFilters
  1100. )
  1101. /*++
  1102. Routine Description:
  1103. This function creates enumerated specific filters.
  1104. Arguments:
  1105. pIniTxSFilterList - List of specific filters to enumerate.
  1106. dwResumeHandle - Location in the specific filter list from which
  1107. to resume enumeration.
  1108. dwPreferredNumEntries - Preferred number of enumeration entries.
  1109. ppTxFilters - Enumerated filters returned to the caller.
  1110. pdwNumTxFilters - Number of filters actually enumerated.
  1111. Return Value:
  1112. ERROR_SUCCESS - Success.
  1113. Win32 Error - Failure.
  1114. --*/
  1115. {
  1116. DWORD dwError = 0;
  1117. DWORD dwNumToEnum = 0;
  1118. PINITXSFILTER pIniTxSFilter = NULL;
  1119. DWORD i = 0;
  1120. PINITXSFILTER pTemp = NULL;
  1121. DWORD dwNumTxFilters = 0;
  1122. PTRANSPORT_FILTER pTxFilters = 0;
  1123. PTRANSPORT_FILTER pTxFilter = 0;
  1124. if (!dwPreferredNumEntries ||
  1125. (dwPreferredNumEntries > MAX_TRANSPORTFILTER_ENUM_COUNT)) {
  1126. dwNumToEnum = MAX_TRANSPORTFILTER_ENUM_COUNT;
  1127. }
  1128. else {
  1129. dwNumToEnum = dwPreferredNumEntries;
  1130. }
  1131. pIniTxSFilter = pIniTxSFilterList;
  1132. for (i = 0; (i < dwResumeHandle) && (pIniTxSFilter != NULL); i++) {
  1133. pIniTxSFilter = pIniTxSFilter->pNext;
  1134. }
  1135. if (!pIniTxSFilter) {
  1136. dwError = ERROR_NO_DATA;
  1137. BAIL_ON_WIN32_ERROR(dwError);
  1138. }
  1139. pTemp = pIniTxSFilter;
  1140. while (pTemp && (dwNumTxFilters < dwNumToEnum)) {
  1141. dwNumTxFilters++;
  1142. pTemp = pTemp->pNext;
  1143. }
  1144. dwError = SPDApiBufferAllocate(
  1145. sizeof(TRANSPORT_FILTER)*dwNumTxFilters,
  1146. &pTxFilters
  1147. );
  1148. BAIL_ON_WIN32_ERROR(dwError);
  1149. pTemp = pIniTxSFilter;
  1150. pTxFilter = pTxFilters;
  1151. for (i = 0; i < dwNumTxFilters; i++) {
  1152. dwError = CopyTxSFilter(
  1153. pTemp,
  1154. pTxFilter
  1155. );
  1156. BAIL_ON_WIN32_ERROR(dwError);
  1157. pTemp = pTemp->pNext;
  1158. pTxFilter++;
  1159. }
  1160. *ppTxFilters = pTxFilters;
  1161. *pdwNumTxFilters = dwNumTxFilters;
  1162. return (dwError);
  1163. error:
  1164. if (pTxFilters) {
  1165. FreeTxFilters(
  1166. i,
  1167. pTxFilters
  1168. );
  1169. }
  1170. *ppTxFilters = NULL;
  1171. *pdwNumTxFilters = 0;
  1172. return (dwError);
  1173. }
  1174. DWORD
  1175. CopyTxSFilter(
  1176. PINITXSFILTER pIniTxSFilter,
  1177. PTRANSPORT_FILTER pTxFilter
  1178. )
  1179. /*++
  1180. Routine Description:
  1181. This function copies an internal filter into an external filter
  1182. container.
  1183. Arguments:
  1184. pIniTxSFilter - Internal filter to copy.
  1185. pTxFilter - External filter container in which to copy.
  1186. Return Value:
  1187. ERROR_SUCCESS - Success.
  1188. Win32 Error - Failure.
  1189. --*/
  1190. {
  1191. DWORD dwError = 0;
  1192. CopyGuid(pIniTxSFilter->gParentID, &(pTxFilter->gFilterID));
  1193. dwError = CopyName(
  1194. pIniTxSFilter->pszFilterName,
  1195. &(pTxFilter->pszFilterName)
  1196. );
  1197. BAIL_ON_WIN32_ERROR(dwError);
  1198. pTxFilter->InterfaceType = pIniTxSFilter->InterfaceType;
  1199. pTxFilter->bCreateMirror = FALSE;
  1200. pTxFilter->dwFlags = pIniTxSFilter->dwFlags;
  1201. CopyAddresses(pIniTxSFilter->SrcAddr, &(pTxFilter->SrcAddr));
  1202. CopyAddresses(pIniTxSFilter->DesAddr, &(pTxFilter->DesAddr));
  1203. CopyProtocols(pIniTxSFilter->Protocol, &(pTxFilter->Protocol));
  1204. CopyPorts(pIniTxSFilter->SrcPort, &(pTxFilter->SrcPort));
  1205. CopyPorts(pIniTxSFilter->DesPort, &(pTxFilter->DesPort));
  1206. pTxFilter->InboundFilterFlag = pIniTxSFilter->InboundFilterFlag;
  1207. pTxFilter->OutboundFilterFlag = pIniTxSFilter->OutboundFilterFlag;
  1208. pTxFilter->dwDirection = pIniTxSFilter->dwDirection;
  1209. pTxFilter->dwWeight = pIniTxSFilter->dwWeight;
  1210. CopyGuid(pIniTxSFilter->gPolicyID, &(pTxFilter->gPolicyID));
  1211. error:
  1212. return (dwError);
  1213. }
  1214. DWORD
  1215. EnumSelectSpecificTxFilters(
  1216. PINITXFILTER pIniTxFilter,
  1217. DWORD dwResumeHandle,
  1218. DWORD dwPreferredNumEntries,
  1219. PTRANSPORT_FILTER * ppTxFilters,
  1220. PDWORD pdwNumTxFilters
  1221. )
  1222. /*++
  1223. Routine Description:
  1224. This function creates enumerated specific filters for
  1225. the given generic filter.
  1226. Arguments:
  1227. pIniTxFilter - Generic filter for which specific filters
  1228. are to be enumerated.
  1229. dwResumeHandle - Location in the specific filter list for the
  1230. given generic filter from which to resume
  1231. enumeration.
  1232. dwPreferredNumEntries - Preferred number of enumeration entries.
  1233. ppTxFilters - Enumerated filters returned to the caller.
  1234. pdwNumTxFilters - Number of filters actually enumerated.
  1235. Return Value:
  1236. ERROR_SUCCESS - Success.
  1237. Win32 Error - Failure.
  1238. --*/
  1239. {
  1240. DWORD dwError = 0;
  1241. DWORD dwNumToEnum = 0;
  1242. DWORD dwNumTxSFilters = 0;
  1243. PINITXSFILTER * ppIniTxSFilters = NULL;
  1244. DWORD i = 0;
  1245. DWORD dwNumTxFilters = 0;
  1246. PTRANSPORT_FILTER pTxFilters = 0;
  1247. PTRANSPORT_FILTER pTxFilter = 0;
  1248. if (!dwPreferredNumEntries ||
  1249. (dwPreferredNumEntries > MAX_TRANSPORTFILTER_ENUM_COUNT)) {
  1250. dwNumToEnum = MAX_TRANSPORTFILTER_ENUM_COUNT;
  1251. }
  1252. else {
  1253. dwNumToEnum = dwPreferredNumEntries;
  1254. }
  1255. dwNumTxSFilters = pIniTxFilter->dwNumTxSFilters;
  1256. ppIniTxSFilters = pIniTxFilter->ppIniTxSFilters;
  1257. if (!dwNumTxSFilters || (dwNumTxSFilters <= dwResumeHandle)) {
  1258. dwError = ERROR_NO_DATA;
  1259. BAIL_ON_WIN32_ERROR(dwError);
  1260. }
  1261. dwNumTxFilters = min((dwNumTxSFilters-dwResumeHandle),
  1262. dwNumToEnum);
  1263. dwError = SPDApiBufferAllocate(
  1264. sizeof(TRANSPORT_FILTER)*dwNumTxFilters,
  1265. &pTxFilters
  1266. );
  1267. BAIL_ON_WIN32_ERROR(dwError);
  1268. pTxFilter = pTxFilters;
  1269. for (i = 0; i < dwNumTxFilters; i++) {
  1270. dwError = CopyTxSFilter(
  1271. *(ppIniTxSFilters + (dwResumeHandle + i)),
  1272. pTxFilter
  1273. );
  1274. BAIL_ON_WIN32_ERROR(dwError);
  1275. pTxFilter++;
  1276. }
  1277. *ppTxFilters = pTxFilters;
  1278. *pdwNumTxFilters = dwNumTxFilters;
  1279. return (dwError);
  1280. error:
  1281. if (pTxFilters) {
  1282. FreeTxFilters(
  1283. i,
  1284. pTxFilters
  1285. );
  1286. }
  1287. *ppTxFilters = NULL;
  1288. *pdwNumTxFilters = 0;
  1289. return (dwError);
  1290. }
  1291. DWORD
  1292. MatchTransportFilter(
  1293. LPWSTR pServerName,
  1294. PTRANSPORT_FILTER pTxFilter,
  1295. DWORD dwFlags,
  1296. PTRANSPORT_FILTER * ppMatchedTxFilters,
  1297. PIPSEC_QM_POLICY * ppMatchedQMPolicies,
  1298. DWORD dwPreferredNumEntries,
  1299. LPDWORD pdwNumMatches,
  1300. LPDWORD pdwResumeHandle
  1301. )
  1302. /*++
  1303. Routine Description:
  1304. This function finds the matching transport filters for the
  1305. given transport filter template. The matched filters can not
  1306. be more specific than the given filter template.
  1307. Arguments:
  1308. pServerName - Server on which a filter template is to be matched.
  1309. pTxFilter - Filter template to match.
  1310. dwFlags - Flags.
  1311. ppMatchedTxFilters - Matched transport filters returned to the
  1312. caller.
  1313. ppMatchedQMPolicies - Quick mode policies corresponding to the
  1314. matched transport filters returned to the
  1315. caller.
  1316. dwPreferredNumEntries - Preferred number of matched entries.
  1317. pdwNumMatches - Number of filters actually matched.
  1318. pdwResumeHandle - Handle to the location in the matched filter
  1319. list from which to resume enumeration.
  1320. Return Value:
  1321. ERROR_SUCCESS - Success.
  1322. Win32 Error - Failure.
  1323. --*/
  1324. {
  1325. DWORD dwError = 0;
  1326. DWORD dwResumeHandle = 0;
  1327. DWORD dwNumToMatch = 0;
  1328. PINITXSFILTER pIniTxSFilter = NULL;
  1329. DWORD i = 0;
  1330. BOOL bMatches = FALSE;
  1331. PINITXSFILTER pTemp = NULL;
  1332. DWORD dwNumMatches = 0;
  1333. PINITXSFILTER pLastMatchedFilter = NULL;
  1334. PTRANSPORT_FILTER pMatchedTxFilters = NULL;
  1335. PIPSEC_QM_POLICY pMatchedQMPolicies = NULL;
  1336. DWORD dwNumFilters = 0;
  1337. DWORD dwNumPolicies = 0;
  1338. PTRANSPORT_FILTER pMatchedTxFilter = NULL;
  1339. PIPSEC_QM_POLICY pMatchedQMPolicy = NULL;
  1340. dwError = ValidateTxFilterTemplate(
  1341. pTxFilter
  1342. );
  1343. BAIL_ON_WIN32_ERROR(dwError);
  1344. dwResumeHandle = *pdwResumeHandle;
  1345. if (!dwPreferredNumEntries) {
  1346. dwNumToMatch = 1;
  1347. }
  1348. else if (dwPreferredNumEntries > MAX_TRANSPORTFILTER_ENUM_COUNT) {
  1349. dwNumToMatch = MAX_TRANSPORTFILTER_ENUM_COUNT;
  1350. }
  1351. else {
  1352. dwNumToMatch = dwPreferredNumEntries;
  1353. }
  1354. ENTER_SPD_SECTION();
  1355. dwError = ValidateTxSecurity(
  1356. SPD_OBJECT_SERVER,
  1357. SERVER_ACCESS_ADMINISTER,
  1358. NULL,
  1359. NULL
  1360. );
  1361. BAIL_ON_LOCK_ERROR(dwError);
  1362. pIniTxSFilter = gpIniTxSFilter;
  1363. while ((i < dwResumeHandle) && (pIniTxSFilter != NULL)) {
  1364. bMatches = MatchIniTxSFilter(
  1365. pIniTxSFilter,
  1366. pTxFilter
  1367. );
  1368. if (bMatches) {
  1369. i++;
  1370. }
  1371. pIniTxSFilter = pIniTxSFilter->pNext;
  1372. }
  1373. if (!pIniTxSFilter) {
  1374. if (!(dwFlags & RETURN_DEFAULTS_ON_NO_MATCH)) {
  1375. dwError = ERROR_NO_DATA;
  1376. BAIL_ON_LOCK_ERROR(dwError);
  1377. }
  1378. else {
  1379. dwError = CopyTxMatchDefaults(
  1380. &pMatchedTxFilters,
  1381. &pMatchedQMPolicies,
  1382. &dwNumMatches
  1383. );
  1384. BAIL_ON_LOCK_ERROR(dwError);
  1385. BAIL_ON_LOCK_SUCCESS(dwError);
  1386. }
  1387. }
  1388. pTemp = pIniTxSFilter;
  1389. while (pTemp && (dwNumMatches < dwNumToMatch)) {
  1390. bMatches = MatchIniTxSFilter(
  1391. pTemp,
  1392. pTxFilter
  1393. );
  1394. if (bMatches) {
  1395. pLastMatchedFilter = pTemp;
  1396. dwNumMatches++;
  1397. }
  1398. pTemp = pTemp->pNext;
  1399. }
  1400. if (!dwNumMatches) {
  1401. if (!(dwFlags & RETURN_DEFAULTS_ON_NO_MATCH)) {
  1402. dwError = ERROR_NO_DATA;
  1403. BAIL_ON_LOCK_ERROR(dwError);
  1404. }
  1405. else {
  1406. dwError = CopyTxMatchDefaults(
  1407. &pMatchedTxFilters,
  1408. &pMatchedQMPolicies,
  1409. &dwNumMatches
  1410. );
  1411. BAIL_ON_LOCK_ERROR(dwError);
  1412. BAIL_ON_LOCK_SUCCESS(dwError);
  1413. }
  1414. }
  1415. dwError = SPDApiBufferAllocate(
  1416. sizeof(TRANSPORT_FILTER)*dwNumMatches,
  1417. &pMatchedTxFilters
  1418. );
  1419. BAIL_ON_LOCK_ERROR(dwError);
  1420. dwError = SPDApiBufferAllocate(
  1421. sizeof(IPSEC_QM_POLICY)*dwNumMatches,
  1422. &pMatchedQMPolicies
  1423. );
  1424. BAIL_ON_LOCK_ERROR(dwError);
  1425. if (dwNumMatches == 1) {
  1426. dwError = CopyTxSFilter(
  1427. pLastMatchedFilter,
  1428. pMatchedTxFilters
  1429. );
  1430. BAIL_ON_LOCK_ERROR(dwError);
  1431. dwNumFilters++;
  1432. if (pLastMatchedFilter->pIniQMPolicy) {
  1433. dwError = CopyQMPolicy(
  1434. pLastMatchedFilter->pIniQMPolicy,
  1435. pMatchedQMPolicies
  1436. );
  1437. BAIL_ON_LOCK_ERROR(dwError);
  1438. }
  1439. else {
  1440. memset(pMatchedQMPolicies, 0, sizeof(IPSEC_QM_POLICY));
  1441. }
  1442. dwNumPolicies++;
  1443. }
  1444. else {
  1445. pTemp = pIniTxSFilter;
  1446. pMatchedTxFilter = pMatchedTxFilters;
  1447. pMatchedQMPolicy = pMatchedQMPolicies;
  1448. i = 0;
  1449. while (i < dwNumMatches) {
  1450. bMatches = MatchIniTxSFilter(
  1451. pTemp,
  1452. pTxFilter
  1453. );
  1454. if (bMatches) {
  1455. dwError = CopyTxSFilter(
  1456. pTemp,
  1457. pMatchedTxFilter
  1458. );
  1459. BAIL_ON_LOCK_ERROR(dwError);
  1460. pMatchedTxFilter++;
  1461. dwNumFilters++;
  1462. if (pTemp->pIniQMPolicy) {
  1463. dwError = CopyQMPolicy(
  1464. pTemp->pIniQMPolicy,
  1465. pMatchedQMPolicy
  1466. );
  1467. BAIL_ON_LOCK_ERROR(dwError);
  1468. }
  1469. else {
  1470. memset(pMatchedQMPolicy, 0, sizeof(IPSEC_QM_POLICY));
  1471. }
  1472. pMatchedQMPolicy++;
  1473. dwNumPolicies++;
  1474. i++;
  1475. }
  1476. pTemp = pTemp->pNext;
  1477. }
  1478. }
  1479. lock_success:
  1480. LEAVE_SPD_SECTION();
  1481. *ppMatchedTxFilters = pMatchedTxFilters;
  1482. *ppMatchedQMPolicies = pMatchedQMPolicies;
  1483. *pdwNumMatches = dwNumMatches;
  1484. *pdwResumeHandle = dwResumeHandle + dwNumMatches;
  1485. return (dwError);
  1486. lock:
  1487. LEAVE_SPD_SECTION();
  1488. error:
  1489. if (pMatchedTxFilters) {
  1490. FreeTxFilters(
  1491. dwNumFilters,
  1492. pMatchedTxFilters
  1493. );
  1494. }
  1495. if (pMatchedQMPolicies) {
  1496. FreeQMPolicies(
  1497. dwNumPolicies,
  1498. pMatchedQMPolicies
  1499. );
  1500. }
  1501. *ppMatchedTxFilters = NULL;
  1502. *ppMatchedQMPolicies = NULL;
  1503. *pdwNumMatches = 0;
  1504. *pdwResumeHandle = dwResumeHandle;
  1505. return (dwError);
  1506. }
  1507. DWORD
  1508. ValidateTxFilterTemplate(
  1509. PTRANSPORT_FILTER pTxFilter
  1510. )
  1511. {
  1512. DWORD dwError = 0;
  1513. BOOL bConflicts = FALSE;
  1514. if (!pTxFilter) {
  1515. dwError = ERROR_INVALID_PARAMETER;
  1516. BAIL_ON_WIN32_ERROR(dwError);
  1517. }
  1518. dwError = VerifyAddresses(pTxFilter->SrcAddr, TRUE, FALSE);
  1519. BAIL_ON_WIN32_ERROR(dwError);
  1520. dwError = VerifyAddresses(pTxFilter->DesAddr, TRUE, TRUE);
  1521. BAIL_ON_WIN32_ERROR(dwError);
  1522. bConflicts = AddressesConflict(
  1523. pTxFilter->SrcAddr,
  1524. pTxFilter->DesAddr
  1525. );
  1526. if (bConflicts) {
  1527. dwError = ERROR_INVALID_PARAMETER;
  1528. BAIL_ON_WIN32_ERROR(dwError);
  1529. }
  1530. dwError = VerifyProtocols(pTxFilter->Protocol);
  1531. BAIL_ON_WIN32_ERROR(dwError);
  1532. dwError = VerifyPortsForProtocol(
  1533. pTxFilter->SrcPort,
  1534. pTxFilter->Protocol
  1535. );
  1536. BAIL_ON_WIN32_ERROR(dwError);
  1537. dwError = VerifyPortsForProtocol(
  1538. pTxFilter->DesPort,
  1539. pTxFilter->Protocol
  1540. );
  1541. BAIL_ON_WIN32_ERROR(dwError);
  1542. if (pTxFilter->dwDirection) {
  1543. if ((pTxFilter->dwDirection != FILTER_DIRECTION_INBOUND) &&
  1544. (pTxFilter->dwDirection != FILTER_DIRECTION_OUTBOUND)) {
  1545. dwError = ERROR_INVALID_PARAMETER;
  1546. BAIL_ON_WIN32_ERROR(dwError);
  1547. }
  1548. }
  1549. error:
  1550. return (dwError);
  1551. }
  1552. BOOL
  1553. MatchIniTxSFilter(
  1554. PINITXSFILTER pIniTxSFilter,
  1555. PTRANSPORT_FILTER pTxFilter
  1556. )
  1557. {
  1558. BOOL bMatches = FALSE;
  1559. if (pTxFilter->dwDirection) {
  1560. if (pTxFilter->dwDirection != pIniTxSFilter->dwDirection) {
  1561. return (FALSE);
  1562. }
  1563. }
  1564. if ((pIniTxSFilter->InboundFilterFlag != NEGOTIATE_SECURITY) &&
  1565. (pIniTxSFilter->OutboundFilterFlag != NEGOTIATE_SECURITY)) {
  1566. return (FALSE);
  1567. }
  1568. bMatches = MatchAddresses(
  1569. pIniTxSFilter->SrcAddr,
  1570. pTxFilter->SrcAddr
  1571. );
  1572. if (!bMatches) {
  1573. return (FALSE);
  1574. }
  1575. bMatches = MatchAddresses(
  1576. pIniTxSFilter->DesAddr,
  1577. pTxFilter->DesAddr
  1578. );
  1579. if (!bMatches) {
  1580. return (FALSE);
  1581. }
  1582. bMatches = MatchPorts(
  1583. pIniTxSFilter->SrcPort,
  1584. pTxFilter->SrcPort
  1585. );
  1586. if (!bMatches) {
  1587. return (FALSE);
  1588. }
  1589. bMatches = MatchPorts(
  1590. pIniTxSFilter->DesPort,
  1591. pTxFilter->DesPort
  1592. );
  1593. if (!bMatches) {
  1594. return (FALSE);
  1595. }
  1596. bMatches = MatchProtocols(
  1597. pIniTxSFilter->Protocol,
  1598. pTxFilter->Protocol
  1599. );
  1600. if (!bMatches) {
  1601. return (FALSE);
  1602. }
  1603. return (TRUE);
  1604. }
  1605. DWORD
  1606. CopyTxMatchDefaults(
  1607. PTRANSPORT_FILTER * ppTxFilters,
  1608. PIPSEC_QM_POLICY * ppQMPolicies,
  1609. PDWORD pdwNumMatches
  1610. )
  1611. {
  1612. DWORD dwError = 0;
  1613. PTRANSPORT_FILTER pTxFilters = NULL;
  1614. PIPSEC_QM_POLICY pQMPolicies = NULL;
  1615. DWORD dwNumFilters = 0;
  1616. DWORD dwNumPolicies = 0;
  1617. if (!gpIniDefaultQMPolicy) {
  1618. dwError = ERROR_IPSEC_DEFAULT_QM_POLICY_NOT_FOUND;
  1619. BAIL_ON_WIN32_ERROR(dwError);
  1620. }
  1621. dwError = SPDApiBufferAllocate(
  1622. sizeof(TRANSPORT_FILTER),
  1623. &pTxFilters
  1624. );
  1625. BAIL_ON_WIN32_ERROR(dwError);
  1626. dwError = SPDApiBufferAllocate(
  1627. sizeof(IPSEC_QM_POLICY),
  1628. &pQMPolicies
  1629. );
  1630. BAIL_ON_WIN32_ERROR(dwError);
  1631. dwError = CopyDefaultTxFilter(
  1632. pTxFilters,
  1633. gpIniDefaultQMPolicy
  1634. );
  1635. BAIL_ON_WIN32_ERROR(dwError);
  1636. dwNumFilters++;
  1637. dwError = CopyQMPolicy(
  1638. gpIniDefaultQMPolicy,
  1639. pQMPolicies
  1640. );
  1641. BAIL_ON_WIN32_ERROR(dwError);
  1642. pQMPolicies->dwFlags |= IPSEC_QM_POLICY_ON_NO_MATCH;
  1643. dwNumPolicies++;
  1644. *ppTxFilters = pTxFilters;
  1645. *ppQMPolicies = pQMPolicies;
  1646. *pdwNumMatches = 1;
  1647. return (dwError);
  1648. error:
  1649. if (pTxFilters) {
  1650. FreeTxFilters(
  1651. dwNumFilters,
  1652. pTxFilters
  1653. );
  1654. }
  1655. if (pQMPolicies) {
  1656. FreeQMPolicies(
  1657. dwNumPolicies,
  1658. pQMPolicies
  1659. );
  1660. }
  1661. *ppTxFilters = NULL;
  1662. *ppQMPolicies = NULL;
  1663. *pdwNumMatches = 0;
  1664. return (dwError);
  1665. }
  1666. DWORD
  1667. CopyDefaultTxFilter(
  1668. PTRANSPORT_FILTER pTxFilter,
  1669. PINIQMPOLICY pIniQMPolicy
  1670. )
  1671. {
  1672. DWORD dwError = 0;
  1673. UuidCreate(&(pTxFilter->gFilterID));
  1674. dwError = CopyName(
  1675. L"0",
  1676. &(pTxFilter->pszFilterName)
  1677. );
  1678. BAIL_ON_WIN32_ERROR(dwError);
  1679. pTxFilter->InterfaceType = INTERFACE_TYPE_ALL;
  1680. pTxFilter->bCreateMirror = TRUE;
  1681. pTxFilter->dwFlags = 0;
  1682. pTxFilter->dwFlags |= IPSEC_QM_POLICY_DEFAULT_POLICY;
  1683. pTxFilter->SrcAddr.AddrType = IP_ADDR_SUBNET;
  1684. pTxFilter->SrcAddr.uIpAddr = SUBNET_ADDRESS_ANY;
  1685. pTxFilter->SrcAddr.uSubNetMask = SUBNET_MASK_ANY;
  1686. pTxFilter->DesAddr.AddrType = IP_ADDR_SUBNET;
  1687. pTxFilter->DesAddr.uIpAddr = SUBNET_ADDRESS_ANY;
  1688. pTxFilter->DesAddr.uSubNetMask = SUBNET_MASK_ANY;
  1689. pTxFilter->Protocol.ProtocolType = PROTOCOL_UNIQUE;
  1690. pTxFilter->Protocol.dwProtocol = 0;
  1691. pTxFilter->SrcPort.PortType = PORT_UNIQUE;
  1692. pTxFilter->SrcPort.wPort = 0;
  1693. pTxFilter->DesPort.PortType = PORT_UNIQUE;
  1694. pTxFilter->DesPort.wPort = 0;
  1695. pTxFilter->InboundFilterFlag = NEGOTIATE_SECURITY;
  1696. pTxFilter->OutboundFilterFlag = NEGOTIATE_SECURITY;
  1697. pTxFilter->dwDirection = 0;
  1698. pTxFilter->dwWeight = 0;
  1699. CopyGuid(pIniQMPolicy->gPolicyID, &(pTxFilter->gPolicyID));
  1700. error:
  1701. return (dwError);
  1702. }
  1703. DWORD
  1704. SeparateInterfaceAddresses(
  1705. PADDR pAddrList,
  1706. DWORD dwAddrCnt,
  1707. MATCHING_ADDR * pMatchingAddresses,
  1708. DWORD dwLocalAddrCnt,
  1709. PADDR * ppIsMeAddrList,
  1710. PDWORD pdwIsMeAddrCnt,
  1711. PADDR * ppIsNotMeAddrList,
  1712. PDWORD pdwIsNotMeAddrCnt
  1713. )
  1714. {
  1715. DWORD dwError = 0;
  1716. PADDR pIsMeAddrList = NULL;
  1717. DWORD i = 0;
  1718. if (dwAddrCnt) {
  1719. dwError = AllocateSPDMemory(
  1720. sizeof(ADDR) * dwAddrCnt,
  1721. &pIsMeAddrList
  1722. );
  1723. BAIL_ON_WIN32_ERROR(dwError);
  1724. }
  1725. for (i = 0; i < dwAddrCnt; i++) {
  1726. memcpy(
  1727. &(pIsMeAddrList[i]),
  1728. &(pAddrList[i]),
  1729. sizeof(ADDR)
  1730. );
  1731. }
  1732. *ppIsMeAddrList = pIsMeAddrList;
  1733. *pdwIsMeAddrCnt = dwAddrCnt;
  1734. *ppIsNotMeAddrList = NULL;
  1735. *pdwIsNotMeAddrCnt = 0;
  1736. return (dwError);
  1737. error:
  1738. if (pIsMeAddrList) {
  1739. FreeSPDMemory(pIsMeAddrList);
  1740. }
  1741. *ppIsMeAddrList = NULL;
  1742. *pdwIsMeAddrCnt = 0;
  1743. *ppIsNotMeAddrList = NULL;
  1744. *pdwIsNotMeAddrCnt = 0;
  1745. return (dwError);
  1746. }