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.

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