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.

446 lines
10 KiB

  1. /*++
  2. Copyright (c) 1997-2001 Microsoft Corporation
  3. Module Name:
  4. NsPacket.h
  5. Abstract:
  6. IpSec NAT shim packet handling routines
  7. Author:
  8. Jonathan Burstein (jonburs) 11-July-2001
  9. Environment:
  10. Kernel mode
  11. Revision History:
  12. --*/
  13. #include "precomp.h"
  14. #pragma hdrstop
  15. NTSTATUS
  16. NsInitializePacketManagement(
  17. VOID
  18. )
  19. /*++
  20. Routine Description:
  21. This routine is invoked to initialize the packet management module.
  22. Arguments:
  23. none.
  24. Return Value:
  25. NTSTATUS.
  26. --*/
  27. {
  28. CALLTRACE(("NsInitializePacketManagement\n"));
  29. return STATUS_SUCCESS;
  30. } // NsInitializePacketManagement
  31. NTSTATUS
  32. NsProcessOutgoingPacket(
  33. IPHeader UNALIGNED *pIpHeader,
  34. PVOID pvProtocolHeader,
  35. ULONG ulProtocolHeaderSize,
  36. PVOID *ppvIpSecContext
  37. )
  38. /*++
  39. Routine Description:
  40. This routine is invoked by IpSec for each outgoing packet. If this
  41. packet matches a known connection the remote port will be translated
  42. (if necessary), and the IpSec context will be returned to the caller.
  43. Arguments:
  44. pIpHeader - points to the IP header for the packet
  45. pvProtocolHeader - points to the upper level protocol header (i.e., TCP,
  46. UDP, or ICMP) for the packet. Will be NULL if this is not a TCP, UDP,
  47. or ICMP packet.
  48. ulProtocolHeaderSize - the length of the buffer pointed to by
  49. pvProtocolHeader
  50. ppvIpSecContext - receives the IpSec context for this packet; will
  51. receive NULL if this packet does not belong to a known connection.
  52. Return Value:
  53. NTSTATUS.
  54. --*/
  55. {
  56. NS_PACKET_CONTEXT Context;
  57. KIRQL Irql;
  58. NTSTATUS Status;
  59. PNS_CONNECTION_ENTRY pEntry;
  60. ULONG64 ul64AddressKey;
  61. ULONG ulPortKey;
  62. ASSERT(NULL != pIpHeader);
  63. ASSERT(NULL != ppvIpSecContext);
  64. //
  65. // Set context to default value
  66. //
  67. *ppvIpSecContext = NULL;
  68. Status =
  69. NsBuildPacketContext(
  70. pIpHeader,
  71. pvProtocolHeader,
  72. ulProtocolHeaderSize,
  73. &Context
  74. );
  75. //
  76. // Return immediately if the packet is malformed, or if it
  77. // is not TCP, UDP, or ICMP
  78. //
  79. if (!NT_SUCCESS(Status)
  80. || (NS_PROTOCOL_ICMP != Context.ucProtocol
  81. && NS_PROTOCOL_TCP != Context.ucProtocol
  82. && NS_PROTOCOL_UDP != Context.ucProtocol))
  83. {
  84. TRACE(PACKET,
  85. ("NsProcessOutgoingPacket: Bad or non-TCP/UDP/ICMP packet\n"));
  86. return Status;
  87. }
  88. TRACE(
  89. PACKET,
  90. ("NsProcessOutgoingPacket: %d: %d.%d.%d.%d/%d -> %d.%d.%d.%d/%d\n",
  91. Context.ucProtocol,
  92. ADDRESS_BYTES(Context.ulSourceAddress),
  93. NTOHS(Context.usSourcePort),
  94. ADDRESS_BYTES(Context.ulDestinationAddress),
  95. NTOHS(Context.usDestinationPort)
  96. ));
  97. if (NS_PROTOCOL_ICMP != Context.ucProtocol)
  98. {
  99. //
  100. // Build the connection lookup keys
  101. //
  102. MAKE_ADDRESS_KEY(
  103. ul64AddressKey,
  104. Context.ulSourceAddress,
  105. Context.ulDestinationAddress
  106. );
  107. MAKE_PORT_KEY(
  108. ulPortKey,
  109. Context.usSourcePort,
  110. Context.usDestinationPort
  111. );
  112. //
  113. // See if this packet matches an existing connection entry
  114. //
  115. KeAcquireSpinLock(&NsConnectionLock, &Irql);
  116. pEntry =
  117. NsLookupOutboundConnectionEntry(
  118. ul64AddressKey,
  119. ulPortKey,
  120. Context.ucProtocol,
  121. NULL
  122. );
  123. if (NULL != pEntry
  124. && NsReferenceConnectionEntry(pEntry))
  125. {
  126. KeReleaseSpinLockFromDpcLevel(&NsConnectionLock);
  127. *ppvIpSecContext = pEntry->pvIpSecContext;
  128. Status =
  129. pEntry->PacketRoutine[NsOutboundDirection](pEntry, &Context);
  130. NsDereferenceConnectionEntry(pEntry);
  131. KeLowerIrql(Irql);
  132. }
  133. else
  134. {
  135. //
  136. // No match (or entry already deleted) -- nothing more to do.
  137. //
  138. KeReleaseSpinLock(&NsConnectionLock, Irql);
  139. }
  140. }
  141. else
  142. {
  143. //
  144. // Branch to ICMP logic
  145. //
  146. Status = NsProcessOutgoingIcmpPacket(&Context, ppvIpSecContext);
  147. }
  148. return Status;
  149. } // NsProcessOutgoingPacket
  150. NTSTATUS
  151. NsProcessIncomingPacket(
  152. IPHeader UNALIGNED *pIpHeader,
  153. PVOID pvProtocolHeader,
  154. ULONG ulProtocolHeaderSize,
  155. PVOID pvIpSecContext
  156. )
  157. /*++
  158. Routine Description:
  159. This routine is invoked by IpSec for each incoming packet. It
  160. will record the connection information and context for the
  161. packet (if such information does not yet exist), and, if necessary,
  162. allocate a new remote port and modify the packet accordingly.
  163. Arguments:
  164. pIpHeader - points to the IP header for the packet
  165. pvProtocolHeader - points to the upper level protocol header (i.e., TCP,
  166. UDP, or ICMP) for the packet. Will be NULL if this is not a TCP, UDP,
  167. or ICMP packet.
  168. ulProtocolHeaderSize - the length of the buffer pointed to by
  169. pvProtocolHeader
  170. pvIpSecContext - the IpSec context for this packet; this is considered
  171. an opaque value.
  172. Return Value:
  173. NTSTATUS.
  174. --*/
  175. {
  176. NS_PACKET_CONTEXT Context;
  177. BOOLEAN fPortConflicts;
  178. KIRQL Irql;
  179. NTSTATUS Status;
  180. PNS_CONNECTION_ENTRY pEntry;
  181. PNS_CONNECTION_ENTRY pInboundInsertionPoint;
  182. PNS_CONNECTION_ENTRY pOutboundInsertionPoint;
  183. ULONG64 ul64AddressKey;
  184. ULONG ulPortKey;
  185. ULONG ulTranslatedPortKey;
  186. ASSERT(NULL != pIpHeader);
  187. Status =
  188. NsBuildPacketContext(
  189. pIpHeader,
  190. pvProtocolHeader,
  191. ulProtocolHeaderSize,
  192. &Context
  193. );
  194. //
  195. // Return immediately if the packet is malformed, or if it
  196. // is not TCP, UDP, or ICMP
  197. //
  198. if (!NT_SUCCESS(Status)
  199. || (NS_PROTOCOL_ICMP != Context.ucProtocol
  200. && NS_PROTOCOL_TCP != Context.ucProtocol
  201. && NS_PROTOCOL_UDP != Context.ucProtocol))
  202. {
  203. TRACE(PACKET,
  204. ("NsProcessIncomingPacket: Bad or non-TCP/UDP/ICMP packet\n"));
  205. return Status;
  206. }
  207. TRACE(
  208. PACKET,
  209. ("NsProcessIncomingPacket: %d: %d.%d.%d.%d/%d -> %d.%d.%d.%d/%d\n",
  210. Context.ucProtocol,
  211. ADDRESS_BYTES(Context.ulSourceAddress),
  212. NTOHS(Context.usSourcePort),
  213. ADDRESS_BYTES(Context.ulDestinationAddress),
  214. NTOHS(Context.usDestinationPort)
  215. ));
  216. if (NS_PROTOCOL_ICMP != Context.ucProtocol)
  217. {
  218. //
  219. // Build the connection lookup keys
  220. //
  221. MAKE_ADDRESS_KEY(
  222. ul64AddressKey,
  223. Context.ulDestinationAddress,
  224. Context.ulSourceAddress
  225. );
  226. MAKE_PORT_KEY(
  227. ulPortKey,
  228. Context.usDestinationPort,
  229. Context.usSourcePort
  230. );
  231. KeAcquireSpinLock(&NsConnectionLock, &Irql);
  232. //
  233. // See if this packet matches an existing connection entry
  234. //
  235. pEntry =
  236. NsLookupInboundConnectionEntry(
  237. ul64AddressKey,
  238. ulPortKey,
  239. Context.ucProtocol,
  240. pvIpSecContext,
  241. &fPortConflicts,
  242. &pInboundInsertionPoint
  243. );
  244. if (NULL != pEntry
  245. && NsReferenceConnectionEntry(pEntry))
  246. {
  247. KeReleaseSpinLockFromDpcLevel(&NsConnectionLock);
  248. Status =
  249. pEntry->PacketRoutine[NsInboundDirection](pEntry, &Context);
  250. NsDereferenceConnectionEntry(pEntry);
  251. KeLowerIrql(Irql);
  252. }
  253. else
  254. {
  255. //
  256. // No valid connection entry was found for this packet. Allocate
  257. // a new source port for the connection (if necessary).
  258. //
  259. Status =
  260. NsAllocateSourcePort(
  261. ul64AddressKey,
  262. ulPortKey,
  263. Context.ucProtocol,
  264. fPortConflicts,
  265. &pOutboundInsertionPoint,
  266. &ulTranslatedPortKey
  267. );
  268. if (NT_SUCCESS(Status))
  269. {
  270. //
  271. // Create the new connection entry
  272. //
  273. Status =
  274. NsCreateConnectionEntry(
  275. ul64AddressKey,
  276. ulPortKey,
  277. ulTranslatedPortKey,
  278. Context.ucProtocol,
  279. pvIpSecContext,
  280. pInboundInsertionPoint,
  281. pOutboundInsertionPoint,
  282. &pEntry
  283. );
  284. KeReleaseSpinLockFromDpcLevel(&NsConnectionLock);
  285. if (NT_SUCCESS(Status))
  286. {
  287. Status =
  288. pEntry->PacketRoutine[NsInboundDirection](
  289. pEntry,
  290. &Context
  291. );
  292. NsDereferenceConnectionEntry(pEntry);
  293. }
  294. KeLowerIrql(Irql);
  295. }
  296. else
  297. {
  298. KeReleaseSpinLock(&NsConnectionLock, Irql);
  299. }
  300. }
  301. }
  302. else
  303. {
  304. //
  305. // Branch to ICMP logic
  306. //
  307. Status = NsProcessIncomingIcmpPacket(&Context, pvIpSecContext);
  308. }
  309. return Status;
  310. } // NsProcessIncomingPacket
  311. VOID
  312. NsShutdownPacketManagement(
  313. VOID
  314. )
  315. /*++
  316. Routine Description:
  317. This routine is invoked to shutdown the packet management module.
  318. Arguments:
  319. none.
  320. Return Value:
  321. none.
  322. --*/
  323. {
  324. CALLTRACE(("NsShutdownPacketManagement\n"));
  325. } // NsShutdownPacketManagement
  326. //
  327. // Now include the code for the per-packet routines --
  328. // see NsPacketRoutines.h for details
  329. //
  330. #define NS_INBOUND
  331. #include "NsPacketRoutines.h"
  332. #undef NS_INBOUND
  333. #define NS_OUTBOUND
  334. #include "NsPacketRoutines.h"
  335. #undef NS_OUTBOUND