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.

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