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.

868 lines
23 KiB

  1. /*++
  2. Copyright (c) 1999-2001 Microsoft Corporation
  3. Module Name:
  4. gpc.c
  5. Abstract:
  6. This module contains the GPC implementation
  7. Author:
  8. ChunYe
  9. Environment:
  10. Kernel mode
  11. Revision History:
  12. --*/
  13. #include "precomp.h"
  14. #if GPC
  15. NTSTATUS
  16. IPSecGpcInitialize()
  17. {
  18. NTSTATUS status;
  19. INT cf, i;
  20. PAGED_CODE();
  21. //
  22. // Initialize FilterList for patterns that are not installed in GPC.
  23. //
  24. for (i = MIN_FILTER; i <= MAX_FILTER; i++) {
  25. InitializeListHead(&g_ipsec.GpcFilterList[i]);
  26. }
  27. //
  28. // Start with inactive state for the error path.
  29. //
  30. IPSEC_DRIVER_INIT_GPC() = FALSE;
  31. IPSEC_UNSET_GPC_ACTIVE();
  32. //
  33. // GPC registration.
  34. //
  35. status = GpcInitialize(&g_ipsec.GpcEntries);
  36. if (status == STATUS_SUCCESS) {
  37. for (cf = GPC_CF_IPSEC_MIN; cf <= GPC_CF_IPSEC_MAX; cf++) {
  38. status = GPC_REGISTER_CLIENT( cf,
  39. 0,
  40. GPC_PRIORITY_IPSEC,
  41. NULL,
  42. NULL,
  43. &g_ipsec.GpcClients[cf]);
  44. if (status != STATUS_SUCCESS) {
  45. IPSEC_DEBUG(LOAD, ("GPC failed to register cf %d\n", cf));
  46. g_ipsec.GpcClients[cf] = NULL;
  47. IPSecGpcDeinitialize();
  48. return status;
  49. }
  50. }
  51. } else {
  52. IPSEC_DEBUG(LOAD, ("Failed to init GPC structures\n"));
  53. return status;
  54. }
  55. IPSEC_SET_GPC_ACTIVE();
  56. IPSEC_DRIVER_INIT_GPC() = TRUE;
  57. return STATUS_SUCCESS;
  58. }
  59. NTSTATUS
  60. IPSecGpcDeinitialize()
  61. {
  62. INT cf;
  63. PAGED_CODE();
  64. IPSEC_UNSET_GPC_ACTIVE();
  65. //
  66. // GPC deregistration.
  67. //
  68. for (cf = GPC_CF_IPSEC_MIN; cf <= GPC_CF_IPSEC_MAX; cf++) {
  69. if (g_ipsec.GpcClients[cf]) {
  70. GPC_DEREGISTER_CLIENT(g_ipsec.GpcClients[cf]);
  71. }
  72. }
  73. GpcDeinitialize(&g_ipsec.GpcEntries);
  74. return STATUS_SUCCESS;
  75. }
  76. NTSTATUS
  77. IPSecEnableGpc()
  78. {
  79. KIRQL kIrql;
  80. PAGED_CODE();
  81. if (IPSEC_DRIVER_INIT_GPC()) {
  82. AcquireWriteLock(&g_ipsec.SADBLock, &kIrql);
  83. IPSEC_SET_GPC_ACTIVE();
  84. ReleaseWriteLock(&g_ipsec.SADBLock, kIrql);
  85. }
  86. return STATUS_SUCCESS;
  87. }
  88. NTSTATUS
  89. IPSecDisableGpc()
  90. {
  91. KIRQL kIrql;
  92. PAGED_CODE();
  93. if (IPSEC_DRIVER_INIT_GPC()) {
  94. AcquireWriteLock(&g_ipsec.SADBLock, &kIrql);
  95. IPSEC_UNSET_GPC_ACTIVE();
  96. ReleaseWriteLock(&g_ipsec.SADBLock, kIrql);
  97. }
  98. return STATUS_SUCCESS;
  99. }
  100. NTSTATUS
  101. IPSecInitGpcFilter(
  102. IN PFILTER pFilter,
  103. IN PGPC_IP_PATTERN pPattern,
  104. IN PGPC_IP_PATTERN pMask
  105. )
  106. {
  107. PAGED_CODE();
  108. RtlZeroMemory(pPattern, sizeof(GPC_IP_PATTERN));
  109. RtlZeroMemory(pMask, sizeof(GPC_IP_PATTERN));
  110. pPattern->SrcAddr = pFilter->SRC_ADDR;
  111. pPattern->DstAddr = pFilter->DEST_ADDR;
  112. pPattern->ProtocolId = (UCHAR)pFilter->PROTO;
  113. pPattern->gpcSrcPort = FI_SRC_PORT(pFilter);
  114. pPattern->gpcDstPort = FI_DEST_PORT(pFilter);
  115. pMask->SrcAddr = pFilter->SRC_MASK;
  116. pMask->DstAddr = pFilter->DEST_MASK;
  117. pMask->ProtocolId = (UCHAR)IPSEC_GPC_MASK_ALL;
  118. pMask->gpcSrcPort = IPSEC_GPC_MASK_NONE;
  119. pMask->gpcDstPort = IPSEC_GPC_MASK_NONE;
  120. switch (pFilter->PROTO) {
  121. case FILTER_PROTO_ANY:
  122. if (FI_SRC_PORT(pFilter) != FILTER_TCPUDP_PORT_ANY) {
  123. RtlFillMemory( &pMask->gpcSrcPort,
  124. sizeof(pMask->gpcSrcPort),
  125. IPSEC_GPC_MASK_ALL);
  126. }
  127. if (FI_DEST_PORT(pFilter) != FILTER_TCPUDP_PORT_ANY) {
  128. RtlFillMemory( &pMask->gpcDstPort,
  129. sizeof(pMask->gpcDstPort),
  130. IPSEC_GPC_MASK_ALL);
  131. }
  132. pMask->ProtocolId = (UCHAR)IPSEC_GPC_MASK_NONE;
  133. break;
  134. case FILTER_PROTO_TCP:
  135. case FILTER_PROTO_UDP:
  136. if (FI_SRC_PORT(pFilter) != FILTER_TCPUDP_PORT_ANY) {
  137. RtlFillMemory( &pMask->gpcSrcPort,
  138. sizeof(pMask->gpcSrcPort),
  139. IPSEC_GPC_MASK_ALL);
  140. }
  141. if (FI_DEST_PORT(pFilter) != FILTER_TCPUDP_PORT_ANY) {
  142. RtlFillMemory( &pMask->gpcDstPort,
  143. sizeof(pMask->gpcDstPort),
  144. IPSEC_GPC_MASK_ALL);
  145. }
  146. break;
  147. default:
  148. break;
  149. }
  150. return STATUS_SUCCESS;
  151. }
  152. NTSTATUS
  153. IPSecInsertGpcPattern(
  154. IN PFILTER pFilter
  155. )
  156. {
  157. CLASSIFICATION_HANDLE GpcHandle;
  158. GPC_IP_PATTERN GpcPattern;
  159. GPC_IP_PATTERN GpcMask;
  160. ULONG GpcPriority;
  161. INT GpcCf;
  162. NTSTATUS status;
  163. PAGED_CODE();
  164. GpcCf = IPSecResolveGpcCf(IS_OUTBOUND_FILTER(pFilter));
  165. //
  166. // Add the filter as a CfInfo
  167. //
  168. status = GPC_ADD_CFINFO(g_ipsec.GpcClients[GpcCf],
  169. sizeof(PFILTER),
  170. (PVOID)&pFilter,
  171. (GPC_CLIENT_HANDLE)pFilter,
  172. &pFilter->GpcFilter.GpcCfInfoHandle);
  173. if (status == STATUS_SUCCESS) {
  174. //
  175. // Now add the filter as a pattern
  176. //
  177. IPSecInitGpcFilter(pFilter, &GpcPattern, &GpcMask);
  178. if (FI_DEST_PORT(pFilter) == FILTER_TCPUDP_PORT_ANY) {
  179. GpcPriority = 1;
  180. } else {
  181. GpcPriority = 0;
  182. }
  183. ASSERT(GpcPriority < GPC_PRIORITY_IPSEC);
  184. status = GPC_ADD_PATTERN( g_ipsec.GpcClients[GpcCf],
  185. GPC_PROTOCOL_TEMPLATE_IP,
  186. &GpcPattern,
  187. &GpcMask,
  188. GpcPriority,
  189. pFilter->GpcFilter.GpcCfInfoHandle,
  190. &pFilter->GpcFilter.GpcPatternHandle,
  191. &GpcHandle);
  192. if (status != STATUS_SUCCESS) {
  193. IPSEC_DEBUG(GPC, ("GpcAddPattern: failed with status %lx\n", status));
  194. GPC_REMOVE_CFINFO( g_ipsec.GpcClients[GpcCf],
  195. pFilter->GpcFilter.GpcCfInfoHandle);
  196. pFilter->GpcFilter.GpcCfInfoHandle = NULL;
  197. pFilter->GpcFilter.GpcPatternHandle = NULL;
  198. } else {
  199. g_ipsec.GpcNumFilters[GpcPriority]++;
  200. }
  201. }
  202. return status;
  203. }
  204. NTSTATUS
  205. IPSecDeleteGpcPattern(
  206. IN PFILTER pFilter
  207. )
  208. {
  209. ULONG GpcPriority;
  210. INT GpcCf = IPSecResolveGpcCf(IS_OUTBOUND_FILTER(pFilter));
  211. PAGED_CODE();
  212. if (pFilter->GpcFilter.GpcPatternHandle) {
  213. GPC_REMOVE_PATTERN( g_ipsec.GpcClients[GpcCf],
  214. pFilter->GpcFilter.GpcPatternHandle);
  215. pFilter->GpcFilter.GpcPatternHandle = NULL;
  216. ASSERT(pFilter->GpcFilter.GpcCfInfoHandle);
  217. if (pFilter->GpcFilter.GpcCfInfoHandle) {
  218. GPC_REMOVE_CFINFO( g_ipsec.GpcClients[GpcCf],
  219. pFilter->GpcFilter.GpcCfInfoHandle);
  220. pFilter->GpcFilter.GpcCfInfoHandle = NULL;
  221. }
  222. if (FI_DEST_PORT(pFilter) == FILTER_TCPUDP_PORT_ANY) {
  223. GpcPriority = 1;
  224. } else {
  225. GpcPriority = 0;
  226. }
  227. ASSERT(GpcPriority < GPC_PRIORITY_IPSEC);
  228. g_ipsec.GpcNumFilters[GpcPriority]--;
  229. }
  230. return STATUS_SUCCESS;
  231. }
  232. NTSTATUS
  233. IPSecInsertGpcFilter(
  234. IN PFILTER pFilter
  235. )
  236. {
  237. NTSTATUS status;
  238. PFILTER pTempFilter;
  239. BOOL InsertedFilter = FALSE;
  240. PLIST_ENTRY pEntry, pPrev;
  241. PLIST_ENTRY pFilterList;
  242. KIRQL kIrql;
  243. PAGED_CODE();
  244. AcquireWriteLock(&g_ipsec.SADBLock, &kIrql);
  245. pFilterList = IPSecResolveGpcFilterList(IS_TUNNEL_FILTER(pFilter),
  246. IS_OUTBOUND_FILTER(pFilter));
  247. pEntry = pFilterList->Flink;
  248. pPrev = pFilterList;
  249. while (pEntry != pFilterList) {
  250. pTempFilter = CONTAINING_RECORD(pEntry,
  251. FILTER,
  252. GpcLinkage);
  253. if (pFilter->Index > pTempFilter->Index) {
  254. //
  255. // found the spot, insert it before pTempFilter
  256. //
  257. InsertHeadList(pPrev, &pFilter->GpcLinkage);
  258. InsertedFilter = TRUE;
  259. break;
  260. }
  261. pPrev = pEntry;
  262. pEntry = pEntry->Flink;
  263. }
  264. if (!InsertedFilter) {
  265. //
  266. // didn't find spot, stick it in the end
  267. //
  268. InsertTailList(pFilterList, &pFilter->GpcLinkage);
  269. }
  270. ReleaseWriteLock(&g_ipsec.SADBLock, kIrql);
  271. return STATUS_SUCCESS;
  272. }
  273. NTSTATUS
  274. IPSecDeleteGpcFilter(
  275. IN PFILTER pFilter
  276. )
  277. {
  278. KIRQL kIrql;
  279. PAGED_CODE();
  280. if (!pFilter->GpcLinkage.Flink || !pFilter->GpcLinkage.Blink) {
  281. return STATUS_SUCCESS;
  282. }
  283. AcquireWriteLock(&g_ipsec.SADBLock, &kIrql);
  284. IPSecRemoveEntryList(&pFilter->GpcLinkage);
  285. ReleaseWriteLock(&g_ipsec.SADBLock, kIrql);
  286. return STATUS_SUCCESS;
  287. }
  288. NTSTATUS
  289. IPSecInstallGpcFilter(
  290. IN PFILTER pFilter
  291. )
  292. {
  293. PAGED_CODE();
  294. if (IS_TUNNEL_FILTER(pFilter)) {
  295. return STATUS_SUCCESS;
  296. }
  297. if (IS_GPC_FILTER(pFilter)) {
  298. return IPSecInsertGpcPattern(pFilter);
  299. } else {
  300. return IPSecInsertGpcFilter(pFilter);
  301. }
  302. }
  303. NTSTATUS
  304. IPSecUninstallGpcFilter(
  305. IN PFILTER pFilter
  306. )
  307. {
  308. PAGED_CODE();
  309. if (IS_TUNNEL_FILTER(pFilter)) {
  310. return STATUS_SUCCESS;
  311. }
  312. if (IS_GPC_FILTER(pFilter)) {
  313. return IPSecDeleteGpcPattern(pFilter);
  314. } else {
  315. return IPSecDeleteGpcFilter(pFilter);
  316. }
  317. }
  318. NTSTATUS
  319. IPSecLookupGpcSA(
  320. IN ULARGE_INTEGER uliSrcDstAddr,
  321. IN ULARGE_INTEGER uliProtoSrcDstPort,
  322. IN CLASSIFICATION_HANDLE GpcHandle,
  323. OUT PFILTER *ppFilter,
  324. OUT PSA_TABLE_ENTRY *ppSA,
  325. OUT PSA_TABLE_ENTRY *ppNextSA,
  326. OUT PSA_TABLE_ENTRY *ppTunnelSA,
  327. IN BOOLEAN fOutbound
  328. )
  329. {
  330. PFILTER pFilter;
  331. PFILTER pTempFilter;
  332. PLIST_ENTRY pEntry;
  333. PLIST_ENTRY pFilterList;
  334. PLIST_ENTRY pSAChain;
  335. PSA_TABLE_ENTRY pSA;
  336. REGISTER ULARGE_INTEGER uliPort;
  337. REGISTER ULARGE_INTEGER uliAddr;
  338. BOOLEAN fFound = FALSE;
  339. INT GpcCf;
  340. CLASSIFICATION_HANDLE TempGpcHandle;
  341. *ppSA = NULL;
  342. *ppFilter = NULL;
  343. *ppTunnelSA = NULL;
  344. //
  345. // Search in Tunnel filters list first.
  346. //
  347. pFilterList = IPSecResolveFilterList(TRUE, fOutbound);
  348. for ( pEntry = pFilterList->Flink;
  349. pEntry != pFilterList;
  350. pEntry = pEntry->Flink) {
  351. pFilter = CONTAINING_RECORD(pEntry,
  352. FILTER,
  353. MaskedLinkage);
  354. uliAddr.QuadPart = uliSrcDstAddr.QuadPart & pFilter->uliSrcDstMask.QuadPart;
  355. uliPort.QuadPart = uliProtoSrcDstPort.QuadPart & pFilter->uliProtoSrcDstMask.QuadPart;
  356. if ((uliAddr.QuadPart == pFilter->uliSrcDstAddr.QuadPart) &&
  357. (uliPort.QuadPart == pFilter->uliProtoSrcDstPort.QuadPart)) {
  358. //
  359. // Found filter
  360. //
  361. fFound = TRUE;
  362. break;
  363. }
  364. }
  365. if (fFound) {
  366. //
  367. // Search for the particular SA now.
  368. //
  369. fFound = FALSE;
  370. pSAChain = IPSecResolveSAChain(pFilter, fOutbound? DEST_ADDR: SRC_ADDR);
  371. for ( pEntry = pSAChain->Flink;
  372. pEntry != pSAChain;
  373. pEntry = pEntry->Flink) {
  374. pSA = CONTAINING_RECORD(pEntry,
  375. SA_TABLE_ENTRY,
  376. sa_FilterLinkage);
  377. ASSERT(pSA->sa_Flags & FLAGS_SA_TUNNEL);
  378. if (pFilter->TunnelAddr != 0) {
  379. //
  380. // match the outbound flag also
  381. //
  382. ASSERT(fOutbound == (BOOLEAN)((pSA->sa_Flags & FLAGS_SA_OUTBOUND) != 0));
  383. fFound = TRUE;
  384. *ppTunnelSA = pSA;
  385. break;
  386. }
  387. }
  388. if (fFound) {
  389. fFound = FALSE;
  390. *ppFilter = pFilter;
  391. } else {
  392. //
  393. // Found a filter entry, but need to negotiate keys.
  394. //
  395. *ppFilter = pFilter;
  396. return STATUS_PENDING;
  397. }
  398. }
  399. #if DBG
  400. if (fOutbound) {
  401. ADD_TO_LARGE_INTEGER(&g_ipsec.GpcTotalPassedIn, 1);
  402. }
  403. #endif
  404. GpcCf = IPSecResolveGpcCf(fOutbound);
  405. TempGpcHandle = 0;
  406. if (GpcHandle == 0) {
  407. #if DBG
  408. if (fOutbound) {
  409. ADD_TO_LARGE_INTEGER(&g_ipsec.GpcClassifyNeeded, 1);
  410. }
  411. #endif
  412. //
  413. // Classify directly if no GpcHandle passed in.
  414. //
  415. IPSEC_CLASSIFY_PACKET( GpcCf,
  416. uliSrcDstAddr,
  417. uliProtoSrcDstPort,
  418. &pFilter,
  419. &TempGpcHandle);
  420. } else {
  421. NTSTATUS status;
  422. //
  423. // Or we use GpcHandle directly to get the filter installed.
  424. //
  425. pFilter = NULL;
  426. status = GPC_GET_CLIENT_CONTEXT(g_ipsec.GpcClients[GpcCf],
  427. GpcHandle,
  428. &pFilter);
  429. if (status == STATUS_INVALID_HANDLE) {
  430. //
  431. // Re-classify if handle is invalid.
  432. //
  433. IPSEC_CLASSIFY_PACKET( GpcCf,
  434. uliSrcDstAddr,
  435. uliProtoSrcDstPort,
  436. &pFilter,
  437. &TempGpcHandle);
  438. }
  439. }
  440. #if DBG
  441. if (IPSecDebug & IPSEC_DEBUG_GPC) {
  442. PFILTER pDbgFilter = NULL;
  443. pFilterList = IPSecResolveFilterList(FALSE, fOutbound);
  444. for ( pEntry = pFilterList->Flink;
  445. pEntry != pFilterList;
  446. pEntry = pEntry->Flink) {
  447. pTempFilter = CONTAINING_RECORD(pEntry,
  448. FILTER,
  449. MaskedLinkage);
  450. uliAddr.QuadPart = uliSrcDstAddr.QuadPart & pTempFilter->uliSrcDstMask.QuadPart;
  451. uliPort.QuadPart = uliProtoSrcDstPort.QuadPart & pTempFilter->uliProtoSrcDstMask.QuadPart;
  452. if ((uliAddr.QuadPart == pTempFilter->uliSrcDstAddr.QuadPart) &&
  453. (uliPort.QuadPart == pTempFilter->uliProtoSrcDstPort.QuadPart)) {
  454. pDbgFilter = pTempFilter;
  455. break;
  456. }
  457. }
  458. if (pFilter != pDbgFilter &&
  459. (!pDbgFilter || IS_GPC_FILTER(pDbgFilter))) {
  460. IPSEC_DEBUG(GPC, ("LookupGpcSA: pFilter %lx, pDbgFilter %lx, GpcHandle %lx, TempGpcHandle %lx\n", pFilter, pDbgFilter, GpcHandle, TempGpcHandle));
  461. IPSEC_DEBUG(GPC, ("LookupGpcSA: Src %lx, Dest %lx, Protocol %d, SPort %lx, DPort %lx\n", SRC_ADDR, DEST_ADDR, PROTO, SRC_PORT, DEST_PORT));
  462. if (DebugGPC) {
  463. DbgBreakPoint();
  464. }
  465. }
  466. }
  467. #endif
  468. //
  469. // Continue searching the local GPC filter list if not found.
  470. //
  471. if (!pFilter) {
  472. pFilterList = IPSecResolveGpcFilterList(FALSE, fOutbound);
  473. for ( pEntry = pFilterList->Flink;
  474. pEntry != pFilterList;
  475. pEntry = pEntry->Flink) {
  476. pTempFilter = CONTAINING_RECORD(pEntry,
  477. FILTER,
  478. GpcLinkage);
  479. uliAddr.QuadPart = uliSrcDstAddr.QuadPart & pTempFilter->uliSrcDstMask.QuadPart;
  480. uliPort.QuadPart = uliProtoSrcDstPort.QuadPart & pTempFilter->uliProtoSrcDstMask.QuadPart;
  481. if ((uliAddr.QuadPart == pTempFilter->uliSrcDstAddr.QuadPart) &&
  482. (uliPort.QuadPart == pTempFilter->uliProtoSrcDstPort.QuadPart)) {
  483. pFilter = pTempFilter;
  484. break;
  485. }
  486. }
  487. }
  488. if (pFilter) {
  489. //
  490. // Search for the particular SA now.
  491. //
  492. fFound=FALSE;
  493. pSAChain = IPSecResolveSAChain(pFilter, fOutbound? DEST_ADDR: SRC_ADDR);
  494. for ( pEntry = pSAChain->Flink;
  495. pEntry != pSAChain;
  496. pEntry = pEntry->Flink) {
  497. pSA = CONTAINING_RECORD(pEntry,
  498. SA_TABLE_ENTRY,
  499. sa_FilterLinkage);
  500. if (IS_CLASSD(NET_LONG(pSA->SA_SRC_ADDR))
  501. || IS_CLASSD(NET_LONG(pSA->SA_DEST_ADDR))) {
  502. uliAddr.QuadPart = uliSrcDstAddr.QuadPart & pSA->sa_uliSrcDstMask.QuadPart;
  503. IPSEC_DEBUG(HASH, ("MCAST: %d %d %d %d", uliAddr.LowPart, uliAddr.HighPart,
  504. pSA->sa_uliSrcDstAddr.LowPart,pSA->sa_uliSrcDstAddr.HighPart));
  505. if (uliAddr.QuadPart == pSA->sa_uliSrcDstAddr.QuadPart) {
  506. fFound=TRUE;
  507. }
  508. } else if (uliSrcDstAddr.QuadPart == pSA->sa_uliSrcDstAddr.QuadPart) {
  509. fFound=TRUE;
  510. }
  511. if (fFound) {
  512. IPSEC_DEBUG(HASH, ("Matched entry: %lx\n", pSA));
  513. ASSERT(fOutbound == (BOOLEAN)((pSA->sa_Flags & FLAGS_SA_OUTBOUND) != 0));
  514. //
  515. // if there is also a tunnel SA, associate it here.
  516. //
  517. if (*ppTunnelSA && fOutbound) {
  518. *ppNextSA = *ppTunnelSA;
  519. *ppTunnelSA = NULL;
  520. }
  521. *ppFilter = pFilter;
  522. *ppSA = pSA;
  523. return STATUS_SUCCESS;
  524. }
  525. }
  526. //
  527. // Found a filter entry, but need to negotiate keys
  528. // Also, ppTunnelSA is set to the proper tunnel SA we need
  529. // to hook to this end-2-end SA once it is negotiated.
  530. //
  531. *ppFilter = pFilter;
  532. return STATUS_PENDING;
  533. } else {
  534. //
  535. // if only tunnel SA found, return that as the SA found.
  536. //
  537. if (*ppTunnelSA) {
  538. *ppSA = *ppTunnelSA;
  539. *ppTunnelSA = NULL;
  540. return STATUS_SUCCESS;
  541. }
  542. }
  543. //
  544. // no entry found
  545. //
  546. return STATUS_NOT_FOUND;
  547. }
  548. NTSTATUS
  549. IPSecLookupGpcMaskedSA(
  550. IN ULARGE_INTEGER uliSrcDstAddr,
  551. IN ULARGE_INTEGER uliProtoSrcDstPort,
  552. OUT PFILTER *ppFilter,
  553. OUT PSA_TABLE_ENTRY *ppSA,
  554. IN BOOLEAN fOutbound
  555. )
  556. /*++
  557. Routine Description:
  558. Looks up the SA given the relevant addresses.
  559. Arguments:
  560. uliSrcDstAddr - src/dest IP addr
  561. uliProtoSrcDstPort - protocol, src/dest port
  562. ppFilter - filter found
  563. ppSA - SA found
  564. fOutbound - direction flag
  565. Return Value:
  566. STATUS_SUCCESS - both filter and SA found
  567. STATUS_UNSUCCESSFUL - none found
  568. STATUS_PENDING - filter found, but no SA
  569. Notes:
  570. Called with SADBLock held.
  571. --*/
  572. {
  573. REGISTER ULARGE_INTEGER uliPort;
  574. REGISTER ULARGE_INTEGER uliAddr;
  575. PFILTER pFilter;
  576. PFILTER pTempFilter;
  577. PLIST_ENTRY pFilterList;
  578. PLIST_ENTRY pSAChain;
  579. PLIST_ENTRY pEntry;
  580. PSA_TABLE_ENTRY pSA;
  581. CLASSIFICATION_HANDLE GpcHandle;
  582. INT GpcCf;
  583. *ppSA = NULL;
  584. *ppFilter = NULL;
  585. GpcCf = IPSecResolveGpcCf(fOutbound);
  586. GpcHandle = 0;
  587. IPSEC_CLASSIFY_PACKET( GpcCf,
  588. uliSrcDstAddr,
  589. uliProtoSrcDstPort,
  590. &pFilter,
  591. &GpcHandle);
  592. #if DBG
  593. if (IPSecDebug & IPSEC_DEBUG_GPC) {
  594. PFILTER pDbgFilter = NULL;
  595. pFilterList = IPSecResolveFilterList(FALSE, fOutbound);
  596. for ( pEntry = pFilterList->Flink;
  597. pEntry != pFilterList;
  598. pEntry = pEntry->Flink) {
  599. pTempFilter = CONTAINING_RECORD(pEntry,
  600. FILTER,
  601. MaskedLinkage);
  602. uliAddr.QuadPart = uliSrcDstAddr.QuadPart & pTempFilter->uliSrcDstMask.QuadPart;
  603. uliPort.QuadPart = uliProtoSrcDstPort.QuadPart & pTempFilter->uliProtoSrcDstMask.QuadPart;
  604. if ((uliAddr.QuadPart == pTempFilter->uliSrcDstAddr.QuadPart) &&
  605. (uliPort.QuadPart == pTempFilter->uliProtoSrcDstPort.QuadPart)) {
  606. pDbgFilter = pTempFilter;
  607. break;
  608. }
  609. }
  610. if (pFilter != pDbgFilter &&
  611. (!pDbgFilter || IS_GPC_FILTER(pDbgFilter))) {
  612. IPSEC_DEBUG(GPC, ("LookupMaskedSA: pFilter %lx, pDbgFilter %lx, GpcHandle %lx\n", pFilter, pDbgFilter, GpcHandle));
  613. IPSEC_DEBUG(GPC, ("LookupMaskedSA: Src %lx, Dest %lx, Protocol %d, SPort %lx, DPort %lx\n", SRC_ADDR, DEST_ADDR, PROTO, SRC_PORT, DEST_PORT));
  614. if (DebugGPC) {
  615. DbgBreakPoint();
  616. }
  617. }
  618. }
  619. #endif
  620. //
  621. // Continue searching the local GPC filter list if not found.
  622. //
  623. if (!pFilter) {
  624. pFilterList = IPSecResolveGpcFilterList(FALSE, fOutbound);
  625. for ( pEntry = pFilterList->Flink;
  626. pEntry != pFilterList;
  627. pEntry = pEntry->Flink) {
  628. pTempFilter = CONTAINING_RECORD(pEntry,
  629. FILTER,
  630. GpcLinkage);
  631. uliAddr.QuadPart = uliSrcDstAddr.QuadPart & pTempFilter->uliSrcDstMask.QuadPart;
  632. uliPort.QuadPart = uliProtoSrcDstPort.QuadPart & pTempFilter->uliProtoSrcDstMask.QuadPart;
  633. if ((uliAddr.QuadPart == pTempFilter->uliSrcDstAddr.QuadPart) &&
  634. (uliPort.QuadPart == pTempFilter->uliProtoSrcDstPort.QuadPart)) {
  635. pFilter = pTempFilter;
  636. break;
  637. }
  638. }
  639. }
  640. if (pFilter) {
  641. //
  642. // Search for the particular SA now.
  643. //
  644. pSAChain = IPSecResolveSAChain(pFilter, fOutbound? DEST_ADDR: SRC_ADDR);
  645. for ( pEntry = pSAChain->Flink;
  646. pEntry != pSAChain;
  647. pEntry = pEntry->Flink) {
  648. pSA = CONTAINING_RECORD(pEntry,
  649. SA_TABLE_ENTRY,
  650. sa_FilterLinkage);
  651. if (uliSrcDstAddr.QuadPart == pSA->sa_uliSrcDstAddr.QuadPart) {
  652. IPSEC_DEBUG(HASH, ("Matched entry: %lx\n", pSA));
  653. ASSERT(fOutbound == (BOOLEAN)((pSA->sa_Flags & FLAGS_SA_OUTBOUND) != 0));
  654. *ppFilter = pFilter;
  655. *ppSA = pSA;
  656. return STATUS_SUCCESS;
  657. }
  658. }
  659. //
  660. // Found a filter entry, but need to negotiate keys
  661. //
  662. *ppFilter = pFilter;
  663. return STATUS_PENDING;
  664. }
  665. //
  666. // no entry found
  667. //
  668. return STATUS_NOT_FOUND;
  669. }
  670. #endif