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.

1382 lines
29 KiB

  1. /*++
  2. Copyright (c) 2001-2002 Microsoft Corporation
  3. Module Name:
  4. client.c
  5. Abstract:
  6. This module contains the teredo client implementation.
  7. Author:
  8. Mohit Talwar (mohitt) Mon Oct 22 15:17:20 2001
  9. Environment:
  10. User mode only.
  11. --*/
  12. #include "precomp.h"
  13. #pragma hdrstop
  14. TEREDO_CLIENT_STATE TeredoClient;
  15. TEREDO_PACKET_IO_COMPLETE TeredoClientReadComplete;
  16. TEREDO_PACKET_IO_COMPLETE TeredoClientWriteComplete;
  17. TEREDO_PACKET_IO_COMPLETE TeredoClientBubbleComplete;
  18. TEREDO_PACKET_IO_COMPLETE TeredoClientReceiveComplete;
  19. TEREDO_PACKET_IO_COMPLETE TeredoClientTransmitComplete;
  20. TEREDO_PACKET_IO_COMPLETE TeredoClientMulticastComplete;
  21. VOID TeredoTransmitMulticastBubble( VOID );
  22. BOOL
  23. TeredoAddressPresent(
  24. VOID
  25. )
  26. /*++
  27. Routine Description:
  28. Determine whether an IPv6 tunnel interface has a teredo address. The
  29. address must have been configured from a router advertisement. If the
  30. address is found, we remember the teredo tunnel interface name.
  31. Arguments:
  32. None.
  33. Return Value:
  34. TRUE if present, FALSE if not.
  35. --*/
  36. {
  37. DWORD Error;
  38. ULONG Bytes;
  39. PIP_ADAPTER_ADDRESSES Adapters, Next;
  40. PIP_ADAPTER_UNICAST_ADDRESS Address;
  41. BOOL Found = FALSE;
  42. TraceEnter("TeredoAddressPresent");
  43. //
  44. // 10 Adapters, each with 3 strings and 4 unicast addresses.
  45. // This would usually be more than enough!
  46. //
  47. Bytes = 10 * (
  48. sizeof(IP_ADAPTER_ADDRESSES) +
  49. 2 * MAX_ADAPTER_NAME_LENGTH + MAX_ADAPTER_DESCRIPTION_LENGTH +
  50. 4 * (sizeof(IP_ADAPTER_UNICAST_ADDRESS) + sizeof(SOCKADDR_IN6)));
  51. Adapters = MALLOC(Bytes);
  52. if (Adapters == NULL) {
  53. return FALSE;
  54. }
  55. do {
  56. Error = GetAdaptersAddresses(
  57. AF_INET6,
  58. GAA_FLAG_SKIP_FRIENDLY_NAME |
  59. GAA_FLAG_SKIP_DNS_SERVER |
  60. GAA_FLAG_SKIP_MULTICAST |
  61. GAA_FLAG_SKIP_ANYCAST,
  62. NULL, Adapters, &Bytes);
  63. if (Error == ERROR_BUFFER_OVERFLOW) {
  64. Next = REALLOC(Adapters, Bytes);
  65. if (Next != NULL) {
  66. Adapters = Next;
  67. } else {
  68. Error = ERROR_OUTOFMEMORY;
  69. }
  70. }
  71. } while (Error == ERROR_BUFFER_OVERFLOW);
  72. if (Error != NO_ERROR) {
  73. goto Bail;
  74. }
  75. for (Next = Adapters; Next != NULL; Next = Next->Next) {
  76. if ((Next->IfType != IF_TYPE_TUNNEL) ||
  77. (Next->OperStatus != IfOperStatusUp)) {
  78. continue;
  79. }
  80. for (Address = Next->FirstUnicastAddress;
  81. Address != NULL;
  82. Address = Address->Next) {
  83. if ((Address->PrefixOrigin != PREFIX_CONF_RA) ||
  84. (Address->DadState != IpDadStatePreferred)) {
  85. continue;
  86. }
  87. if (TeredoEqualPrefix(
  88. &(((PSOCKADDR_IN6) Address->Address.lpSockaddr)->sin6_addr),
  89. &(TeredoClient.Ipv6Prefix))) {
  90. ConvertOemToUnicode(
  91. Next->AdapterName,
  92. TeredoClient.Io.TunnelInterface,
  93. MAX_ADAPTER_NAME_LENGTH);
  94. Found = TRUE;
  95. goto Bail;
  96. }
  97. }
  98. }
  99. Bail:
  100. FREE(Adapters);
  101. return Found;
  102. }
  103. VOID
  104. CALLBACK
  105. TeredoClientIoCompletionCallback(
  106. IN DWORD ErrorCode,
  107. IN DWORD Bytes,
  108. IN LPOVERLAPPED Overlapped
  109. )
  110. /*++
  111. Routine Description:
  112. Callback routine for I/O completion on TUN interface device or UDP socket.
  113. Arguments:
  114. ErrorCode - Supplies the I/O completion status.
  115. Bytes - Supplies the number of bytes transferred.
  116. Overlapped - Supplies the completion context.
  117. Return Value:
  118. None.
  119. --*/
  120. {
  121. static CONST PTEREDO_PACKET_IO_COMPLETE Callback[] =
  122. {
  123. TeredoClientReadComplete,
  124. TeredoClientWriteComplete,
  125. TeredoClientBubbleComplete,
  126. NULL, // No bouncing...
  127. TeredoClientReceiveComplete,
  128. TeredoClientTransmitComplete,
  129. TeredoClientMulticastComplete,
  130. };
  131. PTEREDO_PACKET Packet = Cast(
  132. CONTAINING_RECORD(Overlapped, TEREDO_PACKET, Overlapped),
  133. TEREDO_PACKET);
  134. ASSERT(Packet->Type != TEREDO_PACKET_BOUNCE);
  135. //
  136. // This completion function usually posts the packet for another I/O.
  137. // Since we are called by a non-I/O worker thread, asynchronous I/O
  138. // requests posted here might terminate when this thread does. This
  139. // is rare enough that we don't special case it. Moreover, we only
  140. // make best effort guarantees to the upper layer!
  141. //
  142. (*Callback[Packet->Type])(ErrorCode, Bytes, Packet);
  143. }
  144. VOID
  145. CALLBACK
  146. TeredoClientTimerCallback(
  147. IN PVOID Parameter,
  148. IN BOOLEAN TimerOrWaitFired
  149. )
  150. /*++
  151. Routine Description:
  152. Callback routine for TeredoClient.Timer expiration.
  153. The timer is active in the probe and qualified states.
  154. Arguments:
  155. Parameter, TimerOrWaitFired - Ignored.
  156. Return Value:
  157. None.
  158. --*/
  159. {
  160. ENTER_API();
  161. if (TeredoClient.State == TEREDO_STATE_PROBE) {
  162. if (TeredoClient.RestartQualifiedTimer) {
  163. //
  164. // Probe -> Qualified.
  165. //
  166. if (TeredoAddressPresent()) {
  167. //
  168. // The stack has validated and processed an RA.
  169. //
  170. TeredoQualifyClient();
  171. } else {
  172. //
  173. // The stack has not received any valid RA.
  174. //
  175. TeredoStopClient();
  176. }
  177. } else {
  178. //
  179. // Probe -> Offline.
  180. //
  181. TeredoStopClient();
  182. }
  183. } else {
  184. if (TeredoClient.RestartQualifiedTimer) {
  185. //
  186. // Qualified -> Qualified.
  187. //
  188. TeredoQualifyClient();
  189. } else {
  190. //
  191. // Qualified -> Probe.
  192. //
  193. TeredoProbeClient();
  194. }
  195. }
  196. LEAVE_API();
  197. }
  198. VOID
  199. CALLBACK
  200. TeredoClientTimerCleanup(
  201. IN PVOID Parameter,
  202. IN BOOLEAN TimerOrWaitFired
  203. )
  204. /*++
  205. Routine Description:
  206. Callback routine for TeredoClient.Timer deletion.
  207. Deletion is performed asynchronously since we acquire a lock in
  208. the callback function that we hold when deleting the timer.
  209. Arguments:
  210. Parameter, TimerOrWaitFired - Ignored.
  211. Return Value:
  212. None.
  213. --*/
  214. {
  215. TeredoDereferenceClient();
  216. }
  217. VOID
  218. TeredoClientAddressDeletionNotification(
  219. IN IN_ADDR Address
  220. )
  221. /*++
  222. Routine Description:
  223. Process an address deletion request.
  224. Arguments:
  225. Address - Supplies the address that was deleted.
  226. Return Value:
  227. None.
  228. Caller LOCK: API.
  229. --*/
  230. {
  231. if (!IN4_ADDR_EQUAL(Address, TeredoClient.Io.SourceAddress.sin_addr)) {
  232. return;
  233. }
  234. //
  235. // Refresh the socket state (the socket bound to SourceAddress).
  236. //
  237. if (TeredoRefreshSocket(&(TeredoClient.Io)) != NO_ERROR) {
  238. //
  239. // [Probe | Qualified] -> Offline.
  240. //
  241. TeredoStopClient();
  242. return;
  243. }
  244. if (IN4_ADDR_EQUAL(
  245. TeredoClient.Io.SourceAddress.sin_addr,
  246. TeredoClient.Io.ServerAddress.sin_addr)) {
  247. //
  248. // [Probe | Qualified] -> Offline.
  249. //
  250. TeredoStopClient();
  251. return;
  252. }
  253. //
  254. // [Probe | Qualified] -> Probe.
  255. //
  256. TeredoProbeClient();
  257. }
  258. VOID
  259. TeredoClientRefreshIntervalChangeNotification(
  260. VOID
  261. )
  262. /*++
  263. Routine Description:
  264. Process a refresh interval change request.
  265. Arguments:
  266. None.
  267. Return Value:
  268. None.
  269. Caller LOCK: API.
  270. --*/
  271. {
  272. if (TeredoClient.RefreshInterval == TeredoClientRefreshInterval) {
  273. return;
  274. }
  275. TeredoClient.RefreshInterval = TeredoClientRefreshInterval;
  276. if (TeredoClient.State == TEREDO_STATE_QUALIFIED) {
  277. //
  278. // Refresh interval has been updated.
  279. // Qualified -> Qualified.
  280. //
  281. TeredoQualifyClient();
  282. }
  283. }
  284. VOID
  285. TeredoStartClient(
  286. VOID
  287. )
  288. /*++
  289. Routine Description:
  290. Attempt to start the teredo service at the client.
  291. Events / Transitions
  292. ServiceStart Offline -> Probe.
  293. ServiceEnable Offline -> Probe.
  294. AdapterArrival Offline -> Probe.
  295. AddressAddition Offline -> Probe.
  296. Arguments:
  297. None.
  298. Return Value:
  299. None.
  300. Caller LOCK: API.
  301. --*/
  302. {
  303. TraceEnter("TeredoStartClient");
  304. //
  305. // Can't have both the client and server on the same node.
  306. //
  307. if (TeredoServer.State != TEREDO_STATE_OFFLINE) {
  308. return;
  309. }
  310. //
  311. // Well, the service has already been started!
  312. //
  313. if (TeredoClient.State != TEREDO_STATE_OFFLINE) {
  314. return;
  315. }
  316. TeredoClient.State = TEREDO_STATE_PROBE;
  317. //
  318. // Start I/O processing.
  319. //
  320. if (TeredoStartIo(&(TeredoClient.Io)) != NO_ERROR) {
  321. goto Bail;
  322. }
  323. if (IN4_ADDR_EQUAL(
  324. TeredoClient.Io.SourceAddress.sin_addr,
  325. TeredoClient.Io.ServerAddress.sin_addr)) {
  326. goto Bail;
  327. }
  328. //
  329. // Start a one shot probe timer.
  330. //
  331. if (!CreateTimerQueueTimer(
  332. &(TeredoClient.Timer),
  333. NULL,
  334. TeredoClientTimerCallback,
  335. NULL,
  336. TEREDO_PROBE_INTERVAL * 1000, // in milliseconds.
  337. INFINITE_INTERVAL,
  338. 0)) {
  339. goto Bail;
  340. }
  341. //
  342. // Obtain a reference on the teredo client for the running timer.
  343. //
  344. TeredoReferenceClient();
  345. return;
  346. Bail:
  347. TeredoClient.State = TEREDO_STATE_OFFLINE;
  348. TeredoStopIo(&(TeredoClient.Io));
  349. }
  350. VOID
  351. TeredoStopClient(
  352. VOID
  353. )
  354. /*++
  355. Routine Description:
  356. Stop the teredo service at the client.
  357. Events / Transitions
  358. ProbeTimer Probe -> Offline.
  359. ServiceStop [Probe | Qualified] -> Offline.
  360. ServiceDisable [Probe | Qualified] -> Offline.
  361. AdapterRemoval [Probe | Qualified] -> Offline.
  362. AddressDeletion [Probe | Qualified] -> Offline.
  363. Arguments:
  364. None.
  365. Return Value:
  366. None.
  367. Caller LOCK: API.
  368. --*/
  369. {
  370. TraceEnter("TeredoStopClient");
  371. //
  372. // Well, the service was never started!
  373. //
  374. if (TeredoClient.State == TEREDO_STATE_OFFLINE) {
  375. return;
  376. }
  377. TeredoClient.State = TEREDO_STATE_OFFLINE;
  378. TeredoClient.Ipv6Prefix = in6addr_any;
  379. TeredoClient.RestartQualifiedTimer = FALSE;
  380. DeleteTimerQueueTimer(
  381. NULL, TeredoClient.Timer, TeredoClient.TimerEvent);
  382. TeredoClient.Timer = NULL;
  383. TeredoStopIo(&(TeredoClient.Io));
  384. TeredoUninitializePeerSet();
  385. }
  386. VOID
  387. TeredoProbeClient(
  388. VOID
  389. )
  390. /*++
  391. Routine Description:
  392. Probe the teredo service at the client.
  393. Events / Transitions
  394. QualifiedTimer Qualified -> Probe.
  395. AddressDeletion [Probe | Qualified] -> Probe.
  396. Arguments:
  397. None.
  398. Return Value:
  399. None.
  400. Caller LOCK: API.
  401. --*/
  402. {
  403. TraceEnter("TeredoProbeClient");
  404. TeredoClient.State = TEREDO_STATE_PROBE;
  405. //
  406. // Reconnect!
  407. //
  408. if (!ReconnectInterface(TeredoClient.Io.TunnelInterface)) {
  409. //
  410. // [Probe | Qualified] -> Offline.
  411. //
  412. TeredoStopClient();
  413. return;
  414. }
  415. if (!ChangeTimerQueueTimer(
  416. NULL,
  417. TeredoClient.Timer,
  418. TEREDO_PROBE_INTERVAL * 1000, // in milliseconds.
  419. INFINITE_INTERVAL)) {
  420. TeredoStopClient();
  421. return;
  422. }
  423. TeredoClient.RestartQualifiedTimer = FALSE;
  424. }
  425. VOID
  426. TeredoQualifyClient(
  427. VOID
  428. )
  429. /*++
  430. Routine Description:
  431. Qualify the teredo service at the client.
  432. Events / Transitions
  433. RouterAdvertisement Probe -> Qualified.
  434. NatMappingRefresh Qualified -> Qualified.
  435. RefreshIntervalChange Qualified -> Qualified.
  436. Arguments:
  437. None.
  438. Return Value:
  439. None.
  440. Caller LOCK: API.
  441. --*/
  442. {
  443. TraceEnter("TeredoQualifyClient");
  444. TeredoClient.State = TEREDO_STATE_QUALIFIED;
  445. if (!ChangeTimerQueueTimer(
  446. NULL,
  447. TeredoClient.Timer,
  448. TeredoClient.RefreshInterval * 1000, // in milliseconds.
  449. INFINITE_INTERVAL)) {
  450. //
  451. // [Probe | Qualified] -> Offline.
  452. //
  453. TeredoStopClient();
  454. return;
  455. }
  456. TeredoTransmitMulticastBubble();
  457. TeredoClient.RestartQualifiedTimer = FALSE;
  458. }
  459. DWORD
  460. TeredoInitializeClient(
  461. VOID
  462. )
  463. /*++
  464. Routine Description:
  465. Initializes the client.
  466. Arguments:
  467. None.
  468. Return Value:
  469. NO_ERROR or failure code.
  470. --*/
  471. {
  472. DWORD Error;
  473. //
  474. // Obtain a reference on the teredo client for initialization.
  475. //
  476. TeredoClient.ReferenceCount = 1;
  477. TeredoClient.PeerHeap
  478. = TeredoClient.TimerEvent
  479. = TeredoClient.TimerEventWait
  480. = NULL;
  481. TeredoClient.BubbleTicks = 0;
  482. TeredoClient.BubblePosted = FALSE;
  483. TeredoInitializePacket(&(TeredoClient.Packet));
  484. TeredoClient.Packet.Type = TEREDO_PACKET_MULTICAST;
  485. TeredoClient.Packet.Buffer.len = sizeof(IP6_HDR);
  486. ASSERT(TeredoClient.Packet.Buffer.buf ==
  487. (PUCHAR) &(TeredoClient.Bubble));
  488. TeredoClient.Bubble.ip6_flow = 0;
  489. TeredoClient.Bubble.ip6_plen = 0;
  490. TeredoClient.Bubble.ip6_nxt = IPPROTO_NONE;
  491. TeredoClient.Bubble.ip6_hlim = IPV6_HOPLIMIT;
  492. TeredoClient.Bubble.ip6_vfc = IPV6_VERSION;
  493. // Peer->Bubble.ip6_src... Filled in when sending.
  494. TeredoClient.Bubble.ip6_dest = TeredoIpv6MulticastPrefix;
  495. //
  496. // Multicast bubble destination UDP port & IPv4 address.
  497. //
  498. TeredoParseAddress(
  499. &(TeredoClient.Bubble.ip6_dest),
  500. &(TeredoClient.Packet.SocketAddress.sin_addr),
  501. &(TeredoClient.Packet.SocketAddress.sin_port));
  502. Error = TeredoInitializeIo(
  503. &(TeredoClient.Io),
  504. TeredoClient.Packet.SocketAddress.sin_addr,
  505. TeredoReferenceClient,
  506. TeredoDereferenceClient,
  507. TeredoClientIoCompletionCallback);
  508. if (Error != NO_ERROR) {
  509. return Error;
  510. }
  511. TeredoClient.PeerHeap = HeapCreate(0, 0, 0);
  512. if (TeredoClient.PeerHeap == NULL) {
  513. Error = GetLastError();
  514. goto Bail;
  515. }
  516. TeredoClient.TimerEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  517. if (TeredoClient.TimerEvent == NULL) {
  518. Error = GetLastError();
  519. goto Bail;
  520. }
  521. if (!RegisterWaitForSingleObject(
  522. &(TeredoClient.TimerEventWait),
  523. TeredoClient.TimerEvent,
  524. TeredoClientTimerCleanup,
  525. NULL,
  526. INFINITE,
  527. 0)) {
  528. Error = GetLastError();
  529. goto Bail;
  530. }
  531. TeredoClient.RestartQualifiedTimer = FALSE;
  532. TeredoClient.Time = TeredoGetTime();
  533. TeredoClient.State = TEREDO_STATE_OFFLINE;
  534. TeredoClient.Ipv6Prefix = in6addr_any;
  535. TeredoClient.RefreshInterval = TeredoClientRefreshInterval;
  536. TeredoClient.Timer = INVALID_HANDLE_VALUE;
  537. Error = TeredoInitializePeerSet();
  538. if (Error != NO_ERROR) {
  539. goto Bail;
  540. }
  541. IncEventCount("TeredoInitializeClient");
  542. return NO_ERROR;
  543. Bail:
  544. TeredoCleanupIo(&(TeredoClient.Io));
  545. if (TeredoClient.PeerHeap != NULL) {
  546. HeapDestroy(TeredoClient.PeerHeap);
  547. TeredoClient.PeerHeap = NULL;
  548. }
  549. if (TeredoClient.TimerEventWait != NULL) {
  550. UnregisterWait(TeredoClient.TimerEventWait);
  551. TeredoClient.TimerEventWait = NULL;
  552. }
  553. if (TeredoClient.TimerEvent != NULL) {
  554. CloseHandle(TeredoClient.TimerEvent);
  555. TeredoClient.TimerEvent = NULL;
  556. }
  557. return Error;
  558. }
  559. VOID
  560. TeredoUninitializeClient(
  561. VOID
  562. )
  563. /*++
  564. Routine Description:
  565. Uninitializes the client. Typically invoked upon service stop.
  566. Arguments:
  567. None.
  568. Return Value:
  569. None.
  570. --*/
  571. {
  572. TeredoStopClient();
  573. TeredoDereferenceClient();
  574. }
  575. VOID
  576. TeredoCleanupClient(
  577. VOID
  578. )
  579. /*++
  580. Routine Description:
  581. Cleans up the client after the last reference to it has been released.
  582. Arguments:
  583. None.
  584. Return Value:
  585. None.
  586. --*/
  587. {
  588. TeredoCleanupPeerSet();
  589. UnregisterWait(TeredoClient.TimerEventWait);
  590. TeredoClient.TimerEventWait = NULL;
  591. CloseHandle(TeredoClient.TimerEvent);
  592. TeredoClient.TimerEvent = NULL;
  593. HeapDestroy(TeredoClient.PeerHeap);
  594. TeredoClient.PeerHeap = NULL;
  595. TeredoCleanupIo(&(TeredoClient.Io));
  596. DecEventCount("TeredoCleanupClient");
  597. }
  598. VOID
  599. TeredoTransmitMulticastBubble(
  600. VOID
  601. )
  602. /*++
  603. Routine Description:
  604. Transmit a teredo multicast bubble on the native link.
  605. Arguments:
  606. None.
  607. Return Value:
  608. None.
  609. Caller LOCK: API.
  610. --*/
  611. {
  612. ASSERT(TeredoClient.State == TEREDO_STATE_QUALIFIED);
  613. if (TeredoClient.BubbleTicks == 0) {
  614. //
  615. // No multicast bubbles should be sent.
  616. //
  617. return;
  618. }
  619. if (--TeredoClient.BubbleTicks != 0) {
  620. //
  621. // Our time is not yet up!
  622. //
  623. return;
  624. }
  625. if (TeredoClient.BubblePosted == TRUE) {
  626. //
  627. // At most one outstanding multicast bubble is allowed! Try later.
  628. //
  629. TeredoClient.BubbleTicks = 1;
  630. return;
  631. }
  632. //
  633. // Reset the timer.
  634. //
  635. TeredoClient.BubbleTicks = TEREDO_MULTICAST_BUBBLE_TICKS;
  636. //
  637. // Obtain a reference for the posted multicast bubble.
  638. //
  639. TeredoReferenceClient();
  640. TeredoClient.Bubble.ip6_src = TeredoClient.Ipv6Prefix;
  641. if (TeredoTransmitPacket(
  642. &(TeredoClient.Io), &(TeredoClient.Packet)) != NULL) {
  643. TeredoClientMulticastComplete(
  644. NO_ERROR, sizeof(IP6_HDR), &(TeredoClient.Packet));
  645. }
  646. }
  647. VOID
  648. TeredoTransmitBubble(
  649. IN PTEREDO_PEER Peer
  650. )
  651. /*++
  652. Routine Description:
  653. Transmit a teredo bubble to a peer.
  654. Arguments:
  655. Peer - Supplies the peer of interest.
  656. Return Value:
  657. None.
  658. --*/
  659. {
  660. if (TIME_GREATER(
  661. Peer->LastTransmit,
  662. (TeredoClient.Time - TEREDO_BUBBLE_INTERVAL))) {
  663. //
  664. // Rate limit bubble transmission.
  665. //
  666. return;
  667. }
  668. if (TIME_GREATER(
  669. (TeredoClient.Time - TEREDO_BUBBLE_THRESHHOLD),
  670. Peer->LastReceive) &&
  671. TIME_GREATER(
  672. Peer->LastTransmit,
  673. (TeredoClient.Time - TEREDO_SLOW_BUBBLE_INTERVAL))) {
  674. //
  675. // If the peer refuses to respond, drop rate (to once in 5 minutes).
  676. //
  677. return;
  678. }
  679. if (InterlockedExchange(&(Peer->BubblePosted), TRUE)) {
  680. //
  681. // At most one outstanding bubble is allowed!
  682. //
  683. return;
  684. }
  685. //
  686. // Obtain a reference for the posted bubble.
  687. //
  688. TeredoReferencePeer(Peer);
  689. Peer->LastTransmit = TeredoClient.Time;
  690. Peer->BubbleCount++;
  691. Peer->Bubble.ip6_src = TeredoClient.Ipv6Prefix;
  692. if (TeredoTransmitPacket(
  693. &(TeredoClient.Io), &(Peer->Packet)) != NULL) {
  694. TeredoClientBubbleComplete(
  695. NO_ERROR, sizeof(IP6_HDR), &(Peer->Packet));
  696. }
  697. }
  698. BOOL
  699. TeredoReceiveRouterAdvertisement(
  700. IN PTEREDO_PACKET Packet,
  701. IN ULONG Bytes
  702. )
  703. /*++
  704. Routine Description:
  705. Process the router advertisement packet received on the UDP socket.
  706. Arguments:
  707. Packet - Supplies the packet that was received.
  708. Bytes - Supplies the length of the packet.
  709. Return Value:
  710. TRUE if the packet should be forwarded to the stack, FALSE otherwise.
  711. --*/
  712. {
  713. PUCHAR Buffer = Packet->Buffer.buf;
  714. ICMPv6Header *Icmp6;
  715. UCHAR Type;
  716. ULONG Length;
  717. NDOptionPrefixInformation *Prefix = NULL;
  718. if (!IN4_SOCKADDR_EQUAL(
  719. &(Packet->SocketAddress), &(TeredoClient.Io.ServerAddress))) {
  720. //
  721. // Only the teredo server is allowed to send an RA.
  722. //
  723. return FALSE;
  724. }
  725. //
  726. // Parse up until the ICMPv6 header for the router advertisement.
  727. //
  728. Icmp6 = TeredoParseIpv6Headers(Buffer, Bytes);
  729. if (Icmp6 == NULL) {
  730. return FALSE;
  731. }
  732. if ((Icmp6->Type != ICMPv6_ROUTER_ADVERT) || (Icmp6->Code != 0)) {
  733. return FALSE;
  734. }
  735. Buffer = (PUCHAR) (Icmp6 + 1);
  736. Bytes -= (ULONG) (Buffer - Packet->Buffer.buf);
  737. //
  738. // Parse the rest of the router advertisement header.
  739. //
  740. if (Bytes < sizeof(NDRouterAdvertisement)) {
  741. return FALSE;
  742. }
  743. Buffer += sizeof(NDRouterAdvertisement);
  744. Bytes -= sizeof(NDRouterAdvertisement);
  745. while (Bytes != 0) {
  746. //
  747. // Parse TLV options.
  748. //
  749. if (Bytes < 8) {
  750. return FALSE;
  751. }
  752. Type = Buffer[0];
  753. Length = (Buffer[1] * 8);
  754. if ((Length == 0) || (Bytes < Length)) {
  755. return FALSE;
  756. }
  757. if (Type == ND_OPTION_PREFIX_INFORMATION) {
  758. if (Prefix != NULL) {
  759. //
  760. // There should only be one advertised prefix.
  761. //
  762. return FALSE;
  763. }
  764. if (Length != sizeof(NDOptionPrefixInformation)) {
  765. return FALSE;
  766. }
  767. Prefix = (NDOptionPrefixInformation *) Buffer;
  768. if (!TeredoValidAdvertisedPrefix(
  769. &(Prefix->Prefix), Prefix->PrefixLength)) {
  770. return FALSE;
  771. }
  772. }
  773. Buffer += Length;
  774. Bytes -= Length;
  775. }
  776. //
  777. // We have a valid router advertisement!
  778. // [Probe | Qualified] -> Qualified.
  779. //
  780. if (!IN6_ADDR_EQUAL(&(TeredoClient.Ipv6Prefix), &(Prefix->Prefix))) {
  781. //
  782. // We've either created a new IPv6 address or changed the existing one.
  783. // Transmit a multicast bubble as soon as the client qualifies.
  784. //
  785. TeredoClient.BubbleTicks =
  786. (TEREDO_MULTICAST_BUBBLE_TICKS != 0) ? 1 : 0;
  787. }
  788. TeredoClient.Ipv6Prefix = Prefix->Prefix;
  789. TeredoClient.RestartQualifiedTimer = TRUE;
  790. return TRUE;
  791. }
  792. BOOL
  793. TeredoClientReceiveData(
  794. IN PTEREDO_PACKET Packet
  795. )
  796. /*++
  797. Routine Description:
  798. Process the data packet received on the UDP socket.
  799. Arguments:
  800. Packet - Supplies the packet that was received.
  801. Return Value:
  802. TRUE if the packet should be forwarded to the stack, FALSE otherwise.
  803. --*/
  804. {
  805. PIP6_HDR Ipv6;
  806. IN_ADDR Address;
  807. USHORT Port;
  808. PTEREDO_PEER Peer;
  809. if (IN6_IS_ADDR_UNSPECIFIED(&(TeredoClient.Ipv6Prefix))) {
  810. //
  811. // The client hasn't been qualified ever!
  812. //
  813. return FALSE;
  814. }
  815. if (IN4_SOCKADDR_EQUAL(
  816. &(Packet->SocketAddress), &(TeredoClient.Io.ServerAddress))) {
  817. //
  818. // The client received the packet from the teredo server.
  819. //
  820. if (TeredoClient.State == TEREDO_STATE_QUALIFIED) {
  821. //
  822. // The NAT mapping has been refreshed.
  823. // NOTE: Since we don't acquire the API lock here, there is a small
  824. // chance that we have now transitioned to PROBE state. If so,
  825. // setting the flag to TRUE below will mistakenly cause us to
  826. // re-enter the qualified state. However that's quite harmless.
  827. //
  828. TeredoClient.RestartQualifiedTimer = TRUE;
  829. }
  830. return TRUE;
  831. }
  832. Ipv6 = (PIP6_HDR) Packet->Buffer.buf;
  833. if (!TeredoServicePrefix(&(Ipv6->ip6_src))) {
  834. //
  835. // The IPv6 source address should be a valid teredo address.
  836. //
  837. return FALSE;
  838. }
  839. TeredoParseAddress(&(Ipv6->ip6_src), &Address, &Port);
  840. if (!TeredoIpv4GlobalAddress((PUCHAR) &Address)) {
  841. //
  842. // The IPv4 source address should be global scope.
  843. //
  844. return FALSE;
  845. }
  846. if (!IN4_ADDR_EQUAL(Packet->SocketAddress.sin_addr, Address) ||
  847. (Packet->SocketAddress.sin_port != Port)) {
  848. //
  849. // Should have been constructed by the *right* teredo peer.
  850. //
  851. return FALSE;
  852. }
  853. Peer = TeredoFindOrCreatePeer(&(Ipv6->ip6_src));
  854. if (Peer != NULL) {
  855. Peer->LastReceive = TeredoClient.Time;
  856. TeredoTransmitBubble(Peer);
  857. TeredoDereferencePeer(Peer);
  858. }
  859. return TRUE;
  860. }
  861. VOID
  862. TeredoClientReadComplete(
  863. IN DWORD Error,
  864. IN ULONG Bytes,
  865. IN PTEREDO_PACKET Packet
  866. )
  867. /*++
  868. Routine Description:
  869. Process a read completion on the TUN device.
  870. --*/
  871. {
  872. PIP6_HDR Ipv6;
  873. IN_ADDR Address;
  874. USHORT Port;
  875. PTEREDO_PEER Peer;
  876. if ((Error != NO_ERROR) || (Bytes < sizeof(IP6_HDR))) {
  877. //
  878. // Attempt to post the read again.
  879. // If we are going offline, the packet is destroyed in the attempt.
  880. //
  881. TeredoPostRead(&(TeredoClient.Io), Packet);
  882. return;
  883. }
  884. TraceEnter("TeredoClientReadComplete");
  885. TeredoClient.Time = TeredoGetTime();
  886. Ipv6 = (PIP6_HDR) Packet->Buffer.buf;
  887. //
  888. // Default to tunneling the packet to the teredo server.
  889. //
  890. Packet->SocketAddress = TeredoClient.Io.ServerAddress;
  891. if (TeredoServicePrefix(&(Ipv6->ip6_dest))) {
  892. //
  893. // If the IPv6 destination address is a teredo address,
  894. // the IPv4 destination address should be global scope.
  895. //
  896. TeredoParseAddress(&(Ipv6->ip6_dest), &Address, &Port);
  897. if (!TeredoIpv4GlobalAddress((PUCHAR) &Address)) {
  898. goto Bail;
  899. }
  900. Peer = TeredoFindOrCreatePeer(&(Ipv6->ip6_dest));
  901. if (Peer != NULL) {
  902. if (TIME_GREATER(
  903. Peer->LastReceive,
  904. (TeredoClient.Time - TEREDO_REFRESH_INTERVAL))) {
  905. //
  906. // Tunnel the packet directly to the peer.
  907. //
  908. Packet->SocketAddress.sin_addr = Address;
  909. Packet->SocketAddress.sin_port = Port;
  910. Peer->LastTransmit = TeredoClient.Time;
  911. } else {
  912. TeredoTransmitBubble(Peer);
  913. }
  914. TeredoDereferencePeer(Peer);
  915. }
  916. }
  917. Packet->Type = TEREDO_PACKET_TRANSMIT;
  918. Packet->Buffer.len = Bytes;
  919. if (TeredoTransmitPacket(&(TeredoClient.Io), Packet) == NULL) {
  920. return;
  921. }
  922. Bail:
  923. //
  924. // We are done processing this packet.
  925. //
  926. TeredoClientTransmitComplete(NO_ERROR, Bytes, Packet);
  927. }
  928. VOID
  929. TeredoClientWriteComplete(
  930. IN DWORD Error,
  931. IN ULONG Bytes,
  932. IN PTEREDO_PACKET Packet
  933. )
  934. /*++
  935. Routine Description:
  936. Process a write completion on the TUN device.
  937. --*/
  938. {
  939. TraceEnter("TeredoClientWriteComplete");
  940. //
  941. // Attempt to post the receive again.
  942. // If we are going offline, the packet is destroyed in the attempt.
  943. //
  944. Packet->Type = TEREDO_PACKET_RECEIVE;
  945. Packet->Buffer.len = IPV6_TEREDOMTU;
  946. TeredoPostReceives(&(TeredoClient.Io), Packet);
  947. }
  948. VOID
  949. TeredoClientBubbleComplete(
  950. IN DWORD Error,
  951. IN ULONG Bytes,
  952. IN PTEREDO_PACKET Packet
  953. )
  954. /*++
  955. Routine Description:
  956. Process a bubble transmit completion on the UDP socket.
  957. --*/
  958. {
  959. PTEREDO_PEER Peer = Cast(
  960. CONTAINING_RECORD(Packet, TEREDO_PEER, Packet), TEREDO_PEER);
  961. TraceEnter("TeredoClientBubbleComplete");
  962. Peer->BubblePosted = FALSE;
  963. TeredoDereferencePeer(Peer);
  964. }
  965. VOID
  966. TeredoClientReceiveComplete(
  967. IN DWORD Error,
  968. IN ULONG Bytes,
  969. IN PTEREDO_PACKET Packet
  970. )
  971. /*++
  972. Routine Description:
  973. Process a receive completion on the UDP socket.
  974. --*/
  975. {
  976. PIP6_HDR Ipv6;
  977. BOOL Forward = FALSE;
  978. InterlockedDecrement(&(TeredoClient.Io.PostedReceives));
  979. if ((Error != NO_ERROR) || (Bytes < sizeof(IP6_HDR))) {
  980. //
  981. // Attempt to post the receive again.
  982. // If we are going offline, the packet is destroyed in the attempt.
  983. //
  984. TeredoPostReceives(&(TeredoClient.Io), Packet);
  985. return;
  986. }
  987. TraceEnter("TeredoClientReceiveComplete");
  988. TeredoClient.Time = TeredoGetTime();
  989. Ipv6 = (PIP6_HDR) Packet->Buffer.buf;
  990. if (IN6_IS_ADDR_LINKLOCAL(&(Ipv6->ip6_dest))) {
  991. //
  992. // This should be a valid router advertisement. Note that only router
  993. // advertisement packets are accepted on our link-local address.
  994. //
  995. Forward = TeredoReceiveRouterAdvertisement(Packet, Bytes);
  996. } else {
  997. //
  998. // This may be a packet of any other kind. Note that the IPv6 stack
  999. // drops router advertisements with a non link-local source address.
  1000. //
  1001. Forward = TeredoClientReceiveData(Packet);
  1002. }
  1003. if (Forward) {
  1004. Packet->Type = TEREDO_PACKET_WRITE;
  1005. Packet->Buffer.len = Bytes;
  1006. if (TeredoWritePacket(&(TeredoClient.Io), Packet) == NULL) {
  1007. return;
  1008. }
  1009. }
  1010. //
  1011. // We are done processing this packet.
  1012. //
  1013. TeredoClientWriteComplete(NO_ERROR, Bytes, Packet);
  1014. }
  1015. VOID
  1016. TeredoClientTransmitComplete(
  1017. IN DWORD Error,
  1018. IN ULONG Bytes,
  1019. IN PTEREDO_PACKET Packet
  1020. )
  1021. /*++
  1022. Routine Description:
  1023. Process a transmit completion on the UDP socket.
  1024. --*/
  1025. {
  1026. TraceEnter("TeredoClientTransmitComplete");
  1027. //
  1028. // Attempt to post the read again.
  1029. // If we are going offline, the packet is destroyed in the attempt.
  1030. //
  1031. Packet->Type = TEREDO_PACKET_READ;
  1032. Packet->Buffer.len = IPV6_TEREDOMTU;
  1033. TeredoPostRead(&(TeredoClient.Io), Packet);
  1034. }
  1035. VOID
  1036. TeredoClientMulticastComplete(
  1037. IN DWORD Error,
  1038. IN ULONG Bytes,
  1039. IN PTEREDO_PACKET Packet
  1040. )
  1041. /*++
  1042. Routine Description:
  1043. Process a multicast bubble transmit completion on the UDP socket.
  1044. --*/
  1045. {
  1046. ASSERT(Packet == &(TeredoClient.Packet));
  1047. TraceEnter("TeredoClientMulticastComplete");
  1048. TeredoClient.BubblePosted = FALSE;
  1049. TeredoDereferenceClient();
  1050. }