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.

1019 lines
22 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. struct addrinfo *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. freeaddrinfo(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;
  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. NULL,
  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. DWORD Error;
  557. ULONG i;
  558. TeredoIo->TunnelDevice = CreateFile(
  559. TeredoTunnelDeviceName,
  560. GENERIC_READ | GENERIC_WRITE,
  561. 0,
  562. NULL,
  563. OPEN_EXISTING,
  564. FILE_FLAG_OVERLAPPED,
  565. NULL);
  566. if (TeredoIo->TunnelDevice == INVALID_HANDLE_VALUE) {
  567. return GetLastError();
  568. }
  569. //
  570. // Register for completion callbacks on the tun device.
  571. //
  572. if (!BindIoCompletionCallback(
  573. TeredoIo->TunnelDevice, TeredoIo->IoCompletionCallback, 0)) {
  574. Error = GetLastError();
  575. goto Bail;
  576. }
  577. //
  578. // Post a fixed number of reads on the device.
  579. //
  580. for (i = 0; i < TEREDO_LOW_WATER_MARK; i++) {
  581. if (!TeredoPostRead(TeredoIo, NULL)) {
  582. break;
  583. }
  584. }
  585. if (i != 0) {
  586. return NO_ERROR;
  587. }
  588. Error = ERROR_READ_FAULT;
  589. //
  590. // We couldn't post a single read on the device. What good is it?
  591. //
  592. Bail:
  593. TeredoCloseDevice(TeredoIo);
  594. return Error;
  595. }
  596. VOID
  597. TeredoStopIo(
  598. IN PTEREDO_IO TeredoIo
  599. )
  600. /*++
  601. Routine Description:
  602. Stop I/O processing.
  603. Arguments:
  604. TeredoIo - Supplies the I/O state.
  605. Return Value:
  606. None.
  607. --*/
  608. {
  609. if (TeredoIo->TunnelDevice != INVALID_HANDLE_VALUE) {
  610. TeredoCloseDevice(TeredoIo);
  611. }
  612. if (TeredoIo->Socket != INVALID_SOCKET) {
  613. TeredoDestroySocket(TeredoIo);
  614. }
  615. TeredoIo->ServerAddress.sin_port = 0;
  616. TeredoIo->ServerAddress.sin_addr.s_addr = htonl(INADDR_ANY);
  617. TeredoIo->SourceAddress.sin_addr.s_addr = htonl(INADDR_ANY);
  618. }
  619. DWORD
  620. TeredoStartIo(
  621. IN PTEREDO_IO TeredoIo
  622. )
  623. /*++
  624. Routine Description:
  625. Start I/O processing.
  626. Arguments:
  627. TeredoIo - Supplies the I/O state.
  628. Return Value:
  629. NO_ERROR or failure code.
  630. --*/
  631. {
  632. DWORD Error;
  633. //
  634. // Resolve the teredo server name and service name.
  635. //
  636. Error = TeredoResolveServer(TeredoIo);
  637. if (Error != NO_ERROR) {
  638. Trace1(ERR, _T("TeredoResolveServer: %u"), Error);
  639. return Error;
  640. }
  641. //
  642. // Get the preferred source address to the teredo server.
  643. //
  644. Error = GetPreferredSourceAddress(
  645. &(TeredoIo->ServerAddress), &(TeredoIo->SourceAddress));
  646. if (Error != NO_ERROR) {
  647. Trace1(ERR, _T("GetPreferredSourceAddress: %u"), Error);
  648. goto Bail;
  649. }
  650. //
  651. // Create the UDP Socket.
  652. //
  653. Error = TeredoCreateSocket(TeredoIo);
  654. if (Error != NO_ERROR) {
  655. Trace1(ERR, _T("TeredoCreateSocket: %u"), Error);
  656. goto Bail;
  657. }
  658. //
  659. // Open the TunnelDevice.
  660. //
  661. Error = TeredoOpenDevice(TeredoIo);
  662. if (Error != NO_ERROR) {
  663. Trace1(ERR, _T("TeredoOpenDevice: %u"), Error);
  664. goto Bail;
  665. }
  666. return NO_ERROR;
  667. Bail:
  668. TeredoStopIo(TeredoIo);
  669. return Error;
  670. }
  671. DWORD
  672. TeredoRefreshSocket(
  673. IN PTEREDO_IO TeredoIo
  674. )
  675. /*++
  676. Routine Description:
  677. Refresh the I/O state upon deletion of SourceAddress.
  678. Arguments:
  679. TeredoIo - Supplies the I/O state.
  680. Return Value:
  681. NO_ERROR if the I/O state is successfully refreshed, o/w failure code.
  682. The caller is responsible for cleaning up the I/O state upon failure.
  683. --*/
  684. {
  685. DWORD Error;
  686. SOCKADDR_IN Old = TeredoIo->SourceAddress;
  687. //
  688. // Let's re-resolve the teredo server address and port.
  689. // Refresh might have been triggered by a change in server/service name.
  690. //
  691. Error = TeredoResolveServer(TeredoIo);
  692. if (Error != NO_ERROR) {
  693. return Error;
  694. }
  695. //
  696. // Get the preferred source address to the teredo server.
  697. //
  698. Error = GetPreferredSourceAddress(
  699. &(TeredoIo->ServerAddress), &(TeredoIo->SourceAddress));
  700. if (Error != NO_ERROR) {
  701. return Error;
  702. }
  703. if (IN4_SOCKADDR_EQUAL(&(TeredoIo->SourceAddress), &Old)) {
  704. //
  705. // No change to the bound address and port. Whew!
  706. //
  707. return NO_ERROR;
  708. }
  709. //
  710. // Destroy the old UDP socket.
  711. //
  712. TeredoDestroySocket(TeredoIo);
  713. //
  714. // Create a new UDP socket, bound to the new address and port.
  715. //
  716. Error = TeredoCreateSocket(TeredoIo);
  717. if (Error != NO_ERROR) {
  718. return Error;
  719. }
  720. return NO_ERROR;
  721. }
  722. DWORD
  723. TeredoInitializeIo(
  724. IN PTEREDO_IO TeredoIo,
  725. IN IN_ADDR Group,
  726. IN PTEREDO_REFERENCE Reference,
  727. IN PTEREDO_DEREFERENCE Dereference,
  728. IN LPOVERLAPPED_COMPLETION_ROUTINE IoCompletionCallback
  729. )
  730. /*++
  731. Routine Description:
  732. Initialize the I/O state.
  733. Arguments:
  734. TeredoIo - Supplies the I/O state.
  735. Group - Supplies the multicast group to join (or INADDR_ANY).
  736. Return Value:
  737. NO_ERROR or failure code.
  738. --*/
  739. {
  740. #if DBG
  741. TeredoIo->Signature = TEREDO_IO_SIGNATURE;
  742. #endif // DBG
  743. TeredoIo->PostedReceives = 0;
  744. TeredoIo->ReceiveEvent = TeredoIo->ReceiveEventWait = NULL;
  745. TeredoIo->Group = Group;
  746. ZeroMemory(&(TeredoIo->ServerAddress), sizeof(SOCKADDR_IN));
  747. TeredoIo->ServerAddress.sin_family = AF_INET;
  748. ZeroMemory(&(TeredoIo->SourceAddress), sizeof(SOCKADDR_IN));
  749. TeredoIo->SourceAddress.sin_family = AF_INET;
  750. TeredoIo->Socket = INVALID_SOCKET;
  751. TeredoIo->TunnelDevice = INVALID_HANDLE_VALUE;
  752. wcscpy(TeredoIo->TunnelInterface, L"");
  753. TeredoIo->Reference = Reference;
  754. TeredoIo->Dereference = Dereference;
  755. TeredoIo->IoCompletionCallback = IoCompletionCallback;
  756. TeredoIo->PacketHeap = HeapCreate(0, 0, 0);
  757. if (TeredoIo->PacketHeap == NULL) {
  758. return GetLastError();
  759. }
  760. return NO_ERROR;
  761. }
  762. VOID
  763. TeredoCleanupIo(
  764. IN PTEREDO_IO TeredoIo
  765. )
  766. /*++
  767. Routine Description:
  768. Cleanup the I/O state.
  769. Arguments:
  770. TeredoIo - Supplies the I/O state.
  771. Return Value:
  772. None.
  773. --*/
  774. {
  775. HeapDestroy(TeredoIo->PacketHeap);
  776. TeredoIo->PacketHeap = NULL;
  777. }