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.

343 lines
11 KiB

  1. // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil -*- (for GNU Emacs)
  2. //
  3. // Copyright (c) 1985-2000 Microsoft Corporation
  4. //
  5. // This file is part of the Microsoft Research IPv6 Network Protocol Stack.
  6. // You should have received a copy of the Microsoft End-User License Agreement
  7. // for this software along with this release; see the file "license.txt".
  8. // If not, please see http://www.research.microsoft.com/msripv6/license.htm,
  9. // or write to Microsoft Research, One Microsoft Way, Redmond, WA 98052-6399.
  10. //
  11. // Abstract:
  12. //
  13. // Mobility routines for Internet Protocol Version 6.
  14. //
  15. #include "oscfg.h"
  16. #include "ndis.h"
  17. #include "ip6imp.h"
  18. #include "ip6def.h"
  19. #include "mobile.h"
  20. #include "route.h"
  21. #include "security.h"
  22. #include "ipsec.h"
  23. int MobilitySecurity;
  24. uint MobileIPv6Mode;
  25. //* IPv6SendBindingAck
  26. //
  27. // Sends a Binding Acknowledgement using an explicit routing header.
  28. //
  29. void
  30. IPv6SendBindingAck(
  31. const IPv6Addr *DestAddr,
  32. NetTableEntryOrInterface *NTEorIF,
  33. const IPv6Addr *HomeAddr,
  34. BindingUpdateDisposition StatusCode,
  35. ushort SeqNumber, // Network byte order.
  36. uint Lifetime) // Network byte order, seconds.
  37. {
  38. NDIS_STATUS Status;
  39. PNDIS_PACKET Packet;
  40. uint Offset, PayloadLength;
  41. uchar *Mem;
  42. uint MemLen;
  43. IPv6Header UNALIGNED *IP;
  44. MobileAcknowledgementOption UNALIGNED *MA;
  45. IPv6RoutingHeader UNALIGNED *Routing;
  46. IP_STATUS IPStatus;
  47. RouteCacheEntry *RCE;
  48. IPStatus = RouteToDestination(DestAddr, 0, NTEorIF,
  49. RTD_FLAG_NORMAL, &RCE);
  50. if (IPStatus != IP_SUCCESS) {
  51. //
  52. // No route - drop the packet.
  53. //
  54. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INTERNAL_ERROR,
  55. "IPv6SendBindingNack - no route: %x\n", IPStatus));
  56. return;
  57. }
  58. // Determine size of memory buffer needed.
  59. Offset = RCE->NCE->IF->LinkHeaderSize;
  60. PayloadLength = sizeof(IPv6RoutingHeader) + sizeof(IPv6Addr) +
  61. sizeof(MobileAcknowledgementOption);
  62. MemLen = Offset + sizeof(IPv6Header) + PayloadLength;
  63. // Allocate the packet.
  64. Status = IPv6AllocatePacket(MemLen, &Packet, &Mem);
  65. if (Status != NDIS_STATUS_SUCCESS) {
  66. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_NTOS_ERROR,
  67. "IPv6SendBindingNack: Couldn't allocate packet header!?!\n"));
  68. return;
  69. }
  70. // Prepare IP header of reply packet.
  71. IP = (IPv6Header UNALIGNED *)(Mem + Offset);
  72. IP->VersClassFlow = IP_VERSION;
  73. IP->NextHeader = IP_PROTOCOL_ROUTING;
  74. IP->HopLimit = (uchar)RCE->NCE->IF->CurHopLimit;
  75. IP->Dest = *DestAddr;
  76. IP->Source = (IsNTE(NTEorIF) ? CastToNTE(NTEorIF) : RCE->NTE)->Address;
  77. // Prepare the routing header.
  78. Routing = (IPv6RoutingHeader UNALIGNED *)(IP + 1);
  79. Routing->NextHeader = IP_PROTOCOL_DEST_OPTS;
  80. Routing->HeaderExtLength = 2;
  81. Routing->RoutingType = 0;
  82. RtlZeroMemory(&Routing->Reserved, sizeof Routing->Reserved);
  83. Routing->SegmentsLeft = 1;
  84. RtlCopyMemory(Routing + 1, HomeAddr, sizeof(IPv6Addr));
  85. // Prepare the binding acknowledgement option.
  86. MA = (MobileAcknowledgementOption UNALIGNED *)((uchar *)(Routing + 1) +
  87. sizeof(IPv6Addr));
  88. MA->Header.NextHeader = IP_PROTOCOL_NONE;
  89. MA->Header.HeaderExtLength = 1;
  90. MA->Pad1 = 0;
  91. MA->Option.Type = OPT6_BINDING_ACK;
  92. MA->Option.Length = 11;
  93. MA->Option.Status = StatusCode;
  94. MA->Option.SeqNumber = SeqNumber;
  95. MA->Option.Lifetime = Lifetime;
  96. MA->Option.Refresh = Lifetime;
  97. IPv6Send(Packet, Offset, IP, PayloadLength, RCE,
  98. SEND_FLAG_BYPASS_BINDING_CACHE, 0, 0, 0);
  99. //
  100. // Release the route.
  101. //
  102. ReleaseRCE(RCE);
  103. }
  104. //* ParseSubOptions - Routine for mobile ip sub-option parsing.
  105. //
  106. // Mobile IPv6 destination options may themselves have options, see
  107. // section 5.5 of the draft. This routine parses these sub-options.
  108. //
  109. // We do not return any values to our caller;
  110. // we merely check that the sub-options are well-formed.
  111. //
  112. // Returns TRUE if the sub-options were successfully parsed.
  113. // Returns FALSE if the packet should be discarded.
  114. //
  115. int
  116. ParseSubOptions(
  117. uchar *SubOptPtr, // Start of the sub-option data.
  118. uint SubOptSizeLeft) // Length remaining in the parent option.
  119. {
  120. SubOptionHeader UNALIGNED *SubOptHdr;
  121. uint SubOptLen;
  122. while (SubOptSizeLeft != 0) {
  123. //
  124. // First we check the option length and ensure that it fits.
  125. // We move OptPtr past this option while leaving OptHdr
  126. // for use by the option processing code below.
  127. //
  128. SubOptHdr = (SubOptionHeader UNALIGNED *) SubOptPtr;
  129. if ((sizeof *SubOptHdr > SubOptSizeLeft) ||
  130. ((SubOptLen = sizeof *SubOptHdr + SubOptHdr->DataLength) >
  131. SubOptSizeLeft)) {
  132. //
  133. // Bad length. REVIEW: Should we discard the packet or continue
  134. // processing it? For now, discard it.
  135. //
  136. return FALSE;
  137. }
  138. SubOptPtr += SubOptLen;
  139. SubOptSizeLeft -= SubOptLen;
  140. }
  141. return TRUE;
  142. }
  143. //* IPv6RecvBindingUpdate - handle an incoming binding update.
  144. //
  145. // Process the receipt of a binding update destination option
  146. // from a mobile node.
  147. //
  148. int
  149. IPv6RecvBindingUpdate(
  150. IPv6Packet *Packet, // Packet received.
  151. IPv6BindingUpdateOption UNALIGNED *BindingUpdate)
  152. {
  153. const IPv6Addr *CareOfAddr;
  154. const IPv6Addr *HomeAddr;
  155. BindingUpdateDisposition Status;
  156. uint OptBytesLeft;
  157. //
  158. // If a home address option is not also present
  159. // then we MUST silently drop this packet.
  160. //
  161. if ((Packet->Flags & PACKET_SAW_HA_OPT) == 0)
  162. return 1; // Drop packet.
  163. HomeAddr = Packet->SrcAddr;
  164. //
  165. // Check to make sure we have a reasonable home address.
  166. // Not required by spec but seems like a good idea.
  167. // Most of what we want to protect against has already been checked
  168. // by the time we get here, we ASSERT this is checked builds.
  169. // REVIEW: Final spec may allow/disallow a different set of addresses.
  170. //
  171. ASSERT(!IsInvalidSourceAddress(HomeAddr));
  172. ASSERT(!IsUnspecified(HomeAddr));
  173. ASSERT(!IsLoopback(HomeAddr));
  174. if (IsLinkLocal(HomeAddr) ||
  175. IsSiteLocal(HomeAddr)) {
  176. //
  177. // Since the home address is suspect, do not send binding ack.
  178. //
  179. return 1;
  180. }
  181. //
  182. // While the mobility spec requires that packets containing binding
  183. // update options be authenticated, we currently allow this to be
  184. // turned off for interoperability testing with mobility implementations
  185. // that don't support IPSec yet.
  186. //
  187. if (MobilitySecurity) {
  188. //
  189. // Check if the packet went through some security.
  190. // If the security check fails we MUST silently drop the packet.
  191. //
  192. // REVIEW: This doesn't check that use of this security association
  193. // REVIEW: actually falls within a security policy.
  194. //
  195. if (Packet->SAPerformed == NULL) {
  196. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_NET_ERROR,
  197. "IPv6RecvBindingUpdate: IPSec required "
  198. "for binding update\n"));
  199. return 1;
  200. }
  201. }
  202. CareOfAddr = AlignAddr(&Packet->IP->Source);
  203. ASSERT(!IsInvalidSourceAddress(CareOfAddr));
  204. //
  205. // Sub-options may follow the fixed portion of the header.
  206. //
  207. OptBytesLeft = sizeof(OptionHeader) + BindingUpdate->Length
  208. - sizeof(IPv6BindingUpdateOption);
  209. if (OptBytesLeft != 0) {
  210. //
  211. // Sub-options are present. Parse them.
  212. //
  213. if (!ParseSubOptions((uchar *) (BindingUpdate + 1), OptBytesLeft)) {
  214. //
  215. // Sub-options are malformed. Spec doesn't explicitly say
  216. // what to do, but the implication is to silently drop.
  217. //
  218. return 1;
  219. }
  220. }
  221. //
  222. // Check to make sure we have a reasonable care-of address.
  223. // Not required by spec but seems like a good idea.
  224. // REVIEW: Aren't link-local addresses o.k. as care-of addresses?
  225. //
  226. if (IsUnspecified(CareOfAddr) ||
  227. IsLoopback(CareOfAddr) ||
  228. IsLinkLocal(CareOfAddr)) {
  229. //
  230. // Since the care-of address is suspect, do not send binding ack.
  231. //
  232. return 1;
  233. }
  234. //
  235. // We don't support home agent functionality (yet).
  236. // The spec says we SHOULD send a rejecting acknowledgement in this case.
  237. //
  238. if (BindingUpdate->Flags & IPV6_BINDING_HOME_REG) {
  239. IPv6SendBindingAck(CareOfAddr, Packet->NTEorIF, HomeAddr,
  240. IPV6_BINDING_HOME_REG_NOT_SUPPORTED,
  241. BindingUpdate->SeqNumber, 0);
  242. return 1;
  243. }
  244. //
  245. // Update our binding cache to reflect this binding update.
  246. //
  247. Status = CacheBindingUpdate(BindingUpdate, CareOfAddr, Packet->NTEorIF,
  248. HomeAddr);
  249. if (Status != IPV6_BINDING_ACCEPTED) {
  250. //
  251. // Failed to update our binding cache. If this failure was due to
  252. // an old sequence number being present in the packet, we MUST
  253. // silently ignore it. Otherwise we send a rejecting acknowledgement.
  254. //
  255. if (Status != IPV6_BINDING_SEQ_NO_TOO_SMALL)
  256. IPv6SendBindingAck(CareOfAddr, Packet->NTEorIF, HomeAddr,
  257. Status, BindingUpdate->SeqNumber, 0);
  258. return 1;
  259. }
  260. if (BindingUpdate->Flags & IPV6_BINDING_ACK) {
  261. //
  262. // The mobile node has requested an acknowledgement. In some cases
  263. // this could be delayed until the next packet is sent
  264. // to the mobile node, but for now we always send one immediately.
  265. // We MUST always use a routing header for binding acks.
  266. // If we deleted a binding, we ack with a zero lifetime.
  267. //
  268. IPv6SendBindingAck(CareOfAddr, Packet->NTEorIF, HomeAddr,
  269. Status, BindingUpdate->SeqNumber,
  270. (IP6_ADDR_EQUAL(HomeAddr, CareOfAddr) ?
  271. 0 : BindingUpdate->Lifetime));
  272. }
  273. return 0;
  274. }
  275. //* IPv6RecvHomeAddress - handle an incoming home address option.
  276. //
  277. // Process the receipt of a Home Address destination option.
  278. //
  279. int
  280. IPv6RecvHomeAddress(
  281. IPv6Packet *Packet, // Packet received.
  282. IPv6HomeAddressOption UNALIGNED *HomeAddress)
  283. {
  284. uint OptBytesLeft, OptsLen;
  285. //
  286. // If any mobile sub-options exist, then find out which ones.
  287. // For now we don't do anything with them.
  288. //
  289. OptsLen = HomeAddress->Length + sizeof(OptionHeader);
  290. OptBytesLeft = OptsLen - sizeof(IPv6HomeAddressOption);
  291. if (OptBytesLeft != 0) {
  292. if (!ParseSubOptions((uchar *) HomeAddress + OptsLen - OptBytesLeft,
  293. OptBytesLeft))
  294. return 1;
  295. }
  296. //
  297. // Save the home address for use by upper layers.
  298. //
  299. Packet->SrcAddr = AlignAddr(&HomeAddress->HomeAddress);
  300. Packet->Flags |= PACKET_SAW_HA_OPT;
  301. // Done.
  302. return 0;
  303. }