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.

1057 lines
24 KiB

  1. /*++
  2. Copyright (c) 2001-2002 Microsoft Corporation
  3. Module Name:
  4. io.c
  5. Abstract:
  6. This module contains teredo I/O management functions.
  7. Socket management, overlapped completion indication, and buffer management
  8. ideas were originally implemented for tftpd by JeffV.
  9. Author:
  10. Mohit Talwar (mohitt) Wed Oct 24 14:05:36 2001
  11. Environment:
  12. User mode only.
  13. --*/
  14. #include "precomp.h"
  15. #pragma hdrstop
  16. WCHAR TeredoTunnelDeviceName[] = L"\\\\.\\\\Tun0";
  17. DWORD
  18. GetPreferredSourceAddress(
  19. IN PSOCKADDR_IN Destination,
  20. OUT PSOCKADDR_IN Source
  21. )
  22. {
  23. int BytesReturned;
  24. if (WSAIoctl(
  25. g_sIPv4Socket, SIO_ROUTING_INTERFACE_QUERY,
  26. Destination, sizeof(SOCKADDR_IN), Source, sizeof(SOCKADDR_IN),
  27. &BytesReturned, NULL, NULL) == SOCKET_ERROR) {
  28. return WSAGetLastError();
  29. }
  30. //
  31. // When the source is local, the node is configured as the teredo server.
  32. // Hence it needs to explicitly specify the port to bind to. Assign here!
  33. //
  34. if ((Source->sin_addr.s_addr == Destination->sin_addr.s_addr) ||
  35. (Source->sin_addr.s_addr == htonl(INADDR_LOOPBACK))) {
  36. *Source = *Destination;
  37. }
  38. return NO_ERROR;
  39. }
  40. __inline
  41. DWORD
  42. TeredoResolveServer(
  43. IN PTEREDO_IO TeredoIo
  44. )
  45. /*++
  46. Routine Description:
  47. Resolve the teredo IPv4 server address and UDP service port.
  48. Arguments:
  49. TeredoIo - Supplies the I/O state.
  50. Return Value:
  51. NO_ERROR or failure code.
  52. --*/
  53. {
  54. PADDRINFOW Addresses;
  55. DWORD Error;
  56. //
  57. // Resolve the teredo server name.
  58. //
  59. Error = GetAddrInfoW(TeredoServerName, NULL, NULL, &Addresses);
  60. if (Error == NO_ERROR) {
  61. Error = ERROR_INCORRECT_ADDRESS;
  62. if (Addresses->ai_family == AF_INET) {
  63. TeredoIo->ServerAddress.sin_addr =
  64. ((PSOCKADDR_IN) Addresses->ai_addr)->sin_addr;
  65. TeredoIo->ServerAddress.sin_port = TEREDO_PORT;
  66. Error = NO_ERROR;
  67. } else if (Addresses->ai_family == AF_INET6) {
  68. PIN6_ADDR Ipv6Address;
  69. IN_ADDR Ipv4Address;
  70. USHORT Port;
  71. //
  72. // Extract server's IPv4 address and port from the IPv6 address.
  73. //
  74. Ipv6Address = &(((PSOCKADDR_IN6) Addresses->ai_addr)->sin6_addr);
  75. if (TeredoServicePrefix(Ipv6Address)) {
  76. TeredoParseAddress(Ipv6Address, &Ipv4Address, &Port);
  77. if (Port == TEREDO_PORT) {
  78. TeredoIo->ServerAddress.sin_addr = Ipv4Address;
  79. TeredoIo->ServerAddress.sin_port = Port;
  80. Error = NO_ERROR;
  81. }
  82. }
  83. }
  84. FreeAddrInfoW(Addresses);
  85. }
  86. return Error;
  87. }
  88. PTEREDO_PACKET
  89. TeredoCreatePacket(
  90. IN PTEREDO_IO TeredoIo
  91. )
  92. /*++
  93. Routine Description:
  94. Creates a teredo packet.
  95. Arguments:
  96. TeredoIo - Supplies the I/O state.
  97. Return Value:
  98. Returns the created packet.
  99. --*/
  100. {
  101. PTEREDO_PACKET Packet = (PTEREDO_PACKET) HeapAlloc(
  102. TeredoIo->PacketHeap, 0, sizeof(TEREDO_PACKET) + IPV6_TEREDOMTU);
  103. if (Packet == NULL) {
  104. return NULL;
  105. }
  106. TeredoInitializePacket(Packet);
  107. Packet->Buffer.len = IPV6_TEREDOMTU;
  108. //
  109. // Obtain a reference on the teredo object for each outstanding packet.
  110. //
  111. (*TeredoIo->Reference)();
  112. return Packet;
  113. }
  114. VOID
  115. TeredoDestroyPacket(
  116. IN PTEREDO_IO TeredoIo,
  117. IN PTEREDO_PACKET Packet
  118. )
  119. /*++
  120. Routine Description:
  121. Destroys a teredo packet.
  122. Arguments:
  123. TeredoIo - Supplies the I/O state.
  124. Packet - Supplies the packet to destroy.
  125. Return Value:
  126. None.
  127. --*/
  128. {
  129. ASSERT(Packet->Type != TEREDO_PACKET_BUBBLE);
  130. ASSERT(Packet->Type != TEREDO_PACKET_MULTICAST);
  131. HeapFree(TeredoIo->PacketHeap, 0, Packet);
  132. (*TeredoIo->Dereference)();
  133. }
  134. ULONG
  135. TeredoPostReceives(
  136. IN PTEREDO_IO TeredoIo,
  137. IN PTEREDO_PACKET Packet OPTIONAL
  138. )
  139. /*++
  140. Routine Description:
  141. Post an asynchronous receive request on the UDP socket.
  142. NOTE: The supplied packet (if any) is destroyed if there are already
  143. enough (TEREDO_HIGH_WATER_MARK) receives posted on the UDP socket.
  144. Arguments:
  145. TeredoIo - Supplies the I/O state.
  146. Packet - Supplies the packet to reuse, or NULL.
  147. Return Value:
  148. Returns the number of receives posted on the UDP socket.
  149. --*/
  150. {
  151. ULONG Count = 0, PostedReceives = TeredoIo->PostedReceives;
  152. DWORD Error, Bytes;
  153. //
  154. // Attempt to post as many receives as required to...
  155. // 1. - either - have high water-mark number of posted receives.
  156. // 2. - or - satisfy the current burst of packets.
  157. //
  158. while (PostedReceives < TEREDO_HIGH_WATER_MARK) {
  159. //
  160. // Allocate the Packet if we're not reusing one.
  161. //
  162. if (Packet == NULL) {
  163. Packet = TeredoCreatePacket(TeredoIo);
  164. if (Packet == NULL) {
  165. return PostedReceives;
  166. }
  167. }
  168. Packet->Type = TEREDO_PACKET_RECEIVE;
  169. ZeroMemory((PUCHAR) &(Packet->Overlapped), sizeof(OVERLAPPED));
  170. Error = WSARecvFrom(
  171. TeredoIo->Socket,
  172. &(Packet->Buffer),
  173. 1,
  174. &Bytes,
  175. &(Packet->Flags),
  176. (PSOCKADDR) &(Packet->SocketAddress),
  177. &(Packet->SocketAddressLength),
  178. &(Packet->Overlapped),
  179. NULL);
  180. if (Error == SOCKET_ERROR) {
  181. Error = WSAGetLastError();
  182. }
  183. switch (Error) {
  184. case NO_ERROR:
  185. //
  186. // The completion routine will have already been scheduled.
  187. //
  188. PostedReceives =
  189. InterlockedIncrement(&(TeredoIo->PostedReceives));
  190. if (Count++ > TEREDO_LOW_WATER_MARK) {
  191. //
  192. // Enough already!
  193. //
  194. return PostedReceives;
  195. }
  196. Packet = NULL;
  197. continue;
  198. case WSA_IO_PENDING:
  199. //
  200. // The overlapped operation has been successfully initiated.
  201. // Completion will be indicated at a later time.
  202. //
  203. PostedReceives =
  204. InterlockedIncrement(&(TeredoIo->PostedReceives));
  205. return PostedReceives;
  206. case WSAECONNRESET:
  207. //
  208. // A previous send operation resulted in an ICMP "Port Unreachable"
  209. // message. But why let that stop us? Post the same packet again.
  210. //
  211. continue;
  212. default:
  213. //
  214. // The overlapped operation was not successfully initiated.
  215. // No completion indication will occur.
  216. //
  217. goto Bail;
  218. }
  219. }
  220. Bail:
  221. if (Packet != NULL) {
  222. TeredoDestroyPacket(TeredoIo, Packet);
  223. }
  224. return PostedReceives;
  225. }
  226. VOID
  227. CALLBACK
  228. TeredoReceiveNotification(
  229. IN PVOID Parameter,
  230. IN BOOLEAN TimerOrWaitFired
  231. )
  232. /*++
  233. Routine Description:
  234. Callback for when there are pending read notifications on the UDP socket.
  235. We attempt to post more packets.
  236. Arguments:
  237. Parameter - Supplies the I/O state.
  238. TimerOrWaitFired - Ignored.
  239. Return Value:
  240. None.
  241. --*/
  242. {
  243. ULONG Old, New;
  244. PTEREDO_IO TeredoIo = Cast(Parameter, TEREDO_IO);
  245. New = TeredoIo->PostedReceives;
  246. while(New < TEREDO_LOW_WATER_MARK) {
  247. //
  248. // If this fails, the event triggering this callback will stop
  249. // signalling due to a lack of a successful WSARecvFrom. This will
  250. // likely occur during low-memory or stress conditions. When the
  251. // system returns to normal, the low water-mark packets will be
  252. // reposted, thus re-enabling the event which triggers this callback.
  253. //
  254. Old = New;
  255. New = TeredoPostReceives(TeredoIo, NULL);
  256. if (New == Old) {
  257. //
  258. // There is no change in the number of posted receive packets.
  259. //
  260. return;
  261. }
  262. }
  263. }
  264. PTEREDO_PACKET
  265. TeredoTransmitPacket(
  266. IN PTEREDO_IO TeredoIo,
  267. IN PTEREDO_PACKET Packet
  268. )
  269. /*++
  270. Routine Description:
  271. Post an asynchronous transmit request on the UDP socket.
  272. Arguments:
  273. TeredoIo - Supplies the I/O state.
  274. Packet - Supplies the packet to transmit.
  275. Return Value:
  276. Returns the supplied packet if the transmit completed or failed;
  277. NULL if the transmit will complete asynchronously.
  278. --*/
  279. {
  280. DWORD Error, Bytes;
  281. ASSERT((Packet->Type == TEREDO_PACKET_BUBBLE) ||
  282. (Packet->Type == TEREDO_PACKET_BOUNCE) ||
  283. (Packet->Type == TEREDO_PACKET_TRANSMIT) ||
  284. (Packet->Type == TEREDO_PACKET_MULTICAST));
  285. //
  286. // Try sending it non-blocking.
  287. //
  288. Error = WSASendTo(
  289. TeredoIo->Socket, &(Packet->Buffer), 1, &Bytes, Packet->Flags,
  290. (PSOCKADDR) &(Packet->SocketAddress), Packet->SocketAddressLength,
  291. NULL, NULL);
  292. if ((Error != SOCKET_ERROR) || (WSAGetLastError() != WSAEWOULDBLOCK)) {
  293. return Packet;
  294. }
  295. //
  296. // WSASendTo threatens to block, so we send it overlapped.
  297. //
  298. ZeroMemory((PUCHAR) &(Packet->Overlapped), sizeof(OVERLAPPED));
  299. Error = WSASendTo(
  300. TeredoIo->Socket, &(Packet->Buffer), 1, &Bytes, Packet->Flags,
  301. (PSOCKADDR) &(Packet->SocketAddress), Packet->SocketAddressLength,
  302. &(Packet->Overlapped), NULL);
  303. if ((Error != SOCKET_ERROR) || (WSAGetLastError() != WSA_IO_PENDING)) {
  304. return Packet;
  305. }
  306. //
  307. // The overlapped operation has been successfully initiated.
  308. // Completion will be indicated at a later time.
  309. //
  310. return NULL;
  311. }
  312. VOID
  313. TeredoDestroySocket(
  314. IN PTEREDO_IO TeredoIo
  315. )
  316. /*++
  317. Routine Description:
  318. Close the UDP socket.
  319. Arguments:
  320. TeredoIo - Supplies the I/O state.
  321. Return Value:
  322. None.
  323. --*/
  324. {
  325. if (TeredoIo->ReceiveEventWait != NULL) {
  326. UnregisterWait(TeredoIo->ReceiveEventWait);
  327. TeredoIo->ReceiveEventWait = NULL;
  328. }
  329. if (TeredoIo->ReceiveEvent != NULL) {
  330. CloseHandle(TeredoIo->ReceiveEvent);
  331. TeredoIo->ReceiveEvent = NULL;
  332. }
  333. if (TeredoIo->Socket != INVALID_SOCKET) {
  334. //
  335. // Close the socket. This will disable the FD_READ event select,
  336. // as well as cancel all pending overlapped operations.
  337. //
  338. closesocket(TeredoIo->Socket);
  339. TeredoIo->Socket = INVALID_SOCKET;
  340. }
  341. }
  342. DWORD
  343. TeredoCreateSocket(
  344. IN PTEREDO_IO TeredoIo
  345. )
  346. /*++
  347. Routine Description:
  348. Open the UDP socket for receives and transmits.
  349. Arguments:
  350. TeredoIo - Supplies the I/O state.
  351. Return Value:
  352. NO_ERROR or failure code.
  353. --*/
  354. {
  355. DWORD Error;
  356. struct ip_mreq Multicast;
  357. BOOL Loopback;
  358. //
  359. // Create the socket.
  360. //
  361. TeredoIo->Socket = WSASocket(
  362. AF_INET, SOCK_DGRAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);
  363. if (TeredoIo->Socket == INVALID_SOCKET) {
  364. return GetLastError();
  365. }
  366. //
  367. // Bind the socket on the correct address and port.
  368. //
  369. if (bind(
  370. TeredoIo->Socket,
  371. (PSOCKADDR) &(TeredoIo->SourceAddress),
  372. sizeof(SOCKADDR_IN)) == SOCKET_ERROR) {
  373. goto Bail;
  374. }
  375. //
  376. // Register for completion callbacks on the socket.
  377. //
  378. if (!BindIoCompletionCallback(
  379. (HANDLE) TeredoIo->Socket, TeredoIo->IoCompletionCallback, 0)) {
  380. goto Bail;
  381. }
  382. //
  383. // Select the socket for read notifications so we know when to post
  384. // more packets. This also sets the socket to nonblocking mode.
  385. //
  386. TeredoIo->ReceiveEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  387. if (TeredoIo->ReceiveEvent == NULL) {
  388. goto Bail;
  389. }
  390. if (WSAEventSelect(
  391. TeredoIo->Socket,
  392. TeredoIo->ReceiveEvent,
  393. FD_READ) == SOCKET_ERROR) {
  394. goto Bail;
  395. }
  396. if (!RegisterWaitForSingleObject(
  397. &(TeredoIo->ReceiveEventWait),
  398. TeredoIo->ReceiveEvent,
  399. TeredoReceiveNotification,
  400. (PVOID) TeredoIo,
  401. INFINITE,
  402. 0)) {
  403. goto Bail;
  404. }
  405. //
  406. // Prepost low water-mark number of receive Packets. If the FD_READ event
  407. // signals on the socket before we're done, we'll exceed the low water-mark
  408. // here but that's really quite harmless.
  409. //
  410. SetEvent(TeredoIo->ReceiveEvent);
  411. //
  412. // See if there is a multicast group to join.
  413. //
  414. if (IN4_MULTICAST(TeredoIo->Group)) {
  415. //
  416. // Default TTL of multicast packets is 1, so don't bother setting it.
  417. // Set loopback to ignore self generated multicast packets.
  418. // Failure is not fatal!
  419. //
  420. Loopback = FALSE;
  421. (VOID) setsockopt(
  422. TeredoIo->Socket,
  423. IPPROTO_IP,
  424. IP_MULTICAST_LOOP,
  425. (const CHAR *) &Loopback,
  426. sizeof(BOOL));
  427. //
  428. // Join the multicast group on the native interface.
  429. // Failure is not fatal!
  430. //
  431. Multicast.imr_multiaddr = TeredoIo->Group;
  432. Multicast.imr_interface = TeredoIo->SourceAddress.sin_addr;
  433. (VOID) setsockopt(
  434. TeredoIo->Socket,
  435. IPPROTO_IP,
  436. IP_ADD_MEMBERSHIP,
  437. (const CHAR *) &Multicast,
  438. sizeof(struct ip_mreq));
  439. }
  440. return NO_ERROR;
  441. Bail:
  442. Error = GetLastError();
  443. TeredoDestroySocket(TeredoIo);
  444. return Error;
  445. }
  446. BOOL
  447. TeredoPostRead(
  448. IN PTEREDO_IO TeredoIo,
  449. IN PTEREDO_PACKET Packet OPTIONAL
  450. )
  451. /*++
  452. Routine Description:
  453. Post an asynchronous read request on the TUN interface device.
  454. Arguments:
  455. TeredoIo - Supplies the I/O state.
  456. Packet - Supplies the packet to reuse, or NULL.
  457. Return Value:
  458. TRUE if a read was successfully posted, FALSE otherwise.
  459. --*/
  460. {
  461. BOOL Success;
  462. //
  463. // Allocate the Packet if we're not reusing one.
  464. //
  465. if (Packet == NULL) {
  466. Packet = TeredoCreatePacket(TeredoIo);
  467. if (Packet == NULL) {
  468. return FALSE;
  469. }
  470. }
  471. Packet->Type = TEREDO_PACKET_READ;
  472. ZeroMemory((PUCHAR) &(Packet->Overlapped), sizeof(OVERLAPPED));
  473. Success = ReadFile(
  474. TeredoIo->TunnelDevice,
  475. Packet->Buffer.buf,
  476. Packet->Buffer.len,
  477. NULL,
  478. &(Packet->Overlapped));
  479. if (Success || (GetLastError() == ERROR_IO_PENDING)) {
  480. //
  481. // On success, the completion routine will have already been scheduled.
  482. //
  483. return TRUE;
  484. }
  485. TeredoDestroyPacket(TeredoIo, Packet);
  486. return FALSE;
  487. }
  488. PTEREDO_PACKET
  489. TeredoWritePacket(
  490. IN PTEREDO_IO TeredoIo,
  491. IN PTEREDO_PACKET Packet
  492. )
  493. /*++
  494. Routine Description:
  495. Post an asynchronous write request on the TUN interface device.
  496. Arguments:
  497. TeredoIo - Supplies the I/O state.
  498. Packet - Supplies the packet to write.
  499. Return Value:
  500. Returns the supplied packet if the write failed;
  501. NULL if the write will complete asynchronously.
  502. --*/
  503. {
  504. BOOL Success;
  505. ASSERT(Packet->Type == TEREDO_PACKET_WRITE);
  506. ZeroMemory((PUCHAR) &(Packet->Overlapped), sizeof(OVERLAPPED));
  507. Success = WriteFile(
  508. TeredoIo->TunnelDevice,
  509. Packet->Buffer.buf,
  510. Packet->Buffer.len,
  511. NULL,
  512. &(Packet->Overlapped));
  513. if (Success || (GetLastError() == ERROR_IO_PENDING)) {
  514. //
  515. // On success, the completion routine will have already been scheduled.
  516. //
  517. return NULL;
  518. }
  519. return Packet;
  520. }
  521. VOID
  522. TeredoCloseDevice(
  523. IN PTEREDO_IO TeredoIo
  524. )
  525. /*++
  526. Routine Description:
  527. Close the TUN interface device.
  528. Arguments:
  529. TeredoIo - Supplies the I/O state.
  530. Return Value:
  531. None.
  532. --*/
  533. {
  534. //
  535. // Close the device. This will cancel all pending overlapped operations.
  536. //
  537. if (TeredoIo->TunnelDevice != INVALID_HANDLE_VALUE) {
  538. CloseHandle(TeredoIo->TunnelDevice);
  539. TeredoIo->TunnelDevice = INVALID_HANDLE_VALUE;
  540. wcscpy(TeredoIo->TunnelInterface, L"");
  541. }
  542. }
  543. DWORD
  544. TeredoOpenDevice(
  545. IN PTEREDO_IO TeredoIo
  546. )
  547. /*++
  548. Routine Description:
  549. Open the TUN interface device for reads and writes.
  550. Arguments:
  551. None.
  552. Return Value:
  553. NO_ERROR or failure code.
  554. --*/
  555. {
  556. UCHAR Buffer[sizeof(USHORT) + sizeof(WCHAR) * MAX_ADAPTER_NAME_LENGTH];
  557. USHORT AdapterNameLength;
  558. PWCHAR AdapterGuid;
  559. DWORD AdapterGuidLength, BytesReturned, Error;
  560. ULONG i;
  561. TeredoIo->TunnelDevice = CreateFile(
  562. TeredoTunnelDeviceName,
  563. GENERIC_READ | GENERIC_WRITE,
  564. 0,
  565. NULL,
  566. OPEN_EXISTING,
  567. FILE_FLAG_OVERLAPPED,
  568. NULL);
  569. if (TeredoIo->TunnelDevice == INVALID_HANDLE_VALUE) {
  570. return GetLastError();
  571. }
  572. if (!DeviceIoControl(
  573. TeredoIo->TunnelDevice,
  574. IOCTL_TUN_GET_MINIPORT_NAME,
  575. NULL,
  576. 0,
  577. Buffer,
  578. sizeof(Buffer),
  579. &BytesReturned,
  580. NULL)) {
  581. Error = GetLastError();
  582. goto Bail;
  583. }
  584. if (BytesReturned < sizeof(USHORT)) {
  585. Error = ERROR_INVALID_NAME;
  586. goto Bail;
  587. }
  588. AdapterNameLength = *((PUSHORT) Buffer);
  589. if ((AdapterNameLength < wcslen(DEVICE_PREFIX) * sizeof(WCHAR)) ||
  590. (AdapterNameLength > (MAX_ADAPTER_NAME_LENGTH - 1) * sizeof(WCHAR))) {
  591. Error = ERROR_INVALID_NAME;
  592. goto Bail;
  593. }
  594. AdapterGuidLength =
  595. AdapterNameLength - (USHORT)(wcslen(DEVICE_PREFIX) * sizeof(WCHAR));
  596. AdapterGuid = (PWCHAR)
  597. (Buffer + sizeof(USHORT) + wcslen(DEVICE_PREFIX) * sizeof(WCHAR));
  598. RtlCopyMemory(
  599. TeredoClient.Io.TunnelInterface, AdapterGuid, AdapterGuidLength);
  600. TeredoClient.Io.TunnelInterface[AdapterGuidLength / sizeof(WCHAR)] = L'\0';
  601. Trace1(ANY, L"TeredoAdapter: %s", TeredoClient.Io.TunnelInterface);
  602. //
  603. // Register for completion callbacks on the tun device.
  604. //
  605. if (!BindIoCompletionCallback(
  606. TeredoIo->TunnelDevice, TeredoIo->IoCompletionCallback, 0)) {
  607. Error = GetLastError();
  608. goto Bail;
  609. }
  610. //
  611. // Post a fixed number of reads on the device.
  612. //
  613. for (i = 0; i < TEREDO_LOW_WATER_MARK; i++) {
  614. if (!TeredoPostRead(TeredoIo, NULL)) {
  615. break;
  616. }
  617. }
  618. if (i != 0) {
  619. return NO_ERROR;
  620. }
  621. Error = ERROR_READ_FAULT;
  622. //
  623. // We couldn't post a single read on the device. What good is it?
  624. //
  625. Bail:
  626. TeredoCloseDevice(TeredoIo);
  627. return Error;
  628. }
  629. VOID
  630. TeredoStopIo(
  631. IN PTEREDO_IO TeredoIo
  632. )
  633. /*++
  634. Routine Description:
  635. Stop I/O processing.
  636. Arguments:
  637. TeredoIo - Supplies the I/O state.
  638. Return Value:
  639. None.
  640. --*/
  641. {
  642. if (TeredoIo->TunnelDevice != INVALID_HANDLE_VALUE) {
  643. TeredoCloseDevice(TeredoIo);
  644. }
  645. if (TeredoIo->Socket != INVALID_SOCKET) {
  646. TeredoDestroySocket(TeredoIo);
  647. }
  648. TeredoIo->ServerAddress.sin_port = 0;
  649. TeredoIo->ServerAddress.sin_addr.s_addr = htonl(INADDR_ANY);
  650. TeredoIo->SourceAddress.sin_addr.s_addr = htonl(INADDR_ANY);
  651. }
  652. DWORD
  653. TeredoStartIo(
  654. IN PTEREDO_IO TeredoIo
  655. )
  656. /*++
  657. Routine Description:
  658. Start I/O processing.
  659. Arguments:
  660. TeredoIo - Supplies the I/O state.
  661. Return Value:
  662. NO_ERROR or failure code.
  663. --*/
  664. {
  665. DWORD Error;
  666. //
  667. // Resolve the teredo server name and service name.
  668. //
  669. Error = TeredoResolveServer(TeredoIo);
  670. if (Error != NO_ERROR) {
  671. Trace1(ERR, _T("TeredoResolveServer: %u"), Error);
  672. return Error;
  673. }
  674. //
  675. // Get the preferred source address to the teredo server.
  676. //
  677. Error = GetPreferredSourceAddress(
  678. &(TeredoIo->ServerAddress), &(TeredoIo->SourceAddress));
  679. if (Error != NO_ERROR) {
  680. Trace1(ERR, _T("GetPreferredSourceAddress: %u"), Error);
  681. goto Bail;
  682. }
  683. //
  684. // Create the UDP Socket.
  685. //
  686. Error = TeredoCreateSocket(TeredoIo);
  687. if (Error != NO_ERROR) {
  688. Trace1(ERR, _T("TeredoCreateSocket: %u"), Error);
  689. goto Bail;
  690. }
  691. //
  692. // Open the TunnelDevice.
  693. //
  694. Error = TeredoOpenDevice(TeredoIo);
  695. if (Error != NO_ERROR) {
  696. Trace1(ERR, _T("TeredoOpenDevice: %u"), Error);
  697. goto Bail;
  698. }
  699. return NO_ERROR;
  700. Bail:
  701. TeredoStopIo(TeredoIo);
  702. return Error;
  703. }
  704. DWORD
  705. TeredoRefreshSocket(
  706. IN PTEREDO_IO TeredoIo
  707. )
  708. /*++
  709. Routine Description:
  710. Refresh the I/O state upon deletion of SourceAddress.
  711. Arguments:
  712. TeredoIo - Supplies the I/O state.
  713. Return Value:
  714. NO_ERROR if the I/O state is successfully refreshed, o/w failure code.
  715. The caller is responsible for cleaning up the I/O state upon failure.
  716. --*/
  717. {
  718. DWORD Error;
  719. SOCKADDR_IN Old = TeredoIo->SourceAddress;
  720. //
  721. // Let's re-resolve the teredo server address and port.
  722. // Refresh might have been triggered by a change in server/service name.
  723. //
  724. Error = TeredoResolveServer(TeredoIo);
  725. if (Error != NO_ERROR) {
  726. return Error;
  727. }
  728. //
  729. // Get the preferred source address to the teredo server.
  730. //
  731. Error = GetPreferredSourceAddress(
  732. &(TeredoIo->ServerAddress), &(TeredoIo->SourceAddress));
  733. if (Error != NO_ERROR) {
  734. return Error;
  735. }
  736. if (IN4_SOCKADDR_EQUAL(&(TeredoIo->SourceAddress), &Old)) {
  737. //
  738. // No change to the bound address and port. Whew!
  739. //
  740. return NO_ERROR;
  741. }
  742. //
  743. // Destroy the old UDP socket.
  744. //
  745. TeredoDestroySocket(TeredoIo);
  746. //
  747. // Create a new UDP socket, bound to the new address and port.
  748. //
  749. Error = TeredoCreateSocket(TeredoIo);
  750. if (Error != NO_ERROR) {
  751. return Error;
  752. }
  753. return NO_ERROR;
  754. }
  755. DWORD
  756. TeredoInitializeIo(
  757. IN PTEREDO_IO TeredoIo,
  758. IN IN_ADDR Group,
  759. IN PTEREDO_REFERENCE Reference,
  760. IN PTEREDO_DEREFERENCE Dereference,
  761. IN LPOVERLAPPED_COMPLETION_ROUTINE IoCompletionCallback
  762. )
  763. /*++
  764. Routine Description:
  765. Initialize the I/O state.
  766. Arguments:
  767. TeredoIo - Supplies the I/O state.
  768. Group - Supplies the multicast group to join (or INADDR_ANY).
  769. Return Value:
  770. NO_ERROR or failure code.
  771. --*/
  772. {
  773. #if DBG
  774. TeredoIo->Signature = TEREDO_IO_SIGNATURE;
  775. #endif // DBG
  776. TeredoIo->PostedReceives = 0;
  777. TeredoIo->ReceiveEvent = TeredoIo->ReceiveEventWait = NULL;
  778. TeredoIo->Group = Group;
  779. ZeroMemory(&(TeredoIo->ServerAddress), sizeof(SOCKADDR_IN));
  780. TeredoIo->ServerAddress.sin_family = AF_INET;
  781. ZeroMemory(&(TeredoIo->SourceAddress), sizeof(SOCKADDR_IN));
  782. TeredoIo->SourceAddress.sin_family = AF_INET;
  783. TeredoIo->Socket = INVALID_SOCKET;
  784. TeredoIo->TunnelDevice = INVALID_HANDLE_VALUE;
  785. wcscpy(TeredoIo->TunnelInterface, L"");
  786. TeredoIo->Reference = Reference;
  787. TeredoIo->Dereference = Dereference;
  788. TeredoIo->IoCompletionCallback = IoCompletionCallback;
  789. TeredoIo->PacketHeap = HeapCreate(0, 0, 0);
  790. if (TeredoIo->PacketHeap == NULL) {
  791. return GetLastError();
  792. }
  793. return NO_ERROR;
  794. }
  795. VOID
  796. TeredoCleanupIo(
  797. IN PTEREDO_IO TeredoIo
  798. )
  799. /*++
  800. Routine Description:
  801. Cleanup the I/O state.
  802. Arguments:
  803. TeredoIo - Supplies the I/O state.
  804. Return Value:
  805. None.
  806. --*/
  807. {
  808. HeapDestroy(TeredoIo->PacketHeap);
  809. TeredoIo->PacketHeap = NULL;
  810. }