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

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