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.

885 lines
20 KiB

  1. /*++
  2. Copyright (c) 2001-2002 Microsoft Corporation
  3. Module Name:
  4. server.c
  5. Abstract:
  6. This module contains the teredo server (and relay) implementation.
  7. Author:
  8. Mohit Talwar (mohitt) Fri Nov 02 14:55:38 2001
  9. Environment:
  10. User mode only.
  11. --*/
  12. #include "precomp.h"
  13. #pragma hdrstop
  14. TEREDO_SERVER_STATE TeredoServer;
  15. TEREDO_PACKET_IO_COMPLETE TeredoServerReadComplete;
  16. TEREDO_PACKET_IO_COMPLETE TeredoServerWriteComplete;
  17. TEREDO_PACKET_IO_COMPLETE TeredoServerBounceComplete;
  18. TEREDO_PACKET_IO_COMPLETE TeredoServerReceiveComplete;
  19. TEREDO_PACKET_IO_COMPLETE TeredoServerTransmitComplete;
  20. USHORT
  21. __inline
  22. TeredoChecksumDatagram(
  23. IN CONST IN6_ADDR *Destination,
  24. IN CONST IN6_ADDR *Source,
  25. IN USHORT NextHeader,
  26. IN UCHAR CONST *Buffer,
  27. IN USHORT Bytes
  28. )
  29. /*++
  30. Routine Description:
  31. 16-bit one's complement of the one's complement sum of a 'Buffer'
  32. of size 'Bytes'. NOTE: The sum is independent of the byte order!
  33. Arguments:
  34. Buffer - Supplies the buffer containing data to compute checksum for.
  35. Bytes - Supplies the number of bytes to compute checksum for.
  36. Return Value:
  37. The checksum.
  38. --*/
  39. {
  40. DWORD Sum, Words, i;
  41. PUSHORT Start = (PUSHORT) Buffer;
  42. //
  43. // If 'Bytes' is odd, this has to be handled differently.
  44. // That, however, is never the case for us, so we optimize.
  45. // Also ensure that 'Buffer' is aligned on a 2 byte boundary.
  46. //
  47. ASSERT(((((DWORD_PTR) Buffer) % 2) == 0) && ((Bytes % 2) == 0));
  48. Words = Bytes / 2;
  49. //
  50. // Start with the pseudo-header.
  51. //
  52. Sum = htons(Bytes) + (NextHeader << 8);
  53. for (i = 0; i < 8; i++) {
  54. Sum += Source->s6_words[i] + Destination->s6_words[i];
  55. }
  56. for (i = 0; i < Words; i++) {
  57. Sum += Start[i];
  58. }
  59. Sum = (Sum & 0x0000ffff) + (Sum >> 16);
  60. Sum += (Sum >> 16);
  61. return LOWORD(~((DWORD_PTR) Sum));
  62. }
  63. VOID
  64. CALLBACK
  65. TeredoServerIoCompletionCallback(
  66. IN DWORD ErrorCode,
  67. IN DWORD Bytes,
  68. IN LPOVERLAPPED Overlapped
  69. )
  70. /*++
  71. Routine Description:
  72. Callback routine for I/O completion on TUN interface device or UDP socket.
  73. Arguments:
  74. ErrorCode - Supplies the I/O completion status.
  75. Bytes - Supplies the number of bytes transferred.
  76. Overlapped - Supplies the completion context.
  77. Return Value:
  78. None.
  79. --*/
  80. {
  81. static CONST PTEREDO_PACKET_IO_COMPLETE Callback[] =
  82. {
  83. TeredoServerReadComplete,
  84. TeredoServerWriteComplete,
  85. NULL, // No bubbling...
  86. TeredoServerBounceComplete,
  87. TeredoServerReceiveComplete,
  88. TeredoServerTransmitComplete,
  89. NULL, // No multicasting...
  90. };
  91. PTEREDO_PACKET Packet = Cast(
  92. CONTAINING_RECORD(Overlapped, TEREDO_PACKET, Overlapped),
  93. TEREDO_PACKET);
  94. ASSERT((Packet->Type != TEREDO_PACKET_BUBBLE) &&
  95. (Packet->Type != TEREDO_PACKET_MULTICAST));
  96. //
  97. // This completion function usually posts the packet for another I/O.
  98. // Since we are called by a non-I/O worker thread, asynchronous I/O
  99. // requests posted here might terminate when this thread does. This
  100. // is rare enough that we don't special case it. Moreover, we only
  101. // make best effort guarantees to the upper layer!
  102. //
  103. (*Callback[Packet->Type])(ErrorCode, Bytes, Packet);
  104. }
  105. VOID
  106. TeredoServerAddressDeletionNotification(
  107. IN IN_ADDR Address
  108. )
  109. /*++
  110. Routine Description:
  111. Process an address deletion request.
  112. Arguments:
  113. Address - Supplies the address that was deleted.
  114. Return Value:
  115. None.
  116. Caller LOCK: API.
  117. --*/
  118. {
  119. if (!IN4_ADDR_EQUAL(Address, TeredoServer.Io.SourceAddress.sin_addr)) {
  120. return;
  121. }
  122. //
  123. // Refresh the socket state (the socket bound to SourceAddress).
  124. //
  125. if (TeredoRefreshSocket(&(TeredoServer.Io)) != NO_ERROR) {
  126. //
  127. // Online -> Offline.
  128. //
  129. TeredoStopServer();
  130. return;
  131. }
  132. if (!IN4_ADDR_EQUAL(
  133. TeredoServer.Io.SourceAddress.sin_addr,
  134. TeredoServer.Io.ServerAddress.sin_addr)) {
  135. //
  136. // Online -> Offline.
  137. //
  138. TeredoStopServer();
  139. return;
  140. }
  141. }
  142. VOID
  143. TeredoStartServer(
  144. VOID
  145. )
  146. /*++
  147. Routine Description:
  148. Attempt to start the teredo service at the server.
  149. Events / Transitions
  150. ServiceStart Offline -> Online.
  151. ServiceEnable Offline -> Online.
  152. AdapterArrival Offline -> Online.
  153. AddressAddition Offline -> Online.
  154. Arguments:
  155. None.
  156. Return Value:
  157. None.
  158. Caller LOCK: API.
  159. --*/
  160. {
  161. TraceEnter("TeredoStartServer");
  162. //
  163. // Can't have both the client and server on the same node.
  164. //
  165. if (TeredoClient.State != TEREDO_STATE_OFFLINE) {
  166. return;
  167. }
  168. //
  169. // Well, the service has already been started!
  170. //
  171. if (TeredoServer.State != TEREDO_STATE_OFFLINE) {
  172. return;
  173. }
  174. TeredoServer.State = TEREDO_STATE_ONLINE;
  175. //
  176. // Start I/O processing.
  177. //
  178. if (TeredoStartIo(&(TeredoServer.Io)) != NO_ERROR) {
  179. goto Bail;
  180. }
  181. if (!IN4_ADDR_EQUAL(
  182. TeredoServer.Io.SourceAddress.sin_addr,
  183. TeredoServer.Io.ServerAddress.sin_addr)) {
  184. goto Bail;
  185. }
  186. return;
  187. Bail:
  188. TeredoServer.State = TEREDO_STATE_OFFLINE;
  189. TeredoStopIo(&(TeredoServer.Io));
  190. }
  191. VOID
  192. TeredoStopServer(
  193. VOID
  194. )
  195. /*++
  196. Routine Description:
  197. Stop the teredo service at the server.
  198. Events / Transitions
  199. ServiceStop Online -> Offline.
  200. ServiceDisable Online -> Offline.
  201. AdapterRemoval Online -> Offline.
  202. AddressDeletion Online -> Offline.
  203. Arguments:
  204. None.
  205. Return Value:
  206. None.
  207. Caller LOCK: API.
  208. --*/
  209. {
  210. TraceEnter("TeredoStopServer");
  211. //
  212. // Well, the service was never started!
  213. //
  214. if (TeredoServer.State == TEREDO_STATE_OFFLINE) {
  215. return;
  216. }
  217. TeredoServer.State = TEREDO_STATE_OFFLINE;
  218. TeredoStopIo(&(TeredoServer.Io));
  219. }
  220. DWORD
  221. TeredoInitializeServer(
  222. VOID
  223. )
  224. /*++
  225. Routine Description:
  226. Initializes the server.
  227. Arguments:
  228. None.
  229. Return Value:
  230. NO_ERROR or failure code.
  231. --*/
  232. {
  233. DWORD Error;
  234. IN_ADDR Group;
  235. Group.s_addr = htonl(INADDR_ANY);
  236. //
  237. // Obtain a reference on the teredo server for initialization.
  238. //
  239. TeredoServer.ReferenceCount = 1;
  240. Error = TeredoInitializeIo(
  241. &(TeredoServer.Io),
  242. Group,
  243. TeredoReferenceServer,
  244. TeredoDereferenceServer,
  245. TeredoServerIoCompletionCallback);
  246. if (Error != NO_ERROR) {
  247. return Error;
  248. }
  249. TeredoServer.State = TEREDO_STATE_OFFLINE;
  250. IncEventCount("TeredoInitializeServer");
  251. return NO_ERROR;
  252. }
  253. VOID
  254. TeredoUninitializeServer(
  255. VOID
  256. )
  257. /*++
  258. Routine Description:
  259. Uninitializes the server. Typically invoked upon service stop.
  260. Arguments:
  261. None.
  262. Return Value:
  263. None.
  264. --*/
  265. {
  266. TeredoStopServer();
  267. TeredoDereferenceServer();
  268. }
  269. VOID
  270. TeredoCleanupServer(
  271. VOID
  272. )
  273. /*++
  274. Routine Description:
  275. Cleans up the server after the last reference to it has been released.
  276. Arguments:
  277. None.
  278. Return Value:
  279. None.
  280. --*/
  281. {
  282. TeredoCleanupIo(&(TeredoServer.Io));
  283. DecEventCount("TeredoCleanupServer");
  284. }
  285. VOID
  286. TeredoBuildRouterAdvertisementPacket(
  287. OUT PTEREDO_PACKET Packet,
  288. IN IN6_ADDR Destination,
  289. IN IN_ADDR Address,
  290. IN USHORT Port
  291. )
  292. /*++
  293. Routine Description:
  294. Construct an RA in response to the client's RS.
  295. Arguments:
  296. Packet - Returns the constructed RA in the caller supplied packet.
  297. Destination - Supplies the destination address of the RA,
  298. the client's random link-local address in the triggering RS.
  299. Passed by value so this function may reuse the packet buffer.
  300. Address - Supplies the client's address, used to source the RS.
  301. Port - Supplies the client's port, used to source the RS.
  302. Return Value:
  303. None.
  304. --*/
  305. {
  306. PIP6_HDR Ipv6 = (PIP6_HDR) Packet->Buffer.buf;
  307. ICMPv6Header *Icmpv6 = (ICMPv6Header *) (Ipv6 + 1);
  308. NDRouterAdvertisement *Ra = (NDRouterAdvertisement *) (Icmpv6 + 1);
  309. NDOptionPrefixInformation *Prefix = (NDOptionPrefixInformation *) (Ra + 1);
  310. NDOptionMTU *Mtu = (NDOptionMTU *) (Prefix + 1);
  311. PUCHAR End = (PUCHAR) (Mtu + 1);
  312. Packet->Buffer.len = (ULONG) (End - (Packet->Buffer.buf));
  313. ZeroMemory(Packet->Buffer.buf, Packet->Buffer.len);
  314. //
  315. // Construct the IPv6 Header...
  316. //
  317. Ipv6->ip6_plen = htons((USHORT) (Packet->Buffer.len - sizeof(IP6_HDR)));
  318. Ipv6->ip6_nxt = IP_PROTOCOL_ICMPv6;
  319. Ipv6->ip6_hlim = 255;
  320. Ipv6->ip6_vfc = IPV6_VERSION;
  321. //
  322. // ...using the server's link local address: fe80:IPv4 Address:UDP Port::1
  323. //
  324. Ipv6->ip6_src.s6_words[0] = 0x80fe;
  325. Ipv6->ip6_src.s6_words[1] =
  326. ((PUSHORT) &TeredoServer.Io.ServerAddress.sin_addr)[0];
  327. Ipv6->ip6_src.s6_words[2] =
  328. ((PUSHORT) &TeredoServer.Io.ServerAddress.sin_addr)[1];
  329. Ipv6->ip6_src.s6_words[3] =
  330. TeredoServer.Io.ServerAddress.sin_port;
  331. Ipv6->ip6_src.s6_words[7] = 0x0100;
  332. Ipv6->ip6_dest = Destination;
  333. //
  334. // Construct ICMPv6 Header.
  335. //
  336. Icmpv6->Type = ICMPv6_ROUTER_ADVERT;
  337. //
  338. // Construct RouterAdvertisement Header.
  339. //
  340. Ra->RouterLifetime = htons(TEREDO_ROUTER_LIFETIME);
  341. Ra->Flags = ROUTE_PREF_LOW;
  342. //
  343. // Construct Prefix Option.
  344. //
  345. Prefix->Type = ND_OPTION_PREFIX_INFORMATION;
  346. Prefix->Length = sizeof(NDOptionPrefixInformation) / 8;
  347. Prefix->PrefixLength = 64;
  348. Prefix->Flags = ND_PREFIX_FLAG_AUTONOMOUS;
  349. Prefix->ValidLifetime = Prefix->PreferredLifetime = IPV6_INFINITE_LIFETIME;
  350. Prefix->Prefix.s6_words[0] = TeredoIpv6ServicePrefix.s6_words[0];
  351. Prefix->Prefix.s6_words[1] = ((PUSHORT) &Address)[0];
  352. Prefix->Prefix.s6_words[2] = ((PUSHORT) &Address)[1];
  353. Prefix->Prefix.s6_words[3] = Port;
  354. //
  355. // Construct MTU Option.
  356. //
  357. Mtu->Type = ND_OPTION_MTU;
  358. Mtu->Length = sizeof(NDOptionMTU) / 8;
  359. Mtu->MTU = htonl(IPV6_TEREDOMTU);
  360. //
  361. // Checksum Packet!
  362. //
  363. Icmpv6->Checksum = TeredoChecksumDatagram(
  364. &(Ipv6->ip6_dest),
  365. &(Ipv6->ip6_src),
  366. IP_PROTOCOL_ICMPv6,
  367. (PUCHAR) Icmpv6,
  368. (USHORT) (End - ((PUCHAR) Icmpv6)));
  369. }
  370. PTEREDO_PACKET
  371. TeredoReceiveRouterSolicitation(
  372. IN PTEREDO_PACKET Packet,
  373. IN ULONG Bytes
  374. )
  375. /*++
  376. Routine Description:
  377. Process the router solicitation packet received on the UDP socket.
  378. Arguments:
  379. Packet - Supplies the packet that was received.
  380. Bytes - Supplies the length of the packet.
  381. Return Value:
  382. Returns the supplied packet if processing completed or failed;
  383. NULL if the processing will complete asynchronously.
  384. --*/
  385. {
  386. PUCHAR Buffer = Packet->Buffer.buf;
  387. ICMPv6Header *Icmpv6;
  388. ULONG Length;
  389. PIP6_HDR Ipv6 = (PIP6_HDR) Packet->Buffer.buf;
  390. Icmpv6 = TeredoParseIpv6Headers(Buffer, Bytes);
  391. if (Icmpv6 == NULL) {
  392. return Packet;
  393. }
  394. if ((Icmpv6->Type != ICMPv6_ROUTER_SOLICIT) || (Icmpv6->Code != 0)) {
  395. return Packet;
  396. }
  397. Buffer = (PUCHAR) (Icmpv6 + 1);
  398. Bytes -= (ULONG) (Buffer - Packet->Buffer.buf);
  399. //
  400. // Parse the rest of the router solicitation header.
  401. //
  402. if (Bytes < sizeof(ULONG)) {
  403. return Packet;
  404. }
  405. Buffer += sizeof(ULONG);
  406. Bytes -= sizeof(ULONG);
  407. while (Bytes != 0) {
  408. //
  409. // Parse TLV options.
  410. //
  411. if (Bytes < 8) {
  412. return Packet;
  413. }
  414. Length = (Buffer[1] * 8);
  415. if ((Length == 0) || (Bytes < Length)) {
  416. return Packet;
  417. }
  418. Buffer += Length;
  419. Bytes -= Length;
  420. }
  421. //
  422. // Checksum Packet!
  423. //
  424. if (TeredoChecksumDatagram(
  425. &(Ipv6->ip6_dest),
  426. &(Ipv6->ip6_src),
  427. IP_PROTOCOL_ICMPv6,
  428. (PUCHAR) Icmpv6,
  429. (USHORT) (Buffer - ((PUCHAR) Icmpv6))) != 0) {
  430. return Packet;
  431. }
  432. //
  433. // We have a valid router solicitation, so tunnel an advertisement!
  434. // Reuse the RS packet to bounce the RA.
  435. //
  436. TeredoBuildRouterAdvertisementPacket(
  437. Packet,
  438. Ipv6->ip6_src,
  439. Packet->SocketAddress.sin_addr,
  440. Packet->SocketAddress.sin_port);
  441. Packet->Type = TEREDO_PACKET_BOUNCE;
  442. return TeredoTransmitPacket(&(TeredoServer.Io), Packet);
  443. }
  444. PTEREDO_PACKET
  445. TeredoServerReceiveData(
  446. IN PTEREDO_PACKET Packet,
  447. IN ULONG Bytes
  448. )
  449. /*++
  450. Routine Description:
  451. Process the data packet received on the UDP socket.
  452. Arguments:
  453. Packet - Supplies the packet that was received.
  454. Bytes - Supplies the length of the packet.
  455. Return Value:
  456. Returns the supplied packet if processing completed or failed;
  457. NULL if the processing will complete asynchronously.
  458. --*/
  459. {
  460. PIP6_HDR Ipv6 = (PIP6_HDR) Packet->Buffer.buf;
  461. IN_ADDR Address;
  462. USHORT Port;
  463. //
  464. // Validate source address.
  465. //
  466. if (!TeredoServicePrefix(&(Ipv6->ip6_src))) {
  467. return Packet;
  468. }
  469. TeredoParseAddress(&(Ipv6->ip6_src), &Address, &Port);
  470. if (!IN4_ADDR_EQUAL(Packet->SocketAddress.sin_addr, Address) ||
  471. (Packet->SocketAddress.sin_port != Port)) {
  472. //
  473. // Should have been constructed by the *right* teredo peer.
  474. //
  475. return Packet;
  476. }
  477. //
  478. // NOTE: Caller has previously verified that the source has global scope.
  479. //
  480. //
  481. // Validate destination address.
  482. //
  483. if (TeredoServicePrefix(&(Ipv6->ip6_dest))) {
  484. TeredoParseAddress(&(Ipv6->ip6_dest), &Address, &Port);
  485. if (!TeredoIpv4GlobalAddress((PUCHAR) &Address)) {
  486. //
  487. // The IPv4 destination address should be global scope.
  488. //
  489. return Packet;
  490. }
  491. //
  492. // Now tunnel it to the destination.
  493. //
  494. Packet->SocketAddress.sin_addr = Address;
  495. Packet->SocketAddress.sin_port = Port;
  496. Packet->Type = TEREDO_PACKET_BOUNCE;
  497. Packet->Buffer.len = Bytes;
  498. return TeredoTransmitPacket(&(TeredoServer.Io), Packet);
  499. }
  500. if (!TeredoIpv6GlobalAddress(&(Ipv6->ip6_dest))) {
  501. //
  502. // The IPv6 destination address should be global scope.
  503. //
  504. return Packet;
  505. }
  506. //
  507. // Else forward it to the stack for forwarding.
  508. //
  509. Packet->Type = TEREDO_PACKET_WRITE;
  510. Packet->Buffer.len = Bytes;
  511. return TeredoWritePacket(&(TeredoServer.Io), Packet);
  512. }
  513. VOID
  514. TeredoServerReadComplete(
  515. IN DWORD Error,
  516. IN ULONG Bytes,
  517. IN PTEREDO_PACKET Packet
  518. )
  519. /*++
  520. Routine Description:
  521. Process a read completion on the TUN device.
  522. --*/
  523. {
  524. PIP6_HDR Ipv6 = (PIP6_HDR) Packet->Buffer.buf;
  525. IN_ADDR Address;
  526. USHORT Port;
  527. if ((Error != NO_ERROR) || (Bytes < sizeof(IP6_HDR))) {
  528. //
  529. // Attempt to post the read again.
  530. // If we are going offline, the packet is destroyed in the attempt.
  531. //
  532. TeredoPostRead(&(TeredoServer.Io), Packet);
  533. return;
  534. }
  535. TraceEnter("TeredoServerReadComplete");
  536. //
  537. // Validate destination address.
  538. //
  539. if (!TeredoServicePrefix(&(Ipv6->ip6_dest))) {
  540. TeredoPostRead(&(TeredoServer.Io), Packet);
  541. return;
  542. }
  543. TeredoParseAddress(&(Ipv6->ip6_dest), &Address, &Port);
  544. if (!TeredoIpv4GlobalAddress((PUCHAR) &Address)) {
  545. //
  546. // The IPv4 source address should be global scope.
  547. //
  548. TeredoPostRead(&(TeredoServer.Io), Packet);
  549. return;
  550. }
  551. //
  552. // Now tunnel it to the destination.
  553. //
  554. Packet->SocketAddress.sin_addr = Address;
  555. Packet->SocketAddress.sin_port = Port;
  556. Packet->Type = TEREDO_PACKET_TRANSMIT;
  557. Packet->Buffer.len = Bytes;
  558. if (TeredoTransmitPacket(&(TeredoServer.Io), Packet) == NULL) {
  559. return;
  560. }
  561. //
  562. // We are done processing this packet.
  563. //
  564. TeredoServerTransmitComplete(NO_ERROR, Bytes, Packet);
  565. }
  566. VOID
  567. TeredoServerWriteComplete(
  568. IN DWORD Error,
  569. IN ULONG Bytes,
  570. IN PTEREDO_PACKET Packet
  571. )
  572. /*++
  573. Routine Description:
  574. Process a write completion on the TUN device.
  575. --*/
  576. {
  577. TraceEnter("TeredoServerWriteComplete");
  578. //
  579. // Attempt to post the receive again.
  580. // If we are going offline, the packet is destroyed in the attempt.
  581. //
  582. Packet->Type = TEREDO_PACKET_RECEIVE;
  583. Packet->Buffer.len = IPV6_TEREDOMTU;
  584. TeredoPostReceives(&(TeredoServer.Io), Packet);
  585. }
  586. VOID
  587. TeredoServerBounceComplete(
  588. IN DWORD Error,
  589. IN ULONG Bytes,
  590. IN PTEREDO_PACKET Packet
  591. )
  592. /*++
  593. Routine Description:
  594. Process a bounce completion on the UDP socket.
  595. --*/
  596. {
  597. TraceEnter("TeredoServerBounceComplete");
  598. //
  599. // Attempt to post the receive again.
  600. // If we are going offline, the packet is destroyed in the attempt.
  601. //
  602. Packet->Type = TEREDO_PACKET_RECEIVE;
  603. Packet->Buffer.len = IPV6_TEREDOMTU;
  604. TeredoPostReceives(&(TeredoServer.Io), Packet);
  605. }
  606. VOID
  607. TeredoServerReceiveComplete(
  608. IN DWORD Error,
  609. IN ULONG Bytes,
  610. IN PTEREDO_PACKET Packet
  611. )
  612. /*++
  613. Routine Description:
  614. Process a receive completion on the UDP socket.
  615. --*/
  616. {
  617. PIP6_HDR Ipv6 = (PIP6_HDR) Packet->Buffer.buf;
  618. InterlockedDecrement(&(TeredoServer.Io.PostedReceives));
  619. if ((Error != NO_ERROR) ||
  620. (Bytes < sizeof(IP6_HDR)) ||
  621. ((Ipv6->ip6_vfc & IP_VER_MASK) != IPV6_VERSION) ||
  622. (Bytes < (ntohs(Ipv6->ip6_plen) + sizeof(IP6_HDR))) ||
  623. (!TeredoIpv4GlobalAddress(
  624. (PUCHAR) &(Packet->SocketAddress.sin_addr)))) {
  625. //
  626. // Attempt to post the receive again.
  627. // If we are going offline, the packet is destroyed in the attempt.
  628. //
  629. TeredoPostReceives(&(TeredoServer.Io), Packet);
  630. return;
  631. }
  632. TraceEnter("TeredoServerReceiveComplete");
  633. if (IN6_IS_ADDR_LINKLOCAL(&(Ipv6->ip6_src)) ||
  634. IN6_IS_ADDR_UNSPECIFIED(&(Ipv6->ip6_src))) {
  635. //
  636. // This should be a valid router solicitation. Note that only router
  637. // solicitation packets are accepted with a link-local source address.
  638. //
  639. Packet = TeredoReceiveRouterSolicitation(Packet, Bytes);
  640. } else {
  641. //
  642. // This may be a packet of any other kind.
  643. //
  644. Packet = TeredoServerReceiveData(Packet, Bytes);
  645. }
  646. if (Packet != NULL) {
  647. //
  648. // We are done processing this packet.
  649. //
  650. TeredoServerWriteComplete(NO_ERROR, Bytes, Packet);
  651. }
  652. }
  653. VOID
  654. TeredoServerTransmitComplete(
  655. IN DWORD Error,
  656. IN ULONG Bytes,
  657. IN PTEREDO_PACKET Packet
  658. )
  659. /*++
  660. Routine Description:
  661. Process a transmit completion on the UDP socket.
  662. --*/
  663. {
  664. TraceEnter("TeredoServerTransmitComplete");
  665. //
  666. // Attempt to post the read again.
  667. // If we are going offline, the packet is destroyed in the attempt.
  668. //
  669. Packet->Type = TEREDO_PACKET_READ;
  670. Packet->Buffer.len = IPV6_TEREDOMTU;
  671. TeredoPostRead(&(TeredoServer.Io), Packet);
  672. }