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.

3940 lines
111 KiB

  1. /*++
  2. Copyright (c) 1989-1993 Microsoft Corporation
  3. Module Name:
  4. mac.c
  5. Abstract:
  6. This module contains code which implements Mac type dependent code for
  7. the IPX transport.
  8. Environment:
  9. Kernel mode (Actually, unimportant)
  10. Revision History:
  11. Sanjay Anand (SanjayAn) - 22-Sept-1995
  12. BackFill optimization changes added under #if BACK_FILL
  13. --*/
  14. #include "precomp.h"
  15. #pragma hdrstop
  16. #define TR_LENGTH_MASK 0x1F // low 5 bits in byte
  17. #define TR_DIRECTION_MASK 0x80 // returns direction bit
  18. #define TR_DEFAULT_LENGTH 0x70 // default for outgoing
  19. #define TR_MAX_SIZE_MASK 0x70
  20. #define TR_PREAMBLE_AC 0x10
  21. #define TR_PREAMBLE_FC 0x40
  22. #define FDDI_HEADER_BYTE 0x57
  23. static UCHAR AllRouteSourceRouting[2] = { 0x82, TR_DEFAULT_LENGTH };
  24. static UCHAR SingleRouteSourceRouting[2] = { 0xc2, TR_DEFAULT_LENGTH };
  25. #define ROUTE_EQUAL(_A,_B) { \
  26. (*(UNALIGNED USHORT *)(_A) == *(UNALIGNED USHORT *)(_B)) \
  27. }
  28. //
  29. // For back-fillable packets, chains the back-fill space as a MAC header
  30. // to the packet and sets the header pointer.
  31. //
  32. //
  33. // We dont need to test for IDENTIFIER_IPX since it will always be
  34. // true for the mediumframe specific send handlers.
  35. //
  36. #define BACK_FILL_HEADER(_header, _reserved, _headerlength, _packet) \
  37. if ((_reserved)->Identifier == IDENTIFIER_IPX) { \
  38. if((_reserved)->BackFill) { \
  39. CTEAssert ((_reserved)->HeaderBuffer); \
  40. CTEAssert ((_reserved)->HeaderBuffer->MdlFlags & MDL_NETWORK_HEADER); \
  41. _header = (PCHAR)(_reserved)->HeaderBuffer->MappedSystemVa - (_headerlength); \
  42. (_reserved)->HeaderBuffer->MappedSystemVa = (PCHAR)(_reserved)->HeaderBuffer->MappedSystemVa - (_headerlength); \
  43. (_reserved)->HeaderBuffer->ByteOffset -= (_headerlength); \
  44. ASSERT((LONG)(_reserved)->HeaderBuffer->ByteOffset >= 0); \
  45. NdisChainBufferAtFront(_packet,(PNDIS_BUFFER)(_reserved)->HeaderBuffer); \
  46. } \
  47. }
  48. //
  49. // In case of back-fillable packets, the adjusted length should include
  50. // the prev. bytecount of the headerbuffer.
  51. //
  52. #define BACK_FILL_ADJUST_BUFFER_LENGTH(_reserved, _headerlength) \
  53. if((_reserved)->BackFill){ \
  54. NdisAdjustBufferLength ((_reserved)->HeaderBuffer, _headerlength+(_reserved)->HeaderBuffer->ByteCount); \
  55. IPX_DEBUG(SEND,("mac user mdl %x\n", (_reserved)->HeaderBuffer)); \
  56. } else { \
  57. NdisAdjustBufferLength ((_reserved)->HeaderBuffer, _headerlength); \
  58. }
  59. //
  60. // This is the interpretation of the length bits in
  61. // the 802.5 source-routing information.
  62. //
  63. ULONG SR802_5Lengths[8] = { 516, 1500, 2052, 4472,
  64. 8144, 11407, 17800, 17800 };
  65. VOID
  66. MacInitializeBindingInfo(
  67. IN struct _BINDING * Binding,
  68. IN struct _ADAPTER * Adapter
  69. )
  70. /*++
  71. Routine Description:
  72. Fills in the binding info based on the adapter's MacInfo
  73. and the frame type of the binding.
  74. Arguments:
  75. Binding - The newly created binding.
  76. Adapter - The adapter.
  77. Return Value:
  78. None.
  79. --*/
  80. {
  81. ULONG MaxUserData;
  82. Binding->DefHeaderSize = Adapter->DefHeaderSizes[Binding->FrameType];
  83. Binding->BcMcHeaderSize = Adapter->BcMcHeaderSizes[Binding->FrameType];
  84. MacReturnMaxDataSize(
  85. &Adapter->MacInfo,
  86. NULL,
  87. 0,
  88. Binding->MaxSendPacketSize,
  89. &MaxUserData);
  90. Binding->MaxLookaheadData =
  91. Adapter->MaxReceivePacketSize -
  92. sizeof(IPX_HEADER) -
  93. (Binding->DefHeaderSize - Adapter->MacInfo.MinHeaderLength);
  94. Binding->AnnouncedMaxDatagramSize =
  95. MaxUserData -
  96. sizeof(IPX_HEADER) -
  97. (Binding->DefHeaderSize - Adapter->MacInfo.MinHeaderLength);
  98. Binding->RealMaxDatagramSize =
  99. Binding->MaxSendPacketSize -
  100. Adapter->MacInfo.MaxHeaderLength -
  101. sizeof(IPX_HEADER) -
  102. (Binding->DefHeaderSize - Adapter->MacInfo.MinHeaderLength);
  103. } /* MacInitializeBindingInfo */
  104. VOID
  105. MacInitializeMacInfo(
  106. IN NDIS_MEDIUM MacType,
  107. OUT PNDIS_INFORMATION MacInfo
  108. )
  109. /*++
  110. Routine Description:
  111. Fills in the MacInfo table based on MacType.
  112. Arguments:
  113. MacType - The MAC type we wish to decode.
  114. MacInfo - The MacInfo structure to fill in.
  115. Return Value:
  116. None.
  117. --*/
  118. {
  119. switch (MacType) {
  120. case NdisMedium802_3:
  121. MacInfo->SourceRouting = FALSE;
  122. MacInfo->MediumAsync = FALSE;
  123. MacInfo->BroadcastMask = 0x01;
  124. MacInfo->MaxHeaderLength = 14;
  125. MacInfo->MinHeaderLength = 14;
  126. MacInfo->MediumType = NdisMedium802_3;
  127. break;
  128. case NdisMedium802_5:
  129. MacInfo->SourceRouting = TRUE;
  130. MacInfo->MediumAsync = FALSE;
  131. MacInfo->BroadcastMask = 0x80;
  132. MacInfo->MaxHeaderLength = 32;
  133. MacInfo->MinHeaderLength = 14;
  134. MacInfo->MediumType = NdisMedium802_5;
  135. break;
  136. case NdisMediumFddi:
  137. MacInfo->SourceRouting = FALSE;
  138. MacInfo->MediumAsync = FALSE;
  139. MacInfo->BroadcastMask = 0x01;
  140. MacInfo->MaxHeaderLength = 13;
  141. MacInfo->MinHeaderLength = 13;
  142. MacInfo->MediumType = NdisMediumFddi;
  143. break;
  144. case NdisMediumArcnet878_2:
  145. MacInfo->SourceRouting = FALSE;
  146. MacInfo->MediumAsync = FALSE;
  147. MacInfo->BroadcastMask = 0x00;
  148. MacInfo->MaxHeaderLength = 3;
  149. MacInfo->MinHeaderLength = 3;
  150. MacInfo->MediumType = NdisMediumArcnet878_2;
  151. break;
  152. case NdisMediumWan:
  153. MacInfo->SourceRouting = FALSE;
  154. MacInfo->MediumAsync = TRUE;
  155. MacInfo->BroadcastMask = 0x01;
  156. MacInfo->MaxHeaderLength = 14;
  157. MacInfo->MinHeaderLength = 14;
  158. MacInfo->MediumType = NdisMedium802_3;
  159. break;
  160. default:
  161. CTEAssert(FALSE);
  162. }
  163. MacInfo->RealMediumType = MacType;
  164. } /* MacInitializeMacInfo */
  165. VOID
  166. MacMapFrameType(
  167. IN NDIS_MEDIUM MacType,
  168. IN ULONG FrameType,
  169. OUT ULONG * MappedFrameType
  170. )
  171. /*++
  172. Routine Description:
  173. Maps the specified frame type to a value which is
  174. valid for the medium.
  175. Arguments:
  176. MacType - The MAC type we wish to map for.
  177. FrameType - The frame type in question.
  178. MappedFrameType - Returns the mapped frame type.
  179. Return Value:
  180. --*/
  181. {
  182. switch (MacType) {
  183. //
  184. // Ethernet accepts all values, the default is 802.2.
  185. //
  186. case NdisMedium802_3:
  187. if (FrameType >= ISN_FRAME_TYPE_MAX) {
  188. *MappedFrameType = ISN_FRAME_TYPE_802_2;
  189. } else {
  190. *MappedFrameType = FrameType;
  191. }
  192. break;
  193. //
  194. // Token-ring supports SNAP and 802.2 only.
  195. //
  196. case NdisMedium802_5:
  197. if (FrameType == ISN_FRAME_TYPE_SNAP) {
  198. *MappedFrameType = ISN_FRAME_TYPE_SNAP;
  199. } else {
  200. *MappedFrameType = ISN_FRAME_TYPE_802_2;
  201. }
  202. break;
  203. //
  204. // FDDI supports SNAP, 802.2, and 802.3 only.
  205. //
  206. case NdisMediumFddi:
  207. if ((FrameType == ISN_FRAME_TYPE_SNAP) || (FrameType == ISN_FRAME_TYPE_802_3)) {
  208. *MappedFrameType = FrameType;
  209. } else {
  210. *MappedFrameType = ISN_FRAME_TYPE_802_2;
  211. }
  212. break;
  213. //
  214. // On arcnet there is only one frame type, use 802.3
  215. // (it doesn't matter what we use).
  216. //
  217. case NdisMediumArcnet878_2:
  218. *MappedFrameType = ISN_FRAME_TYPE_802_3;
  219. break;
  220. //
  221. // WAN uses ethernet II because it includes the ethertype.
  222. //
  223. case NdisMediumWan:
  224. *MappedFrameType = ISN_FRAME_TYPE_ETHERNET_II;
  225. break;
  226. default:
  227. CTEAssert(FALSE);
  228. }
  229. } /* MacMapFrameType */
  230. //
  231. // use symbols instead of hardcoded values for mac header lengths
  232. // --pradeepb
  233. //
  234. VOID
  235. MacReturnMaxDataSize(
  236. IN PNDIS_INFORMATION MacInfo,
  237. IN PUCHAR SourceRouting,
  238. IN UINT SourceRoutingLength,
  239. IN UINT DeviceMaxFrameSize,
  240. OUT PUINT MaxFrameSize
  241. )
  242. /*++
  243. Routine Description:
  244. This routine returns the space available for user data in a MAC packet.
  245. This will be the available space after the MAC header; all headers
  246. headers will be included in this space.
  247. Arguments:
  248. MacInfo - Describes the MAC we wish to decode.
  249. SourceRouting - If we are concerned about a reply to a specific
  250. frame, then this information is used.
  251. SourceRouting - The length of SourceRouting.
  252. MaxFrameSize - The maximum frame size as returned by the adapter.
  253. MaxDataSize - The maximum data size computed.
  254. Return Value:
  255. None.
  256. --*/
  257. {
  258. switch (MacInfo->MediumType) {
  259. case NdisMedium802_3:
  260. //
  261. // For 802.3, we always have a 14-byte MAC header.
  262. //
  263. *MaxFrameSize = DeviceMaxFrameSize - 14;
  264. break;
  265. case NdisMedium802_5:
  266. //
  267. // For 802.5, if we have source routing information then
  268. // use that, otherwise assume the worst.
  269. //
  270. if (SourceRouting && SourceRoutingLength >= 2) {
  271. UINT SRLength;
  272. SRLength = SR802_5Lengths[(SourceRouting[1] & TR_MAX_SIZE_MASK) >> 4];
  273. DeviceMaxFrameSize -= (SourceRoutingLength + 14);
  274. if (DeviceMaxFrameSize < SRLength) {
  275. *MaxFrameSize = DeviceMaxFrameSize;
  276. } else {
  277. *MaxFrameSize = SRLength;
  278. }
  279. } else {
  280. #if 0
  281. if (DeviceMaxFrameSize < 608) {
  282. *MaxFrameSize = DeviceMaxFrameSize - 32;
  283. } else {
  284. *MaxFrameSize = 576;
  285. }
  286. #endif
  287. //
  288. // bug # 6192. There is no point in assuming the worst. It only
  289. // leads to lower throughput. Packets can get dropped by an
  290. // an intermediate router for both cases (this one and the one
  291. // above where 576 is chosen). In the above case, they will
  292. // get dropped if two ethernet machines are communicating via
  293. // a token ring. In this case, they will if two token ring
  294. // machines with a frame size > max ethernet frame size are
  295. // going over an ethernet. To fix the packet drop case, one
  296. // should adjust the MaxPktSize Parameter of the card.
  297. //
  298. *MaxFrameSize = DeviceMaxFrameSize - 32;
  299. }
  300. break;
  301. case NdisMediumFddi:
  302. //
  303. // For FDDI, we always have a 13-byte MAC header.
  304. //
  305. *MaxFrameSize = DeviceMaxFrameSize - 13;
  306. break;
  307. case NdisMediumArcnet878_2:
  308. //
  309. // For Arcnet, we always have a 3-byte MAC header.
  310. //
  311. *MaxFrameSize = DeviceMaxFrameSize - 3;
  312. break;
  313. }
  314. } /* MacReturnMaxDataSize */
  315. VOID
  316. IpxUpdateWanInactivityCounter(
  317. IN PBINDING Binding,
  318. IN IPX_HEADER UNALIGNED * IpxHeader,
  319. IN ULONG IncludedHeaderLength,
  320. IN PNDIS_PACKET Packet,
  321. IN ULONG PacketLength
  322. )
  323. /*++
  324. Routine Description:
  325. This routine is called when a frame is being sent on a WAN
  326. line. It updates the inactivity counter for this binding
  327. unless:
  328. - The frame is from the RIP socket
  329. - The frame is from the SAP socket
  330. - The frame is a netbios keep alive
  331. - The frame is an NCP keep alive
  332. Take the identifier as a parameter to optimize.
  333. Arguments:
  334. Binding - The binding the frame is sent on.
  335. IpxHeader - May contain the first bytes of the packet.
  336. IncludedHeaderLength - The number of packet bytes at IpxHeader.
  337. Packet - The full NDIS packet.
  338. PacketLength - The length of the packet.
  339. Return Value:
  340. None, but in some cases we return without resetting the
  341. inactivity counter.
  342. Comments: Improve the instruction count here - pradeepb
  343. --*/
  344. {
  345. USHORT SourceSocket;
  346. PNDIS_BUFFER DataBuffer = NULL;
  347. PUCHAR DataBufferData;
  348. UINT DataBufferLength;
  349. //
  350. // First get the source socket.
  351. //
  352. SourceSocket = IpxHeader->SourceSocket;
  353. if ((SourceSocket == RIP_SOCKET) ||
  354. (SourceSocket == SAP_SOCKET)) {
  355. return;
  356. }
  357. if (SourceSocket == NB_SOCKET) {
  358. UCHAR ConnectionControlFlag;
  359. UCHAR DataStreamType;
  360. USHORT TotalDataLength;
  361. //
  362. // ConnectionControlFlag and DataStreamType will always follow
  363. // IpxHeader
  364. //
  365. ConnectionControlFlag = ((PUCHAR)(IpxHeader+1))[0];
  366. DataStreamType = ((PUCHAR)(IpxHeader+1))[1];
  367. //
  368. // If this is a SYS packet with or without a request for ACK and
  369. // has session data in it.
  370. //
  371. if (((ConnectionControlFlag == 0x80) || (ConnectionControlFlag == 0xc0)) &&
  372. (DataStreamType == 0x06)) {
  373. //
  374. // TotalDataLength is in the same buffer.
  375. //
  376. TotalDataLength = ((USHORT UNALIGNED *)(IpxHeader+1))[4];
  377. //
  378. // No need to update the WAN activity counter
  379. //
  380. if (TotalDataLength == 0) {
  381. return;
  382. }
  383. }
  384. } else {
  385. UCHAR KeepAliveSignature;
  386. //
  387. // Now see if it is an NCP keep alive. It can be from rip or from
  388. // NCP on this machine
  389. //
  390. // NOTE: We cannot come here for an SMB packet - [IsaacHe - 12/15].
  391. //
  392. if (PacketLength == sizeof(IPX_HEADER) + 2) {
  393. //
  394. // Get the client data buffer
  395. //
  396. NdisQueryPacket(Packet, NULL, NULL, &DataBuffer, NULL);
  397. //
  398. // If the included header length is 0, it is from rip
  399. //
  400. if (IncludedHeaderLength == 0) {
  401. //
  402. // Get the second buffer in the packet. The second buffer
  403. // contains the IPX header + other stuff
  404. //
  405. DataBuffer = NDIS_BUFFER_LINKAGE(DataBuffer);
  406. } else {
  407. //
  408. // Get the third buffer in the packet.
  409. //
  410. DataBuffer = NDIS_BUFFER_LINKAGE(NDIS_BUFFER_LINKAGE(DataBuffer));
  411. }
  412. NdisQueryBufferSafe (DataBuffer, (PVOID *)&DataBufferData, &DataBufferLength, NormalPagePriority);
  413. if (DataBufferData == NULL) {
  414. return;
  415. }
  416. if (IncludedHeaderLength == 0) {
  417. KeepAliveSignature = DataBufferData[sizeof(IPX_HEADER) + 1];
  418. } else {
  419. KeepAliveSignature = DataBufferData[1];
  420. }
  421. if ((KeepAliveSignature == '?') ||
  422. (KeepAliveSignature == 'Y')) {
  423. return;
  424. }
  425. }
  426. }
  427. //
  428. // This was a normal packet, so reset this.
  429. //
  430. Binding->WanInactivityCounter = 0;
  431. } /* IpxUpdateWanInactivityCounter */
  432. #if DBG
  433. ULONG IpxPadCount = 0;
  434. #endif
  435. NDIS_STATUS
  436. IpxSendFramePreFwd(
  437. IN PIPX_LOCAL_TARGET LocalTarget,
  438. IN PNDIS_PACKET Packet,
  439. IN ULONG PacketLength,
  440. IN ULONG IncludedHeaderLength
  441. )
  442. /*++
  443. Routine Description:
  444. This routine is called by NB/SPX to send a frame.
  445. Arguments:
  446. LocalTarget - The local target of the send - NB will have the LocalTarget in the Send_Reserved part
  447. of the packet; SPX will not now, but will later.
  448. Packet - The NDIS packet.
  449. PacketLength - The length of the packet, starting at the IPX header.
  450. IncludedHeaderLength - The length of the header included in the
  451. first buffer that needs to be moved if it does not wind up
  452. MacHeaderOffset bytes into the packet.
  453. Return Value:
  454. Return of IpxSendFrame
  455. --*/
  456. {
  457. PIPX_SEND_RESERVED Reserved = (PIPX_SEND_RESERVED)(Packet->ProtocolReserved);
  458. PUCHAR Header;
  459. PNDIS_BUFFER HeaderBuffer;
  460. PUCHAR IpxHeader;
  461. PUCHAR EthernetHeader;
  462. PIPX_HEADER pIpxHeader;
  463. UINT TempHeaderBufferLength;
  464. PDEVICE Device = IpxDevice;
  465. PIPX_HEADER TempHeader;
  466. NTSTATUS ret;
  467. BOOLEAN fIterate=FALSE;
  468. PBINDING pBinding = NULL;
  469. //
  470. // Figure out the IpxHeader - it is always at the top of the second MDL.
  471. //
  472. NdisQueryPacket (Packet, NULL, NULL, &HeaderBuffer, NULL);
  473. NdisQueryBufferSafe (HeaderBuffer, &EthernetHeader, &TempHeaderBufferLength, HighPagePriority);
  474. NdisQueryBufferSafe (NDIS_BUFFER_LINKAGE(HeaderBuffer), &IpxHeader, &TempHeaderBufferLength, HighPagePriority);
  475. if (EthernetHeader == NULL || IpxHeader == NULL) {
  476. return NDIS_STATUS_FAILURE;
  477. }
  478. //
  479. // Set this now, will change later
  480. //
  481. Reserved->CurrentNicId = 0;
  482. //
  483. // Copy the LocalTarget into the send reserved area of the packet.
  484. //
  485. Reserved->LocalTarget = *LocalTarget;
  486. //
  487. // If the NicId in the handle is ITERATIVE_NIC_ID, then this could be a send
  488. // over all NICs in the case of NB/SPX.
  489. //
  490. if (NIC_FROM_LOCAL_TARGET(LocalTarget) == (USHORT)ITERATIVE_NIC_ID) {
  491. CTEAssert(Reserved->Identifier == IDENTIFIER_NB ||
  492. Reserved->Identifier == IDENTIFIER_SPX);
  493. //
  494. // If there are no real adapters, send on loopback and then quit.
  495. if (Device->RealAdapters) {
  496. //
  497. // Start with the first REAL NIC
  498. //
  499. Reserved->CurrentNicId = FIRST_REAL_BINDING;
  500. FILL_LOCAL_TARGET(&Reserved->LocalTarget, FIRST_REAL_BINDING);
  501. } else {
  502. //
  503. // Use loopback
  504. //
  505. Reserved->CurrentNicId = LOOPBACK_NIC_ID;
  506. FILL_LOCAL_TARGET(&Reserved->LocalTarget, LOOPBACK_NIC_ID);
  507. }
  508. IPX_DEBUG(SEND, ("Iteration over NICs started, reserved: %lx\n", Reserved));
  509. Reserved->Net0SendSucceeded = FALSE;
  510. Reserved->PacketLength = PacketLength;
  511. fIterate = TRUE;
  512. }
  513. //
  514. // If the Forwarder is installed, send the packet out for filtering
  515. //
  516. if (Device->ForwarderBound) {
  517. #ifdef SUNDOWN
  518. ULONG_PTR FwdAdapterContext = INVALID_CONTEXT_VALUE;
  519. #else
  520. ULONG FwdAdapterContext = INVALID_CONTEXT_VALUE;
  521. #endif
  522. PBINDING Binding;
  523. //
  524. // Figure out the FwdAdapterContext; if the NicId is 0
  525. // then no NicId is specified (since we never return a
  526. // NicId of 0 in a FindRoute).
  527. //
  528. //
  529. // We need to fix the following problems with respect to type 20 iterative bcasts :
  530. // 1. IPX will not bcast on a down WAN line (thus the Fwd cannot bring up a demand-dial line).
  531. // 2. IPX bcasts on every Nic (since it is not any wiser about selecting relevant Nics).
  532. // 3. If the first bcast fails, the whole send fails.
  533. //
  534. // All the above (except 3.) occur because the Fwd knows more about the Nics than IPX does; hence
  535. // we let the Fwd decide which lines he wants to send a bcast on. Thus, for Type20 pkts, we pass
  536. // up the invalid Fwd context so the Fwd decides the next Nic to send on.
  537. //
  538. if (!((((PIPX_HEADER)IpxHeader)->PacketType == 0x14) && fIterate) &&
  539. Reserved->LocalTarget.NicId &&
  540. (Binding = NIC_ID_TO_BINDING(Device, Reserved->LocalTarget.NicId)) &&
  541. (GET_LONG_VALUE(Binding->ReferenceCount) == 2)) {
  542. //
  543. // If proper NicId specified, and the adapter has been opened by
  544. // the forwarder, set the FwdAdapterContext.
  545. //
  546. FwdAdapterContext = Binding->FwdAdapterContext;
  547. }
  548. #if DBG
  549. else {
  550. if (((PIPX_HEADER)IpxHeader)->PacketType == 0x14) {
  551. IPX_DEBUG(SEND, ("SendComplete: IpxHeader has Type20: %lx\n", IpxHeader));
  552. }
  553. }
  554. #endif
  555. //
  556. // Call the InternalSend to filter the packet and get to know
  557. // the correct adapter context
  558. //
  559. ret = (*Device->UpperDrivers[IDENTIFIER_RIP].InternalSendHandler)(
  560. &Reserved->LocalTarget,
  561. FwdAdapterContext,
  562. Packet,
  563. IpxHeader,
  564. IpxHeader+sizeof(IPX_HEADER), // the data starts after the IPX Header.
  565. PacketLength,
  566. fIterate);
  567. //
  568. // The FWD might not yet know of the Nics going away [109160].
  569. //
  570. if (NULL == NIC_ID_TO_BINDING(Device, Reserved->LocalTarget.NicId)) {
  571. ret = STATUS_DROP_SILENTLY;
  572. }
  573. if (ret == STATUS_SUCCESS) {
  574. //
  575. // The adapter could have gone away and we have indicated to the Forwarder
  576. // but the Forwarder has not yet closed the adapter.
  577. // [ZZ] adapters do not go away now.
  578. //
  579. // what if the binding is NULL here? Can we trust the Forwarder to
  580. // give us a non-NULL binding?
  581. //
  582. if (GET_LONG_VALUE(NIC_ID_TO_BINDING(Device, Reserved->LocalTarget.NicId)->ReferenceCount) == 1) {
  583. IPX_DEBUG(SEND, ("IPX: SendFramePreFwd: FWD returned SUCCESS, Ref count is 1\n"));
  584. return NDIS_STATUS_SUCCESS;
  585. } else {
  586. //
  587. // Fill up the changed LocalTarget for the client except in the ITERATE case.
  588. //
  589. if (!fIterate) {
  590. *LocalTarget = Reserved->LocalTarget;
  591. }
  592. IPX_DEBUG(SEND, ("IPX: SendFramePreFwd: FWD returned SUCCESS, sending out on wire\n"));
  593. goto SendPkt;
  594. }
  595. } else if (ret == STATUS_PENDING) {
  596. //
  597. // LocalTarget will get filled up in InternalSendComplete
  598. //
  599. IPX_DEBUG(SEND, ("SendFramePreFwd: FWD returned PENDING\n"));
  600. return NDIS_STATUS_PENDING;
  601. } else if (ret == STATUS_DROP_SILENTLY) {
  602. //
  603. // This was a keepalive which the router is spoofing. Drop it silently.
  604. //
  605. IPX_DEBUG(SEND, ("IPX: SendFramePreFwd: FWD returned STATUS_DROP_SILENTLY - dropping pkt.\n"));
  606. return NDIS_STATUS_SUCCESS;
  607. }
  608. //
  609. // else DISCARD - this means that either the packet failed the send
  610. // or that the preferred NicId was not good.
  611. //
  612. return STATUS_NETWORK_UNREACHABLE;
  613. } else {
  614. //
  615. // Work around NdisMBlahX bug.
  616. // Check if this is a self-directed packet and loop it back.
  617. //
  618. SendPkt:
  619. pIpxHeader = (PIPX_HEADER) IpxHeader;
  620. if ((IPX_NODE_EQUAL(pIpxHeader->SourceNode, pIpxHeader->DestinationNode)) &&
  621. (*(UNALIGNED ULONG *)pIpxHeader->SourceNetwork == *(UNALIGNED ULONG *)pIpxHeader->DestinationNetwork)) {
  622. IPX_DEBUG(TEMP, ("Source Net: %lx + Source Address: %2.2x-%2.2x-%2.2x-%2.2x-%2.2x-%2.2x\n",
  623. *(UNALIGNED ULONG *)pIpxHeader->SourceNetwork,
  624. pIpxHeader->SourceNode[0],
  625. pIpxHeader->SourceNode[1],
  626. pIpxHeader->SourceNode[2],
  627. pIpxHeader->SourceNode[3],
  628. pIpxHeader->SourceNode[4],
  629. pIpxHeader->SourceNode[5]));
  630. IPX_DEBUG(TEMP, ("Dest Net: %lx + DestinationAddress: %2.2x-%2.2x-%2.2x-%2.2x-%2.2x-%2.2x \n",
  631. *(UNALIGNED ULONG *)pIpxHeader->DestinationNetwork,
  632. pIpxHeader->DestinationNode[0],
  633. pIpxHeader->DestinationNode[1],
  634. pIpxHeader->DestinationNode[2],
  635. pIpxHeader->DestinationNode[3],
  636. pIpxHeader->DestinationNode[4],
  637. pIpxHeader->DestinationNode[5]
  638. ));
  639. IPX_DEBUG(TEMP, ("Well, It is self-directed. Loop it back ourselves\n"));
  640. FILL_LOCAL_TARGET(LocalTarget, LOOPBACK_NIC_ID);
  641. } else {
  642. pBinding = NIC_ID_TO_BINDING(Device, Reserved->LocalTarget.NicId);
  643. if (pBinding) {
  644. if (IPX_NODE_EQUAL(Reserved->LocalTarget.MacAddress, pBinding->LocalAddress.NodeAddress)) {
  645. IPX_DEBUG(TEMP, ("Source Net:%lx, Source Address: %2.2x-%2.2x-%2.2x-%2.2x-%2.2x-%2.2x\n",
  646. *(UNALIGNED ULONG *)pIpxHeader->SourceNetwork,
  647. pIpxHeader->SourceNode[0],
  648. pIpxHeader->SourceNode[1],
  649. pIpxHeader->SourceNode[2],
  650. pIpxHeader->SourceNode[3],
  651. pIpxHeader->SourceNode[4],
  652. pIpxHeader->SourceNode[5]));
  653. IPX_DEBUG(TEMP, ("Dest Net:%lx, DestAddress: %2.2x-%2.2x-%2.2x-%2.2x-%2.2x-%2.2x \n",
  654. *(UNALIGNED ULONG *)pIpxHeader->DestinationNetwork,
  655. pIpxHeader->DestinationNode[0],
  656. pIpxHeader->DestinationNode[1],
  657. pIpxHeader->DestinationNode[2],
  658. pIpxHeader->DestinationNode[3],
  659. pIpxHeader->DestinationNode[4],
  660. pIpxHeader->DestinationNode[5]
  661. ));
  662. IPX_DEBUG(TEMP, ("Well, It is self-directed. Loop it back ourselves (NIC_HANDLE is the same!)\n"));
  663. FILL_LOCAL_TARGET(LocalTarget, LOOPBACK_NIC_ID);
  664. }
  665. } else {
  666. IPX_DEBUG(TEMP, ("Source Net:%lx, Source Address: %2.2x-%2.2x-%2.2x-%2.2x-%2.2x-%2.2x\n",
  667. *(UNALIGNED ULONG *)pIpxHeader->SourceNetwork,
  668. pIpxHeader->SourceNode[0],
  669. pIpxHeader->SourceNode[1],
  670. pIpxHeader->SourceNode[2],
  671. pIpxHeader->SourceNode[3],
  672. pIpxHeader->SourceNode[4],
  673. pIpxHeader->SourceNode[5]));
  674. IPX_DEBUG(TEMP, ("Dest Net: %lx, LocalAddress: %2.2x-%2.2x-%2.2x-%2.2x-%2.2x-%2.2x \n",
  675. *(UNALIGNED ULONG *)pIpxHeader->DestinationNetwork,
  676. pIpxHeader->DestinationNode[0],
  677. pIpxHeader->DestinationNode[1],
  678. pIpxHeader->DestinationNode[2],
  679. pIpxHeader->DestinationNode[3],
  680. pIpxHeader->DestinationNode[4],
  681. pIpxHeader->DestinationNode[5]
  682. ));
  683. }
  684. }
  685. if (NIC_FROM_LOCAL_TARGET(LocalTarget) == (USHORT)LOOPBACK_NIC_ID) {
  686. //
  687. // Enque this packet to the LoopbackQueue on the binding.
  688. // If the LoopbackRtn is not already scheduled, schedule it.
  689. //
  690. IPX_DEBUG(LOOPB, ("Mac.c: Packet: %x\n", Packet));
  691. //
  692. // Recalculate packet counts here.
  693. // Assume an 802_3802_2 header and use that length.
  694. // Adjust the MAC header's length to the right value
  695. //
  696. NdisAdjustBufferLength (HeaderBuffer, 17);
  697. NdisRecalculatePacketCounts (Packet);
  698. IpxLoopbackEnque(Packet, NIC_ID_TO_BINDING(Device, LOOPBACK_NIC_ID)->Adapter);
  699. //
  700. // The upper driver waits for the SendComplete.
  701. //
  702. return STATUS_PENDING;
  703. }
  704. return IpxSendFrame (
  705. &Reserved->LocalTarget,
  706. Packet,
  707. PacketLength,
  708. IncludedHeaderLength);
  709. }
  710. }
  711. NDIS_STATUS
  712. IpxSendFrame(
  713. IN PIPX_LOCAL_TARGET LocalTarget,
  714. IN PNDIS_PACKET Packet,
  715. IN ULONG PacketLength,
  716. IN ULONG IncludedHeaderLength
  717. )
  718. /*++
  719. Routine Description:
  720. This routine constructs a MAC header in a packet and submits
  721. it to the appropriate NDIS driver.
  722. It is assumed that the first buffer in the packet contains
  723. an IPX header at an offset based on the media type. This
  724. IPX header is moved around if needed.
  725. Check that Binding is not NULL.
  726. Arguments:
  727. LocalTarget - The local target of the send.
  728. Packet - The NDIS packet.
  729. PacketLength - The length of the packet, starting at the IPX header.
  730. IncludedHeaderLength - The length of the header included in the
  731. first buffer that needs to be moved if it does not wind up
  732. MacHeaderOffset bytes into the packet.
  733. Return Value:
  734. None.
  735. --*/
  736. {
  737. PIPX_SEND_RESERVED Reserved = (PIPX_SEND_RESERVED)(Packet->ProtocolReserved);
  738. PDEVICE Device = IpxDevice;
  739. PUCHAR Header;
  740. PBINDING Binding, MasterBinding;
  741. PADAPTER Adapter;
  742. ULONG TwoBytes;
  743. PNDIS_BUFFER HeaderBuffer;
  744. UINT TempHeaderBufferLength;
  745. ULONG HeaderLength=0;
  746. UCHAR SourceRoutingBuffer[18];
  747. PUCHAR SourceRouting;
  748. ULONG SourceRoutingLength;
  749. NDIS_STATUS Status;
  750. ULONG BufferLength;
  751. UCHAR DestinationType;
  752. UCHAR SourceRoutingIdentifier;
  753. ULONG HeaderSizeRequired;
  754. PIPX_HEADER TempHeader;
  755. USHORT PktLength;
  756. IPX_DEFINE_LOCK_HANDLE(LockHandle1)
  757. IPX_DEFINE_LOCK_HANDLE(LockHandle)
  758. #ifdef SNMP
  759. //
  760. // This should not include the forwarded packets; on host side, it is 0.
  761. // On router, the AdvSysForwPackets are subtracted in the sub-agent code.
  762. //
  763. ++IPX_MIB_ENTRY(Device, SysOutRequests);
  764. #endif SNMP
  765. //
  766. // Get the lock on the binding array
  767. //
  768. IPX_GET_LOCK1(&Device->BindAccessLock, &LockHandle1);
  769. Binding = NIC_HANDLE_TO_BINDING(Device, &LocalTarget->NicHandle);
  770. if (Binding == NULL) {
  771. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  772. IPX_DEBUG(PNP, ("Invalid NIC handle: %lx\n", LocalTarget->NicHandle));
  773. //
  774. // Return a unique error that NB/SPX see and re-query the NicId.
  775. //
  776. #ifdef SNMP
  777. ++IPX_MIB_ENTRY(Device, SysOutMalformedRequests);
  778. #endif SNMP
  779. return STATUS_DEVICE_DOES_NOT_EXIST;
  780. }
  781. IpxReferenceBinding1(Binding, BREF_DEVICE_ACCESS);
  782. Adapter = Binding->Adapter;
  783. IpxReferenceAdapter(Adapter);
  784. //
  785. // Release the lock
  786. //
  787. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  788. //
  789. // For IPX and other protocols that are guaranteed to have allocated
  790. // the header from non-paged pool, use the buffer directly. For others,
  791. // query the packet for the pointer to the MDL.
  792. //
  793. if (Reserved->Identifier >= IDENTIFIER_IPX) {
  794. HeaderBuffer = Reserved->HeaderBuffer;
  795. Header = Reserved->Header;
  796. } else {
  797. NdisQueryPacket (Packet, NULL, NULL, &HeaderBuffer, NULL);
  798. NdisQueryBufferSafe(HeaderBuffer, &Header, &TempHeaderBufferLength, HighPagePriority);
  799. if (Header == NULL) {
  800. return NDIS_STATUS_FAILURE;
  801. }
  802. }
  803. CTEAssert (Reserved->PaddingBuffer == NULL);
  804. //
  805. // First move the packet around if needed.
  806. //
  807. if (Reserved->Identifier < IDENTIFIER_IPX) {
  808. //
  809. // Only RIP will have IncludedHeaderLength as 0. I don't know
  810. // why we have the comment about RIP inside this if statement.
  811. //
  812. if (IncludedHeaderLength > 0) {
  813. //
  814. // Spx can handle a virtual net as long as it is
  815. // not 0. Netbios always needs to use the real address.
  816. // We need to hack the ipx source address for packets
  817. // which are sent by spx if we have a fake virtual
  818. // net, and packets sent by netbios unless we are
  819. // bound to only one card.
  820. //
  821. //
  822. // We handle binding sets as follows, based on who
  823. // sent the frame to us:
  824. //
  825. // RIP: Since we only tell RIP about the masters at
  826. // bind time, and hide slaves on indications, it should
  827. // never be sending on a slave binding. Since RIP knows
  828. // the real net and node of every binding we don't
  829. // need to modify the packet at all.
  830. //
  831. // NB: For broadcasts we want to put the first card's
  832. // address in the IPX source but round-robin the
  833. // actual sends over all cards (broadcasts shouldn't
  834. // be passed in with a slave's NIC ID). For directed
  835. // packets, which may come in on a slave, we should
  836. // put the slave's address in the IPX source.
  837. //
  838. // SPX: SPX does not send broadcasts. For directed
  839. // frames we want to use the slave's net and node
  840. // in the IPX source.
  841. //
  842. if (Reserved->Identifier == IDENTIFIER_NB) {
  843. CTEAssert (IncludedHeaderLength >= sizeof(IPX_HEADER));
  844. //
  845. // Get the packet length from the ipx header. Compare with
  846. // the max. allowed datagram size.
  847. //
  848. TempHeader = (PIPX_HEADER)(&Header[Device->IncludedHeaderOffset]);
  849. PktLength = ((TempHeader->PacketLength[0] << 8) |
  850. (TempHeader->PacketLength[1]));
  851. //
  852. // Not the most efficient way to do this. NWLNKNB should do this.
  853. // Doing it in ipx means doing it for all packets (even those sent on
  854. // connections). Will remove this later when nwlnknb change has been
  855. // tested.
  856. //
  857. if (PktLength > (Binding->AnnouncedMaxDatagramSize + sizeof(IPX_HEADER))) {
  858. IPX_DEBUG (SEND, ("Send %d bytes too large (%d)\n",
  859. PktLength,
  860. Binding->AnnouncedMaxDatagramSize + sizeof(IPX_HEADER)));
  861. //
  862. // Dereference the binding and adapter
  863. //
  864. IpxDereferenceBinding1(Binding, BREF_DEVICE_ACCESS);
  865. IpxDereferenceAdapter(Adapter);
  866. #ifdef SNMP
  867. ++IPX_MIB_ENTRY(Device, SysOutMalformedRequests);
  868. #endif SNMP
  869. return STATUS_INVALID_BUFFER_SIZE;
  870. }
  871. if (Device->ValidBindings > 1) {
  872. //
  873. // Store this now, since even if we round-robin the
  874. // actual send we want the binding set master's net
  875. // and node in the IPX source address.
  876. //
  877. *(UNALIGNED ULONG *)TempHeader->SourceNetwork = Binding->LocalAddress.NetworkAddress;
  878. RtlCopyMemory (TempHeader->SourceNode, Binding->LocalAddress.NodeAddress, 6);
  879. if (Binding->BindingSetMember) {
  880. if (IPX_NODE_BROADCAST(LocalTarget->MacAddress)) {
  881. //
  882. // This is a broadcast, so we round-robin the
  883. // sends through the binding set.
  884. //
  885. //
  886. // We dont have a lock here - the masterbinding could be bogus
  887. //
  888. IpxDereferenceBinding1(Binding, BREF_DEVICE_ACCESS);
  889. IpxDereferenceAdapter(Adapter);
  890. MasterBinding = Binding->MasterBinding;
  891. Binding = MasterBinding->CurrentSendBinding;
  892. MasterBinding->CurrentSendBinding = Binding->NextBinding;
  893. Adapter = Binding->Adapter;
  894. IpxReferenceBinding1(Binding, BREF_DEVICE_ACCESS);
  895. IpxReferenceAdapter(Adapter);
  896. }
  897. }
  898. }
  899. //
  900. // [STEFANS]: Replace all source addresses with the virtualnet# to allow for sends
  901. // on 0 network number WAN lines (typically between routers).
  902. //
  903. if (Device->VirtualNetwork) {
  904. *(UNALIGNED ULONG *)TempHeader->SourceNetwork = Device->SourceAddress.NetworkAddress;
  905. RtlCopyMemory (TempHeader->SourceNode, Device->SourceAddress.NodeAddress, 6);
  906. }
  907. } else if (Reserved->Identifier == IDENTIFIER_SPX) {
  908. //
  909. // Need to update this if we have multiple cards but
  910. // a zero virtual net.
  911. //
  912. if (Device->MultiCardZeroVirtual) {
  913. CTEAssert (IncludedHeaderLength >= sizeof(IPX_HEADER));
  914. TempHeader = (PIPX_HEADER)(&Header[Device->IncludedHeaderOffset]);
  915. *(UNALIGNED ULONG *)TempHeader->SourceNetwork = Binding->LocalAddress.NetworkAddress;
  916. RtlCopyMemory (TempHeader->SourceNode, Binding->LocalAddress.NodeAddress, 6);
  917. }
  918. } else {
  919. //
  920. // For a rip packet it should not be in a binding set,
  921. // or if it is it should be the master.
  922. //
  923. #if DBG
  924. CTEAssert ((!Binding->BindingSetMember) ||
  925. (Binding->CurrentSendBinding));
  926. #endif
  927. }
  928. #if 0
  929. //
  930. // There is a header included, we need to adjust it.
  931. // The header will be at Device->IncludedHeaderOffset.
  932. //
  933. if (LocalTarget->MacAddress[0] & Adapter->MacInfo.BroadcastMask) {
  934. HeaderSizeRequired = Adapter->BcMcHeaderSizes[Binding->FrameType];
  935. } else {
  936. HeaderSizeRequired = Adapter->DefHeaderSizes[Binding->FrameType];
  937. }
  938. if (HeaderSizeRequired != Device->IncludedHeaderOffset) {
  939. RtlMoveMemory(
  940. &Header[HeaderSizeRequired],
  941. &Header[Device->IncludedHeaderOffset],
  942. IncludedHeaderLength);
  943. }
  944. #endif
  945. }
  946. }
  947. IPX_GET_LOCK (&Adapter->Lock, &LockHandle);
  948. if (Adapter->State != ADAPTER_STATE_STOPPING) {
  949. IpxReferenceAdapter1(Adapter,ADAP_REF_SEND);
  950. IPX_FREE_LOCK (&Adapter->Lock, LockHandle);
  951. } else {
  952. IpxDereferenceBinding1(Binding, BREF_DEVICE_ACCESS);
  953. IpxDereferenceAdapter(Adapter);
  954. IPX_FREE_LOCK (&Adapter->Lock, LockHandle);
  955. return NDIS_STATUS_FAILURE;
  956. }
  957. switch (Adapter->MacInfo.MediumType) {
  958. case NdisMedium802_3:
  959. //
  960. // [FW] This will allow both LINE_UP and LINE_CONFIG states
  961. //
  962. if (!Binding->LineUp) {
  963. //
  964. // Bug #17273 return proper error message
  965. //
  966. // return STATUS_DEVICE_DOES_NOT_EXIST; // Make this a separate switch that generally falls through?
  967. //
  968. // Derefernce the binding and adapter
  969. //
  970. IpxDereferenceBinding1(Binding, BREF_DEVICE_ACCESS);
  971. IpxDereferenceAdapter(Adapter);
  972. IpxDereferenceAdapter1(Adapter,ADAP_REF_SEND);
  973. #ifdef SNMP
  974. ++IPX_MIB_ENTRY(Device, SysOutDiscards);
  975. #endif SNMP
  976. return STATUS_NETWORK_UNREACHABLE;
  977. }
  978. if (Adapter->MacInfo.MediumAsync) {
  979. IPX_HEADER UNALIGNED * IpxHeader;
  980. PNDIS_BUFFER IpxNdisBuff;
  981. UINT IpxHeaderLen;
  982. #if 0
  983. //
  984. // The header should have been moved here.
  985. //
  986. CTEAssert(Adapter->BcMcHeaderSizes[ISN_FRAME_TYPE_ETHERNET_II] ==
  987. Adapter->DefHeaderSizes[ISN_FRAME_TYPE_ETHERNET_II]);
  988. IpxHeader = (IPX_HEADER UNALIGNED *)
  989. (&Header[Adapter->DefHeaderSizes[ISN_FRAME_TYPE_ETHERNET_II]]);
  990. #endif
  991. //
  992. // The Ipx header is always the second ndis buffer in the mdl
  993. // chain. Get it and then query the va of the same.
  994. //
  995. IpxNdisBuff = NDIS_BUFFER_LINKAGE(HeaderBuffer);
  996. NdisQueryBufferSafe (IpxNdisBuff, (PVOID *)&IpxHeader, &IpxHeaderLen, HighPagePriority);
  997. if (IpxHeader == NULL) {
  998. return NDIS_STATUS_FAILURE;
  999. }
  1000. // IpxHeader = (IPX_HEADER UNALIGNED *) (&Header[MAC_HEADER_SIZE]);
  1001. //
  1002. // If this is a type 20 name frame from Netbios and we are
  1003. // on a dialin WAN line, drop it if configured to.
  1004. //
  1005. // The 0x01 bit of DisableDialinNetbios controls
  1006. // internal->WAN packets, which we handle here.
  1007. //
  1008. //
  1009. //
  1010. // SS# 33592: In case of iterative sends, the IncludedHeaderLength is not set properly
  1011. // since we dont keep track of the length that came in the first time (we track the PacketLength
  1012. // however). The included length field is used here for checking for NB_NAME_FRAMES, but elsewhere
  1013. // used only to distinguish between whether RIP or NB/SPX sent the packet (IncludedHeaderLen ==0 for RIP)
  1014. // The ideal solution here is to do way with this field altogether, but for the beta we will just use the
  1015. // PacketLength field for comparison here since we are assured that this will be equal to the InclHeaderLen
  1016. // for any type 0x14 packet that comes down from NB.
  1017. //
  1018. // Remove the IncludedHeaderLength field.
  1019. //
  1020. //
  1021. // [FW] do this only if the forwarder is not bound
  1022. //
  1023. if (!Device->ForwarderBound &&
  1024. (!Binding->DialOutAsync) &&
  1025. (Reserved->Identifier == IDENTIFIER_NB) &&
  1026. // (IncludedHeaderLength == sizeof(IPX_HEADER) + 50) && // 50 == sizeof(NB_NAME_FRAME)
  1027. (PacketLength == sizeof(IPX_HEADER) + 50) && // 50 == sizeof(NB_NAME_FRAME)
  1028. ((Device->DisableDialinNetbios & 0x01) != 0) &&
  1029. (IpxHeader->PacketType == 0x14)) {
  1030. //
  1031. // Derefernce the binding and adapter
  1032. //
  1033. IpxDereferenceBinding1(Binding, BREF_DEVICE_ACCESS);
  1034. IpxDereferenceAdapter(Adapter);
  1035. IpxDereferenceAdapter1(Adapter,ADAP_REF_SEND);
  1036. return STATUS_SUCCESS;
  1037. }
  1038. //
  1039. // We do checks to see if we should reset the inactivity
  1040. // counter. We normally need to check for netbios
  1041. // session alives, packets from rip, packets from
  1042. // sap, and ncp keep alives. In fact sap and ncp
  1043. // packets don't come through here.
  1044. //
  1045. IpxUpdateWanInactivityCounter(
  1046. Binding,
  1047. IpxHeader,
  1048. IncludedHeaderLength,
  1049. Packet,
  1050. PacketLength);
  1051. //
  1052. // In order for loopback to work properly, we need to put the local MAC address for locally destined
  1053. // pkts so NdisWAN can loop them back.
  1054. //
  1055. if (IPX_NODE_EQUAL(LocalTarget->MacAddress, Binding->LocalAddress.NodeAddress)) {
  1056. RtlCopyMemory (Header, Binding->LocalMacAddress.Address, 6);
  1057. } else {
  1058. RtlCopyMemory (Header, Binding->RemoteMacAddress.Address, 6);
  1059. }
  1060. } else {
  1061. RtlCopyMemory (Header, LocalTarget->MacAddress, 6);
  1062. }
  1063. RtlCopyMemory (Header+6, Binding->LocalMacAddress.Address, 6);
  1064. switch (Binding->FrameType) {
  1065. case ISN_FRAME_TYPE_802_2:
  1066. TwoBytes = PacketLength + 3;
  1067. Header[14] = 0xe0;
  1068. Header[15] = 0xe0;
  1069. Header[16] = 0x03;
  1070. HeaderLength = 17;
  1071. break;
  1072. case ISN_FRAME_TYPE_802_3:
  1073. TwoBytes = PacketLength;
  1074. HeaderLength = 14;
  1075. break;
  1076. case ISN_FRAME_TYPE_ETHERNET_II:
  1077. TwoBytes = Adapter->BindSap;
  1078. HeaderLength = 14;
  1079. break;
  1080. case ISN_FRAME_TYPE_SNAP:
  1081. TwoBytes = PacketLength + 8;
  1082. Header[14] = 0xaa;
  1083. Header[15] = 0xaa;
  1084. Header[16] = 0x03;
  1085. Header[17] = 0x00;
  1086. Header[18] = 0x00;
  1087. Header[19] = 0x00;
  1088. *(UNALIGNED USHORT *)(&Header[20]) = Adapter->BindSapNetworkOrder;
  1089. HeaderLength = 22;
  1090. break;
  1091. }
  1092. Header[12] = (UCHAR)(TwoBytes / 256);
  1093. Header[13] = (UCHAR)(TwoBytes % 256);
  1094. //BufferLength = IncludedHeaderLength + HeaderLength;
  1095. BufferLength = HeaderLength;
  1096. //
  1097. // Pad odd-length packets if needed.
  1098. //
  1099. if ((((PacketLength + HeaderLength) & 1) != 0) &&
  1100. (Device->EthernetPadToEven) &&
  1101. (!Adapter->MacInfo.MediumAsync)) {
  1102. PNDIS_BUFFER CurBuffer;
  1103. PIPX_PADDING_BUFFER PaddingBuffer = IpxPaddingBuffer;
  1104. UINT Offset;
  1105. UINT LastBufferLength;
  1106. //
  1107. // Find the tail of the current packet.
  1108. //
  1109. CurBuffer = HeaderBuffer;
  1110. while (NDIS_BUFFER_LINKAGE(CurBuffer) != NULL) {
  1111. CurBuffer = NDIS_BUFFER_LINKAGE(CurBuffer);
  1112. }
  1113. //
  1114. // If the last byte of the last NDIS_BUFFER is not at the end of
  1115. // the page, then we can simply increase the NDIS_BUFFER ByteCount
  1116. // by one.
  1117. // Otherwise, we must use the global padding buffer.
  1118. //
  1119. NdisQueryBufferOffset( CurBuffer, &Offset, &LastBufferLength );
  1120. if ( ((Offset + LastBufferLength) & (PAGE_SIZE - 1)) != 0) {
  1121. if ( CurBuffer == HeaderBuffer ) {
  1122. BufferLength++; // Just bump this length
  1123. } else {
  1124. NdisAdjustBufferLength( CurBuffer, (LastBufferLength + 1) );
  1125. Reserved->PreviousTail = NULL;
  1126. Reserved->PaddingBuffer = (PIPX_PADDING_BUFFER)CurBuffer;
  1127. IPX_DEBUG(TEMP,("IpxSendFrame:Set PaddingBuffer for %p\n", Packet));
  1128. }
  1129. } else {
  1130. CTEAssert (NDIS_BUFFER_LINKAGE(PaddingBuffer->NdisBuffer) == NULL);
  1131. Reserved->PreviousTail = CurBuffer;
  1132. NDIS_BUFFER_LINKAGE (CurBuffer) = PaddingBuffer->NdisBuffer;
  1133. Reserved->PaddingBuffer = PaddingBuffer;
  1134. IPX_DEBUG(TEMP,("IpxSendFrame:Set PaddingBuffer for %p\n", Packet));
  1135. }
  1136. if (TwoBytes != Adapter->BindSap) {
  1137. CTEAssert(TwoBytes & 1);
  1138. TwoBytes += 1;
  1139. Header[12] = (UCHAR)(TwoBytes / 256);
  1140. Header[13] = (UCHAR)(TwoBytes % 256);
  1141. }
  1142. #if DBG
  1143. ++IpxPadCount;
  1144. #endif
  1145. }
  1146. break;
  1147. case NdisMedium802_5:
  1148. if (Reserved->Identifier >= IDENTIFIER_IPX) {
  1149. DestinationType = Reserved->DestinationType;
  1150. SourceRoutingIdentifier = IDENTIFIER_IPX;
  1151. } else {
  1152. if (LocalTarget->MacAddress[0] & 0x80) {
  1153. if (*(UNALIGNED ULONG *)(&LocalTarget->MacAddress[2]) != 0xffffffff) {
  1154. DestinationType = DESTINATION_MCAST;
  1155. } else {
  1156. DestinationType = DESTINATION_BCAST;
  1157. }
  1158. } else {
  1159. DestinationType = DESTINATION_DEF;
  1160. }
  1161. SourceRoutingIdentifier = Reserved->Identifier;
  1162. }
  1163. if (DestinationType == DESTINATION_DEF) {
  1164. MacLookupSourceRouting(
  1165. SourceRoutingIdentifier,
  1166. Binding,
  1167. LocalTarget->MacAddress,
  1168. SourceRoutingBuffer,
  1169. &SourceRoutingLength);
  1170. if (SourceRoutingLength != 0) {
  1171. // PUCHAR IpxHeader = Header + Binding->DefHeaderSize;
  1172. PUCHAR IpxHeader = Header + MAC_HEADER_SIZE;
  1173. //
  1174. // Need to slide the header down to accomodate the SR.
  1175. //
  1176. SourceRouting = SourceRoutingBuffer;
  1177. // RtlMoveMemory (IpxHeader+SourceRoutingLength, IpxHeader, IncludedHeaderLength);
  1178. }
  1179. } else {
  1180. //
  1181. // For these packets we assume that the header is in the
  1182. // right place.
  1183. //
  1184. if (!Adapter->SourceRouting) {
  1185. SourceRoutingLength = 0;
  1186. } else {
  1187. if (DestinationType == DESTINATION_BCAST) {
  1188. if (Binding->AllRouteBroadcast) {
  1189. SourceRouting = AllRouteSourceRouting;
  1190. } else {
  1191. SourceRouting = SingleRouteSourceRouting;
  1192. }
  1193. SourceRoutingLength = 2;
  1194. } else {
  1195. CTEAssert (DestinationType == DESTINATION_MCAST);
  1196. if (Binding->AllRouteMulticast) {
  1197. SourceRouting = AllRouteSourceRouting;
  1198. } else {
  1199. SourceRouting = SingleRouteSourceRouting;
  1200. }
  1201. SourceRoutingLength = 2;
  1202. }
  1203. }
  1204. #if 0
  1205. if (SourceRoutingLength != 0) {
  1206. // PUCHAR IpxHeader = Header + Binding->BcMcHeaderSize;
  1207. PUCHAR IpxHeader = Header + MAC_HEADER_SIZE;
  1208. //
  1209. // Need to slide the header down to accomodate the SR.
  1210. //
  1211. RtlMoveMemory (IpxHeader+SourceRoutingLength, IpxHeader, IncludedHeaderLength);
  1212. }
  1213. #endif
  1214. }
  1215. Header[0] = TR_PREAMBLE_AC;
  1216. Header[1] = TR_PREAMBLE_FC;
  1217. RtlCopyMemory (Header+2, LocalTarget->MacAddress, 6);
  1218. RtlCopyMemory (Header+8, Binding->LocalMacAddress.Address, 6);
  1219. if (SourceRoutingLength != 0) {
  1220. Header[8] |= TR_SOURCE_ROUTE_FLAG;
  1221. RtlCopyMemory (Header+14, SourceRouting, SourceRoutingLength);
  1222. }
  1223. Header += (14 + SourceRoutingLength);
  1224. switch (Binding->FrameType) {
  1225. case ISN_FRAME_TYPE_802_2:
  1226. case ISN_FRAME_TYPE_802_3:
  1227. case ISN_FRAME_TYPE_ETHERNET_II:
  1228. Header[0] = 0xe0;
  1229. Header[1] = 0xe0;
  1230. Header[2] = 0x03;
  1231. HeaderLength = 17;
  1232. break;
  1233. case ISN_FRAME_TYPE_SNAP:
  1234. Header[0] = 0xaa;
  1235. Header[1] = 0xaa;
  1236. Header[2] = 0x03;
  1237. Header[3] = 0x00;
  1238. Header[4] = 0x00;
  1239. Header[5] = 0x00;
  1240. *(UNALIGNED USHORT *)(&Header[6]) = Adapter->BindSapNetworkOrder;
  1241. HeaderLength = 22;
  1242. break;
  1243. }
  1244. // BufferLength = IncludedHeaderLength + HeaderLength + SourceRoutingLength;
  1245. BufferLength = HeaderLength + SourceRoutingLength;
  1246. break;
  1247. case NdisMediumFddi:
  1248. Header[0] = FDDI_HEADER_BYTE;
  1249. RtlCopyMemory (Header+1, LocalTarget->MacAddress, 6);
  1250. RtlCopyMemory (Header+7, Binding->LocalMacAddress.Address, 6);
  1251. switch (Binding->FrameType) {
  1252. case ISN_FRAME_TYPE_802_3:
  1253. HeaderLength = 13;
  1254. break;
  1255. case ISN_FRAME_TYPE_802_2:
  1256. case ISN_FRAME_TYPE_ETHERNET_II:
  1257. Header[13] = 0xe0;
  1258. Header[14] = 0xe0;
  1259. Header[15] = 0x03;
  1260. HeaderLength = 16;
  1261. break;
  1262. case ISN_FRAME_TYPE_SNAP:
  1263. Header[13] = 0xaa;
  1264. Header[14] = 0xaa;
  1265. Header[15] = 0x03;
  1266. Header[16] = 0x00;
  1267. Header[17] = 0x00;
  1268. Header[18] = 0x00;
  1269. *(UNALIGNED USHORT *)(&Header[19]) = Adapter->BindSapNetworkOrder;
  1270. HeaderLength = 21;
  1271. break;
  1272. }
  1273. // BufferLength = IncludedHeaderLength + HeaderLength;
  1274. BufferLength = HeaderLength;
  1275. break;
  1276. case NdisMediumArcnet878_2:
  1277. //
  1278. // Convert broadcast address to 0 (the arcnet broadcast).
  1279. //
  1280. Header[0] = Binding->LocalMacAddress.Address[5];
  1281. if (LocalTarget->MacAddress[5] == 0xff) {
  1282. Header[1] = 0x00;
  1283. } else {
  1284. Header[1] = LocalTarget->MacAddress[5];
  1285. }
  1286. Header[2] = ARCNET_PROTOCOL_ID;
  1287. //
  1288. // Binding->FrameType is not used.
  1289. //
  1290. HeaderLength = 3;
  1291. // BufferLength = IncludedHeaderLength + HeaderLength;
  1292. BufferLength = HeaderLength;
  1293. break;
  1294. }
  1295. //
  1296. // Adjust the MAC header's length to the right value
  1297. //
  1298. NdisAdjustBufferLength (HeaderBuffer, BufferLength);
  1299. NdisRecalculatePacketCounts (Packet);
  1300. #if 0
  1301. {
  1302. PMDL mdl;
  1303. mdl = (PMDL)NDIS_BUFFER_LINKAGE(HeaderBuffer);
  1304. if (mdl) {
  1305. KdPrint(("**Bytecount %x %x\n",mdl->ByteCount, mdl));
  1306. if ((LONG)mdl->ByteCount < 0) {
  1307. DbgBreakPoint();
  1308. }
  1309. }
  1310. }
  1311. #endif
  1312. #if DBG
  1313. {
  1314. ULONG SendFlag;
  1315. ULONG Temp;
  1316. PNDIS_BUFFER FirstPacketBuffer;
  1317. PNDIS_BUFFER SecondPacketBuffer;
  1318. IPX_HEADER DumpHeader;
  1319. UCHAR DumpData[14];
  1320. NdisQueryPacket (Packet, NULL, NULL, &FirstPacketBuffer, NULL);
  1321. SecondPacketBuffer = NDIS_BUFFER_LINKAGE(FirstPacketBuffer);
  1322. TdiCopyMdlToBuffer(SecondPacketBuffer, 0, &DumpHeader, 0, sizeof(IPX_HEADER), &Temp);
  1323. if (Reserved->Identifier == IDENTIFIER_NB) {
  1324. SendFlag = IPX_PACKET_LOG_SEND_NB;
  1325. } else if (Reserved->Identifier == IDENTIFIER_SPX) {
  1326. SendFlag = IPX_PACKET_LOG_SEND_SPX;
  1327. } else if (Reserved->Identifier == IDENTIFIER_RIP) {
  1328. SendFlag = IPX_PACKET_LOG_SEND_RIP;
  1329. } else {
  1330. if (DumpHeader.SourceSocket == IpxPacketLogSocket) {
  1331. SendFlag = IPX_PACKET_LOG_SEND_SOCKET | IPX_PACKET_LOG_SEND_OTHER;
  1332. } else {
  1333. SendFlag = IPX_PACKET_LOG_SEND_OTHER;
  1334. }
  1335. }
  1336. #if 0
  1337. if (PACKET_LOG(SendFlag)) {
  1338. TdiCopyMdlToBuffer(SecondPacketBuffer, sizeof(IPX_HEADER), &DumpData, 0, 14, &Temp);
  1339. IpxLogPacket(
  1340. TRUE,
  1341. LocalTarget->MacAddress,
  1342. Binding->LocalMacAddress.Address,
  1343. (USHORT)PacketLength,
  1344. &DumpHeader,
  1345. DumpData);
  1346. }
  1347. #endif
  1348. }
  1349. #endif
  1350. ++Device->Statistics.PacketsSent;
  1351. NdisSend(
  1352. &Status,
  1353. Adapter->NdisBindingHandle,
  1354. Packet);
  1355. IpxDereferenceAdapter1(Adapter,ADAP_REF_SEND);
  1356. if (Status != STATUS_PENDING) {
  1357. IPX_DEBUG(TEMP,("Status is not pending (%ld). Reserved (%p)\n",Status,Reserved));
  1358. if (Reserved->PaddingBuffer) {
  1359. IPX_DEBUG(TEMP,("Padding buffer is not null. \n"));
  1360. //
  1361. // Remove padding if it was done.
  1362. //
  1363. if ( Reserved->PreviousTail ) {
  1364. NDIS_BUFFER_LINKAGE (Reserved->PreviousTail) = (PNDIS_BUFFER)NULL;
  1365. } else {
  1366. PNDIS_BUFFER LastBuffer = (PNDIS_BUFFER)Reserved->PaddingBuffer;
  1367. UINT LastBufferLength;
  1368. NdisQueryBuffer( LastBuffer, NULL, &LastBufferLength );
  1369. NdisAdjustBufferLength( LastBuffer, (LastBufferLength - 1) );
  1370. #if DBG
  1371. if ((Reserved->Identifier == IDENTIFIER_RIP) &&
  1372. (LastBufferLength == 1500)) {
  1373. DbgPrint("Packet: %lx\n", Packet);
  1374. DbgBreakPoint();
  1375. }
  1376. #endif DBG
  1377. }
  1378. Reserved->PaddingBuffer = NULL;
  1379. IPX_DEBUG(TEMP,("IpxSendFrame:Cleared PaddingBuffer for %p\n", Packet));
  1380. if (Reserved->Identifier < IDENTIFIER_IPX) {
  1381. NdisRecalculatePacketCounts (Packet);
  1382. }
  1383. }
  1384. //
  1385. // If this was an NB/SPX packet, and there was an
  1386. // iterative send going on, then call the SendComplete
  1387. // handler.
  1388. //
  1389. if ((Reserved->Identifier == IDENTIFIER_NB ||
  1390. Reserved->Identifier == IDENTIFIER_SPX) &&
  1391. (Reserved->CurrentNicId)) {
  1392. IpxSendComplete(
  1393. (NDIS_HANDLE)Binding->Adapter,
  1394. Packet,
  1395. Status);
  1396. Status = STATUS_PENDING;
  1397. }
  1398. }
  1399. //
  1400. // Derefernce the binding and adapter
  1401. //
  1402. IpxDereferenceBinding1(Binding, BREF_DEVICE_ACCESS);
  1403. IpxDereferenceAdapter(Adapter);
  1404. return Status;
  1405. } /* IpxSendFrame */
  1406. NDIS_STATUS
  1407. IpxSendFrame802_3802_3(
  1408. IN PADAPTER Adapter,
  1409. IN PIPX_LOCAL_TARGET LocalTarget,
  1410. IN PNDIS_PACKET Packet,
  1411. IN ULONG PacketLength,
  1412. IN ULONG IncludedHeaderLength
  1413. )
  1414. /*++
  1415. Routine Description:
  1416. This routine constructs a MAC header in a packet and submits
  1417. it to the appropriate NDIS driver.
  1418. It is assumed that the first buffer in the packet contains
  1419. an IPX header at an offset based on the media type. This
  1420. IPX header is moved around if needed.
  1421. THIS FUNCTION ONLY CONSTRUCT NDISMEDIUM802_3 FRAMES IN
  1422. THE ISN_FRAME_TYPE_802_3 FORMAT.
  1423. Arguments:
  1424. Adapter - The adapter on which we are sending.
  1425. LocalTarget - The local target of the send.
  1426. Packet - The NDIS packet.
  1427. PacketLength - The length of the packet, starting at the IPX header.
  1428. IncludedHeaderLength - The length of the header included in the
  1429. first buffer that needs to be moved if it does not wind up
  1430. MacHeaderOffset bytes into the packet.
  1431. //
  1432. // Remove the IncludedHeaderLength parameter from here
  1433. //
  1434. Return Value:
  1435. None.
  1436. --*/
  1437. {
  1438. PIPX_SEND_RESERVED Reserved = (PIPX_SEND_RESERVED)(Packet->ProtocolReserved);
  1439. PUCHAR Header;
  1440. NDIS_STATUS Status;
  1441. LONG HeaderLength;
  1442. IPX_DEFINE_LOCK_HANDLE(LockHandle)
  1443. IPX_GET_LOCK (&Adapter->Lock, &LockHandle);
  1444. if (Adapter->State != ADAPTER_STATE_STOPPING) {
  1445. IpxReferenceAdapter1(Adapter,ADAP_REF_SEND);
  1446. IPX_FREE_LOCK (&Adapter->Lock, LockHandle);
  1447. } else {
  1448. IPX_FREE_LOCK (&Adapter->Lock, LockHandle);
  1449. return NDIS_STATUS_FAILURE;
  1450. }
  1451. Header = Reserved->Header;
  1452. #if BACK_FILL
  1453. BACK_FILL_HEADER(Header, Reserved, 14, Packet);
  1454. IPX_DEBUG(SEND,("Backfill request 802_3802_3!! %x %x %x\n", Packet, Reserved, Reserved->HeaderBuffer));
  1455. #endif
  1456. RtlCopyMemory (Header, LocalTarget->MacAddress, 6);
  1457. RtlCopyMemory (Header+6, Adapter->LocalMacAddress.Address, 6);
  1458. //
  1459. // Pad odd-length packets if needed.
  1460. //
  1461. if (((PacketLength & 1) != 0) &&
  1462. (IpxDevice->EthernetPadToEven)) {
  1463. PNDIS_BUFFER CurBuffer;
  1464. PIPX_PADDING_BUFFER PaddingBuffer = IpxPaddingBuffer;
  1465. UINT Offset;
  1466. UINT LastBufferLength;
  1467. //
  1468. // Find the tail of the current packet.
  1469. //
  1470. CurBuffer = Reserved->HeaderBuffer;
  1471. while (NDIS_BUFFER_LINKAGE(CurBuffer) != NULL) {
  1472. CurBuffer = NDIS_BUFFER_LINKAGE(CurBuffer);
  1473. }
  1474. //
  1475. // If the last byte of the last NDIS_BUFFER is not at the end of
  1476. // the page, then we can simply increase the NDIS_BUFFER ByteCount
  1477. // by one.
  1478. // Otherwise, we must use the global padding buffer.
  1479. //
  1480. NdisQueryBufferOffset( CurBuffer, &Offset, &LastBufferLength );
  1481. if ( ((Offset + LastBufferLength) & (PAGE_SIZE - 1)) != 0) {
  1482. #if BACK_FILL
  1483. if (0) {
  1484. #else
  1485. if ( CurBuffer == Reserved->HeaderBuffer ) {
  1486. IncludedHeaderLength++; // Just bump this length
  1487. #endif
  1488. } else {
  1489. NdisAdjustBufferLength( CurBuffer, (LastBufferLength + 1) );
  1490. Reserved->PreviousTail = NULL;
  1491. Reserved->PaddingBuffer = (PIPX_PADDING_BUFFER)CurBuffer;
  1492. }
  1493. } else {
  1494. CTEAssert (NDIS_BUFFER_LINKAGE(PaddingBuffer->NdisBuffer) == NULL);
  1495. Reserved->PreviousTail = CurBuffer;
  1496. NDIS_BUFFER_LINKAGE (CurBuffer) = PaddingBuffer->NdisBuffer;
  1497. Reserved->PaddingBuffer = PaddingBuffer;
  1498. }
  1499. ++PacketLength;
  1500. #if DBG
  1501. ++IpxPadCount;
  1502. #endif
  1503. }
  1504. Header[12] = (UCHAR)(PacketLength / 256);
  1505. Header[13] = (UCHAR)(PacketLength % 256);
  1506. //NdisAdjustBufferLength (Reserved->HeaderBuffer, IncludedHeaderLength + 14);
  1507. #if BACK_FILL
  1508. BACK_FILL_ADJUST_BUFFER_LENGTH(Reserved, 14);
  1509. #else
  1510. NdisAdjustBufferLength (Reserved->HeaderBuffer, 14);
  1511. #endif
  1512. NdisRecalculatePacketCounts (Packet);
  1513. NdisSend(
  1514. &Status,
  1515. Adapter->NdisBindingHandle,
  1516. Packet);
  1517. IpxDereferenceAdapter1(Adapter,ADAP_REF_SEND);
  1518. return Status;
  1519. } /* IpxSendFrame802_3802_3 */
  1520. NDIS_STATUS
  1521. IpxSendFrame802_3802_2(
  1522. IN PADAPTER Adapter,
  1523. IN PIPX_LOCAL_TARGET LocalTarget,
  1524. IN PNDIS_PACKET Packet,
  1525. IN ULONG PacketLength,
  1526. IN ULONG IncludedHeaderLength
  1527. )
  1528. /*++
  1529. Routine Description:
  1530. This routine constructs a MAC header in a packet and submits
  1531. it to the appropriate NDIS driver.
  1532. It is assumed that the first buffer in the packet contains
  1533. an IPX header at an offset based on the media type. This
  1534. IPX header is moved around if needed.
  1535. THIS FUNCTION ONLY CONSTRUCT NDISMEDIUM802_3 FRAMES IN
  1536. THE ISN_FRAME_TYPE_802_2 FORMAT.
  1537. Arguments:
  1538. Adapter - The adapter on which we are sending.
  1539. LocalTarget - The local target of the send.
  1540. Packet - The NDIS packet.
  1541. PacketLength - The length of the packet, starting at the IPX header.
  1542. IncludedHeaderLength - The length of the header included in the
  1543. first buffer that needs to be moved if it does not wind up
  1544. MacHeaderOffset bytes into the packet.
  1545. Return Value:
  1546. None.
  1547. --*/
  1548. {
  1549. PIPX_SEND_RESERVED Reserved = (PIPX_SEND_RESERVED)(Packet->ProtocolReserved);
  1550. PUCHAR Header;
  1551. ULONG TwoBytes;
  1552. NDIS_STATUS Status;
  1553. IPX_DEFINE_LOCK_HANDLE(LockHandle)
  1554. IPX_GET_LOCK (&Adapter->Lock, &LockHandle);
  1555. if (Adapter->State != ADAPTER_STATE_STOPPING) {
  1556. IpxReferenceAdapter1(Adapter,ADAP_REF_SEND);
  1557. IPX_FREE_LOCK (&Adapter->Lock, LockHandle);
  1558. } else {
  1559. IPX_FREE_LOCK (&Adapter->Lock, LockHandle);
  1560. return NDIS_STATUS_FAILURE;
  1561. }
  1562. Header = Reserved->Header;
  1563. #if BACK_FILL
  1564. BACK_FILL_HEADER(Header, Reserved, 17, Packet);
  1565. IPX_DEBUG(SEND, ("Backfill request 802_3802_3!! %x %x %x\n", Packet, Reserved, Reserved->HeaderBuffer));
  1566. IPX_DEBUG(SEND, ("packet=%x, usermdl %x\n",Packet,Reserved->HeaderBuffer));
  1567. #endif
  1568. RtlCopyMemory (Header, LocalTarget->MacAddress, 6);
  1569. RtlCopyMemory (Header+6, Adapter->LocalMacAddress.Address, 6);
  1570. TwoBytes = PacketLength + 3;
  1571. Header[14] = 0xe0;
  1572. Header[15] = 0xe0;
  1573. Header[16] = 0x03;
  1574. //
  1575. // Pad odd-length packets if needed.
  1576. //
  1577. if (((PacketLength & 1) == 0) &&
  1578. (IpxDevice->EthernetPadToEven)) {
  1579. PNDIS_BUFFER CurBuffer;
  1580. PIPX_PADDING_BUFFER PaddingBuffer = IpxPaddingBuffer;
  1581. UINT Offset;
  1582. UINT LastBufferLength;
  1583. //
  1584. // Find the tail of the current packet.
  1585. //
  1586. CurBuffer = Reserved->HeaderBuffer;
  1587. while (NDIS_BUFFER_LINKAGE(CurBuffer) != NULL) {
  1588. CurBuffer = NDIS_BUFFER_LINKAGE(CurBuffer);
  1589. }
  1590. //
  1591. // If the last byte of the last NDIS_BUFFER is not at the end of
  1592. // the page, then we can simply increase the NDIS_BUFFER ByteCount
  1593. // by one.
  1594. // Otherwise, we must use the global padding buffer.
  1595. //
  1596. NdisQueryBufferOffset( CurBuffer, &Offset, &LastBufferLength );
  1597. if ( ((Offset + LastBufferLength) & (PAGE_SIZE - 1)) != 0 ) {
  1598. #if BACK_FILL
  1599. if (0) {
  1600. #else
  1601. if ( CurBuffer == Reserved->HeaderBuffer ) {
  1602. IncludedHeaderLength++; // Just bump this length
  1603. #endif
  1604. } else {
  1605. NdisAdjustBufferLength( CurBuffer, (LastBufferLength + 1) );
  1606. Reserved->PreviousTail = NULL;
  1607. Reserved->PaddingBuffer = (PIPX_PADDING_BUFFER)CurBuffer;
  1608. IPX_DEBUG(TEMP,("IpxSendFrame802_3802_2:Set PaddingBuffer for %p\n", Packet));
  1609. }
  1610. } else {
  1611. CTEAssert (NDIS_BUFFER_LINKAGE(PaddingBuffer->NdisBuffer) == NULL);
  1612. Reserved->PreviousTail = CurBuffer;
  1613. NDIS_BUFFER_LINKAGE (CurBuffer) = PaddingBuffer->NdisBuffer;
  1614. Reserved->PaddingBuffer = PaddingBuffer;
  1615. IPX_DEBUG(TEMP,("IpxSendFrame802_3802_:Set PaddingBuffer for %p\n", Packet));
  1616. }
  1617. ++TwoBytes;
  1618. #if DBG
  1619. ++IpxPadCount;
  1620. #endif
  1621. }
  1622. Header[12] = (UCHAR)(TwoBytes / 256);
  1623. Header[13] = (UCHAR)(TwoBytes % 256);
  1624. // NdisAdjustBufferLength (Reserved->HeaderBuffer, IncludedHeaderLength + 17);
  1625. #if BACK_FILL
  1626. BACK_FILL_ADJUST_BUFFER_LENGTH(Reserved, 17);
  1627. #else
  1628. NdisAdjustBufferLength (Reserved->HeaderBuffer, 17);
  1629. #endif
  1630. NdisRecalculatePacketCounts (Packet);
  1631. NdisSend(
  1632. &Status,
  1633. Adapter->NdisBindingHandle,
  1634. Packet);
  1635. IpxDereferenceAdapter1(Adapter,ADAP_REF_SEND);
  1636. return Status;
  1637. } /* IpxSendFrame802_3802_2 */
  1638. NDIS_STATUS
  1639. IpxSendFrame802_3EthernetII(
  1640. IN PADAPTER Adapter,
  1641. IN PIPX_LOCAL_TARGET LocalTarget,
  1642. IN PNDIS_PACKET Packet,
  1643. IN ULONG PacketLength,
  1644. IN ULONG IncludedHeaderLength
  1645. )
  1646. /*++
  1647. Routine Description:
  1648. This routine constructs a MAC header in a packet and submits
  1649. it to the appropriate NDIS driver.
  1650. It is assumed that the first buffer in the packet contains
  1651. an IPX header at an offset based on the media type. This
  1652. IPX header is moved around if needed.
  1653. THIS FUNCTION ONLY CONSTRUCT NDISMEDIUM802_3 FRAMES IN
  1654. THE ISN_FRAME_TYPE_ETHERNET_II FORMAT.
  1655. Arguments:
  1656. Adapter - The adapter on which we are sending.
  1657. LocalTarget - The local target of the send.
  1658. Packet - The NDIS packet.
  1659. PacketLength - The length of the packet, starting at the IPX header.
  1660. IncludedHeaderLength - The length of the header included in the
  1661. first buffer that needs to be moved if it does not wind up
  1662. MacHeaderOffset bytes into the packet.
  1663. Return Value:
  1664. None.
  1665. --*/
  1666. {
  1667. PIPX_SEND_RESERVED Reserved = (PIPX_SEND_RESERVED)(Packet->ProtocolReserved);
  1668. PUCHAR Header;
  1669. NDIS_STATUS Status;
  1670. IPX_DEFINE_LOCK_HANDLE(LockHandle)
  1671. IPX_GET_LOCK (&Adapter->Lock, &LockHandle);
  1672. if (Adapter->State != ADAPTER_STATE_STOPPING) {
  1673. IpxReferenceAdapter1(Adapter,ADAP_REF_SEND);
  1674. IPX_FREE_LOCK (&Adapter->Lock, LockHandle);
  1675. } else {
  1676. IPX_FREE_LOCK (&Adapter->Lock, LockHandle);
  1677. return NDIS_STATUS_FAILURE;
  1678. }
  1679. Header = Reserved->Header;
  1680. #if BACK_FILL
  1681. BACK_FILL_HEADER(Header, Reserved, 14, Packet);
  1682. #endif BACK_FILL
  1683. RtlCopyMemory (Header, LocalTarget->MacAddress, 6);
  1684. RtlCopyMemory (Header+6, Adapter->LocalMacAddress.Address, 6);
  1685. *(UNALIGNED USHORT *)(&Header[12]) = Adapter->BindSapNetworkOrder;
  1686. //
  1687. // Pad odd-length packets if needed.
  1688. //
  1689. if (((PacketLength & 1) != 0) &&
  1690. (IpxDevice->EthernetPadToEven)) {
  1691. PNDIS_BUFFER CurBuffer;
  1692. PIPX_PADDING_BUFFER PaddingBuffer = IpxPaddingBuffer;
  1693. UINT Offset;
  1694. UINT LastBufferLength;
  1695. //
  1696. // Find the tail of the current packet.
  1697. //
  1698. CurBuffer = Reserved->HeaderBuffer;
  1699. while (NDIS_BUFFER_LINKAGE(CurBuffer) != NULL) {
  1700. CurBuffer = NDIS_BUFFER_LINKAGE(CurBuffer);
  1701. }
  1702. //
  1703. // If the last byte of the last NDIS_BUFFER is not at the end of
  1704. // the page, then we can simply increase the NDIS_BUFFER ByteCount
  1705. // by one.
  1706. // Otherwise, we must use the global padding buffer.
  1707. //
  1708. NdisQueryBufferOffset( CurBuffer, &Offset, &LastBufferLength );
  1709. if ( ((Offset + LastBufferLength) & (PAGE_SIZE - 1)) != 0) {
  1710. #if BACK_FILL
  1711. if (0) {
  1712. #else
  1713. if ( CurBuffer == Reserved->HeaderBuffer ) {
  1714. IncludedHeaderLength++; // Just bump this length
  1715. #endif
  1716. } else {
  1717. NdisAdjustBufferLength( CurBuffer, (LastBufferLength + 1) );
  1718. Reserved->PreviousTail = NULL;
  1719. Reserved->PaddingBuffer = (PIPX_PADDING_BUFFER)CurBuffer;
  1720. }
  1721. } else {
  1722. CTEAssert (NDIS_BUFFER_LINKAGE(PaddingBuffer->NdisBuffer) == NULL);
  1723. Reserved->PreviousTail = CurBuffer;
  1724. NDIS_BUFFER_LINKAGE (CurBuffer) = PaddingBuffer->NdisBuffer;
  1725. Reserved->PaddingBuffer = PaddingBuffer;
  1726. }
  1727. #if DBG
  1728. ++IpxPadCount;
  1729. #endif
  1730. }
  1731. // NdisAdjustBufferLength (Reserved->HeaderBuffer, IncludedHeaderLength + 14);
  1732. #if BACK_FILL
  1733. BACK_FILL_ADJUST_BUFFER_LENGTH(Reserved, 14);
  1734. #else
  1735. NdisAdjustBufferLength (Reserved->HeaderBuffer, 14);
  1736. #endif
  1737. NdisRecalculatePacketCounts (Packet);
  1738. NdisSend(
  1739. &Status,
  1740. Adapter->NdisBindingHandle,
  1741. Packet);
  1742. IpxDereferenceAdapter1(Adapter,ADAP_REF_SEND);
  1743. return Status;
  1744. } /* IpxSendFrame802_3EthernetII */
  1745. NDIS_STATUS
  1746. IpxSendFrame802_3Snap(
  1747. IN PADAPTER Adapter,
  1748. IN PIPX_LOCAL_TARGET LocalTarget,
  1749. IN PNDIS_PACKET Packet,
  1750. IN ULONG PacketLength,
  1751. IN ULONG IncludedHeaderLength
  1752. )
  1753. /*++
  1754. Routine Description:
  1755. This routine constructs a MAC header in a packet and submits
  1756. it to the appropriate NDIS driver.
  1757. It is assumed that the first buffer in the packet contains
  1758. an IPX header at an offset based on the media type. This
  1759. IPX header is moved around if needed.
  1760. THIS FUNCTION ONLY CONSTRUCT NDISMEDIUM802_3 FRAMES IN
  1761. THE ISN_FRAME_TYPE_SNAP FORMAT.
  1762. Arguments:
  1763. Adapter - The adapter on which we are sending.
  1764. LocalTarget - The local target of the send.
  1765. Packet - The NDIS packet.
  1766. PacketLength - The length of the packet, starting at the IPX header.
  1767. IncludedHeaderLength - The length of the header included in the
  1768. first buffer that needs to be moved if it does not wind up
  1769. MacHeaderOffset bytes into the packet.
  1770. Return Value:
  1771. None.
  1772. --*/
  1773. {
  1774. PIPX_SEND_RESERVED Reserved = (PIPX_SEND_RESERVED)(Packet->ProtocolReserved);
  1775. PUCHAR Header;
  1776. ULONG TwoBytes;
  1777. NDIS_STATUS Status;
  1778. IPX_DEFINE_LOCK_HANDLE(LockHandle)
  1779. IPX_GET_LOCK (&Adapter->Lock, &LockHandle);
  1780. if (Adapter->State != ADAPTER_STATE_STOPPING) {
  1781. IpxReferenceAdapter1(Adapter,ADAP_REF_SEND);
  1782. IPX_FREE_LOCK (&Adapter->Lock, LockHandle);
  1783. } else {
  1784. IPX_FREE_LOCK (&Adapter->Lock, LockHandle);
  1785. return NDIS_STATUS_FAILURE;
  1786. }
  1787. Header = Reserved->Header;
  1788. #if BACK_FILL
  1789. BACK_FILL_HEADER(Header, Reserved, 22, Packet);
  1790. #endif BACK_FILL
  1791. RtlCopyMemory (Header, LocalTarget->MacAddress, 6);
  1792. RtlCopyMemory (Header+6, Adapter->LocalMacAddress.Address, 6);
  1793. TwoBytes = PacketLength + 8;
  1794. Header[14] = 0xaa;
  1795. Header[15] = 0xaa;
  1796. Header[16] = 0x03;
  1797. Header[17] = 0x00;
  1798. Header[18] = 0x00;
  1799. Header[19] = 0x00;
  1800. *(UNALIGNED USHORT *)(&Header[20]) = Adapter->BindSapNetworkOrder;
  1801. //
  1802. // Pad odd-length packets if needed.
  1803. //
  1804. if (((PacketLength & 1) == 0) &&
  1805. (IpxDevice->EthernetPadToEven)) {
  1806. PNDIS_BUFFER CurBuffer;
  1807. PIPX_PADDING_BUFFER PaddingBuffer = IpxPaddingBuffer;
  1808. UINT Offset;
  1809. UINT LastBufferLength;
  1810. //
  1811. // Find the tail of the current packet.
  1812. //
  1813. CurBuffer = Reserved->HeaderBuffer;
  1814. while (NDIS_BUFFER_LINKAGE(CurBuffer) != NULL) {
  1815. CurBuffer = NDIS_BUFFER_LINKAGE(CurBuffer);
  1816. }
  1817. //
  1818. // If the last byte of the last NDIS_BUFFER is not at the end of
  1819. // the page, then we can simply increase the NDIS_BUFFER ByteCount
  1820. // by one.
  1821. // Otherwise, we must use the global padding buffer.
  1822. //
  1823. NdisQueryBufferOffset( CurBuffer, &Offset, &LastBufferLength );
  1824. if ( ((Offset + LastBufferLength) & (PAGE_SIZE - 1)) != 0) {
  1825. #if BACK_FILL
  1826. if (0) {
  1827. #else
  1828. if ( CurBuffer == Reserved->HeaderBuffer ) {
  1829. IncludedHeaderLength++; // Just bump this length
  1830. #endif
  1831. } else {
  1832. NdisAdjustBufferLength( CurBuffer, (LastBufferLength + 1) );
  1833. Reserved->PreviousTail = NULL;
  1834. Reserved->PaddingBuffer = (PIPX_PADDING_BUFFER)CurBuffer;
  1835. }
  1836. } else {
  1837. CTEAssert (NDIS_BUFFER_LINKAGE(PaddingBuffer->NdisBuffer) == NULL);
  1838. Reserved->PreviousTail = CurBuffer;
  1839. NDIS_BUFFER_LINKAGE (CurBuffer) = PaddingBuffer->NdisBuffer;
  1840. Reserved->PaddingBuffer = PaddingBuffer;
  1841. }
  1842. ++TwoBytes;
  1843. #if DBG
  1844. ++IpxPadCount;
  1845. #endif
  1846. }
  1847. Header[12] = (UCHAR)(TwoBytes / 256);
  1848. Header[13] = (UCHAR)(TwoBytes % 256);
  1849. // NdisAdjustBufferLength (Reserved->HeaderBuffer, IncludedHeaderLength + 22);
  1850. #if BACK_FILL
  1851. BACK_FILL_ADJUST_BUFFER_LENGTH(Reserved, 22);
  1852. #else
  1853. NdisAdjustBufferLength (Reserved->HeaderBuffer, 22);
  1854. #endif
  1855. NdisRecalculatePacketCounts (Packet);
  1856. NdisSend(
  1857. &Status,
  1858. Adapter->NdisBindingHandle,
  1859. Packet);
  1860. IpxDereferenceAdapter1(Adapter,ADAP_REF_SEND);
  1861. return Status;
  1862. } /* IpxSendFrame802_3Snap */
  1863. NDIS_STATUS
  1864. IpxSendFrame802_5802_2(
  1865. IN PADAPTER Adapter,
  1866. IN PIPX_LOCAL_TARGET LocalTarget,
  1867. IN PNDIS_PACKET Packet,
  1868. IN ULONG PacketLength,
  1869. IN ULONG IncludedHeaderLength
  1870. )
  1871. /*++
  1872. Routine Description:
  1873. This routine constructs a MAC header in a packet and submits
  1874. it to the appropriate NDIS driver.
  1875. It is assumed that the first buffer in the packet contains
  1876. an IPX header at an offset based on the media type. This
  1877. IPX header is moved around if needed.
  1878. THIS FUNCTION ONLY CONSTRUCT NDISMEDIUM802_5 FRAMES IN
  1879. THE ISN_FRAME_TYPE_802_2 FORMAT.
  1880. Arguments:
  1881. Adapter - The adapter on which we are sending.
  1882. LocalTarget - The local target of the send.
  1883. Packet - The NDIS packet.
  1884. PacketLength - The length of the packet, starting at the IPX header.
  1885. IncludedHeaderLength - The length of the header included in the
  1886. first buffer that needs to be moved if it does not wind up
  1887. MacHeaderOffset bytes into the packet.
  1888. Return Value:
  1889. None.
  1890. --*/
  1891. {
  1892. PIPX_SEND_RESERVED Reserved = (PIPX_SEND_RESERVED)(Packet->ProtocolReserved);
  1893. PBINDING Binding = Adapter->Bindings[ISN_FRAME_TYPE_802_2];
  1894. PUCHAR Header;
  1895. ULONG HeaderLength;
  1896. UCHAR SourceRoutingBuffer[18];
  1897. PUCHAR SourceRouting;
  1898. ULONG SourceRoutingLength;
  1899. NDIS_STATUS Status;
  1900. ULONG BufferLength;
  1901. UCHAR DestinationType;
  1902. IPX_DEFINE_LOCK_HANDLE(LockHandle)
  1903. IPX_GET_LOCK (&Adapter->Lock, &LockHandle);
  1904. if (Adapter->State != ADAPTER_STATE_STOPPING) {
  1905. IpxReferenceAdapter1(Adapter,ADAP_REF_SEND);
  1906. IPX_FREE_LOCK (&Adapter->Lock, LockHandle);
  1907. } else {
  1908. IPX_FREE_LOCK (&Adapter->Lock, LockHandle);
  1909. return NDIS_STATUS_FAILURE;
  1910. }
  1911. Header = Reserved->Header;
  1912. #if BACK_FILL
  1913. BACK_FILL_HEADER(Header, Reserved, 17, Packet);
  1914. #endif BACK_FILL
  1915. DestinationType = Reserved->DestinationType;
  1916. if (DestinationType == DESTINATION_DEF) {
  1917. MacLookupSourceRouting(
  1918. Reserved->Identifier,
  1919. Binding,
  1920. LocalTarget->MacAddress,
  1921. SourceRoutingBuffer,
  1922. &SourceRoutingLength);
  1923. if (SourceRoutingLength != 0) {
  1924. //PUCHAR IpxHeader = Header + Binding->DefHeaderSize;
  1925. PUCHAR IpxHeader = Header + MAC_HEADER_SIZE;
  1926. //
  1927. // Need to slide the header down to accomodate the SR.
  1928. //
  1929. SourceRouting = SourceRoutingBuffer;
  1930. // RtlMoveMemory (IpxHeader+SourceRoutingLength, IpxHeader, IncludedHeaderLength);
  1931. }
  1932. } else {
  1933. //
  1934. // For these packets we assume that the header is in the
  1935. // right place.
  1936. //
  1937. if (!Adapter->SourceRouting) {
  1938. SourceRoutingLength = 0;
  1939. } else {
  1940. if (DestinationType == DESTINATION_BCAST) {
  1941. if (Binding->AllRouteBroadcast) {
  1942. SourceRouting = AllRouteSourceRouting;
  1943. } else {
  1944. SourceRouting = SingleRouteSourceRouting;
  1945. }
  1946. SourceRoutingLength = 2;
  1947. } else {
  1948. CTEAssert (DestinationType == DESTINATION_MCAST);
  1949. if (Binding->AllRouteMulticast) {
  1950. SourceRouting = AllRouteSourceRouting;
  1951. } else {
  1952. SourceRouting = SingleRouteSourceRouting;
  1953. }
  1954. SourceRoutingLength = 2;
  1955. }
  1956. }
  1957. #if 0
  1958. if (SourceRoutingLength != 0) {
  1959. PUCHAR IpxHeader = Header + Binding->BcMcHeaderSize;
  1960. //
  1961. // Need to slide the header down to accomodate the SR.
  1962. //
  1963. RtlMoveMemory (IpxHeader+SourceRoutingLength, IpxHeader, IncludedHeaderLength);
  1964. }
  1965. #endif
  1966. }
  1967. Header[0] = TR_PREAMBLE_AC;
  1968. Header[1] = TR_PREAMBLE_FC;
  1969. RtlCopyMemory (Header+2, LocalTarget->MacAddress, 6);
  1970. RtlCopyMemory (Header+8, Adapter->LocalMacAddress.Address, 6);
  1971. if (SourceRoutingLength != 0) {
  1972. Header[8] |= TR_SOURCE_ROUTE_FLAG;
  1973. RtlCopyMemory (Header+14, SourceRouting, SourceRoutingLength);
  1974. }
  1975. Header += (14 + SourceRoutingLength);
  1976. Header[0] = 0xe0;
  1977. Header[1] = 0xe0;
  1978. Header[2] = 0x03;
  1979. HeaderLength = 17;
  1980. //BufferLength = IncludedHeaderLength + HeaderLength + SourceRoutingLength;
  1981. BufferLength = HeaderLength + SourceRoutingLength;
  1982. #if BACK_FILL
  1983. BACK_FILL_ADJUST_BUFFER_LENGTH(Reserved, BufferLength);
  1984. #else
  1985. NdisAdjustBufferLength (Reserved->HeaderBuffer, BufferLength);
  1986. #endif
  1987. NdisRecalculatePacketCounts (Packet);
  1988. NdisSend(
  1989. &Status,
  1990. Adapter->NdisBindingHandle,
  1991. Packet);
  1992. IpxDereferenceAdapter1(Adapter,ADAP_REF_SEND);
  1993. return Status;
  1994. } /* IpxSendFrame802_5802_2 */
  1995. NDIS_STATUS
  1996. IpxSendFrame802_5Snap(
  1997. IN PADAPTER Adapter,
  1998. IN PIPX_LOCAL_TARGET LocalTarget,
  1999. IN PNDIS_PACKET Packet,
  2000. IN ULONG PacketLength,
  2001. IN ULONG IncludedHeaderLength
  2002. )
  2003. /*++
  2004. Routine Description:
  2005. This routine constructs a MAC header in a packet and submits
  2006. it to the appropriate NDIS driver.
  2007. It is assumed that the first buffer in the packet contains
  2008. an IPX header at an offset based on the media type. This
  2009. IPX header is moved around if needed.
  2010. THIS FUNCTION ONLY CONSTRUCT NDISMEDIUM802_5 FRAMES IN
  2011. THE ISN_FRAME_TYPE_SNAP FORMAT.
  2012. Arguments:
  2013. Adapter - The adapter on which we are sending.
  2014. LocalTarget - The local target of the send.
  2015. Packet - The NDIS packet.
  2016. PacketLength - The length of the packet, starting at the IPX header.
  2017. IncludedHeaderLength - The length of the header included in the
  2018. first buffer that needs to be moved if it does not wind up
  2019. MacHeaderOffset bytes into the packet.
  2020. Return Value:
  2021. None.
  2022. --*/
  2023. {
  2024. PIPX_SEND_RESERVED Reserved = (PIPX_SEND_RESERVED)(Packet->ProtocolReserved);
  2025. PBINDING Binding = Adapter->Bindings[ISN_FRAME_TYPE_SNAP];
  2026. PUCHAR Header;
  2027. ULONG HeaderLength;
  2028. UCHAR SourceRoutingBuffer[18];
  2029. PUCHAR SourceRouting;
  2030. ULONG SourceRoutingLength;
  2031. NDIS_STATUS Status;
  2032. ULONG BufferLength;
  2033. UCHAR DestinationType;
  2034. IPX_DEFINE_LOCK_HANDLE(LockHandle)
  2035. IPX_GET_LOCK (&Adapter->Lock, &LockHandle);
  2036. if (Adapter->State != ADAPTER_STATE_STOPPING) {
  2037. IpxReferenceAdapter1(Adapter,ADAP_REF_SEND);
  2038. IPX_FREE_LOCK (&Adapter->Lock, LockHandle);
  2039. } else {
  2040. IPX_FREE_LOCK (&Adapter->Lock, LockHandle);
  2041. return NDIS_STATUS_FAILURE;
  2042. }
  2043. Header = Reserved->Header;
  2044. #if BACK_FILL
  2045. BACK_FILL_HEADER(Header, Reserved, 22, Packet);
  2046. #endif BACK_FILL
  2047. DestinationType = Reserved->DestinationType;
  2048. if (DestinationType == DESTINATION_DEF) {
  2049. MacLookupSourceRouting(
  2050. Reserved->Identifier,
  2051. Binding,
  2052. LocalTarget->MacAddress,
  2053. SourceRoutingBuffer,
  2054. &SourceRoutingLength);
  2055. if (SourceRoutingLength != 0) {
  2056. // PUCHAR IpxHeader = Header + Binding->DefHeaderSize;
  2057. //
  2058. // Need to slide the header down to accomodate the SR.
  2059. //
  2060. SourceRouting = SourceRoutingBuffer;
  2061. // RtlMoveMemory (IpxHeader+SourceRoutingLength, IpxHeader, IncludedHeaderLength);
  2062. }
  2063. } else {
  2064. //
  2065. // For these packets we assume that the header is in the
  2066. // right place.
  2067. //
  2068. if (!Adapter->SourceRouting) {
  2069. SourceRoutingLength = 0;
  2070. } else {
  2071. if (DestinationType == DESTINATION_BCAST) {
  2072. if (Binding->AllRouteBroadcast) {
  2073. SourceRouting = AllRouteSourceRouting;
  2074. } else {
  2075. SourceRouting = SingleRouteSourceRouting;
  2076. }
  2077. SourceRoutingLength = 2;
  2078. } else {
  2079. CTEAssert (DestinationType == DESTINATION_MCAST);
  2080. if (Binding->AllRouteMulticast) {
  2081. SourceRouting = AllRouteSourceRouting;
  2082. } else {
  2083. SourceRouting = SingleRouteSourceRouting;
  2084. }
  2085. SourceRoutingLength = 2;
  2086. }
  2087. if (SourceRoutingLength != 0) {
  2088. // PUCHAR IpxHeader = Header + Binding->BcMcHeaderSize;
  2089. //
  2090. // Need to slide the header down to accomodate the SR.
  2091. //
  2092. // RtlMoveMemory (IpxHeader+SourceRoutingLength, IpxHeader, IncludedHeaderLength);
  2093. }
  2094. }
  2095. }
  2096. Header[0] = TR_PREAMBLE_AC;
  2097. Header[1] = TR_PREAMBLE_FC;
  2098. RtlCopyMemory (Header+2, LocalTarget->MacAddress, 6);
  2099. RtlCopyMemory (Header+8, Adapter->LocalMacAddress.Address, 6);
  2100. if (SourceRoutingLength != 0) {
  2101. Header[8] |= TR_SOURCE_ROUTE_FLAG;
  2102. RtlCopyMemory (Header+14, SourceRouting, SourceRoutingLength);
  2103. }
  2104. Header += (14 + SourceRoutingLength);
  2105. Header[0] = 0xaa;
  2106. Header[1] = 0xaa;
  2107. Header[2] = 0x03;
  2108. Header[3] = 0x00;
  2109. Header[4] = 0x00;
  2110. Header[5] = 0x00;
  2111. *(UNALIGNED USHORT *)(&Header[6]) = Adapter->BindSapNetworkOrder;
  2112. HeaderLength = 22;
  2113. //BufferLength = IncludedHeaderLength + HeaderLength + SourceRoutingLength;
  2114. BufferLength = HeaderLength + SourceRoutingLength;
  2115. #if BACK_FILL
  2116. BACK_FILL_ADJUST_BUFFER_LENGTH(Reserved, BufferLength);
  2117. #else
  2118. NdisAdjustBufferLength (Reserved->HeaderBuffer, BufferLength);
  2119. #endif
  2120. NdisRecalculatePacketCounts (Packet);
  2121. NdisSend(
  2122. &Status,
  2123. Adapter->NdisBindingHandle,
  2124. Packet);
  2125. IpxDereferenceAdapter1(Adapter,ADAP_REF_SEND);
  2126. return Status;
  2127. } /* IpxSendFrame802_5Snap */
  2128. NDIS_STATUS
  2129. IpxSendFrameFddi802_3(
  2130. IN PADAPTER Adapter,
  2131. IN PIPX_LOCAL_TARGET LocalTarget,
  2132. IN PNDIS_PACKET Packet,
  2133. IN ULONG PacketLength,
  2134. IN ULONG IncludedHeaderLength
  2135. )
  2136. /*++
  2137. Routine Description:
  2138. This routine constructs a MAC header in a packet and submits
  2139. it to the appropriate NDIS driver.
  2140. It is assumed that the first buffer in the packet contains
  2141. an IPX header at an offset based on the media type. This
  2142. IPX header is moved around if needed.
  2143. THIS FUNCTION ONLY CONSTRUCT NDISMEDIUMFDDI FRAMES IN
  2144. THE ISN_FRAME_TYPE_802_3 FORMAT.
  2145. Arguments:
  2146. Adapter - The adapter on which we are sending.
  2147. LocalTarget - The local target of the send.
  2148. Packet - The NDIS packet.
  2149. PacketLength - The length of the packet, starting at the IPX header.
  2150. IncludedHeaderLength - The length of the header included in the
  2151. first buffer that needs to be moved if it does not wind up
  2152. MacHeaderOffset bytes into the packet.
  2153. Return Value:
  2154. None.
  2155. --*/
  2156. {
  2157. PIPX_SEND_RESERVED Reserved = (PIPX_SEND_RESERVED)(Packet->ProtocolReserved);
  2158. PUCHAR Header;
  2159. NDIS_STATUS Status;
  2160. IPX_DEFINE_LOCK_HANDLE(LockHandle)
  2161. IPX_GET_LOCK (&Adapter->Lock, &LockHandle);
  2162. if (Adapter->State != ADAPTER_STATE_STOPPING) {
  2163. IpxReferenceAdapter1(Adapter,ADAP_REF_SEND);
  2164. IPX_FREE_LOCK (&Adapter->Lock, LockHandle);
  2165. } else {
  2166. IPX_FREE_LOCK (&Adapter->Lock, LockHandle);
  2167. return NDIS_STATUS_FAILURE;
  2168. }
  2169. Header = Reserved->Header;
  2170. #if BACK_FILL
  2171. BACK_FILL_HEADER(Header, Reserved, 13, Packet);
  2172. #endif BACK_FILL
  2173. Header[0] = FDDI_HEADER_BYTE;
  2174. RtlCopyMemory (Header+1, LocalTarget->MacAddress, 6);
  2175. RtlCopyMemory (Header+7, Adapter->LocalMacAddress.Address, 6);
  2176. // NdisAdjustBufferLength (Reserved->HeaderBuffer, IncludedHeaderLength + 13);
  2177. #if BACK_FILL
  2178. BACK_FILL_ADJUST_BUFFER_LENGTH(Reserved, 13);
  2179. #else
  2180. NdisAdjustBufferLength (Reserved->HeaderBuffer, 13);
  2181. #endif
  2182. NdisRecalculatePacketCounts (Packet);
  2183. NdisSend(
  2184. &Status,
  2185. Adapter->NdisBindingHandle,
  2186. Packet);
  2187. IpxDereferenceAdapter1(Adapter,ADAP_REF_SEND);
  2188. return Status;
  2189. } /* IpxSendFrameFddi802_3 */
  2190. NDIS_STATUS
  2191. IpxSendFrameFddi802_2(
  2192. IN PADAPTER Adapter,
  2193. IN PIPX_LOCAL_TARGET LocalTarget,
  2194. IN PNDIS_PACKET Packet,
  2195. IN ULONG PacketLength,
  2196. IN ULONG IncludedHeaderLength
  2197. )
  2198. /*++
  2199. Routine Description:
  2200. This routine constructs a MAC header in a packet and submits
  2201. it to the appropriate NDIS driver.
  2202. It is assumed that the first buffer in the packet contains
  2203. an IPX header at an offset based on the media type. This
  2204. IPX header is moved around if needed.
  2205. THIS FUNCTION ONLY CONSTRUCT NDISMEDIUMFDDI FRAMES IN
  2206. THE ISN_FRAME_TYPE_802_2 FORMAT.
  2207. Arguments:
  2208. Adapter - The adapter on which we are sending.
  2209. LocalTarget - The local target of the send.
  2210. Packet - The NDIS packet.
  2211. PacketLength - The length of the packet, starting at the IPX header.
  2212. IncludedHeaderLength - The length of the header included in the
  2213. first buffer that needs to be moved if it does not wind up
  2214. MacHeaderOffset bytes into the packet.
  2215. Return Value:
  2216. None.
  2217. --*/
  2218. {
  2219. PIPX_SEND_RESERVED Reserved = (PIPX_SEND_RESERVED)(Packet->ProtocolReserved);
  2220. PUCHAR Header;
  2221. NDIS_STATUS Status;
  2222. IPX_DEFINE_LOCK_HANDLE(LockHandle)
  2223. IPX_GET_LOCK (&Adapter->Lock, &LockHandle);
  2224. if (Adapter->State != ADAPTER_STATE_STOPPING) {
  2225. IpxReferenceAdapter1(Adapter,ADAP_REF_SEND);
  2226. IPX_FREE_LOCK (&Adapter->Lock, LockHandle);
  2227. } else {
  2228. IPX_FREE_LOCK (&Adapter->Lock, LockHandle);
  2229. return NDIS_STATUS_FAILURE;
  2230. }
  2231. Header = Reserved->Header;
  2232. #if BACK_FILL
  2233. BACK_FILL_HEADER(Header, Reserved, 16, Packet);
  2234. #endif BACK_FILL
  2235. Header[0] = FDDI_HEADER_BYTE;
  2236. RtlCopyMemory (Header+1, LocalTarget->MacAddress, 6);
  2237. RtlCopyMemory (Header+7, Adapter->LocalMacAddress.Address, 6);
  2238. Header[13] = 0xe0;
  2239. Header[14] = 0xe0;
  2240. Header[15] = 0x03;
  2241. // NdisAdjustBufferLength (Reserved->HeaderBuffer, IncludedHeaderLength + 16);
  2242. #if BACK_FILL
  2243. BACK_FILL_ADJUST_BUFFER_LENGTH(Reserved, 16);
  2244. #else
  2245. NdisAdjustBufferLength (Reserved->HeaderBuffer, 16);
  2246. #endif
  2247. NdisRecalculatePacketCounts (Packet);
  2248. NdisSend(
  2249. &Status,
  2250. Adapter->NdisBindingHandle,
  2251. Packet);
  2252. IpxDereferenceAdapter1(Adapter,ADAP_REF_SEND);
  2253. return Status;
  2254. } /* IpxSendFrameFddi802_2 */
  2255. NDIS_STATUS
  2256. IpxSendFrameFddiSnap(
  2257. IN PADAPTER Adapter,
  2258. IN PIPX_LOCAL_TARGET LocalTarget,
  2259. IN PNDIS_PACKET Packet,
  2260. IN ULONG PacketLength,
  2261. IN ULONG IncludedHeaderLength
  2262. )
  2263. /*++
  2264. Routine Description:
  2265. This routine constructs a MAC header in a packet and submits
  2266. it to the appropriate NDIS driver.
  2267. It is assumed that the first buffer in the packet contains
  2268. an IPX header at an offset based on the media type. This
  2269. IPX header is moved around if needed.
  2270. THIS FUNCTION ONLY CONSTRUCT NDISMEDIUMFDDI FRAMES IN
  2271. THE ISN_FRAME_TYPE_SNAP FORMAT.
  2272. Arguments:
  2273. Adapter - The adapter on which we are sending.
  2274. LocalTarget - The local target of the send.
  2275. Packet - The NDIS packet.
  2276. PacketLength - The length of the packet, starting at the IPX header.
  2277. IncludedHeaderLength - The length of the header included in the
  2278. first buffer that needs to be moved if it does not wind up
  2279. MacHeaderOffset bytes into the packet.
  2280. Return Value:
  2281. None.
  2282. --*/
  2283. {
  2284. PIPX_SEND_RESERVED Reserved = (PIPX_SEND_RESERVED)(Packet->ProtocolReserved);
  2285. PUCHAR Header;
  2286. NDIS_STATUS Status;
  2287. IPX_DEFINE_LOCK_HANDLE(LockHandle)
  2288. IPX_GET_LOCK (&Adapter->Lock, &LockHandle);
  2289. if (Adapter->State != ADAPTER_STATE_STOPPING) {
  2290. IpxReferenceAdapter1(Adapter,ADAP_REF_SEND);
  2291. IPX_FREE_LOCK (&Adapter->Lock, LockHandle);
  2292. } else {
  2293. IPX_FREE_LOCK (&Adapter->Lock, LockHandle);
  2294. return NDIS_STATUS_FAILURE;
  2295. }
  2296. Header = Reserved->Header;
  2297. #if BACK_FILL
  2298. BACK_FILL_HEADER(Header, Reserved, 21, Packet);
  2299. #endif BACK_FILL
  2300. Header[0] = FDDI_HEADER_BYTE;
  2301. RtlCopyMemory (Header+1, LocalTarget->MacAddress, 6);
  2302. RtlCopyMemory (Header+7, Adapter->LocalMacAddress.Address, 6);
  2303. Header[13] = 0xaa;
  2304. Header[14] = 0xaa;
  2305. Header[15] = 0x03;
  2306. Header[16] = 0x00;
  2307. Header[17] = 0x00;
  2308. Header[18] = 0x00;
  2309. *(UNALIGNED USHORT *)(&Header[19]) = Adapter->BindSapNetworkOrder;
  2310. // NdisAdjustBufferLength (Reserved->HeaderBuffer, IncludedHeaderLength + 21);
  2311. #if BACK_FILL
  2312. BACK_FILL_ADJUST_BUFFER_LENGTH(Reserved, 21);
  2313. #else
  2314. NdisAdjustBufferLength (Reserved->HeaderBuffer, 21);
  2315. #endif
  2316. NdisRecalculatePacketCounts (Packet);
  2317. NdisSend(
  2318. &Status,
  2319. Adapter->NdisBindingHandle,
  2320. Packet);
  2321. IpxDereferenceAdapter1(Adapter,ADAP_REF_SEND);
  2322. return Status;
  2323. } /* IpxSendFrameFddiSnap */
  2324. NDIS_STATUS
  2325. IpxSendFrameArcnet878_2(
  2326. IN PADAPTER Adapter,
  2327. IN PIPX_LOCAL_TARGET LocalTarget,
  2328. IN PNDIS_PACKET Packet,
  2329. IN ULONG PacketLength,
  2330. IN ULONG IncludedHeaderLength
  2331. )
  2332. /*++
  2333. Routine Description:
  2334. This routine constructs a MAC header in a packet and submits
  2335. it to the appropriate NDIS driver.
  2336. It is assumed that the first buffer in the packet contains
  2337. an IPX header at an offset based on the media type. This
  2338. IPX header is moved around if needed.
  2339. THIS FUNCTION ONLY CONSTRUCT NDISMEDIUMARCNET878_2 FRAMES IN
  2340. THE ISN_FRAME_TYPE_802_2 FORMAT.
  2341. Arguments:
  2342. Adapter - The adapter on which we are sending.
  2343. LocalTarget - The local target of the send.
  2344. Packet - The NDIS packet.
  2345. PacketLength - The length of the packet, starting at the IPX header.
  2346. IncludedHeaderLength - The length of the header included in the
  2347. first buffer that needs to be moved if it does not wind up
  2348. MacHeaderOffset bytes into the packet.
  2349. Return Value:
  2350. None.
  2351. --*/
  2352. {
  2353. PIPX_SEND_RESERVED Reserved = (PIPX_SEND_RESERVED)(Packet->ProtocolReserved);
  2354. PUCHAR Header;
  2355. NDIS_STATUS Status;
  2356. IPX_DEFINE_LOCK_HANDLE(LockHandle)
  2357. IPX_GET_LOCK (&Adapter->Lock, &LockHandle);
  2358. if (Adapter->State != ADAPTER_STATE_STOPPING) {
  2359. IpxReferenceAdapter1(Adapter,ADAP_REF_SEND);
  2360. IPX_FREE_LOCK (&Adapter->Lock, LockHandle);
  2361. } else {
  2362. IPX_FREE_LOCK (&Adapter->Lock, LockHandle);
  2363. return NDIS_STATUS_FAILURE;
  2364. }
  2365. Header = Reserved->Header;
  2366. #if BACK_FILL
  2367. BACK_FILL_HEADER(Header, Reserved, 3, Packet);
  2368. #endif BACK_FILL
  2369. //
  2370. // Convert broadcast address to 0 (the arcnet broadcast).
  2371. //
  2372. Header[0] = Adapter->LocalMacAddress.Address[5];
  2373. if (LocalTarget->MacAddress[5] == 0xff) {
  2374. Header[1] = 0x00;
  2375. } else {
  2376. Header[1] = LocalTarget->MacAddress[5];
  2377. }
  2378. Header[2] = ARCNET_PROTOCOL_ID;
  2379. // NdisAdjustBufferLength (Reserved->HeaderBuffer, IncludedHeaderLength + 3);
  2380. #if BACK_FILL
  2381. BACK_FILL_ADJUST_BUFFER_LENGTH(Reserved, 3);
  2382. #else
  2383. NdisAdjustBufferLength (Reserved->HeaderBuffer, 3);
  2384. #endif
  2385. NdisRecalculatePacketCounts (Packet);
  2386. NdisSend(
  2387. &Status,
  2388. Adapter->NdisBindingHandle,
  2389. Packet);
  2390. IpxDereferenceAdapter1(Adapter,ADAP_REF_SEND);
  2391. return Status;
  2392. } /* IpxSendFrameFddiArcnet878_2 */
  2393. NDIS_STATUS
  2394. IpxSendFrameWanEthernetII(
  2395. IN PADAPTER Adapter,
  2396. IN PIPX_LOCAL_TARGET LocalTarget,
  2397. IN PNDIS_PACKET Packet,
  2398. IN ULONG PacketLength,
  2399. IN ULONG IncludedHeaderLength
  2400. )
  2401. /*++
  2402. Routine Description:
  2403. This routine constructs a MAC header in a packet and submits
  2404. it to the appropriate NDIS driver.
  2405. It is assumed that the first buffer in the packet contains
  2406. an IPX header at an offset based on the media type. This
  2407. IPX header is moved around if needed.
  2408. THIS FUNCTION ONLY CONSTRUCT NDISMEDIUMWAN FRAMES IN
  2409. THE ISN_FRAME_TYPE_ETHERNET_II FORMAT.
  2410. Arguments:
  2411. Adapter - The adapter on which we are sending.
  2412. LocalTarget - The local target of the send.
  2413. Packet - The NDIS packet.
  2414. PacketLength - The length of the packet, starting at the IPX header.
  2415. IncludedHeaderLength - The length of the header included in the
  2416. first buffer that needs to be moved if it does not wind up
  2417. MacHeaderOffset bytes into the packet.
  2418. Return Value:
  2419. None.
  2420. --*/
  2421. {
  2422. PIPX_SEND_RESERVED Reserved = (PIPX_SEND_RESERVED)(Packet->ProtocolReserved);
  2423. PUCHAR Header;
  2424. NDIS_STATUS Status;
  2425. PBINDING Binding;
  2426. IPX_DEFINE_LOCK_HANDLE(LockHandle1)
  2427. IPX_GET_LOCK1(&IpxDevice->BindAccessLock, &LockHandle1);
  2428. Binding = NIC_ID_TO_BINDING(IpxDevice, NIC_FROM_LOCAL_TARGET(LocalTarget));
  2429. IpxReferenceBinding1(Binding, BREF_DEVICE_ACCESS);
  2430. IPX_FREE_LOCK1(&IpxDevice->BindAccessLock, LockHandle1);
  2431. //
  2432. // [FW] This will allow both LINE_UP and LINE_CONFIG states
  2433. //
  2434. if (Binding->LineUp) {
  2435. IPX_DEFINE_LOCK_HANDLE(LockHandle)
  2436. IPX_GET_LOCK (&Adapter->Lock, &LockHandle);
  2437. if (Adapter->State != ADAPTER_STATE_STOPPING) {
  2438. IpxReferenceAdapter1(Adapter,ADAP_REF_SEND);
  2439. IPX_FREE_LOCK (&Adapter->Lock, LockHandle);
  2440. } else {
  2441. IPX_FREE_LOCK (&Adapter->Lock, LockHandle);
  2442. IpxDereferenceBinding1(Binding, BREF_DEVICE_ACCESS);
  2443. return NDIS_STATUS_FAILURE;
  2444. }
  2445. Header = Reserved->Header;
  2446. #if BACK_FILL
  2447. BACK_FILL_HEADER(Header, Reserved, 14, Packet);
  2448. //
  2449. // Call UpdateWanInactivity only if this is not a backfill packet, since
  2450. // SMB server does not do KeepAlives. In case, of backfilled packets, reset
  2451. // the counter regardless.
  2452. //
  2453. if (!Reserved->BackFill) {
  2454. IpxUpdateWanInactivityCounter(
  2455. Binding,
  2456. (IPX_HEADER UNALIGNED *)(Header + IpxDevice->IncludedHeaderOffset),
  2457. IncludedHeaderLength,
  2458. Packet,
  2459. PacketLength);
  2460. } else {
  2461. Binding->WanInactivityCounter = 0;
  2462. }
  2463. #else
  2464. //
  2465. // We do checks to see if we should reset the inactivity
  2466. // counter. We normally need to check for netbios
  2467. // session alives, packets from rip, packets from
  2468. // sap, and ncp keep alives. In fact netbios packets
  2469. // and rip packets don't come through here.
  2470. //
  2471. IpxUpdateWanInactivityCounter(
  2472. Binding,
  2473. (IPX_HEADER UNALIGNED *)(Header + IpxDevice->IncludedHeaderOffset),
  2474. IncludedHeaderLength,
  2475. Packet,
  2476. PacketLength);
  2477. #endif BACK_FILL
  2478. //
  2479. // In order for loopback to work properly, we need to put the local MAC address for locally destined
  2480. // pkts so NdisWAN can loop them back.
  2481. //
  2482. if (IPX_NODE_EQUAL(LocalTarget->MacAddress, Binding->LocalAddress.NodeAddress)) {
  2483. RtlCopyMemory (Header, Binding->LocalMacAddress.Address, 6);
  2484. } else {
  2485. RtlCopyMemory (Header, Binding->RemoteMacAddress.Address, 6);
  2486. }
  2487. // RtlCopyMemory (Header, Binding->RemoteMacAddress.Address, 6);
  2488. RtlCopyMemory (Header+6, Binding->LocalMacAddress.Address, 6);
  2489. *(UNALIGNED USHORT *)(&Header[12]) = Adapter->BindSapNetworkOrder;
  2490. // NdisAdjustBufferLength (Reserved->HeaderBuffer, IncludedHeaderLength + 14);
  2491. #if BACK_FILL
  2492. BACK_FILL_ADJUST_BUFFER_LENGTH(Reserved, 14);
  2493. #else
  2494. NdisAdjustBufferLength (Reserved->HeaderBuffer, 14);
  2495. #endif
  2496. NdisRecalculatePacketCounts (Packet);
  2497. NdisSend(
  2498. &Status,
  2499. Adapter->NdisBindingHandle,
  2500. Packet);
  2501. IpxDereferenceAdapter1(Adapter,ADAP_REF_SEND);
  2502. IpxDereferenceBinding1(Binding, BREF_DEVICE_ACCESS);
  2503. return Status;
  2504. } else {
  2505. //
  2506. // Bug #17273 return proper error message
  2507. //
  2508. // return STATUS_DEVICE_DOES_NOT_EXIST;
  2509. IpxDereferenceBinding1(Binding, BREF_DEVICE_ACCESS);
  2510. return STATUS_NETWORK_UNREACHABLE;
  2511. }
  2512. } /* IpxSendFrameWanEthernetII */
  2513. VOID
  2514. MacUpdateSourceRouting(
  2515. IN ULONG Database,
  2516. IN PADAPTER Adapter,
  2517. IN PUCHAR MacHeader,
  2518. IN ULONG MacHeaderLength
  2519. )
  2520. /*++
  2521. Routine Description:
  2522. This routine is called when a valid IPX frame is received from
  2523. a remote. It gives the source routing database a change to
  2524. update itself to include information about this remote.
  2525. Arguments:
  2526. Database - The "database" to use (IPX, SPX, NB, RIP).
  2527. Adapter - The adapter the frame was received on.
  2528. MacHeader - The MAC header of the received frame.
  2529. MacHeaderLength - The length of the MAC header.
  2530. Return Value:
  2531. None.
  2532. --*/
  2533. {
  2534. PSOURCE_ROUTE Current;
  2535. ULONG Hash;
  2536. LONG Result;
  2537. IPX_DEFINE_LOCK_HANDLE (LockHandle)
  2538. CTEAssert (((LONG)Database >= 0) && (Database <= 3));
  2539. //
  2540. // If this adapter is configured for no source routing, don't
  2541. // need to do anything.
  2542. //
  2543. if (!Adapter->SourceRouting) {
  2544. return;
  2545. }
  2546. //
  2547. // See if this source routing is relevant. We don't
  2548. // care about two-byte source routing since that
  2549. // indicates it did not cross a router. If there
  2550. // is nothing in the database, then don't add
  2551. // this if it is minimal (if it is not, we need
  2552. // to add it so we will find it on sending).
  2553. //
  2554. if ((Adapter->SourceRoutingEmpty[Database]) &&
  2555. (MacHeaderLength <= 16)) {
  2556. return;
  2557. }
  2558. IPX_GET_LOCK (&Adapter->Lock, &LockHandle);
  2559. //
  2560. // Try to find this address in the database.
  2561. //
  2562. Hash = MacSourceRoutingHash (MacHeader+8);
  2563. Current = Adapter->SourceRoutingHeads[Database][Hash];
  2564. while (Current != (PSOURCE_ROUTE)NULL) {
  2565. IPX_NODE_COMPARE (MacHeader+8, Current->MacAddress, &Result);
  2566. if (Result == 0) {
  2567. //
  2568. // We found routing for this node. If the data is the
  2569. // same as what we have, update the time since used to
  2570. // prevent aging.
  2571. //
  2572. if ((Current->SourceRoutingLength == MacHeaderLength-14) &&
  2573. (RtlEqualMemory (Current->SourceRouting, MacHeader+14, MacHeaderLength-14))) {
  2574. Current->TimeSinceUsed = 0;
  2575. }
  2576. IPX_FREE_LOCK (&Adapter->Lock, LockHandle);
  2577. return;
  2578. } else {
  2579. Current = Current->Next;
  2580. }
  2581. }
  2582. //
  2583. // Not found, insert a new node at the front of the list.
  2584. //
  2585. Current = (PSOURCE_ROUTE)IpxAllocateMemory (SOURCE_ROUTE_SIZE(MacHeaderLength-14), MEMORY_SOURCE_ROUTE, "SourceRouting");
  2586. if (Current == (PSOURCE_ROUTE)NULL) {
  2587. IPX_FREE_LOCK (&Adapter->Lock, LockHandle);
  2588. return;
  2589. }
  2590. Current->Next = Adapter->SourceRoutingHeads[Database][Hash];
  2591. Adapter->SourceRoutingHeads[Database][Hash] = Current;
  2592. Adapter->SourceRoutingEmpty[Database] = FALSE;
  2593. RtlCopyMemory (Current->MacAddress, MacHeader+8, 6);
  2594. Current->MacAddress[0] &= 0x7f;
  2595. Current->SourceRoutingLength = (UCHAR)(MacHeaderLength - 14);
  2596. RtlCopyMemory (Current->SourceRouting, MacHeader+14, MacHeaderLength - 14);
  2597. Current->TimeSinceUsed = 0;
  2598. IPX_DEBUG (SOURCE_ROUTE, ("Adding source route %lx for %2.2x-%2.2x-%2.2x-%2.2x-%2.2x-%2.2x\n",
  2599. Current, Current->MacAddress[0], Current->MacAddress[1],
  2600. Current->MacAddress[2], Current->MacAddress[3],
  2601. Current->MacAddress[4], Current->MacAddress[5]));
  2602. IPX_FREE_LOCK (&Adapter->Lock, LockHandle);
  2603. } /* MacUpdateSourceRouting */
  2604. VOID
  2605. MacLookupSourceRouting(
  2606. IN ULONG Database,
  2607. IN PBINDING Binding,
  2608. IN UCHAR MacAddress[6],
  2609. IN OUT UCHAR SourceRouting[18],
  2610. OUT PULONG SourceRoutingLength
  2611. )
  2612. /*++
  2613. Routine Description:
  2614. This routine looks up a target address in the adapter's
  2615. source routing database to see if source routing information
  2616. needs to be added to the frame.
  2617. Arguments:
  2618. Database - The "database" to use (IPX, SPX, NB, RIP).
  2619. Binding - The binding the frame is being sent on.
  2620. MacAddress - The destination address.
  2621. SourceRouting - Buffer to hold the returned source routing info.
  2622. SourceRoutingLength - The returned source routing length.
  2623. Return Value:
  2624. None.
  2625. --*/
  2626. {
  2627. PSOURCE_ROUTE Current;
  2628. PADAPTER Adapter = Binding->Adapter;
  2629. ULONG Hash;
  2630. LONG Result;
  2631. IPX_DEFINE_LOCK_HANDLE (LockHandle)
  2632. //
  2633. // If this adapter is configured for no source routing, don't
  2634. // insert any.
  2635. //
  2636. if (!Adapter->SourceRouting) {
  2637. *SourceRoutingLength = 0;
  2638. return;
  2639. }
  2640. //
  2641. // See if source routing has not been important so far.
  2642. //
  2643. // This is wrong because we may be sending a directed
  2644. // packet to somebody on the other side of a router, without
  2645. // ever having received a routed packet. We fix this for the
  2646. // moment by only setting SourceRoutingEmpty for netbios
  2647. // which uses broadcasts for discovery.
  2648. //
  2649. if (Adapter->SourceRoutingEmpty[Database]) {
  2650. *SourceRoutingLength = 0;
  2651. return;
  2652. }
  2653. Hash = MacSourceRoutingHash (MacAddress);
  2654. IPX_GET_LOCK (&Adapter->Lock, &LockHandle);
  2655. Current = Adapter->SourceRoutingHeads[Database][Hash];
  2656. while (Current != (PSOURCE_ROUTE)NULL) {
  2657. IPX_NODE_COMPARE (MacAddress, Current->MacAddress, &Result);
  2658. if (Result == 0) {
  2659. //
  2660. // We found routing for this node.
  2661. //
  2662. if (Current->SourceRoutingLength <= 2) {
  2663. *SourceRoutingLength = 0;
  2664. } else {
  2665. RtlCopyMemory (SourceRouting, Current->SourceRouting, Current->SourceRoutingLength);
  2666. SourceRouting[0] = (SourceRouting[0] & TR_LENGTH_MASK);
  2667. SourceRouting[1] = (SourceRouting[1] ^ TR_DIRECTION_MASK);
  2668. *SourceRoutingLength = Current->SourceRoutingLength;
  2669. }
  2670. IPX_FREE_LOCK (&Adapter->Lock, LockHandle);
  2671. return;
  2672. } else {
  2673. Current = Current->Next;
  2674. }
  2675. }
  2676. IPX_FREE_LOCK (&Adapter->Lock, LockHandle);
  2677. //
  2678. // We did not find this node, use the default.
  2679. //
  2680. if (Binding->AllRouteDirected) {
  2681. RtlCopyMemory (SourceRouting, AllRouteSourceRouting, 2);
  2682. } else {
  2683. RtlCopyMemory (SourceRouting, SingleRouteSourceRouting, 2);
  2684. }
  2685. *SourceRoutingLength = 2;
  2686. } /* MacLookupSourceRouting */
  2687. VOID
  2688. MacSourceRoutingTimeout(
  2689. CTEEvent * Event,
  2690. PVOID Context
  2691. )
  2692. /*++
  2693. Routine Description:
  2694. This routine is called when the source routing timer expires.
  2695. It is called every minute.
  2696. Arguments:
  2697. Event - The event used to queue the timer.
  2698. Context - The context, which is the device pointer.
  2699. Return Value:
  2700. None.
  2701. --*/
  2702. {
  2703. PDEVICE Device = (PDEVICE)Context;
  2704. PADAPTER Adapter;
  2705. PBINDING Binding;
  2706. PSOURCE_ROUTE Current, OldCurrent, Previous;
  2707. UINT i, j, k;
  2708. IPX_DEFINE_LOCK_HANDLE (LockHandle)
  2709. IPX_DEFINE_LOCK_HANDLE(LockHandle1)
  2710. //
  2711. // Get a lock on the access path.
  2712. //
  2713. IPX_GET_LOCK1(&Device->BindAccessLock, &LockHandle1);
  2714. ++Device->SourceRoutingTime;
  2715. {
  2716. ULONG Index = MIN (Device->MaxBindings, Device->ValidBindings);
  2717. for (i = FIRST_REAL_BINDING; i <= Index; i++) {
  2718. if (Binding = NIC_ID_TO_BINDING(Device, i)) {
  2719. Adapter = Binding->Adapter;
  2720. if (Adapter->LastSourceRoutingTime != Device->SourceRoutingTime) {
  2721. //
  2722. // We need to scan this adapter's source routing
  2723. // tree for stale routes. To simplify the scan we
  2724. // only delete entries that have at least one
  2725. // child that is NULL.
  2726. //
  2727. Adapter->LastSourceRoutingTime = Device->SourceRoutingTime;
  2728. for (j = 0; j < IDENTIFIER_TOTAL; j++) {
  2729. for (k = 0; k < SOURCE_ROUTE_HASH_SIZE; k++) {
  2730. if (Adapter->SourceRoutingHeads[j][k] == (PSOURCE_ROUTE)NULL) {
  2731. continue;
  2732. }
  2733. IPX_GET_LOCK (&Adapter->Lock, &LockHandle);
  2734. Current = Adapter->SourceRoutingHeads[j][k];
  2735. Previous = (PSOURCE_ROUTE)NULL;
  2736. while (Current != (PSOURCE_ROUTE)NULL) {
  2737. ++Current->TimeSinceUsed;
  2738. if (Current->TimeSinceUsed >= Device->SourceRouteUsageTime) {
  2739. //
  2740. // A stale entry needs to be aged.
  2741. //
  2742. if (Previous) {
  2743. Previous->Next = Current->Next;
  2744. } else {
  2745. Adapter->SourceRoutingHeads[j][k] = Current->Next;
  2746. }
  2747. OldCurrent = Current;
  2748. Current = Current->Next;
  2749. IPX_DEBUG (SOURCE_ROUTE, ("Aging out source-route entry %lx\n", OldCurrent));
  2750. IpxFreeMemory (OldCurrent, SOURCE_ROUTE_SIZE (OldCurrent->SourceRoutingLength), MEMORY_SOURCE_ROUTE, "SourceRouting");
  2751. } else {
  2752. Previous = Current;
  2753. Current = Current->Next;
  2754. }
  2755. }
  2756. IPX_FREE_LOCK (&Adapter->Lock, LockHandle);
  2757. } // for loop through the database's hash list
  2758. } // for loop through the adapter's four databases
  2759. } // if adapter's database needs to be checked
  2760. } // if binding exists
  2761. } // for loop through every binding
  2762. }
  2763. IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
  2764. //
  2765. // Now restart the timer unless we should not (which means
  2766. // we are being unloaded).
  2767. //
  2768. if (Device->SourceRoutingUsed) {
  2769. CTEStartTimer(
  2770. &Device->SourceRoutingTimer,
  2771. 60000, // one minute timeout
  2772. MacSourceRoutingTimeout,
  2773. (PVOID)Device);
  2774. } else {
  2775. IpxDereferenceDevice (Device, DREF_SR_TIMER);
  2776. }
  2777. } /* MacSourceRoutingTimeout */
  2778. VOID
  2779. MacSourceRoutingRemove(
  2780. IN PBINDING Binding,
  2781. IN UCHAR MacAddress[6]
  2782. )
  2783. /*++
  2784. Routine Description:
  2785. This routine is called by the IPX action handler when an
  2786. IPXROUTE use has specified that source routing for a given
  2787. MAC address should be removed.
  2788. Arguments:
  2789. Binding - The binding to modify.
  2790. MacAddress - The MAC address to remove.
  2791. Return Value:
  2792. None.
  2793. --*/
  2794. {
  2795. PSOURCE_ROUTE Current, Previous;
  2796. PADAPTER Adapter = Binding->Adapter;
  2797. ULONG Hash;
  2798. ULONG Database;
  2799. LONG Result;
  2800. IPX_DEFINE_LOCK_HANDLE (LockHandle)
  2801. //
  2802. // Scan through to find the matching entry in each database.
  2803. //
  2804. Hash = MacSourceRoutingHash (MacAddress);
  2805. IPX_GET_LOCK (&Adapter->Lock, &LockHandle);
  2806. for (Database = 0; Database < IDENTIFIER_TOTAL; Database++) {
  2807. Current = Adapter->SourceRoutingHeads[Database][Hash];
  2808. Previous = NULL;
  2809. while (Current != (PSOURCE_ROUTE)NULL) {
  2810. IPX_NODE_COMPARE (MacAddress, Current->MacAddress, &Result);
  2811. if (Result == 0) {
  2812. if (Previous) {
  2813. Previous->Next = Current->Next;
  2814. } else {
  2815. Adapter->SourceRoutingHeads[Database][Hash] = Current->Next;
  2816. }
  2817. IPX_DEBUG (SOURCE_ROUTE, ("IPXROUTE freeing source-route entry %lx\n", Current));
  2818. IpxFreeMemory (Current, SOURCE_ROUTE_SIZE (Current->SourceRoutingLength), MEMORY_SOURCE_ROUTE, "SourceRouting");
  2819. break;
  2820. } else {
  2821. Previous = Current;
  2822. Current = Current->Next;
  2823. }
  2824. }
  2825. }
  2826. IPX_FREE_LOCK (&Adapter->Lock, LockHandle);
  2827. } /* MacSourceRoutingRemove */
  2828. VOID
  2829. MacSourceRoutingClear(
  2830. IN PBINDING Binding
  2831. )
  2832. /*++
  2833. Routine Description:
  2834. This routine is called by the IPX action handler when an
  2835. IPXROUTE use has specified that source routing for a given
  2836. binding should be cleared entirely.
  2837. Arguments:
  2838. Binding - The binding to be cleared.
  2839. MacAddress - The MAC address to remove.
  2840. Return Value:
  2841. None.
  2842. --*/
  2843. {
  2844. PSOURCE_ROUTE Current;
  2845. PADAPTER Adapter = Binding->Adapter;
  2846. ULONG Database, Hash;
  2847. IPX_DEFINE_LOCK_HANDLE (LockHandle)
  2848. //
  2849. // Scan through and remove every entry in the database.
  2850. //
  2851. IPX_GET_LOCK (&Adapter->Lock, &LockHandle);
  2852. for (Database = 0; Database < IDENTIFIER_TOTAL; Database++) {
  2853. for (Hash = 0; Hash < SOURCE_ROUTE_HASH_SIZE; Hash++) {
  2854. while (Adapter->SourceRoutingHeads[Database][Hash]) {
  2855. Current = Adapter->SourceRoutingHeads[Database][Hash];
  2856. Adapter->SourceRoutingHeads[Database][Hash] = Current->Next;
  2857. IpxFreeMemory (Current, SOURCE_ROUTE_SIZE (Current->SourceRoutingLength), MEMORY_SOURCE_ROUTE, "SourceRouting");
  2858. }
  2859. }
  2860. }
  2861. IPX_FREE_LOCK (&Adapter->Lock, LockHandle);
  2862. } /* MacSourceRoutingClear */