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.

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