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.

2002 lines
63 KiB

  1. // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil -*- (for GNU Emacs)
  2. //
  3. // Copyright (c) 1985-2000 Microsoft Corporation
  4. //
  5. // This file is part of the Microsoft Research IPv6 Network Protocol Stack.
  6. // You should have received a copy of the Microsoft End-User License Agreement
  7. // for this software along with this release; see the file "license.txt".
  8. // If not, please see http://www.research.microsoft.com/msripv6/license.htm,
  9. // or write to Microsoft Research, One Microsoft Way, Redmond, WA 98052-6399.
  10. //
  11. // Abstract:
  12. //
  13. // Internet Protocol Version 6 link-level support for some common
  14. // LAN types: Ethernet, Token Ring, etc.
  15. //
  16. //
  17. // This manifest constant causes the NDIS_PROTOCOL_CHARACTERISTICS struct to
  18. // use the NDIS 5 format if compiled using the NT 5 ddk. If using the NT4 ddk
  19. // this has no effect.
  20. //
  21. #ifndef NDIS50
  22. #define NDIS50 1
  23. #endif
  24. #include "oscfg.h"
  25. #include "ndis.h"
  26. #include "tunuser.h"
  27. #include "ip6imp.h"
  28. #include "llip6if.h"
  29. #include "lan.h"
  30. #include "ntddip6.h"
  31. #include "ip6def.h"
  32. #ifndef NDIS_API
  33. #define NDIS_API
  34. #endif
  35. uint NdisVersion; // The major NDIS version we actualy register with.
  36. static ulong LanLookahead = LOOKAHEAD_SIZE;
  37. #define LAN_TUNNEL_DEFAULT_PREFERENCE 1
  38. #define NdisMediumTunnel NdisMediumMax
  39. static WCHAR LanName[] = TCPIPV6_NAME;
  40. NDIS_HANDLE LanHandle; // Our NDIS protocol handle.
  41. typedef struct LanRequest {
  42. NDIS_REQUEST Request;
  43. KEVENT Event;
  44. NDIS_STATUS Status;
  45. } LanRequest;
  46. //* DoNDISRequest - Submit a request to an NDIS driver.
  47. //
  48. // This is a utility routine to submit a general request to an NDIS
  49. // driver. The caller specifes the request code (OID), a buffer and
  50. // a length. This routine allocates a request structure, fills it in,
  51. // and submits the request.
  52. //
  53. NDIS_STATUS
  54. DoNDISRequest(
  55. LanInterface *Adapter, // Pointer to the LanInterface adapter strucuture.
  56. NDIS_REQUEST_TYPE RT, // Type of request to be done (Set or Query).
  57. NDIS_OID OID, // Value to be set/queried.
  58. void *Info, // Pointer to the buffer to be passed.
  59. uint Length, // Length of data in above buffer.
  60. uint *Needed) // Location to fill in with bytes needed in buffer.
  61. {
  62. LanRequest Request;
  63. NDIS_STATUS Status;
  64. // Now fill it in.
  65. Request.Request.RequestType = RT;
  66. if (RT == NdisRequestSetInformation) {
  67. Request.Request.DATA.SET_INFORMATION.Oid = OID;
  68. Request.Request.DATA.SET_INFORMATION.InformationBuffer = Info;
  69. Request.Request.DATA.SET_INFORMATION.InformationBufferLength = Length;
  70. } else {
  71. Request.Request.DATA.QUERY_INFORMATION.Oid = OID;
  72. Request.Request.DATA.QUERY_INFORMATION.InformationBuffer = Info;
  73. Request.Request.DATA.QUERY_INFORMATION.InformationBufferLength = Length;
  74. }
  75. //
  76. // Note that we can NOT use Adapter->ai_event and ai_status here.
  77. // There may be multiple concurrent DoNDISRequest calls.
  78. //
  79. // Initialize our event.
  80. KeInitializeEvent(&Request.Event, SynchronizationEvent, FALSE);
  81. if (!Adapter->ai_resetting) {
  82. // Submit the request.
  83. NdisRequest(&Status, Adapter->ai_handle, &Request.Request);
  84. // Wait for it to finish.
  85. if (Status == NDIS_STATUS_PENDING) {
  86. (void) KeWaitForSingleObject(&Request.Event, UserRequest,
  87. KernelMode, FALSE, NULL);
  88. Status = Request.Status;
  89. }
  90. } else
  91. Status = NDIS_STATUS_NOT_ACCEPTED;
  92. if (Needed != NULL)
  93. *Needed = Request.Request.DATA.QUERY_INFORMATION.BytesNeeded;
  94. return Status;
  95. }
  96. //* LanRequestComplete - Lan request complete handler.
  97. //
  98. // This routine is called by the NDIS driver when a general request
  99. // completes. Lan blocks on all requests, so we'll just wake up
  100. // whoever's blocked on this request.
  101. //
  102. void NDIS_API
  103. LanRequestComplete(
  104. NDIS_HANDLE Handle, // Binding handle (really our LanInterface).
  105. PNDIS_REQUEST Context, // Request that completed.
  106. NDIS_STATUS Status) // Final status of requested command.
  107. {
  108. LanRequest *Request = (LanRequest *) Context;
  109. UNREFERENCED_PARAMETER(Handle);
  110. //
  111. // Signal the completion of a generic synchronous request.
  112. // See DoNDISRequest.
  113. //
  114. Request->Status = Status;
  115. KeSetEvent(&Request->Event, 0, FALSE);
  116. }
  117. //* LanTransmitComplete - Lan transmit complete handler.
  118. //
  119. // This routine is called by the NDIS driver when a send completes.
  120. // This is a pretty time critical operation, we need to get through here
  121. // quickly. We just take statistics and call the upper layer send
  122. // complete handler.
  123. //
  124. void NDIS_API
  125. LanTransmitComplete(
  126. NDIS_HANDLE Handle, // Binding handle (really LanInterface we sent on).
  127. PNDIS_PACKET Packet, // Packet that was sent.
  128. NDIS_STATUS Status) // Final status of send.
  129. {
  130. LanInterface *Interface = (LanInterface *)Handle;
  131. Interface->ai_qlen--;
  132. //
  133. // Take statistics.
  134. //
  135. if (Status == NDIS_STATUS_SUCCESS) {
  136. UINT TotalLength;
  137. NdisQueryPacket(Packet, NULL, NULL, NULL, &TotalLength);
  138. Interface->ai_outoctets += TotalLength;
  139. } else {
  140. if (Status == NDIS_STATUS_RESOURCES)
  141. Interface->ai_outdiscards++;
  142. else
  143. Interface->ai_outerrors++;
  144. }
  145. UndoAdjustPacketBuffer(Packet);
  146. IPv6SendComplete(Interface->ai_context, Packet,
  147. ((Status == NDIS_STATUS_SUCCESS) ?
  148. IP_SUCCESS : IP_GENERAL_FAILURE));
  149. }
  150. //* LanTransmit - Send a frame.
  151. //
  152. // The main Lan transmit routine, called by the upper layer.
  153. //
  154. void
  155. LanTransmit(
  156. void *Context, // A pointer to the LanInterface.
  157. PNDIS_PACKET Packet, // Packet to send.
  158. uint Offset, // Offset from start of packet to IP header.
  159. const void *LinkAddress) // Link-level address of destination.
  160. {
  161. LanInterface *Interface = (LanInterface *)Context;
  162. void *BufAddr;
  163. NDIS_STATUS Status;
  164. //
  165. // Loopback (for both unicast & multicast) happens in IPv6SendLL.
  166. // We never want the link layer to loopback.
  167. //
  168. Packet->Private.Flags = NDIS_FLAGS_DONT_LOOPBACK;
  169. //
  170. // Obtain a pointer to space for the link-level header.
  171. //
  172. BufAddr = AdjustPacketBuffer(Packet, Offset, Interface->ai_hdrsize);
  173. switch (Interface->ai_media) {
  174. case NdisMedium802_3: {
  175. EtherHeader *Ether;
  176. // This is an Ethernet.
  177. Ether = (EtherHeader *)BufAddr;
  178. RtlCopyMemory(Ether->eh_daddr, LinkAddress, IEEE_802_ADDR_LENGTH);
  179. RtlCopyMemory(Ether->eh_saddr, Interface->ai_addr,
  180. IEEE_802_ADDR_LENGTH);
  181. Ether->eh_type = net_short(ETYPE_IPv6);
  182. #if 0
  183. //
  184. // See if we're using SNAP here.
  185. //
  186. if (Interface->ai_hdrsize != sizeof(EtherHeader)) {
  187. ...
  188. }
  189. #endif
  190. break;
  191. }
  192. case NdisMediumFddi: {
  193. FDDIHeader *FDDI;
  194. SNAPHeader *SNAP;
  195. // This is a FDDI link.
  196. FDDI = (FDDIHeader *)BufAddr;
  197. FDDI->fh_pri = FDDI_PRI; // Default frame code.
  198. RtlCopyMemory(FDDI->fh_daddr, LinkAddress, IEEE_802_ADDR_LENGTH);
  199. RtlCopyMemory(FDDI->fh_saddr, Interface->ai_addr,
  200. IEEE_802_ADDR_LENGTH);
  201. // FDDI always uses SNAP.
  202. SNAP = (SNAPHeader *)(FDDI + 1);
  203. SNAP->sh_dsap = SNAP_SAP;
  204. SNAP->sh_ssap = SNAP_SAP;
  205. SNAP->sh_ctl = SNAP_UI;
  206. SNAP->sh_protid[0] = 0;
  207. SNAP->sh_protid[1] = 0;
  208. SNAP->sh_protid[2] = 0;
  209. SNAP->sh_etype = net_short(ETYPE_IPv6);
  210. break;
  211. }
  212. case NdisMediumTunnel: {
  213. //
  214. // There is no header to construct!
  215. //
  216. break;
  217. }
  218. default:
  219. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INTERNAL_ERROR,
  220. "LanTransmit: Unknown media type\n"));
  221. break;
  222. }
  223. //
  224. // Send the packet down to NDIS.
  225. //
  226. (Interface->ai_outpcount[AI_UCAST_INDEX])++;
  227. Interface->ai_qlen++;
  228. if (!Interface->ai_resetting) {
  229. NdisSend(&Status, Interface->ai_handle, Packet);
  230. } else
  231. Status = NDIS_STATUS_NOT_ACCEPTED;
  232. if (Status != NDIS_STATUS_PENDING) {
  233. //
  234. // The send finished synchronously.
  235. // Call LanTransmitComplete, unifying our treatment
  236. // of the synchronous and asynchronous cases.
  237. //
  238. LanTransmitComplete((NDIS_HANDLE)Interface, Packet, Status);
  239. }
  240. }
  241. //* LanOpenAdapterComplete - LanOpen completion handler.
  242. //
  243. // This routine is called by the NDIS driver when an open adapter
  244. // call completes. Wakeup anyone who is waiting for this event.
  245. //
  246. void NDIS_API
  247. LanOpenAdapterComplete(
  248. NDIS_HANDLE Handle, // Binding handle (really our LanInterface).
  249. NDIS_STATUS Status, // Final status of command.
  250. NDIS_STATUS ErrorStatus) // Final error status.
  251. {
  252. LanInterface *ai = (LanInterface *)Handle;
  253. UNREFERENCED_PARAMETER(ErrorStatus);
  254. //
  255. // Signal whoever is waiting and pass the final status.
  256. //
  257. ai->ai_status = Status;
  258. KeSetEvent(&ai->ai_event, 0, FALSE);
  259. }
  260. //* LanCloseAdapterComplete - Lan close adapter complete handler.
  261. //
  262. // This routine is called by the NDIS driver when a close adapter
  263. // call completes.
  264. //
  265. // At this point, NDIS guarantees that it has no other outstanding
  266. // calls to us.
  267. //
  268. void NDIS_API
  269. LanCloseAdapterComplete(
  270. NDIS_HANDLE Handle, // Binding handle (really our LanInterface).
  271. NDIS_STATUS Status) // Final status of command.
  272. {
  273. LanInterface *ai = (LanInterface *)Handle;
  274. //
  275. // Signal whoever is waiting and pass the final status.
  276. //
  277. ai->ai_status = Status;
  278. KeSetEvent(&ai->ai_event, 0, FALSE);
  279. }
  280. //* LanTDComplete - Lan transfer data complete handler.
  281. //
  282. // This routine is called by the NDIS driver when a transfer data
  283. // call completes. Hopefully we now have a complete packet we can
  284. // pass up to IP. Recycle our TD packet descriptor in any event.
  285. //
  286. void NDIS_API
  287. LanTDComplete(
  288. NDIS_HANDLE Handle, // Binding handle (really our LanInterface).
  289. PNDIS_PACKET Packet, // The packet used for the Transfer Data (TD).
  290. NDIS_STATUS Status, // Final status of command.
  291. uint BytesCopied) // Number of bytes copied.
  292. {
  293. LanInterface *Interface = (LanInterface *)Handle;
  294. UNREFERENCED_PARAMETER(BytesCopied);
  295. //
  296. // If things went well, pass TD packet up to IP.
  297. //
  298. if (Status == NDIS_STATUS_SUCCESS) {
  299. PNDIS_BUFFER Buffer;
  300. IPv6Packet IPPacket;
  301. RtlZeroMemory(&IPPacket, sizeof IPPacket);
  302. NdisGetFirstBufferFromPacket(Packet, &Buffer, &IPPacket.FlatData,
  303. &IPPacket.ContigSize,
  304. &IPPacket.TotalSize);
  305. ASSERT(IPPacket.ContigSize == IPPacket.TotalSize);
  306. IPPacket.Data = IPPacket.FlatData;
  307. if (PC(Packet)->pc_nucast)
  308. IPPacket.Flags |= PACKET_NOT_LINK_UNICAST;
  309. IPPacket.NTEorIF = Interface->ai_context;
  310. (void) IPv6Receive(&IPPacket);
  311. }
  312. //
  313. // In any case, put the packet back on the list.
  314. //
  315. KeAcquireSpinLockAtDpcLevel(&Interface->ai_lock);
  316. PC(Packet)->pc_link = Interface->ai_tdpacket;
  317. Interface->ai_tdpacket = Packet;
  318. KeReleaseSpinLockFromDpcLevel(&Interface->ai_lock);
  319. }
  320. //* LanResetComplete - Lan reset complete handler.
  321. //
  322. // This routine is called by the NDIS driver when a reset completes.
  323. //
  324. void NDIS_API
  325. LanResetComplete(
  326. NDIS_HANDLE Handle, // Binding handle (really LanInterface which reset)
  327. NDIS_STATUS Status) // Final status of command.
  328. {
  329. UNREFERENCED_PARAMETER(Handle);
  330. UNREFERENCED_PARAMETER(Status);
  331. // REVIEW: Do anything here? Axe this routine?
  332. }
  333. //* LanReceive - Lan receive data handler.
  334. //
  335. // This routine is called when data arrives from the NDIS driver.
  336. // Note that newer NDIS drivers are likely to call LanReceivePacket to
  337. // indicate data arrival instead of this routine.
  338. //
  339. NDIS_STATUS // Indication of whether or not we took the packet.
  340. NDIS_API
  341. LanReceive(
  342. NDIS_HANDLE Handle, // The binding handle we gave NDIS earlier.
  343. NDIS_HANDLE Context, // NDIS Context for TransferData operations.
  344. void *Header, // Pointer to packet link-level header.
  345. uint HeaderSize, // Size of above header (in bytes).
  346. void *Data, // Pointer to look-ahead received data buffer.
  347. uint Size, // Size of above data (in bytes).
  348. uint TotalSize) // Total received data size (in bytes).
  349. {
  350. LanInterface *Interface = Handle; // Interface for this driver.
  351. ushort Type; // Protocol type.
  352. uint ProtOffset; // Offset in Data to non-media info.
  353. uint NUCast; // TRUE if the frame is not unicast.
  354. IPv6Packet IPPacket;
  355. if (Interface->ai_state != INTERFACE_UP) {
  356. //
  357. // Interface is marked as down.
  358. //
  359. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INFO_RARE,
  360. "IPv6 LanReceive: Interface down\n"));
  361. return NDIS_STATUS_NOT_RECOGNIZED;
  362. }
  363. Interface->ai_inoctets += TotalSize;
  364. switch (Interface->ai_media) {
  365. case NdisMedium802_3: {
  366. EtherHeader UNALIGNED *Ether = (EtherHeader UNALIGNED *)Header;
  367. if (HeaderSize < sizeof(*Ether)) {
  368. //
  369. // Header region too small to contain Ethernet header.
  370. //
  371. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_BAD_PACKET,
  372. "IPv6 LanReceive: Bogus header size (%d bytes)\n",
  373. HeaderSize));
  374. return NDIS_STATUS_NOT_RECOGNIZED;
  375. }
  376. if ((Type = net_short(Ether->eh_type)) >= ETYPE_MIN) {
  377. //
  378. // Classic Ethernet, no SNAP header.
  379. //
  380. ProtOffset = 0;
  381. break;
  382. }
  383. //
  384. // 802.3 Ethernet w/ SNAP header. Protocol type is in
  385. // different spot. This is handled the same as FDDI, so
  386. // just fall into that code...
  387. //
  388. }
  389. case NdisMediumFddi: {
  390. SNAPHeader UNALIGNED *SNAP = (SNAPHeader UNALIGNED *)Data;
  391. //
  392. // If we have a SNAP header that's all we need to look at.
  393. //
  394. if (Size >= sizeof(SNAPHeader) && SNAP->sh_dsap == SNAP_SAP &&
  395. SNAP->sh_ssap == SNAP_SAP && SNAP->sh_ctl == SNAP_UI) {
  396. Type = net_short(SNAP->sh_etype);
  397. ProtOffset = sizeof(SNAPHeader);
  398. } else {
  399. // handle XID/TEST here.
  400. Interface->ai_uknprotos++;
  401. return NDIS_STATUS_NOT_RECOGNIZED;
  402. }
  403. break;
  404. }
  405. case NdisMediumTunnel: {
  406. //
  407. // We accept everything over the tunnel.
  408. //
  409. Type = ETYPE_IPv6;
  410. ProtOffset = 0;
  411. break;
  412. }
  413. default:
  414. // Should never happen.
  415. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INTERNAL_ERROR,
  416. "IPv6 LanReceive: Got a packet from an unknown media!?!\n"));
  417. return NDIS_STATUS_NOT_RECOGNIZED;
  418. }
  419. //
  420. // See if the packet is for a protocol we handle.
  421. //
  422. if (Type != ETYPE_IPv6) {
  423. Interface->ai_uknprotos++;
  424. return NDIS_STATUS_NOT_RECOGNIZED;
  425. }
  426. //
  427. // Notice if this packet wasn't received in a unicast frame.
  428. // REVIEW: Is this really a media independent solution? Do we care?
  429. //
  430. NUCast = ((*((uchar UNALIGNED *)Header + Interface->ai_bcastoff) &
  431. Interface->ai_bcastmask) == Interface->ai_bcastval) ?
  432. AI_NONUCAST_INDEX : AI_UCAST_INDEX;
  433. (Interface->ai_inpcount[NUCast])++;
  434. //
  435. // Check to see if we have the entire packet.
  436. //
  437. if (Size < TotalSize) {
  438. uint Transferred;
  439. NDIS_STATUS Status;
  440. PNDIS_PACKET TdPacket; // Packet used by NdisTransferData.
  441. //
  442. // We need to issue a Transfer Data request to get the
  443. // portion of the packet we're missing, so we might as well
  444. // get the whole packet this way and have it be contiguous.
  445. //
  446. //
  447. // Pull a packet to use for the Transfer Data off the queue.
  448. //
  449. KeAcquireSpinLockAtDpcLevel(&Interface->ai_lock);
  450. TdPacket = Interface->ai_tdpacket;
  451. if (TdPacket == (PNDIS_PACKET)NULL) {
  452. // Don't have a packet to put it in.
  453. // Have to drop it, but let NDIS know we recognized it.
  454. KeReleaseSpinLockFromDpcLevel(&Interface->ai_lock);
  455. return NDIS_STATUS_SUCCESS;
  456. }
  457. Interface->ai_tdpacket = PC(TdPacket)->pc_link;
  458. KeReleaseSpinLockFromDpcLevel(&Interface->ai_lock);
  459. //
  460. // Remember NUCast in a handy field in the packet context.
  461. //
  462. PC(TdPacket)->pc_nucast = NUCast;
  463. //
  464. // Issue the TD. Start transfer at the IP header.
  465. //
  466. NdisTransferData(&Status, Interface->ai_handle, Context,
  467. ProtOffset, TotalSize - ProtOffset,
  468. TdPacket, &Transferred);
  469. if (Status != NDIS_STATUS_PENDING) {
  470. //
  471. // TD completed synchronously,
  472. // so call the completion function directly.
  473. //
  474. LanTDComplete(Handle, TdPacket, Status, Transferred);
  475. }
  476. return NDIS_STATUS_SUCCESS;
  477. }
  478. //
  479. // We were given all the data directly. Just need to skip
  480. // over any link level headers.
  481. //
  482. (uchar *)Data += ProtOffset;
  483. ASSERT(Size == TotalSize);
  484. TotalSize -= ProtOffset;
  485. //
  486. // Pass incoming data up to IPv6.
  487. //
  488. RtlZeroMemory(&IPPacket, sizeof IPPacket);
  489. IPPacket.FlatData = Data;
  490. IPPacket.Data = Data;
  491. IPPacket.ContigSize = TotalSize;
  492. IPPacket.TotalSize = TotalSize;
  493. if (NUCast)
  494. IPPacket.Flags |= PACKET_NOT_LINK_UNICAST;
  495. IPPacket.NTEorIF = Interface->ai_context;
  496. (void) IPv6Receive(&IPPacket);
  497. return NDIS_STATUS_SUCCESS;
  498. }
  499. //* LanReceiveComplete - Lan receive complete handler.
  500. //
  501. // This routine is called by the NDIS driver after some number of
  502. // receives. In some sense, it indicates 'idle time'.
  503. //
  504. void NDIS_API
  505. LanReceiveComplete(
  506. NDIS_HANDLE Handle) // Binding handle (really our LanInterface).
  507. {
  508. UNREFERENCED_PARAMETER(Handle);
  509. IPv6ReceiveComplete();
  510. }
  511. //* LanReceivePacket - Lan receive data handler.
  512. //
  513. // This routine is called when data arrives from the NDIS driver.
  514. // Note that older NDIS drivers are likely to call LanReceive to
  515. // indicate data arrival instead of this routine.
  516. //
  517. int // Returns: number of references we hold to Packet upon return.
  518. LanReceivePacket(
  519. NDIS_HANDLE Handle, // The binding handle we gave NDIS earlier.
  520. PNDIS_PACKET Packet) // Packet descriptor for incoming packet.
  521. {
  522. LanInterface *Interface = Handle; // Interface for this driver.
  523. PNDIS_BUFFER Buffer; // Buffer in packet chain.
  524. void *Address; // Address of above Buffer.
  525. uint Length, TotalLength; // Length of Buffer, Packet.
  526. EtherHeader UNALIGNED *Ether; // Header for Ethernet media.
  527. ushort Type; // Protocol type.
  528. uint Position; // Offset to non-media info.
  529. uint NUCast; // TRUE if the frame is not unicast.
  530. IPv6Packet IPPacket;
  531. if (Interface->ai_state != INTERFACE_UP) {
  532. // Interface is marked as down.
  533. return 0;
  534. }
  535. //
  536. // Find out about the packet we've been handed.
  537. //
  538. NdisGetFirstBufferFromPacket(Packet, &Buffer, &Address, &Length,
  539. &TotalLength);
  540. Interface->ai_inoctets += TotalLength; // Take statistic.
  541. //
  542. // Check for obviously bogus packets.
  543. //
  544. if (TotalLength < (uint)Interface->ai_hdrsize) {
  545. //
  546. // Packet too small to hold media header, drop it.
  547. //
  548. return 0;
  549. }
  550. if (Length < (uint)Interface->ai_hdrsize) {
  551. //
  552. // First buffer in chain too small to hold header.
  553. // This shouldn't happen because of LanLookahead.
  554. //
  555. return 0;
  556. }
  557. //
  558. // Figure out what protocol type this packet is by looking in the
  559. // media-specific header field for this type of media.
  560. //
  561. switch (Interface->ai_media) {
  562. case NdisMedium802_3: {
  563. Ether = (EtherHeader UNALIGNED *)Address;
  564. if ((Type = net_short(Ether->eh_type)) >= ETYPE_MIN) {
  565. //
  566. // Classic Ethernet, no SNAP header.
  567. //
  568. Position = sizeof(EtherHeader);
  569. } else {
  570. //
  571. // 802.3 Ethernet w/ SNAP header. Protocol type is in
  572. // different spot and we have to remember to skip over it.
  573. // The great thing about standards is that there are so
  574. // many to choose from.
  575. //
  576. SNAPHeader UNALIGNED *SNAP = (SNAPHeader UNALIGNED *)
  577. ((char *)Address + sizeof(EtherHeader));
  578. if (Length >= (sizeof(EtherHeader) + sizeof(SNAPHeader))
  579. && SNAP->sh_dsap == SNAP_SAP && SNAP->sh_ssap == SNAP_SAP
  580. && SNAP->sh_ctl == SNAP_UI) {
  581. Type = net_short(SNAP->sh_etype);
  582. Position = sizeof(EtherHeader) + sizeof(SNAPHeader);
  583. } else {
  584. // handle XID/TEST here.
  585. Interface->ai_uknprotos++;
  586. return 0;
  587. }
  588. }
  589. break;
  590. }
  591. case NdisMediumFddi: {
  592. SNAPHeader UNALIGNED *SNAP = (SNAPHeader UNALIGNED *)
  593. ((char *)Address + sizeof(FDDIHeader));
  594. if (Length >= (sizeof(FDDIHeader) + sizeof(SNAPHeader))
  595. && SNAP->sh_dsap == SNAP_SAP && SNAP->sh_ssap == SNAP_SAP
  596. && SNAP->sh_ctl == SNAP_UI) {
  597. Type = net_short(SNAP->sh_etype);
  598. Position = sizeof(FDDIHeader) + sizeof(SNAPHeader);
  599. } else {
  600. // handle XID/TEST here.
  601. Interface->ai_uknprotos++;
  602. return 0;
  603. }
  604. break;
  605. }
  606. case NdisMediumTunnel: {
  607. //
  608. // We accept everything over the tunnel.
  609. //
  610. Type = ETYPE_IPv6;
  611. Position = 0;
  612. break;
  613. }
  614. default:
  615. // Should never happen.
  616. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INTERNAL_ERROR,
  617. "IPv6: Got a packet from an unknown media!?!\n"));
  618. return 0;
  619. }
  620. //
  621. // Notice if this packet wasn't received in a unicast frame.
  622. // REVIEW: Is this really a media independent solution?
  623. //
  624. NUCast = ((*((uchar UNALIGNED *)Address + Interface->ai_bcastoff) &
  625. Interface->ai_bcastmask) == Interface->ai_bcastval) ?
  626. AI_NONUCAST_INDEX : AI_UCAST_INDEX;
  627. //
  628. // See if the packet is for a protocol we handle.
  629. //
  630. if (Type == ETYPE_IPv6) {
  631. (Interface->ai_inpcount[NUCast])++;
  632. //
  633. // Skip over any link level headers.
  634. //
  635. (uchar *)Address += Position;
  636. Length -= Position;
  637. TotalLength -= Position;
  638. //
  639. // Pass incoming data up to IPv6.
  640. //
  641. RtlZeroMemory(&IPPacket, sizeof IPPacket);
  642. IPPacket.Position = Position;
  643. IPPacket.Data = Address;
  644. IPPacket.ContigSize = Length;
  645. IPPacket.TotalSize = TotalLength;
  646. IPPacket.NdisPacket = Packet;
  647. if (NUCast)
  648. IPPacket.Flags |= PACKET_NOT_LINK_UNICAST;
  649. IPPacket.NTEorIF = Interface->ai_context;
  650. return IPv6Receive(&IPPacket);
  651. } else {
  652. //
  653. // Not a protocol we handle.
  654. //
  655. Interface->ai_uknprotos++;
  656. return 0;
  657. }
  658. }
  659. //* LanSetInterfaceLinkStatus
  660. //
  661. // Helper function for processing media connectivity indications.
  662. //
  663. void
  664. LanSetInterfaceLinkStatus(
  665. LanInterface *Interface,
  666. int MediaConnected)
  667. {
  668. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INFO_STATE,
  669. "LanSetInterfaceLinkStatus(%p/%p) - %u %u\n",
  670. Interface, Interface->ai_context,
  671. Interface->ai_media_check, MediaConnected));
  672. KeAcquireSpinLockAtDpcLevel(&Interface->ai_lock);
  673. if (Interface->ai_media_check == MEDIA_CHECK_IDLE)
  674. SetInterfaceLinkStatus(Interface->ai_context, MediaConnected);
  675. else
  676. Interface->ai_media_check = MEDIA_CHECK_CONFLICT;
  677. KeReleaseSpinLockFromDpcLevel(&Interface->ai_lock);
  678. }
  679. //* LanStatus - Lan status handler.
  680. //
  681. // Called by the NDIS driver when some sort of status change occurs.
  682. // We take action depending on the type of status.
  683. //
  684. // Entry:
  685. // Handle - The binding handle we specified (really a pointer to an AI).
  686. // GStatus - General type of status that caused the call.
  687. // Status - Pointer to a buffer of status specific information.
  688. // StatusSize - Size of the status buffer.
  689. //
  690. // Exit: Nothing.
  691. //
  692. void NDIS_API
  693. LanStatus(
  694. NDIS_HANDLE Handle, // Binding handle (really our LanInterface).
  695. NDIS_STATUS GStatus, // General status type which caused the call.
  696. void *Status, // Pointer to buffer of status specific info.
  697. uint StatusSize) // Size of the above status buffer.
  698. {
  699. LanInterface *Interface = Handle; // Interface for this driver.
  700. uint Index;
  701. UNREFERENCED_PARAMETER(Status);
  702. switch (GStatus) {
  703. case NDIS_STATUS_RESET_START:
  704. //
  705. // While the interface is resetting, we must avoid calling
  706. // NdisSendPackets, NdisSend, and NdisRequest.
  707. //
  708. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INFO_STATE,
  709. "LanStatus(%p) - start reset\n", Interface));
  710. Interface->ai_resetting = TRUE;
  711. break;
  712. case NDIS_STATUS_RESET_END:
  713. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INFO_STATE,
  714. "LanStatus(%p) - end reset\n", Interface));
  715. Interface->ai_resetting = FALSE;
  716. break;
  717. case NDIS_STATUS_MEDIA_CONNECT:
  718. LanSetInterfaceLinkStatus(Interface, TRUE);
  719. break;
  720. case NDIS_STATUS_MEDIA_DISCONNECT:
  721. LanSetInterfaceLinkStatus(Interface, FALSE);
  722. break;
  723. default:
  724. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INFO_STATE,
  725. "IPv6: LanStatus(%p) - status %x\n",
  726. Interface, GStatus));
  727. for (Index = 0; Index < StatusSize/4; Index++)
  728. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INFO_STATE,
  729. " status %08x\n", ((uint *)Status)[Index]));
  730. break;
  731. }
  732. }
  733. //* LanStatusComplete - Lan status complete handler.
  734. //
  735. // A routine called by the NDIS driver so that we can do postprocessing
  736. // after a status event.
  737. //
  738. void NDIS_API
  739. LanStatusComplete(
  740. NDIS_HANDLE Handle) // Binding handle (really our LanInterface).
  741. {
  742. UNREFERENCED_PARAMETER(Handle);
  743. // REVIEW: Do anything here?
  744. }
  745. extern void NDIS_API
  746. LanBindAdapter(PNDIS_STATUS RetStatus, NDIS_HANDLE BindContext,
  747. PNDIS_STRING AdapterName, PVOID SS1, PVOID SS2);
  748. extern void NDIS_API
  749. LanUnbindAdapter(PNDIS_STATUS RetStatus, NDIS_HANDLE ProtBindContext,
  750. NDIS_HANDLE UnbindContext);
  751. extern NDIS_STATUS NDIS_API
  752. LanPnPEvent(NDIS_HANDLE ProtocolBindingContext,
  753. PNET_PNP_EVENT NetPnPEvent);
  754. //
  755. // Structure passed to NDIS to tell it how to call Lan Interfaces.
  756. //
  757. // This is carefully arranged so that it can build
  758. // with either the NT 4 or NT 5 DDK, and then in either case
  759. // run on NT 4 (registering with NDIS 4) and
  760. // run on NT 5 (registering with NDIS 5).
  761. //
  762. NDIS50_PROTOCOL_CHARACTERISTICS LanCharacteristics = {
  763. 0, // NdisMajorVersion
  764. 0, // NdisMinorVersion
  765. // This field was added in NT 5. (Previously it was just a hole.)
  766. #ifdef NDIS_FLAGS_DONT_LOOPBACK
  767. 0, // Filler
  768. #endif
  769. 0, // Flags
  770. LanOpenAdapterComplete,
  771. LanCloseAdapterComplete,
  772. LanTransmitComplete,
  773. LanTDComplete,
  774. LanResetComplete,
  775. LanRequestComplete,
  776. LanReceive,
  777. LanReceiveComplete,
  778. LanStatus,
  779. LanStatusComplete,
  780. { 0, 0, 0 }, // Name
  781. LanReceivePacket,
  782. LanBindAdapter,
  783. LanUnbindAdapter,
  784. // The type of this field changed between NT 4 and NT 5.
  785. #ifdef NDIS_FLAGS_DONT_LOOPBACK
  786. LanPnPEvent,
  787. #else
  788. (TRANSLATE_HANDLER) LanPnPEvent,
  789. #endif
  790. NULL,
  791. NULL,
  792. NULL,
  793. NULL,
  794. NULL,
  795. NULL
  796. };
  797. #pragma BEGIN_INIT
  798. //* LanInit
  799. //
  800. // This functions intializes the Lan module.
  801. // In particular, it registers with NDIS.
  802. //
  803. // Returns FALSE to indicate failure to initialize.
  804. //
  805. int
  806. LanInit(void)
  807. {
  808. NDIS_STATUS Status;
  809. RtlInitUnicodeString(&LanCharacteristics.Name, LanName);
  810. //
  811. // We try to register with NDIS major version = 5. If this fails we try
  812. // again for NDIS major version = 4. If this also fails we exit without
  813. // any further attempts to register with NDIS.
  814. //
  815. LanCharacteristics.MajorNdisVersion = 5;
  816. NdisRegisterProtocol(&Status, &LanHandle,
  817. (NDIS_PROTOCOL_CHARACTERISTICS *) &LanCharacteristics,
  818. sizeof(NDIS50_PROTOCOL_CHARACTERISTICS));
  819. if (Status != NDIS_STATUS_SUCCESS) {
  820. LanCharacteristics.MajorNdisVersion = 4;
  821. //
  822. // NDIS 4 has a different semantics - it has TranslateHandler
  823. // instead of PnPEventHandler. So do not supply that handler.
  824. //
  825. #ifdef NDIS_FLAGS_DONT_LOOPBACK
  826. LanCharacteristics.PnPEventHandler = NULL;
  827. #else
  828. LanCharacteristics.TranslateHandler = NULL;
  829. #endif
  830. NdisRegisterProtocol(&Status, &LanHandle,
  831. (NDIS_PROTOCOL_CHARACTERISTICS *) &LanCharacteristics,
  832. sizeof(NDIS40_PROTOCOL_CHARACTERISTICS));
  833. if (Status != NDIS_STATUS_SUCCESS) {
  834. //
  835. // Can't register at all. Just bail out...
  836. //
  837. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_NTOS_ERROR,
  838. "LanInit: could not register -> %x\n", Status));
  839. return FALSE;
  840. }
  841. }
  842. //
  843. // We've registered OK using NDIS.
  844. //
  845. NdisVersion = LanCharacteristics.MajorNdisVersion;
  846. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INFO_STATE,
  847. "LanInit: registered with NDIS %u.\n", NdisVersion));
  848. return TRUE;
  849. }
  850. #pragma END_INIT
  851. //* LanUnload
  852. //
  853. // Called when then IPv6 stack is unloading.
  854. // We need to disconnect from NDIS.
  855. //
  856. void
  857. LanUnload(void)
  858. {
  859. NDIS_STATUS Status;
  860. //
  861. // At this point, the adapters should already all be closed
  862. // because IPUnload is called first and does that.
  863. //
  864. NdisDeregisterProtocol(&Status, LanHandle);
  865. }
  866. //* LanFreeInterface - Free a Lan interface
  867. //
  868. // Called in the event of some sort of initialization failure. We free all
  869. // the memory associated with an Lan interface.
  870. //
  871. void
  872. LanFreeInterface(
  873. LanInterface *Interface) // Interface structure to be freed.
  874. {
  875. NDIS_STATUS Status;
  876. //
  877. // If we're bound to the adapter, close it now.
  878. //
  879. if (Interface->ai_handle != NULL) {
  880. KeInitializeEvent(&Interface->ai_event, SynchronizationEvent, FALSE);
  881. NdisCloseAdapter(&Status, Interface->ai_handle);
  882. if (Status == NDIS_STATUS_PENDING) {
  883. (void) KeWaitForSingleObject(&Interface->ai_event, UserRequest,
  884. KernelMode, FALSE, NULL);
  885. Status = Interface->ai_status;
  886. }
  887. }
  888. //
  889. // Free the Transfer Data Packet, if any, for this interface.
  890. //
  891. if (Interface->ai_tdpacket != NULL)
  892. IPv6FreePacket(Interface->ai_tdpacket);
  893. //
  894. // Free the interface structure itself.
  895. //
  896. ExFreePool(Interface);
  897. }
  898. //* LanAllocateTDPacket
  899. //
  900. // Allocate a packet for NdisTransferData.
  901. // We always allocate contiguous space for a full MTU of data.
  902. //
  903. PNDIS_PACKET
  904. LanAllocateTDPacket(
  905. LanInterface *Interface) // Interface for which to allocate TD packet.
  906. {
  907. PNDIS_PACKET Packet;
  908. void *Mem;
  909. NDIS_STATUS Status;
  910. Status = IPv6AllocatePacket(Interface->ai_mtu, &Packet, &Mem);
  911. if (Status != NDIS_STATUS_SUCCESS)
  912. return NULL;
  913. return Packet;
  914. }
  915. extern uint UseEtherSNAP(PNDIS_STRING Name);
  916. //* LanRegister - Register a protocol with the Lan module.
  917. //
  918. // We register an adapter for Lan processing and create a LanInterface
  919. // structure to represent it. We also open the NDIS adapter here.
  920. //
  921. // REVIEW: Should we set the packet filter to NOT accept broadcast packets?
  922. // REVIEW: Broadcast isn't used in IPv6. Junk bcast* stuff as well? Switch
  923. // REVIEW: this to keeping track of multicasts?
  924. //
  925. int
  926. LanRegister(
  927. PNDIS_STRING Adapter, // Name of the adapter to bind to.
  928. struct LanInterface **Interface) // Where to return new interace.
  929. {
  930. LanInterface *ai; // Pointer to interface struct for this interface.
  931. NDIS_STATUS Status, OpenStatus; // Status values.
  932. uint i = 0; // Medium index.
  933. NDIS_MEDIUM MediaArray[2];
  934. uint instance;
  935. uint mss;
  936. uint speed;
  937. uchar bcastmask, bcastval, bcastoff, addrlen, hdrsize;
  938. NDIS_OID OID;
  939. uint PF;
  940. //
  941. // Allocate memory to hold new interface.
  942. //
  943. ai = (LanInterface *) ExAllocatePool(NonPagedPool, sizeof(LanInterface));
  944. if (ai == NULL)
  945. return FALSE; // Couldn't allocate memory for this one.
  946. RtlZeroMemory(ai, sizeof(LanInterface));
  947. //
  948. // In actual practice, we've only tested Ethernet and FDDI.
  949. // So disallow other media for now.
  950. //
  951. MediaArray[0] = NdisMedium802_3;
  952. MediaArray[1] = NdisMediumFddi;
  953. #if 0
  954. MediaArray[2] = NdisMedium802_5;
  955. #endif
  956. // Initialize this adapter interface structure.
  957. ai->ai_state = INTERFACE_INIT;
  958. ai->ai_media_check = MEDIA_CHECK_QUERY;
  959. // Initialize the locks.
  960. KeInitializeSpinLock(&ai->ai_lock);
  961. KeInitializeEvent(&ai->ai_event, SynchronizationEvent, FALSE);
  962. // Open the NDIS adapter.
  963. NdisOpenAdapter(&Status, &OpenStatus, &ai->ai_handle,
  964. &i, MediaArray, 2,
  965. LanHandle, ai, Adapter, 0, NULL);
  966. // Block for open to complete.
  967. if (Status == NDIS_STATUS_PENDING) {
  968. (void) KeWaitForSingleObject(&ai->ai_event, UserRequest, KernelMode,
  969. FALSE, NULL);
  970. Status = ai->ai_status;
  971. }
  972. ai->ai_media = MediaArray[i]; // Fill in media type.
  973. //
  974. // Open adapter completed. If it succeeded, we'll finish our
  975. // intialization. If it failed, bail out now.
  976. //
  977. if (Status != NDIS_STATUS_SUCCESS) {
  978. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_NTOS_ERROR,
  979. "LanRegister: Adapter failed to initialize."
  980. " Status = 0x%x\n", Status));
  981. ai->ai_handle = NULL;
  982. goto ErrorReturn;
  983. }
  984. //
  985. // Read the maximum frame size.
  986. //
  987. Status = DoNDISRequest(ai, NdisRequestQueryInformation,
  988. OID_GEN_MAXIMUM_FRAME_SIZE, &mss,
  989. sizeof(mss), NULL);
  990. if (Status != NDIS_STATUS_SUCCESS) {
  991. //
  992. // Failed to get maximum frame size. Bail.
  993. //
  994. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_NTOS_ERROR,
  995. "LanRegister: Failed to get maximum frame size. "
  996. "Status = 0x%x\n", Status));
  997. goto ErrorReturn;
  998. }
  999. //
  1000. // Read the local link-level address from the adapter.
  1001. //
  1002. switch (ai->ai_media) {
  1003. case NdisMedium802_3:
  1004. addrlen = IEEE_802_ADDR_LENGTH;
  1005. bcastmask = ETHER_BCAST_MASK;
  1006. bcastval = ETHER_BCAST_VAL;
  1007. bcastoff = ETHER_BCAST_OFF;
  1008. OID = OID_802_3_CURRENT_ADDRESS;
  1009. hdrsize = sizeof(EtherHeader);
  1010. if (UseEtherSNAP(Adapter)) {
  1011. hdrsize += sizeof(SNAPHeader);
  1012. }
  1013. PF = NDIS_PACKET_TYPE_BROADCAST | NDIS_PACKET_TYPE_DIRECTED |
  1014. NDIS_PACKET_TYPE_MULTICAST;
  1015. break;
  1016. case NdisMedium802_5:
  1017. addrlen = IEEE_802_ADDR_LENGTH;
  1018. bcastmask = TR_BCAST_MASK;
  1019. bcastval = TR_BCAST_VAL;
  1020. bcastoff = TR_BCAST_OFF;
  1021. OID = OID_802_5_CURRENT_ADDRESS;
  1022. hdrsize = sizeof(TRHeader) + sizeof(SNAPHeader);
  1023. PF = NDIS_PACKET_TYPE_BROADCAST | NDIS_PACKET_TYPE_DIRECTED;
  1024. //
  1025. // Figure out the RC len stuff now.
  1026. //
  1027. mss -= (sizeof(RC) + (MAX_RD * sizeof(ushort)));
  1028. break;
  1029. case NdisMediumFddi:
  1030. addrlen = IEEE_802_ADDR_LENGTH;
  1031. bcastmask = FDDI_BCAST_MASK;
  1032. bcastval = FDDI_BCAST_VAL;
  1033. bcastoff = FDDI_BCAST_OFF;
  1034. OID = OID_FDDI_LONG_CURRENT_ADDR;
  1035. hdrsize = sizeof(FDDIHeader) + sizeof(SNAPHeader);
  1036. PF = NDIS_PACKET_TYPE_BROADCAST | NDIS_PACKET_TYPE_DIRECTED |
  1037. NDIS_PACKET_TYPE_MULTICAST;
  1038. mss = MIN(mss, FDDI_MSS);
  1039. break;
  1040. default:
  1041. ASSERT(!"bad medium from Ndis");
  1042. goto ErrorReturn;
  1043. }
  1044. //
  1045. // NDIS exposes the tunnel interface as 802_3, but ensures that it's the
  1046. // only interface for which OID_CUSTOM_TUNMP_INSTANCE_ID returns success.
  1047. //
  1048. if (DoNDISRequest(ai, NdisRequestQueryInformation,
  1049. OID_CUSTOM_TUNMP_INSTANCE_ID, &instance,
  1050. sizeof(instance), NULL) == NDIS_STATUS_SUCCESS) {
  1051. ai->ai_media = NdisMediumTunnel;
  1052. //
  1053. // These values are chosen so NUCast returns FALSE.
  1054. //
  1055. bcastmask = 0;
  1056. bcastval = 1;
  1057. bcastoff = 0;
  1058. hdrsize = 0;
  1059. //
  1060. // Since we do not construct an ethernet header on transmission, or
  1061. // expect one on receive, we need to ensure that NDIS does not attempt
  1062. // to parse frames on this interface. On transmission this is achieved
  1063. // by setting the NDIS_FLAGS_DONT_LOOPBACK flag. Receives are made
  1064. // NDIS-Safe by setting the interface in promiscuous mode.
  1065. //
  1066. PF |= NDIS_PACKET_TYPE_PROMISCUOUS;
  1067. //
  1068. // This is what NDIS should have provided us.
  1069. //
  1070. mss = IPv6_MINIMUM_MTU;
  1071. }
  1072. ai->ai_bcastmask = bcastmask;
  1073. ai->ai_bcastval = bcastval;
  1074. ai->ai_bcastoff = bcastoff;
  1075. ai->ai_addrlen = addrlen;
  1076. ai->ai_hdrsize = hdrsize;
  1077. ai->ai_pfilter = PF;
  1078. ai->ai_mtu = (ushort)mss;
  1079. Status = DoNDISRequest(ai, NdisRequestQueryInformation, OID,
  1080. ai->ai_addr, addrlen, NULL);
  1081. if (Status != NDIS_STATUS_SUCCESS) {
  1082. //
  1083. // Failed to get link-level address. Bail.
  1084. //
  1085. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_NTOS_ERROR,
  1086. "LanRegister: Failed to get link-level address. "
  1087. "Status = 0x%x\n", Status));
  1088. goto ErrorReturn;
  1089. }
  1090. //
  1091. // Read the speed for local purposes.
  1092. // If we can't read the speed that's OK.
  1093. //
  1094. Status = DoNDISRequest(ai, NdisRequestQueryInformation,
  1095. OID_GEN_LINK_SPEED, &speed, sizeof(speed), NULL);
  1096. if (Status == NDIS_STATUS_SUCCESS) {
  1097. ai->ai_speed = speed * 100L;
  1098. }
  1099. //
  1100. // Set the lookahead. This is the minimum amount of packet data
  1101. // that we wish to see contiguously for every packet received.
  1102. //
  1103. Status = DoNDISRequest(ai, NdisRequestSetInformation,
  1104. OID_GEN_CURRENT_LOOKAHEAD,
  1105. &LanLookahead, sizeof LanLookahead, NULL);
  1106. if (Status != NDIS_STATUS_SUCCESS) {
  1107. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_NTOS_ERROR,
  1108. "LanRegister: Failed to set lookahead. "
  1109. "Status = 0x%x\n", Status));
  1110. goto ErrorReturn;
  1111. }
  1112. //
  1113. // Allocate a Tranfer Data packet for this interface.
  1114. //
  1115. ai->ai_tdpacket = LanAllocateTDPacket(ai);
  1116. *Interface = ai;
  1117. return TRUE;
  1118. ErrorReturn:
  1119. LanFreeInterface(ai);
  1120. return FALSE;
  1121. }
  1122. //* LanCreateToken
  1123. //
  1124. // Given a link-layer address, creates a 64-bit "interface identifier"
  1125. // in the low eight bytes of an IPv6 address.
  1126. // Does not modify the other bytes in the IPv6 address.
  1127. //
  1128. void
  1129. LanCreateToken(
  1130. void *Context, // Interface from which to take interface identifier.
  1131. IPv6Addr *Address) // IPv6 address to place token into.
  1132. {
  1133. LanInterface *Interface = (LanInterface *)Context;
  1134. uchar *IEEEAddress = Interface->ai_addr;
  1135. //
  1136. // This is formed the same way for Ethernet, FDDI and Tunnel.
  1137. //
  1138. Address->s6_bytes[8] = IEEEAddress[0] ^ 0x2;
  1139. Address->s6_bytes[9] = IEEEAddress[1];
  1140. Address->s6_bytes[10] = IEEEAddress[2];
  1141. Address->s6_bytes[11] = 0xff;
  1142. Address->s6_bytes[12] = 0xfe;
  1143. Address->s6_bytes[13] = IEEEAddress[3];
  1144. Address->s6_bytes[14] = IEEEAddress[4];
  1145. Address->s6_bytes[15] = IEEEAddress[5];
  1146. }
  1147. //* LanTunnelCreateToken
  1148. //
  1149. // Given a link-layer address, creates a 64-bit "interface identifier"
  1150. // in the low eight bytes of an IPv6 address.
  1151. // Does not modify the other bytes in the IPv6 address.
  1152. //
  1153. void
  1154. LanTunnelCreateToken(
  1155. void *Context, // Interface from which to take interface identifier.
  1156. IPv6Addr *Address) // IPv6 address to place token into.
  1157. {
  1158. LanInterface *Interface = (LanInterface *)Context;
  1159. //
  1160. // Only called for tunnels configured with the default MAC address.
  1161. //
  1162. ASSERT((Interface->ai_media == NdisMediumTunnel) &&
  1163. RtlEqualMemory(
  1164. TUN_CARD_ADDRESS, Interface->ai_addr, Interface->ai_addrlen));
  1165. //
  1166. // Non link-local addresses still use the regular interface identifier.
  1167. //
  1168. if (!IsLinkLocal(Address)) {
  1169. LanCreateToken(Context, Address);
  1170. return;
  1171. }
  1172. //
  1173. // Create a random interface identifier for the link-local address.
  1174. //
  1175. do {
  1176. uint Identifier[2];
  1177. Identifier[0] = Random();
  1178. Identifier[1] = Random();
  1179. RtlCopyMemory(&Address->s6_bytes[8], (uchar *)Identifier, 8);
  1180. //
  1181. // Clear the universal/local bit to indicate local significance.
  1182. //
  1183. Address->s6_bytes[8] &= ~0x2;
  1184. } while (IsKnownAnycast(Address));
  1185. }
  1186. //* LanReadLinkLayerAddressOption - Parse a ND link-layer address option.
  1187. //
  1188. // Parses a Neighbor Discovery link-layer address option
  1189. // and if valid, returns a pointer to the link-layer address.
  1190. //
  1191. const void *
  1192. LanReadLinkLayerAddressOption(
  1193. void *Context, // Interface for which ND option applies.
  1194. const uchar *OptionData) // Option data to parse.
  1195. {
  1196. LanInterface *Interface = (LanInterface *)Context;
  1197. //
  1198. // Check that the option length is correct,
  1199. // allowing for the option type/length bytes
  1200. // and rounding up to 8-byte units.
  1201. //
  1202. if (((Interface->ai_addrlen + 2 + 7)/8) != OptionData[1])
  1203. return NULL;
  1204. //
  1205. // Skip over the option type and length bytes,
  1206. // and return a pointer to the option data.
  1207. //
  1208. return OptionData + 2;
  1209. }
  1210. //* LanWriteLinkLayerAddressOption - Create a ND link-layer address option.
  1211. //
  1212. // Creates a Neighbor Discovery link-layer address option.
  1213. // Our caller takes care of the option type & length fields.
  1214. // We handle the padding/alignment/placement of the link address
  1215. // into the option data.
  1216. //
  1217. // (Our caller allocates space for the option by adding 2 to the
  1218. // link address length and rounding up to a multiple of 8.)
  1219. //
  1220. void
  1221. LanWriteLinkLayerAddressOption(
  1222. void *Context, // Interface to create option regarding.
  1223. uchar *OptionData, // Where the option data resides.
  1224. const void *LinkAddress) // Link-level address.
  1225. {
  1226. LanInterface *Interface = (LanInterface *)Context;
  1227. //
  1228. // Place the address after the option type/length bytes.
  1229. //
  1230. RtlCopyMemory(OptionData + 2, LinkAddress, Interface->ai_addrlen);
  1231. }
  1232. //* LanTunnelConvertAddress
  1233. //
  1234. // LanTunnel does not use Neighbor Discovery or link-layer addresses.
  1235. //
  1236. ushort
  1237. LanTunnelConvertAddress(
  1238. void *Context, // Unused (nominally, our LanInterface).
  1239. const IPv6Addr *Address, // IPv6 multicast address.
  1240. void *LinkAddress) // Where link-level address to be filled resides.
  1241. {
  1242. LanInterface *Interface = (LanInterface *)Context;
  1243. ASSERT(Interface->ai_media == NdisMediumTunnel);
  1244. UNREFERENCED_PARAMETER(Address);
  1245. RtlCopyMemory(LinkAddress, Interface->ai_addr, Interface->ai_addrlen);
  1246. //
  1247. // Make the neighbor link layer address different from our own. This
  1248. // ensures that IPv6SendLL does not loop back packets destined for them.
  1249. // In fact, a link layer address on the tunnel interface is faked only
  1250. // because IPv6SendLL does not handle zero length link layer addresses!
  1251. //
  1252. ASSERT(Interface->ai_addrlen != 0);
  1253. ((PUCHAR) LinkAddress)[Interface->ai_addrlen - 1] =
  1254. ~((PUCHAR) LinkAddress)[Interface->ai_addrlen - 1];
  1255. return ND_STATE_PERMANENT;
  1256. }
  1257. //* LanConvertAddress
  1258. //
  1259. // Converts an IPv6 multicast address to a link-layer address.
  1260. // Generally this requires hashing the IPv6 address into a set
  1261. // of link-layer addresses, in a link-layer-specific way.
  1262. //
  1263. ushort
  1264. LanConvertAddress(
  1265. void *Context, // Unused (nominally, our LanInterface).
  1266. const IPv6Addr *Address, // IPv6 multicast address.
  1267. void *LinkAddress) // Where link-level address to be filled resides.
  1268. {
  1269. UNREFERENCED_PARAMETER(Context);
  1270. if (IsMulticast(Address)) {
  1271. uchar *IEEEAddress = (uchar *)LinkAddress;
  1272. //
  1273. // This is formed the same way for Ethernet and FDDI.
  1274. //
  1275. IEEEAddress[0] = 0x33;
  1276. IEEEAddress[1] = 0x33;
  1277. IEEEAddress[2] = Address->s6_bytes[12];
  1278. IEEEAddress[3] = Address->s6_bytes[13];
  1279. IEEEAddress[4] = Address->s6_bytes[14];
  1280. IEEEAddress[5] = Address->s6_bytes[15];
  1281. return ND_STATE_PERMANENT;
  1282. }
  1283. else {
  1284. //
  1285. // We can't guess at the correct link-layer address.
  1286. //
  1287. return ND_STATE_INCOMPLETE;
  1288. }
  1289. }
  1290. //* LanSetMulticastAddressList
  1291. //
  1292. // Takes an array of link-layer multicast addresses
  1293. // (from LanConvertMulticastAddress) from which we should
  1294. // receive packets. Passes them to NDIS.
  1295. //
  1296. NDIS_STATUS
  1297. LanSetMulticastAddressList(
  1298. void *Context,
  1299. const void *LinkAddresses,
  1300. uint NumKeep,
  1301. uint NumAdd,
  1302. uint NumDel)
  1303. {
  1304. LanInterface *Interface = (LanInterface *)Context;
  1305. NDIS_STATUS Status;
  1306. NDIS_OID OID;
  1307. UNREFERENCED_PARAMETER(NumDel);
  1308. //
  1309. // Set the multicast address list to the current list.
  1310. // The OID to do this depends upon the media type.
  1311. //
  1312. switch (Interface->ai_media) {
  1313. case NdisMedium802_3:
  1314. OID = OID_802_3_MULTICAST_LIST;
  1315. break;
  1316. case NdisMediumFddi:
  1317. OID = OID_FDDI_LONG_MULTICAST_LIST;
  1318. break;
  1319. default:
  1320. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INTERNAL_ERROR,
  1321. "LanSetMulticastAddressList: Unknown media type\n"));
  1322. return NDIS_STATUS_FAILURE;
  1323. }
  1324. Status = DoNDISRequest(Interface, NdisRequestSetInformation,
  1325. OID, (char *)LinkAddresses,
  1326. (NumKeep + NumAdd) * Interface->ai_addrlen, NULL);
  1327. //
  1328. // If the above request was successful, then turn off the all-multicast
  1329. // or all-packets filter if we had previously set one of them.
  1330. //
  1331. if (Status == NDIS_STATUS_SUCCESS) {
  1332. if (Interface->ai_pfilter & NDIS_PACKET_TYPE_ALL_MULTICAST ||
  1333. Interface->ai_pfilter & NDIS_PACKET_TYPE_PROMISCUOUS) {
  1334. Interface->ai_pfilter &= ~(NDIS_PACKET_TYPE_ALL_MULTICAST |
  1335. NDIS_PACKET_TYPE_PROMISCUOUS);
  1336. DoNDISRequest(Interface, NdisRequestSetInformation,
  1337. OID_GEN_CURRENT_PACKET_FILTER, &Interface->ai_pfilter,
  1338. sizeof(uint), NULL);
  1339. }
  1340. return Status;
  1341. }
  1342. //
  1343. // We get here only if the NDIS request to set the multicast list fails.
  1344. // First we try to set the packet filter for all multicast packets, and if
  1345. // this fails, we try to set the packet filter for all packets.
  1346. //
  1347. // This code was swiped from the V4 stack: arp.c
  1348. Interface->ai_pfilter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
  1349. Status = DoNDISRequest(Interface, NdisRequestSetInformation,
  1350. OID_GEN_CURRENT_PACKET_FILTER, &Interface->ai_pfilter,
  1351. sizeof(uint), NULL);
  1352. if (Status != NDIS_STATUS_SUCCESS) {
  1353. // All multicast failed, try all packets.
  1354. Interface->ai_pfilter &= ~(NDIS_PACKET_TYPE_ALL_MULTICAST);
  1355. Interface->ai_pfilter |= NDIS_PACKET_TYPE_PROMISCUOUS;
  1356. Status = DoNDISRequest(Interface, NdisRequestSetInformation,
  1357. OID_GEN_CURRENT_PACKET_FILTER, &Interface->ai_pfilter,
  1358. sizeof(uint), NULL);
  1359. }
  1360. return Status;
  1361. }
  1362. //* LanCloseAdapter
  1363. //
  1364. // The IPv6 layer calls this function to close a connection to an adapter.
  1365. //
  1366. void
  1367. LanCloseAdapter(void *Context)
  1368. {
  1369. LanInterface *Interface = (LanInterface *)Context;
  1370. //
  1371. // Mark adapter down.
  1372. //
  1373. Interface->ai_state = INTERFACE_DOWN;
  1374. //
  1375. // Shut adapter up, so we don't get any more frames.
  1376. //
  1377. Interface->ai_pfilter = 0;
  1378. DoNDISRequest(Interface, NdisRequestSetInformation,
  1379. OID_GEN_CURRENT_PACKET_FILTER,
  1380. &Interface->ai_pfilter, sizeof(uint), NULL);
  1381. //
  1382. // Release our reference for the interface.
  1383. //
  1384. ReleaseInterface(Interface->ai_context);
  1385. }
  1386. //* LanCleanupAdapter
  1387. //
  1388. // Perform final cleanup of the adapter.
  1389. //
  1390. void
  1391. LanCleanupAdapter(void *Context)
  1392. {
  1393. LanInterface *Interface = (LanInterface *)Context;
  1394. NDIS_STATUS Status;
  1395. KeInitializeEvent(&Interface->ai_event, SynchronizationEvent, FALSE);
  1396. //
  1397. // Close the connection to NDIS.
  1398. //
  1399. NdisCloseAdapter(&Status, Interface->ai_handle);
  1400. //
  1401. // Block for close to complete.
  1402. //
  1403. if (Status == NDIS_STATUS_PENDING) {
  1404. (void) KeWaitForSingleObject(&Interface->ai_event,
  1405. UserRequest, KernelMode,
  1406. FALSE, NULL);
  1407. Status = Interface->ai_status;
  1408. }
  1409. if (Status != NDIS_STATUS_SUCCESS) {
  1410. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_NTOS_ERROR,
  1411. "LanCleanupAdapter(%p) - NdisCloseAdapter -> %x\n",
  1412. Interface, Status));
  1413. }
  1414. //
  1415. // Tell NDIS that we are done.
  1416. // NOTE: IOCTL_IPV6_DELETE_INTERFACE does not set ai_unbind, this
  1417. // ensures that NdisCompleteUnbindAdapter is not invoked along its path.
  1418. //
  1419. if (Interface->ai_unbind != NULL)
  1420. NdisCompleteUnbindAdapter(Interface->ai_unbind, NDIS_STATUS_SUCCESS);
  1421. //
  1422. // Free adapter memory.
  1423. //
  1424. IPv6FreePacket(Interface->ai_tdpacket);
  1425. ExFreePool(Interface);
  1426. }
  1427. //* LanBindAdapter - Bind and initialize an adapter.
  1428. //
  1429. // Called in a PNP environment to initialize and bind an adapter. We open
  1430. // the adapter and get it running, and then we call up to IP to tell him
  1431. // about it. IP will initialize, and if all goes well call us back to start
  1432. // receiving.
  1433. //
  1434. void NDIS_API
  1435. LanBindAdapter(
  1436. PNDIS_STATUS RetStatus, // Where to return status of this call.
  1437. NDIS_HANDLE BindContext, // Handle for calling BindingAdapterComplete.
  1438. PNDIS_STRING AdapterName, // Name of adapter.
  1439. PVOID SS1, // System specific parameter 1.
  1440. PVOID SS2) // System specific parameter 2.
  1441. {
  1442. LanInterface *Interface; // Newly created interface.
  1443. LLIPv6BindInfo BindInfo; // Binding information for IP.
  1444. GUID Guid;
  1445. UNICODE_STRING GuidName;
  1446. uint BindPrefixLength;
  1447. uint MediaStatus;
  1448. NDIS_STATUS Status;
  1449. KIRQL OldIrql;
  1450. UNREFERENCED_PARAMETER(BindContext);
  1451. UNREFERENCED_PARAMETER(SS1);
  1452. UNREFERENCED_PARAMETER(SS2);
  1453. //
  1454. // Convert the NDIS AdapterName to a Guid.
  1455. //
  1456. BindPrefixLength = sizeof(IPV6_BIND_STRING_PREFIX) - sizeof(WCHAR);
  1457. GuidName.Buffer = (PVOID)((char *)AdapterName->Buffer + BindPrefixLength);
  1458. GuidName.Length = AdapterName->Length - BindPrefixLength;
  1459. GuidName.MaximumLength = AdapterName->MaximumLength - BindPrefixLength;
  1460. if (((int)GuidName.Length < 0) ||
  1461. ! NT_SUCCESS(RtlGUIDFromString(&GuidName, &Guid))) {
  1462. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INTERNAL_ERROR,
  1463. "LanBindAdapter(%.*ls) - bad guid\n",
  1464. AdapterName->Length / sizeof(WCHAR),
  1465. AdapterName->Buffer));
  1466. *RetStatus = NDIS_STATUS_FAILURE;
  1467. return;
  1468. }
  1469. //
  1470. // Now open the adapter and get the info.
  1471. //
  1472. if (!LanRegister(AdapterName, &Interface)) {
  1473. *RetStatus = NDIS_STATUS_FAILURE;
  1474. return;
  1475. }
  1476. //
  1477. // OK, we've opened the adapter. Notify IP about it.
  1478. //
  1479. BindInfo.lip_context = Interface;
  1480. BindInfo.lip_transmit = LanTransmit;
  1481. BindInfo.lip_token = LanCreateToken;
  1482. BindInfo.lip_close = LanCloseAdapter;
  1483. BindInfo.lip_cleanup = LanCleanupAdapter;
  1484. BindInfo.lip_defmtu = BindInfo.lip_maxmtu = Interface->ai_mtu;
  1485. BindInfo.lip_hdrsize = Interface->ai_hdrsize;
  1486. BindInfo.lip_addrlen = Interface->ai_addrlen;
  1487. BindInfo.lip_addr = Interface->ai_addr;
  1488. BindInfo.lip_setrtrlladdr = NULL;
  1489. switch (Interface->ai_media) {
  1490. case NdisMediumTunnel:
  1491. BindInfo.lip_type = IF_TYPE_TUNNEL_TEREDO;
  1492. BindInfo.lip_rdllopt = NULL;
  1493. BindInfo.lip_wrllopt = NULL;
  1494. BindInfo.lip_cvaddr = LanTunnelConvertAddress;
  1495. BindInfo.lip_mclist = NULL;
  1496. BindInfo.lip_flags = IF_FLAG_ROUTER_DISCOVERS;
  1497. BindInfo.lip_dadxmit = 0;
  1498. BindInfo.lip_pref = LAN_TUNNEL_DEFAULT_PREFERENCE;
  1499. ASSERT(sizeof(TUN_CARD_ADDRESS) >= Interface->ai_addrlen);
  1500. if (RtlEqualMemory(TUN_CARD_ADDRESS,
  1501. Interface->ai_addr,
  1502. Interface->ai_addrlen)) {
  1503. //
  1504. // Create random interface identifiers for link-local addresses to
  1505. // secure them against attackers. Only required when the adapter
  1506. // is configured with the default MAC address.
  1507. //
  1508. BindInfo.lip_token = LanTunnelCreateToken;
  1509. }
  1510. break;
  1511. case NdisMedium802_3:
  1512. BindInfo.lip_type = IF_TYPE_ETHERNET;
  1513. goto Default;
  1514. case NdisMediumFddi:
  1515. BindInfo.lip_type = IF_TYPE_FDDI;
  1516. goto Default;
  1517. default:
  1518. ASSERT(! "unrecognized ai_media type");
  1519. BindInfo.lip_type = 0;
  1520. Default:
  1521. BindInfo.lip_rdllopt = LanReadLinkLayerAddressOption;
  1522. BindInfo.lip_wrllopt = LanWriteLinkLayerAddressOption;
  1523. BindInfo.lip_cvaddr = LanConvertAddress;
  1524. BindInfo.lip_mclist = LanSetMulticastAddressList;
  1525. BindInfo.lip_flags = IF_FLAG_NEIGHBOR_DISCOVERS |
  1526. IF_FLAG_ROUTER_DISCOVERS | IF_FLAG_MULTICAST;
  1527. BindInfo.lip_dadxmit = 1; // Per RFC 2462.
  1528. BindInfo.lip_pref = 0;
  1529. break;
  1530. }
  1531. //
  1532. // Should we create the interface in the disconnected state?
  1533. //
  1534. Status = DoNDISRequest(Interface, NdisRequestQueryInformation,
  1535. OID_GEN_MEDIA_CONNECT_STATUS,
  1536. &MediaStatus, sizeof MediaStatus, NULL);
  1537. if (Status == NDIS_STATUS_SUCCESS) {
  1538. if (MediaStatus == NdisMediaStateDisconnected) {
  1539. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INFO_STATE,
  1540. "LanBindAdapter(%p) - media disconnect\n", Interface));
  1541. BindInfo.lip_flags |= IF_FLAG_MEDIA_DISCONNECTED;
  1542. }
  1543. }
  1544. if (CreateInterface(&Guid, &BindInfo, &Interface->ai_context) !=
  1545. NDIS_STATUS_SUCCESS) {
  1546. //
  1547. // Attempt to create IP interface failed. Need to close the binding.
  1548. // LanFreeInterface will do that, as well as freeing resources.
  1549. //
  1550. LanFreeInterface(Interface);
  1551. *RetStatus = NDIS_STATUS_FAILURE;
  1552. return;
  1553. }
  1554. //
  1555. // It's quite possible that during our initialization sequence,
  1556. // LanStatus was called to indicate a media connectivity change.
  1557. // Some adapters are bound in the non-connected state and then
  1558. // shortly after indicate that they are connected.
  1559. // The above connectivity query may have returned the wrong result.
  1560. //
  1561. // An intervening LanStatus indication will change ai_media_check
  1562. // from MEDIA_CHECK_QUERY to MEDIA_CHECK_CONFLICT.
  1563. //
  1564. Status = NDIS_STATUS_FAILURE;
  1565. KeAcquireSpinLock(&Interface->ai_lock, &OldIrql);
  1566. while (Interface->ai_media_check == MEDIA_CHECK_CONFLICT) {
  1567. Interface->ai_media_check = MEDIA_CHECK_QUERY;
  1568. KeReleaseSpinLock(&Interface->ai_lock, OldIrql);
  1569. Status = DoNDISRequest(Interface, NdisRequestQueryInformation,
  1570. OID_GEN_MEDIA_CONNECT_STATUS,
  1571. &MediaStatus, sizeof MediaStatus, NULL);
  1572. KeAcquireSpinLock(&Interface->ai_lock, &OldIrql);
  1573. }
  1574. Interface->ai_media_check = MEDIA_CHECK_IDLE;
  1575. if (Status == NDIS_STATUS_SUCCESS)
  1576. SetInterfaceLinkStatus(Interface->ai_context,
  1577. MediaStatus != NdisMediaStateDisconnected);
  1578. KeReleaseSpinLock(&Interface->ai_lock, OldIrql);
  1579. Status = DoNDISRequest(Interface, NdisRequestSetInformation,
  1580. OID_GEN_CURRENT_PACKET_FILTER,
  1581. &Interface->ai_pfilter,
  1582. sizeof Interface->ai_pfilter,
  1583. NULL);
  1584. if (Status == NDIS_STATUS_SUCCESS)
  1585. Interface->ai_state = INTERFACE_UP;
  1586. else
  1587. Interface->ai_state = INTERFACE_DOWN;
  1588. *RetStatus = NDIS_STATUS_SUCCESS;
  1589. }
  1590. //* LanUnbindAdapter - Unbind from an adapter.
  1591. //
  1592. // Called when we need to unbind from an adapter.
  1593. // We'll notify IP, then free our memory and return.
  1594. //
  1595. void NDIS_API // Returns: Nothing.
  1596. LanUnbindAdapter(
  1597. PNDIS_STATUS RetStatus, // Where to return status from this call.
  1598. NDIS_HANDLE ProtBindContext, // Context we gave NDIS earlier.
  1599. NDIS_HANDLE UnbindContext) // Context for completing this request.
  1600. {
  1601. LanInterface *Interface = (LanInterface *)ProtBindContext;
  1602. Interface->ai_unbind = UnbindContext;
  1603. //
  1604. // Call IP to destroy the interface.
  1605. // IP will call LanCloseAdapter then LanCleanupAdapter.
  1606. //
  1607. DestroyInterface(Interface->ai_context);
  1608. //
  1609. // We will call NdisCompleteUnbindAdapter later,
  1610. // when NdisCloseAdapter completes.
  1611. //
  1612. *RetStatus = NDIS_STATUS_PENDING;
  1613. }
  1614. //* LanPnPEvent
  1615. //
  1616. // Gets called for plug'n'play and power-management events.
  1617. //
  1618. NDIS_STATUS NDIS_API
  1619. LanPnPEvent(
  1620. NDIS_HANDLE ProtocolBindingContext,
  1621. PNET_PNP_EVENT NetPnPEvent)
  1622. {
  1623. LanInterface *Interface = (LanInterface *) ProtocolBindingContext;
  1624. switch (NetPnPEvent->NetEvent) {
  1625. case NetEventSetPower: {
  1626. NET_DEVICE_POWER_STATE PowerState;
  1627. //
  1628. // Get the power state of the interface.
  1629. //
  1630. ASSERT(NetPnPEvent->BufferLength >= sizeof PowerState);
  1631. PowerState = * (NET_DEVICE_POWER_STATE *) NetPnPEvent->Buffer;
  1632. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INFO_STATE,
  1633. "LanPnPEvent(%p) - set power %u\n",
  1634. Interface, PowerState));
  1635. //
  1636. // We ignore the events that tell us about power going away.
  1637. // But when power comes back, we query for connect status.
  1638. // NDIS does not report connect/disconnect events that occur
  1639. // while there is no power.
  1640. //
  1641. // Note that we may be redundantly setting the link status.
  1642. // For example saying that it is disconnected when the
  1643. // IPv6 interface status is already disconnected,
  1644. // or vice-versa. The IPv6 code must deal with this.
  1645. //
  1646. if (PowerState == NetDeviceStateD0) {
  1647. uint MediaStatus;
  1648. NDIS_STATUS Status;
  1649. KIRQL OldIrql;
  1650. KeAcquireSpinLock(&Interface->ai_lock, &OldIrql);
  1651. if (Interface->ai_media_check == MEDIA_CHECK_IDLE) {
  1652. do {
  1653. Interface->ai_media_check = MEDIA_CHECK_QUERY;
  1654. KeReleaseSpinLock(&Interface->ai_lock, OldIrql);
  1655. Status = DoNDISRequest(Interface,
  1656. NdisRequestQueryInformation,
  1657. OID_GEN_MEDIA_CONNECT_STATUS,
  1658. &MediaStatus,
  1659. sizeof MediaStatus,
  1660. NULL);
  1661. KeAcquireSpinLock(&Interface->ai_lock, &OldIrql);
  1662. } while (Interface->ai_media_check == MEDIA_CHECK_CONFLICT);
  1663. Interface->ai_media_check = MEDIA_CHECK_IDLE;
  1664. if (Status == NDIS_STATUS_SUCCESS)
  1665. SetInterfaceLinkStatus(Interface->ai_context,
  1666. MediaStatus != NdisMediaStateDisconnected);
  1667. }
  1668. else
  1669. Interface->ai_media_check = MEDIA_CHECK_CONFLICT;
  1670. KeReleaseSpinLock(&Interface->ai_lock, OldIrql);
  1671. }
  1672. break;
  1673. }
  1674. case NetEventBindsComplete:
  1675. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INFO_STATE,
  1676. "LanPnPEvent(%p) - binds complete\n", Interface));
  1677. IPv6ProviderReady();
  1678. break;
  1679. case NetEventQueryPower:
  1680. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INFO_STATE,
  1681. "LanPnPEvent(%p) - query power\n", Interface));
  1682. break;
  1683. case NetEventQueryRemoveDevice:
  1684. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INFO_STATE,
  1685. "LanPnPEvent(%p) - query remove device\n", Interface));
  1686. break;
  1687. case NetEventCancelRemoveDevice:
  1688. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INFO_STATE,
  1689. "LanPnPEvent(%p) - cancel remove device\n", Interface));
  1690. break;
  1691. case NetEventReconfigure:
  1692. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INFO_STATE,
  1693. "LanPnPEvent(%p) - reconfigure\n", Interface));
  1694. break;
  1695. case NetEventBindList:
  1696. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INFO_STATE,
  1697. "LanPnPEvent(%p) - bind list\n", Interface));
  1698. break;
  1699. case NetEventPnPCapabilities:
  1700. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INFO_STATE,
  1701. "LanPnPEvent(%p) - pnp capabilities\n", Interface));
  1702. break;
  1703. default:
  1704. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INFO_STATE,
  1705. "LanPnPEvent(%p) - unknown code %u length %u\n",
  1706. Interface,
  1707. NetPnPEvent->NetEvent,
  1708. NetPnPEvent->BufferLength));
  1709. break;
  1710. }
  1711. return NDIS_STATUS_SUCCESS;
  1712. }