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.

398 lines
9.6 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. encap-hw.c
  5. Abstract:
  6. This module contains all the IPSec routines for UDP ESP encapsulation
  7. SA and parsing entry offload.
  8. Author:
  9. AbhisheV
  10. Environment:
  11. Kernel Level
  12. Revision History:
  13. --*/
  14. #include "precomp.h"
  15. VOID
  16. IPSecFillHwAddEncapSa(
  17. PSA_TABLE_ENTRY pSwSa,
  18. PPARSER_IFENTRY pParserIfEntry,
  19. PUCHAR pucBuffer,
  20. ULONG uBufLen
  21. )
  22. /*++
  23. Routine Description:
  24. Fills in the hardware add encapsulation sa buffer from the passed in
  25. software encapsulation sa.
  26. Arguments:
  27. pSwSa - Pointer to the software encapsulation sa structure.
  28. pParserIfEntry - Pointer to the parser interface entry.
  29. pucBuffer - Pointer to the hardware add encapsulation sa buffer.
  30. uBufLen - Length of the buffer.
  31. Return Value:
  32. None - VOID.
  33. --*/
  34. {
  35. POFFLOAD_IPSEC_ADD_UDPESP_SA pHwSa = (POFFLOAD_IPSEC_ADD_UDPESP_SA) pucBuffer;
  36. POFFLOAD_SECURITY_ASSOCIATION pHwSaInfo = NULL;
  37. LONG lIndex = 0;
  38. ULONG uOffset = 0;
  39. pHwSa->SrcAddr = pSwSa->SA_SRC_ADDR;
  40. pHwSa->SrcMask = pSwSa->SA_SRC_MASK;
  41. pHwSa->DstAddr = pSwSa->SA_DEST_ADDR;
  42. pHwSa->DstMask = pSwSa->SA_DEST_MASK;
  43. pHwSa->Protocol = pSwSa->SA_PROTO;
  44. pHwSa->SrcPort = SA_SRC_PORT(pSwSa);
  45. pHwSa->DstPort = SA_DEST_PORT(pSwSa);
  46. pHwSa->SrcTunnelAddr = 0;
  47. pHwSa->DstTunnelAddr = 0;
  48. if (pSwSa->sa_Flags & FLAGS_SA_TUNNEL) {
  49. pHwSa->SrcTunnelAddr = pSwSa->sa_SrcTunnelAddr;
  50. pHwSa->DstTunnelAddr = pSwSa->sa_TunnelAddr;
  51. }
  52. pHwSa->Flags = 0;
  53. if (pSwSa->sa_Flags & FLAGS_SA_OUTBOUND) {
  54. pHwSa->Flags |= OFFLOAD_OUTBOUND_SA;
  55. }
  56. else {
  57. pHwSa->Flags |= OFFLOAD_INBOUND_SA;
  58. }
  59. pHwSa->NumSAs = (SHORT) pSwSa->sa_NumOps;
  60. ASSERT(OFFLOAD_MAX_SAS >= pSwSa->sa_NumOps);
  61. pHwSa->KeyLen = 0;
  62. for (lIndex = 0; lIndex < pSwSa->sa_NumOps; lIndex++) {
  63. pHwSaInfo = &pHwSa->SecAssoc[lIndex];
  64. pHwSaInfo->Operation = pSwSa->sa_Operation[lIndex];
  65. pHwSaInfo->SPI = pSwSa->sa_OtherSPIs[lIndex];
  66. pHwSaInfo->EXT_INT_ALGO = pSwSa->INT_ALGO(lIndex);
  67. pHwSaInfo->EXT_INT_KEYLEN = pSwSa->INT_KEYLEN(lIndex);
  68. pHwSaInfo->EXT_INT_ROUNDS = pSwSa->INT_ROUNDS(lIndex);
  69. pHwSaInfo->EXT_CONF_ALGO = pSwSa->CONF_ALGO(lIndex);
  70. pHwSaInfo->EXT_CONF_KEYLEN = pSwSa->CONF_KEYLEN(lIndex);
  71. pHwSaInfo->EXT_CONF_ROUNDS = pSwSa->CONF_ROUNDS(lIndex);
  72. ASSERT(
  73. (uBufLen >= (sizeof(OFFLOAD_IPSEC_ADD_UDPESP_SA) +
  74. pHwSa->KeyLen +
  75. pSwSa->INT_KEYLEN(lIndex) +
  76. pSwSa->CONF_KEYLEN(lIndex)))
  77. );
  78. RtlCopyMemory(
  79. pHwSa->KeyMat + uOffset,
  80. pSwSa->CONF_KEY(lIndex),
  81. pSwSa->CONF_KEYLEN(lIndex)
  82. );
  83. RtlCopyMemory(
  84. pHwSa->KeyMat + uOffset + pSwSa->CONF_KEYLEN(lIndex),
  85. pSwSa->INT_KEY(lIndex),
  86. pSwSa->INT_KEYLEN(lIndex)
  87. );
  88. uOffset += pSwSa->INT_KEYLEN(lIndex) + pSwSa->CONF_KEYLEN(lIndex);
  89. pHwSa->KeyLen += uOffset;
  90. }
  91. pHwSa->OffloadHandle = NULL;
  92. if (NULL != pParserIfEntry) {
  93. ASSERT (!(pSwSa->sa_Flags & FLAGS_SA_OUTBOUND));
  94. pHwSa->EncapTypeEntry.UdpEncapType = pParserIfEntry->UdpEncapType;
  95. pHwSa->EncapTypeEntry.DstEncapPort = pParserIfEntry->usDstEncapPort;
  96. pHwSa->EncapTypeEntryOffldHandle = pParserIfEntry->hParserIfOffload;
  97. } else {
  98. ASSERT (pSwSa->sa_Flags & FLAGS_SA_OUTBOUND);
  99. if (SA_UDP_ENCAP_TYPE_IKE == pSwSa->sa_EncapType) {
  100. pHwSa->EncapTypeEntry.UdpEncapType = OFFLOAD_IPSEC_UDPESP_ENCAPTYPE_IKE;
  101. } else if (SA_UDP_ENCAP_TYPE_OTHER == pSwSa->sa_EncapType) {
  102. pHwSa->EncapTypeEntry.UdpEncapType = OFFLOAD_IPSEC_UDPESP_ENCAPTYPE_OTHER;
  103. } else {
  104. ASSERT (0);
  105. }
  106. pHwSa->EncapTypeEntry.DstEncapPort = pSwSa->sa_EncapContext.wSrcEncapPort;
  107. pHwSa->EncapTypeEntryOffldHandle = NULL;
  108. }
  109. return;
  110. }
  111. PPARSER_IFENTRY
  112. FindParserIfEntry (
  113. PPARSER_IFENTRY pParserIfEntry,
  114. PSA_TABLE_ENTRY pSa,
  115. Interface * pInterface
  116. )
  117. {
  118. ASSERT (!(pSa->sa_Flags & FLAGS_SA_OUTBOUND));
  119. while (NULL != pParserIfEntry) {
  120. if ( SA_UDP_ENCAP_TYPE_IKE == pSa->sa_EncapType ) {
  121. if (pParserIfEntry->UdpEncapType == OFFLOAD_IPSEC_UDPESP_ENCAPTYPE_IKE &&
  122. pParserIfEntry->usDstEncapPort == pSa->sa_EncapContext.wDesEncapPort &&
  123. pParserIfEntry->hInterface == pInterface) {
  124. break;
  125. }
  126. } else if (SA_UDP_ENCAP_TYPE_OTHER == pSa->sa_EncapType ) {
  127. if (pParserIfEntry->UdpEncapType == OFFLOAD_IPSEC_UDPESP_ENCAPTYPE_OTHER &&
  128. pParserIfEntry->usDstEncapPort == pSa->sa_EncapContext.wDesEncapPort &&
  129. pParserIfEntry->hInterface == pInterface) {
  130. break;
  131. }
  132. } else {
  133. ASSERT (0);
  134. }
  135. pParserIfEntry = pParserIfEntry->pNext;
  136. }
  137. return pParserIfEntry;
  138. }
  139. NTSTATUS
  140. CreateParserIfEntry(
  141. PSA_TABLE_ENTRY pSa,
  142. Interface * pInterface,
  143. PPARSER_IFENTRY * ppParserIfEntry
  144. )
  145. {
  146. PPARSER_IFENTRY pParserIfEntry = NULL;
  147. NTSTATUS ntStatus = STATUS_SUCCESS;
  148. pParserIfEntry = IPSecAllocateMemory(sizeof(PARSER_IFENTRY), IPSEC_TAG_PARSER);
  149. if (NULL == pParserIfEntry) {
  150. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  151. BAIL_ON_NTSTATUS_ERROR(ntStatus);
  152. }
  153. RtlZeroMemory (pParserIfEntry, sizeof(PARSER_IFENTRY));
  154. ASSERT (!(pSa->sa_Flags & FLAGS_SA_OUTBOUND));
  155. if (SA_UDP_ENCAP_TYPE_IKE == pSa->sa_EncapType ) {
  156. pParserIfEntry->UdpEncapType = OFFLOAD_IPSEC_UDPESP_ENCAPTYPE_IKE;
  157. } else if (SA_UDP_ENCAP_TYPE_OTHER == pSa->sa_EncapType ) {
  158. pParserIfEntry->UdpEncapType = OFFLOAD_IPSEC_UDPESP_ENCAPTYPE_OTHER;
  159. } else {
  160. ASSERT (0);
  161. }
  162. pParserIfEntry->usDstEncapPort = pSa->sa_EncapContext.wDesEncapPort;
  163. pParserIfEntry->hInterface = pInterface;
  164. pParserIfEntry->hParserIfOffload = NULL;
  165. pParserIfEntry->uRefCnt = 1;
  166. *ppParserIfEntry = pParserIfEntry;
  167. return ntStatus;
  168. error:
  169. *ppParserIfEntry = NULL;
  170. return ntStatus;
  171. }
  172. NTSTATUS
  173. GetParserEntry(
  174. PSA_TABLE_ENTRY pSa,
  175. Interface * pInterface,
  176. PPARSER_IFENTRY * ppParserIfEntry
  177. )
  178. {
  179. NTSTATUS ntStatus = STATUS_SUCCESS;
  180. PPARSER_IFENTRY pParserIfEntry = NULL;
  181. pParserIfEntry = FindParserIfEntry(
  182. gpParserIfEntry,
  183. pSa,
  184. pInterface
  185. );
  186. if (NULL == pParserIfEntry) {
  187. ntStatus = CreateParserIfEntry(pSa, pInterface, &pParserIfEntry);
  188. BAIL_ON_NTSTATUS_ERROR(ntStatus);
  189. pParserIfEntry->pNext = gpParserIfEntry;
  190. gpParserIfEntry = pParserIfEntry;
  191. }
  192. IPSEC_INCREMENT(pParserIfEntry->uRefCnt);
  193. *ppParserIfEntry = pParserIfEntry;
  194. return (ntStatus);
  195. error:
  196. *ppParserIfEntry = NULL;
  197. return (ntStatus);
  198. }
  199. VOID
  200. RemoveParserEntry (
  201. PPARSER_IFENTRY pParserIfEntry
  202. )
  203. {
  204. PPARSER_IFENTRY * ppTemp = NULL;
  205. ppTemp = &gpParserIfEntry;
  206. while (*ppTemp) {
  207. if (*ppTemp == pParserIfEntry) {
  208. break;
  209. }
  210. ppTemp = &((*ppTemp)->pNext);
  211. }
  212. if (*ppTemp) {
  213. *ppTemp = pParserIfEntry->pNext;
  214. } else {
  215. ASSERT (0);
  216. }
  217. return;
  218. }
  219. VOID
  220. DerefParserEntry(
  221. PPARSER_IFENTRY pParserIfEntry
  222. )
  223. {
  224. if (1 == IPSEC_DECREMENT(pParserIfEntry->uRefCnt)) {
  225. RemoveParserEntry (pParserIfEntry);
  226. IPSecFreeMemory (pParserIfEntry);
  227. }
  228. }
  229. HANDLE
  230. UploadParserEntryAndGetHandle(
  231. PSA_TABLE_ENTRY pSa,
  232. Interface * pInterface
  233. )
  234. {
  235. PPARSER_IFENTRY pParserIfEntry = NULL;
  236. HANDLE hOffloadHandle = NULL;
  237. pParserIfEntry = FindParserIfEntry(
  238. gpParserIfEntry,
  239. pSa,
  240. pInterface
  241. );
  242. if (NULL != pParserIfEntry) {
  243. if (IPSEC_GET_VALUE(pParserIfEntry->uRefCnt) == 2) {
  244. hOffloadHandle = pParserIfEntry->hParserIfOffload;
  245. }
  246. DerefParserEntry (pParserIfEntry);
  247. }
  248. return hOffloadHandle;
  249. }
  250. VOID
  251. FlushParserEntriesForInterface(
  252. Interface * pInterface
  253. )
  254. {
  255. PPARSER_IFENTRY pParserIfEntry = gpParserIfEntry;
  256. PPARSER_IFENTRY pPrevParserIfEntry = NULL;
  257. PPARSER_IFENTRY pTemp = NULL;
  258. while (NULL != pParserIfEntry) {
  259. if (pParserIfEntry->hInterface == pInterface) {
  260. pTemp = pParserIfEntry;
  261. pParserIfEntry = pParserIfEntry->pNext;
  262. if (NULL != pPrevParserIfEntry) {
  263. pPrevParserIfEntry->pNext = pParserIfEntry;
  264. } else {
  265. gpParserIfEntry = pParserIfEntry;
  266. }
  267. IPSecFreeMemory (pTemp);
  268. } else {
  269. pPrevParserIfEntry = pParserIfEntry;
  270. pParserIfEntry = pParserIfEntry->pNext;
  271. }
  272. }
  273. return;
  274. }
  275. VOID
  276. FlushAllParserEntries(
  277. )
  278. {
  279. PPARSER_IFENTRY pParserIfEntry = gpParserIfEntry;
  280. PPARSER_IFENTRY pTemp = NULL;
  281. while (NULL != pParserIfEntry) {
  282. pTemp = pParserIfEntry;
  283. pParserIfEntry = pParserIfEntry->pNext;
  284. IPSecFreeMemory (pTemp);
  285. }
  286. gpParserIfEntry = NULL;
  287. return;
  288. }