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.

1728 lines
40 KiB

  1. /*++
  2. Copyright (c) 1989-1993 Microsoft Corporation
  3. Module Name:
  4. spxpkt.c
  5. Abstract:
  6. This module contains code that builds various spx packets.
  7. Author:
  8. Nikhil Kamkolkar (nikhilk) 11-November-1993
  9. Environment:
  10. Kernel mode
  11. Revision History:
  12. --*/
  13. #include "precomp.h"
  14. #pragma hdrstop
  15. // Define module number for event logging entries
  16. #define FILENUM SPXPKT
  17. VOID
  18. SpxPktBuildCr(
  19. IN PSPX_CONN_FILE pSpxConnFile,
  20. IN PSPX_ADDR pSpxAddr,
  21. IN OUT PNDIS_PACKET * ppPkt,
  22. IN USHORT State,
  23. IN BOOLEAN fSpx2
  24. )
  25. /*++
  26. Routine Description:
  27. NOTE: If *ppPkt is NULL, we allocate a packet. If not, we just
  28. recreate the data and don't update the packet's state.
  29. Arguments:
  30. Return Value:
  31. --*/
  32. {
  33. PNDIS_PACKET pCrPkt;
  34. PSPX_SEND_RESD pSendResd;
  35. NDIS_STATUS ndisStatus;
  36. PIPXSPX_HDR pIpxSpxHdr;
  37. PNDIS_BUFFER pNdisMacHdr, pNdisIpxHdr;
  38. PNDIS_BUFFER NdisBuf, NdisBuf2;
  39. ULONG BufLen = 0;
  40. if (*ppPkt == NULL) {
  41. SpxAllocSendPacket(SpxDevice, &pCrPkt, &ndisStatus);
  42. if (ndisStatus != NDIS_STATUS_SUCCESS)
  43. {
  44. DBGPRINT(CONNECT, ERR,
  45. ("SpxConnHandleConnReq: Could not allocate ndis packet\n"));
  46. return;
  47. }
  48. } else {
  49. pCrPkt = *ppPkt;
  50. }
  51. //
  52. // Get the MDL that points to the IPX/SPX header. (the second one)
  53. //
  54. NdisQueryPacket(pCrPkt, NULL, NULL, &NdisBuf, NULL);
  55. NdisGetNextBuffer(NdisBuf, &NdisBuf2);
  56. NdisQueryBuffer(NdisBuf2, (PUCHAR) &pIpxSpxHdr, &BufLen);
  57. #if OWN_PKT_POOLS
  58. pIpxSpxHdr = (PIPXSPX_HDR)((PBYTE)pCrPkt +
  59. NDIS_PACKET_SIZE +
  60. sizeof(SPX_SEND_RESD) +
  61. IpxInclHdrOffset);
  62. #endif
  63. NdisQueryPacket(pCrPkt, NULL, NULL, &pNdisMacHdr, NULL);
  64. pNdisIpxHdr = NDIS_BUFFER_LINKAGE(pNdisMacHdr);
  65. if (!fSpx2)
  66. {
  67. NdisAdjustBufferLength(pNdisIpxHdr, MIN_IPXSPX_HDRSIZE);
  68. }
  69. SpxBuildIpxHdr(
  70. pIpxSpxHdr,
  71. MIN_IPXSPX_HDRSIZE,
  72. pSpxConnFile->scf_RemAddr,
  73. pSpxAddr->sa_Socket);
  74. // Build SPX Header.
  75. pIpxSpxHdr->hdr_ConnCtrl = (SPX_CC_SYS | SPX_CC_ACK |
  76. (fSpx2 ? (SPX_CC_SPX2 | SPX_CC_NEG) : 0));
  77. pIpxSpxHdr->hdr_DataType = 0;
  78. PUTSHORT2SHORT(
  79. &pIpxSpxHdr->hdr_SrcConnId,
  80. pSpxConnFile->scf_LocalConnId);
  81. pIpxSpxHdr->hdr_DestConnId = 0xFFFF;
  82. pIpxSpxHdr->hdr_SeqNum = 0;
  83. pIpxSpxHdr->hdr_AckNum = 0;
  84. PUTSHORT2SHORT(
  85. &pIpxSpxHdr->hdr_AllocNum,
  86. pSpxConnFile->scf_SentAllocNum);
  87. // Initialize
  88. if (*ppPkt == NULL) {
  89. pSendResd = (PSPX_SEND_RESD)(pCrPkt->ProtocolReserved);
  90. pSendResd->sr_Id = IDENTIFIER_SPX;
  91. pSendResd->sr_Type = SPX_TYPE_CR;
  92. pSendResd->sr_Reserved1 = NULL;
  93. pSendResd->sr_Reserved2 = NULL;
  94. pSendResd->sr_State = State;
  95. pSendResd->sr_ConnFile = pSpxConnFile;
  96. pSendResd->sr_Request = NULL;
  97. pSendResd->sr_Next = NULL;
  98. pSendResd->sr_Len = pSendResd->sr_HdrLen = MIN_IPXSPX_HDRSIZE;
  99. *ppPkt = pCrPkt;
  100. }
  101. return;
  102. }
  103. VOID
  104. SpxPktBuildCrAck(
  105. IN PSPX_CONN_FILE pSpxConnFile,
  106. IN PSPX_ADDR pSpxAddr,
  107. OUT PNDIS_PACKET * ppPkt,
  108. IN USHORT State,
  109. IN BOOLEAN fNeg,
  110. IN BOOLEAN fSpx2
  111. )
  112. /*++
  113. Routine Description:
  114. Arguments:
  115. Return Value:
  116. --*/
  117. {
  118. PNDIS_PACKET pCrAckPkt;
  119. PSPX_SEND_RESD pSendResd;
  120. PIPXSPX_HDR pIpxSpxHdr;
  121. NDIS_STATUS ndisStatus;
  122. USHORT hdrLen;
  123. PNDIS_BUFFER pNdisMacHdr, pNdisIpxHdr;
  124. PNDIS_BUFFER NdisBuf, NdisBuf2;
  125. ULONG BufLen = 0;
  126. *ppPkt = NULL;
  127. SpxAllocSendPacket(SpxDevice, &pCrAckPkt, &ndisStatus);
  128. if (ndisStatus != NDIS_STATUS_SUCCESS)
  129. {
  130. DBGPRINT(CONNECT, ERR,
  131. ("SpxConnHandleConnReq: Could not allocate ndis packet\n"));
  132. return;
  133. }
  134. //
  135. // Get the MDL that points to the IPX/SPX header. (the second one)
  136. //
  137. NdisQueryPacket(pCrAckPkt, NULL, NULL, &NdisBuf, NULL);
  138. NdisGetNextBuffer(NdisBuf, &NdisBuf2);
  139. NdisQueryBuffer(NdisBuf2, (PUCHAR) &pIpxSpxHdr, &BufLen);
  140. #if OWN_PKT_POOLS
  141. pIpxSpxHdr = (PIPXSPX_HDR)((PBYTE)pCrAckPkt +
  142. NDIS_PACKET_SIZE +
  143. sizeof(SPX_SEND_RESD) +
  144. IpxInclHdrOffset);
  145. #endif
  146. hdrLen = (SPX2_CONN(pSpxConnFile) ? MIN_IPXSPX2_HDRSIZE : MIN_IPXSPX_HDRSIZE);
  147. NdisQueryPacket(pCrAckPkt, NULL, NULL, &pNdisMacHdr, NULL);
  148. pNdisIpxHdr = NDIS_BUFFER_LINKAGE(pNdisMacHdr);
  149. if (!SPX2_CONN(pSpxConnFile))
  150. {
  151. NdisAdjustBufferLength(pNdisIpxHdr, MIN_IPXSPX_HDRSIZE);
  152. }
  153. SpxBuildIpxHdr(
  154. pIpxSpxHdr,
  155. hdrLen,
  156. pSpxConnFile->scf_RemAddr,
  157. pSpxAddr->sa_Socket);
  158. pIpxSpxHdr->hdr_ConnCtrl =
  159. (SPX_CC_SYS |
  160. (fSpx2 ? SPX_CC_SPX2 : 0) |
  161. (fNeg ? SPX_CC_NEG : 0));
  162. pIpxSpxHdr->hdr_DataType = 0;
  163. PUTSHORT2SHORT(
  164. &pIpxSpxHdr->hdr_SrcConnId,
  165. pSpxConnFile->scf_LocalConnId);
  166. pIpxSpxHdr->hdr_DestConnId = pSpxConnFile->scf_RemConnId;
  167. pIpxSpxHdr->hdr_SeqNum = 0;
  168. pIpxSpxHdr->hdr_AckNum = 0;
  169. PUTSHORT2SHORT(
  170. &pIpxSpxHdr->hdr_AllocNum,
  171. pSpxConnFile->scf_SentAllocNum);
  172. if (SPX2_CONN(pSpxConnFile))
  173. {
  174. DBGPRINT(CONNECT, DBG,
  175. ("SpxConnBuildCrAck: Spx2 packet size %d.%lx\n",
  176. pSpxConnFile->scf_MaxPktSize));
  177. PUTSHORT2SHORT(
  178. &pIpxSpxHdr->hdr_NegSize,
  179. pSpxConnFile->scf_MaxPktSize);
  180. }
  181. pSendResd = (PSPX_SEND_RESD)(pCrAckPkt->ProtocolReserved);
  182. pSendResd->sr_Id = IDENTIFIER_SPX;
  183. pSendResd->sr_Type = SPX_TYPE_CRACK;
  184. pSendResd->sr_Reserved1 = NULL;
  185. pSendResd->sr_Reserved2 = NULL;
  186. pSendResd->sr_State = State;
  187. pSendResd->sr_ConnFile = pSpxConnFile;
  188. pSendResd->sr_Request = NULL;
  189. pSendResd->sr_Next = NULL;
  190. pSendResd->sr_Len = pSendResd->sr_HdrLen = hdrLen;
  191. *ppPkt = pCrAckPkt;
  192. return;
  193. }
  194. VOID
  195. SpxPktBuildSn(
  196. IN PSPX_CONN_FILE pSpxConnFile,
  197. OUT PNDIS_PACKET * ppPkt,
  198. IN USHORT State
  199. )
  200. /*++
  201. Routine Description:
  202. Arguments:
  203. Return Value:
  204. --*/
  205. {
  206. PNDIS_PACKET pPkt;
  207. PSPX_SEND_RESD pSendResd;
  208. PNDIS_BUFFER pBuf;
  209. NDIS_STATUS ndisStatus;
  210. PIPXSPX_HDR pIpxSpxHdr;
  211. PBYTE pData;
  212. PNDIS_BUFFER NdisBuf, NdisBuf2;
  213. ULONG BufLen = 0;
  214. do
  215. {
  216. *ppPkt = NULL;
  217. // Allocate a ndis packet for the cr.
  218. SpxAllocSendPacket(SpxDevice, &pPkt, &ndisStatus);
  219. if (ndisStatus != NDIS_STATUS_SUCCESS)
  220. {
  221. break;
  222. }
  223. CTEAssert(pSpxConnFile->scf_MaxPktSize != 0);
  224. DBGPRINT(SEND, DBG,
  225. ("SpxPktBuildSn: Data size %lx\n", pSpxConnFile->scf_MaxPktSize));
  226. if ((pData =
  227. SpxAllocateMemory(
  228. pSpxConnFile->scf_MaxPktSize - MIN_IPXSPX2_HDRSIZE)) == NULL)
  229. {
  230. SpxPktSendRelease(pPkt);
  231. break;
  232. }
  233. // Build ndis buffer desc
  234. NdisAllocateBuffer(
  235. &ndisStatus,
  236. &pBuf,
  237. SpxDevice->dev_NdisBufferPoolHandle,
  238. pData,
  239. pSpxConnFile->scf_MaxPktSize - MIN_IPXSPX2_HDRSIZE);
  240. if (ndisStatus != NDIS_STATUS_SUCCESS)
  241. {
  242. SpxPktSendRelease(pPkt);
  243. SpxFreeMemory(pData);
  244. break;
  245. }
  246. // Chain at back.
  247. NdisChainBufferAtBack(
  248. pPkt,
  249. pBuf);
  250. //
  251. // Get the MDL that points to the IPX/SPX header. (the second one)
  252. //
  253. NdisQueryPacket(pPkt, NULL, NULL, &NdisBuf, NULL);
  254. NdisGetNextBuffer(NdisBuf, &NdisBuf2);
  255. NdisQueryBuffer(NdisBuf2, (PUCHAR) &pIpxSpxHdr, &BufLen);
  256. #if OWN_PKT_POOLS
  257. pIpxSpxHdr = (PIPXSPX_HDR)((PBYTE)pPkt +
  258. NDIS_PACKET_SIZE +
  259. sizeof(SPX_SEND_RESD) +
  260. IpxInclHdrOffset);
  261. #endif
  262. SpxBuildIpxHdr(
  263. pIpxSpxHdr,
  264. pSpxConnFile->scf_MaxPktSize,
  265. pSpxConnFile->scf_RemAddr,
  266. pSpxConnFile->scf_AddrFile->saf_Addr->sa_Socket);
  267. // Build SPX Header.
  268. pIpxSpxHdr->hdr_ConnCtrl = ( SPX_CC_SYS | SPX_CC_ACK |
  269. SPX_CC_NEG | SPX_CC_SPX2);
  270. pIpxSpxHdr->hdr_DataType = 0;
  271. PUTSHORT2SHORT(
  272. &pIpxSpxHdr->hdr_SrcConnId,
  273. pSpxConnFile->scf_LocalConnId);
  274. pIpxSpxHdr->hdr_DestConnId = pSpxConnFile->scf_RemConnId;
  275. pIpxSpxHdr->hdr_SeqNum = 0;
  276. pIpxSpxHdr->hdr_AckNum = 0;
  277. PUTSHORT2SHORT(
  278. &pIpxSpxHdr->hdr_AllocNum,
  279. pSpxConnFile->scf_SentAllocNum);
  280. PUTSHORT2SHORT(
  281. &pIpxSpxHdr->hdr_NegSize,
  282. pSpxConnFile->scf_MaxPktSize);
  283. // Init the data part to indicate no neg values
  284. *(UNALIGNED ULONG *)pData = 0;
  285. pSendResd = (PSPX_SEND_RESD)(pPkt->ProtocolReserved);
  286. pSendResd->sr_Id = IDENTIFIER_SPX;
  287. pSendResd->sr_Type = SPX_TYPE_SN;
  288. pSendResd->sr_Reserved1 = NULL;
  289. pSendResd->sr_Reserved2 = NULL;
  290. pSendResd->sr_State = (State | SPX_SENDPKT_FREEDATA);
  291. pSendResd->sr_ConnFile = pSpxConnFile;
  292. pSendResd->sr_Request = NULL;
  293. pSendResd->sr_Next = NULL;
  294. pSendResd->sr_HdrLen = MIN_IPXSPX2_HDRSIZE;
  295. pSendResd->sr_Len = pSpxConnFile->scf_MaxPktSize;
  296. *ppPkt = pPkt;
  297. } while (FALSE);
  298. return;
  299. }
  300. VOID
  301. SpxPktBuildSnAck(
  302. IN PSPX_CONN_FILE pSpxConnFile,
  303. OUT PNDIS_PACKET * ppPkt,
  304. IN USHORT State
  305. )
  306. /*++
  307. Routine Description:
  308. Arguments:
  309. Return Value:
  310. --*/
  311. {
  312. PNDIS_PACKET pPkt;
  313. NDIS_STATUS ndisStatus;
  314. PIPXSPX_HDR pIpxSpxHdr;
  315. PSPX_SEND_RESD pSendResd;
  316. PNDIS_BUFFER NdisBuf, NdisBuf2;
  317. ULONG BufLen = 0;
  318. do
  319. {
  320. *ppPkt = NULL;
  321. // Allocate a ndis packet for the cr.
  322. SpxAllocSendPacket(SpxDevice, &pPkt, &ndisStatus);
  323. if (ndisStatus != NDIS_STATUS_SUCCESS)
  324. {
  325. break;
  326. }
  327. #if OWN_PKT_POOLS
  328. pIpxSpxHdr = (PIPXSPX_HDR)((PBYTE)pPkt +
  329. NDIS_PACKET_SIZE +
  330. sizeof(SPX_SEND_RESD) +
  331. IpxInclHdrOffset);
  332. #endif
  333. //
  334. // Get the MDL that points to the IPX/SPX header. (the second one)
  335. //
  336. NdisQueryPacket(pPkt, NULL, NULL, &NdisBuf, NULL);
  337. NdisGetNextBuffer(NdisBuf, &NdisBuf2);
  338. NdisQueryBuffer(NdisBuf2, (PUCHAR) &pIpxSpxHdr, &BufLen);
  339. SpxBuildIpxHdr(
  340. pIpxSpxHdr,
  341. MIN_IPXSPX2_HDRSIZE,
  342. pSpxConnFile->scf_RemAddr,
  343. pSpxConnFile->scf_AddrFile->saf_Addr->sa_Socket);
  344. // Build SPX Header.
  345. pIpxSpxHdr->hdr_ConnCtrl = (SPX_CC_SYS | SPX_CC_NEG | SPX_CC_SPX2);
  346. pIpxSpxHdr->hdr_DataType = 0;
  347. PUTSHORT2SHORT(
  348. &pIpxSpxHdr->hdr_SrcConnId,
  349. pSpxConnFile->scf_LocalConnId);
  350. pIpxSpxHdr->hdr_DestConnId = pSpxConnFile->scf_RemConnId;
  351. pIpxSpxHdr->hdr_SeqNum = 0;
  352. pIpxSpxHdr->hdr_AckNum = 0;
  353. PUTSHORT2SHORT(
  354. &pIpxSpxHdr->hdr_AllocNum,
  355. pSpxConnFile->scf_SentAllocNum);
  356. PUTSHORT2SHORT(
  357. &pIpxSpxHdr->hdr_NegSize,
  358. pSpxConnFile->scf_MaxPktSize);
  359. pSendResd = (PSPX_SEND_RESD)(pPkt->ProtocolReserved);
  360. pSendResd->sr_Id = IDENTIFIER_SPX;
  361. pSendResd->sr_Type = SPX_TYPE_SNACK;
  362. pSendResd->sr_Reserved1 = NULL;
  363. pSendResd->sr_Reserved2 = NULL;
  364. pSendResd->sr_State = State;
  365. pSendResd->sr_ConnFile = pSpxConnFile;
  366. pSendResd->sr_Request = NULL;
  367. pSendResd->sr_Next = NULL;
  368. pSendResd->sr_Len = pSendResd->sr_HdrLen = MIN_IPXSPX2_HDRSIZE;
  369. *ppPkt = pPkt;
  370. } while (FALSE);
  371. return;
  372. }
  373. VOID
  374. SpxPktBuildSs(
  375. IN PSPX_CONN_FILE pSpxConnFile,
  376. OUT PNDIS_PACKET * ppPkt,
  377. IN USHORT State
  378. )
  379. /*++
  380. Routine Description:
  381. Arguments:
  382. Return Value:
  383. --*/
  384. {
  385. PNDIS_PACKET pPkt;
  386. PSPX_SEND_RESD pSendResd;
  387. PNDIS_BUFFER pBuf;
  388. NDIS_STATUS ndisStatus;
  389. PIPXSPX_HDR pIpxSpxHdr;
  390. PBYTE pData;
  391. PNDIS_BUFFER NdisBuf, NdisBuf2;
  392. ULONG BufLen = 0;
  393. do
  394. {
  395. *ppPkt = NULL;
  396. // Allocate a ndis packet for the cr.
  397. SpxAllocSendPacket(SpxDevice, &pPkt, &ndisStatus);
  398. if (ndisStatus != NDIS_STATUS_SUCCESS)
  399. {
  400. break;
  401. }
  402. CTEAssert(pSpxConnFile->scf_MaxPktSize != 0);
  403. DBGPRINT(SEND, DBG,
  404. ("SpxPktBuildSs: Data size %lx\n", pSpxConnFile->scf_MaxPktSize));
  405. if ((pData =
  406. SpxAllocateMemory(
  407. pSpxConnFile->scf_MaxPktSize - MIN_IPXSPX2_HDRSIZE)) == NULL)
  408. {
  409. SpxPktSendRelease(pPkt);
  410. break;
  411. }
  412. // Build ndis buffer desc
  413. NdisAllocateBuffer(
  414. &ndisStatus,
  415. &pBuf,
  416. SpxDevice->dev_NdisBufferPoolHandle,
  417. pData,
  418. pSpxConnFile->scf_MaxPktSize - MIN_IPXSPX2_HDRSIZE);
  419. if (ndisStatus != NDIS_STATUS_SUCCESS)
  420. {
  421. SpxPktSendRelease(pPkt);
  422. SpxFreeMemory(pData);
  423. break;
  424. }
  425. // Chain at back.
  426. NdisChainBufferAtBack(
  427. pPkt,
  428. pBuf);
  429. #if OWN_PKT_POOLS
  430. pIpxSpxHdr = (PIPXSPX_HDR)((PBYTE)pPkt +
  431. NDIS_PACKET_SIZE +
  432. sizeof(SPX_SEND_RESD) +
  433. IpxInclHdrOffset);
  434. #endif
  435. //
  436. // Get the MDL that points to the IPX/SPX header. (the second one)
  437. //
  438. NdisQueryPacket(pPkt, NULL, NULL, &NdisBuf, NULL);
  439. NdisGetNextBuffer(NdisBuf, &NdisBuf2);
  440. NdisQueryBuffer(NdisBuf2, (PUCHAR) &pIpxSpxHdr, &BufLen);
  441. SpxBuildIpxHdr(
  442. pIpxSpxHdr,
  443. pSpxConnFile->scf_MaxPktSize,
  444. pSpxConnFile->scf_RemAddr,
  445. pSpxConnFile->scf_AddrFile->saf_Addr->sa_Socket);
  446. // Build SPX Header.
  447. pIpxSpxHdr->hdr_ConnCtrl =
  448. (SPX_CC_SYS | SPX_CC_ACK | SPX_CC_SPX2 |
  449. ((pSpxConnFile->scf_Flags & SPX_CONNFILE_NEG) ? SPX_CC_NEG : 0));
  450. pIpxSpxHdr->hdr_DataType = 0;
  451. PUTSHORT2SHORT(
  452. &pIpxSpxHdr->hdr_SrcConnId,
  453. pSpxConnFile->scf_LocalConnId);
  454. pIpxSpxHdr->hdr_DestConnId = pSpxConnFile->scf_RemConnId;
  455. pIpxSpxHdr->hdr_SeqNum = 0;
  456. pIpxSpxHdr->hdr_AckNum = 0;
  457. PUTSHORT2SHORT(
  458. &pIpxSpxHdr->hdr_AllocNum,
  459. pSpxConnFile->scf_SentAllocNum);
  460. PUTSHORT2SHORT(
  461. &pIpxSpxHdr->hdr_NegSize,
  462. pSpxConnFile->scf_MaxPktSize);
  463. // Init the data part to indicate no neg values
  464. *(UNALIGNED ULONG *)pData = 0;
  465. pSendResd = (PSPX_SEND_RESD)(pPkt->ProtocolReserved);
  466. pSendResd->sr_Id = IDENTIFIER_SPX;
  467. pSendResd->sr_Type = SPX_TYPE_SS;
  468. pSendResd->sr_Reserved1 = NULL;
  469. pSendResd->sr_Reserved2 = NULL;
  470. pSendResd->sr_State = (State | SPX_SENDPKT_FREEDATA);
  471. pSendResd->sr_ConnFile = pSpxConnFile;
  472. pSendResd->sr_Request = NULL;
  473. pSendResd->sr_Next = NULL;
  474. pSendResd->sr_HdrLen = MIN_IPXSPX2_HDRSIZE;
  475. pSendResd->sr_Len = pSpxConnFile->scf_MaxPktSize;
  476. *ppPkt = pPkt;
  477. } while (FALSE);
  478. return;
  479. }
  480. VOID
  481. SpxPktBuildSsAck(
  482. IN PSPX_CONN_FILE pSpxConnFile,
  483. OUT PNDIS_PACKET * ppPkt,
  484. IN USHORT State
  485. )
  486. /*++
  487. Routine Description:
  488. Arguments:
  489. Return Value:
  490. --*/
  491. {
  492. PNDIS_PACKET pPkt;
  493. NDIS_STATUS ndisStatus;
  494. PIPXSPX_HDR pIpxSpxHdr;
  495. PSPX_SEND_RESD pSendResd;
  496. PNDIS_BUFFER NdisBuf, NdisBuf2;
  497. ULONG BufLen = 0;
  498. do
  499. {
  500. *ppPkt = NULL;
  501. // Allocate a ndis packet for the cr.
  502. SpxAllocSendPacket(SpxDevice, &pPkt, &ndisStatus);
  503. if (ndisStatus != NDIS_STATUS_SUCCESS)
  504. {
  505. break;
  506. }
  507. //
  508. // Get the MDL that points to the IPX/SPX header. (the second one)
  509. //
  510. NdisQueryPacket(pPkt, NULL, NULL, &NdisBuf, NULL);
  511. NdisGetNextBuffer(NdisBuf, &NdisBuf2);
  512. NdisQueryBuffer(NdisBuf2, (PUCHAR) &pIpxSpxHdr, &BufLen);
  513. #if OWN_PKT_POOLS
  514. pIpxSpxHdr = (PIPXSPX_HDR)((PBYTE)pPkt +
  515. NDIS_PACKET_SIZE +
  516. sizeof(SPX_SEND_RESD) +
  517. IpxInclHdrOffset);
  518. #endif
  519. SpxBuildIpxHdr(
  520. pIpxSpxHdr,
  521. MIN_IPXSPX2_HDRSIZE,
  522. pSpxConnFile->scf_RemAddr,
  523. pSpxConnFile->scf_AddrFile->saf_Addr->sa_Socket);
  524. // Build SPX Header.
  525. pIpxSpxHdr->hdr_ConnCtrl =
  526. (SPX_CC_SYS | SPX_CC_SPX2 |
  527. ((pSpxConnFile->scf_Flags & SPX_CONNFILE_NEG) ? SPX_CC_NEG : 0));
  528. pIpxSpxHdr->hdr_DataType = 0;
  529. PUTSHORT2SHORT(
  530. &pIpxSpxHdr->hdr_SrcConnId,
  531. pSpxConnFile->scf_LocalConnId);
  532. pIpxSpxHdr->hdr_DestConnId = pSpxConnFile->scf_RemConnId;
  533. pIpxSpxHdr->hdr_SeqNum = 0;
  534. pIpxSpxHdr->hdr_AckNum = 0;
  535. PUTSHORT2SHORT(
  536. &pIpxSpxHdr->hdr_AllocNum,
  537. pSpxConnFile->scf_SentAllocNum);
  538. PUTSHORT2SHORT(
  539. &pIpxSpxHdr->hdr_NegSize,
  540. pSpxConnFile->scf_MaxPktSize);
  541. pSendResd = (PSPX_SEND_RESD)(pPkt->ProtocolReserved);
  542. pSendResd->sr_Id = IDENTIFIER_SPX;
  543. pSendResd->sr_Type = SPX_TYPE_SSACK;
  544. pSendResd->sr_Reserved1 = NULL;
  545. pSendResd->sr_Reserved2 = NULL;
  546. pSendResd->sr_State = State;
  547. pSendResd->sr_ConnFile = pSpxConnFile;
  548. pSendResd->sr_Request = NULL;
  549. pSendResd->sr_Next = NULL;
  550. pSendResd->sr_Len = pSendResd->sr_HdrLen = MIN_IPXSPX2_HDRSIZE;
  551. *ppPkt = pPkt;
  552. } while (FALSE);
  553. return;
  554. }
  555. VOID
  556. SpxPktBuildRr(
  557. IN PSPX_CONN_FILE pSpxConnFile,
  558. OUT PNDIS_PACKET * ppPkt,
  559. IN USHORT SeqNum,
  560. IN USHORT State
  561. )
  562. /*++
  563. Routine Description:
  564. Arguments:
  565. Return Value:
  566. --*/
  567. {
  568. PNDIS_PACKET pPkt;
  569. PSPX_SEND_RESD pSendResd;
  570. PNDIS_BUFFER pBuf;
  571. NDIS_STATUS ndisStatus;
  572. PIPXSPX_HDR pIpxSpxHdr;
  573. PBYTE pData;
  574. PNDIS_BUFFER NdisBuf, NdisBuf2;
  575. ULONG BufLen = 0;
  576. do
  577. {
  578. *ppPkt = NULL;
  579. // Allocate a ndis packet for the cr.
  580. SpxAllocSendPacket(SpxDevice, &pPkt, &ndisStatus);
  581. if (ndisStatus != NDIS_STATUS_SUCCESS)
  582. {
  583. break;
  584. }
  585. if ((pData =
  586. SpxAllocateMemory(
  587. pSpxConnFile->scf_MaxPktSize - MIN_IPXSPX2_HDRSIZE)) == NULL)
  588. {
  589. SpxPktSendRelease(pPkt);
  590. break;
  591. }
  592. // Build ndis buffer desc
  593. NdisAllocateBuffer(
  594. &ndisStatus,
  595. &pBuf,
  596. SpxDevice->dev_NdisBufferPoolHandle,
  597. pData,
  598. pSpxConnFile->scf_MaxPktSize - MIN_IPXSPX2_HDRSIZE);
  599. if (ndisStatus != NDIS_STATUS_SUCCESS)
  600. {
  601. SpxPktSendRelease(pPkt);
  602. SpxFreeMemory(pData);
  603. break;
  604. }
  605. // Chain at back.
  606. NdisChainBufferAtBack(
  607. pPkt,
  608. pBuf);
  609. //
  610. // Get the MDL that points to the IPX/SPX header. (the second one)
  611. //
  612. NdisQueryPacket(pPkt, NULL, NULL, &NdisBuf, NULL);
  613. NdisGetNextBuffer(NdisBuf, &NdisBuf2);
  614. NdisQueryBuffer(NdisBuf2, (PUCHAR) &pIpxSpxHdr, &BufLen);
  615. #if OWN_PKT_POOLS
  616. pIpxSpxHdr = (PIPXSPX_HDR)((PBYTE)pPkt +
  617. NDIS_PACKET_SIZE +
  618. sizeof(SPX_SEND_RESD) +
  619. IpxInclHdrOffset);
  620. #endif
  621. SpxBuildIpxHdr(
  622. pIpxSpxHdr,
  623. pSpxConnFile->scf_MaxPktSize,
  624. pSpxConnFile->scf_RemAddr,
  625. pSpxConnFile->scf_AddrFile->saf_Addr->sa_Socket);
  626. // Build SPX Header.
  627. pIpxSpxHdr->hdr_ConnCtrl = ( SPX_CC_SYS | SPX_CC_ACK |
  628. SPX_CC_NEG | SPX_CC_SPX2);
  629. pIpxSpxHdr->hdr_DataType = 0;
  630. PUTSHORT2SHORT(
  631. &pIpxSpxHdr->hdr_SrcConnId,
  632. pSpxConnFile->scf_LocalConnId);
  633. pIpxSpxHdr->hdr_DestConnId = pSpxConnFile->scf_RemConnId;
  634. // For a renegotiate request, we use the sequence number of
  635. // the first waiting data packet. Passed in.
  636. PUTSHORT2SHORT(
  637. &pIpxSpxHdr->hdr_SeqNum,
  638. SeqNum);
  639. PUTSHORT2SHORT(
  640. &pIpxSpxHdr->hdr_AckNum,
  641. pSpxConnFile->scf_RecvSeqNum);
  642. PUTSHORT2SHORT(
  643. &pIpxSpxHdr->hdr_AllocNum,
  644. pSpxConnFile->scf_SentAllocNum);
  645. PUTSHORT2SHORT(
  646. &pIpxSpxHdr->hdr_NegSize,
  647. pSpxConnFile->scf_MaxPktSize);
  648. // Init the data part to indicate no neg values
  649. *(UNALIGNED ULONG *)pData = 0;
  650. pSendResd = (PSPX_SEND_RESD)(pPkt->ProtocolReserved);
  651. pSendResd->sr_Id = IDENTIFIER_SPX;
  652. pSendResd->sr_Type = SPX_TYPE_RR;
  653. pSendResd->sr_Reserved1 = NULL;
  654. pSendResd->sr_Reserved2 = NULL;
  655. pSendResd->sr_State = (State | SPX_SENDPKT_FREEDATA);
  656. pSendResd->sr_ConnFile = pSpxConnFile;
  657. pSendResd->sr_Request = NULL;
  658. pSendResd->sr_Next = NULL;
  659. pSendResd->sr_SeqNum = SeqNum;
  660. pSendResd->sr_HdrLen = MIN_IPXSPX2_HDRSIZE;
  661. pSendResd->sr_Len = pSpxConnFile->scf_MaxPktSize;
  662. *ppPkt = pPkt;
  663. } while (FALSE);
  664. return;
  665. }
  666. VOID
  667. SpxPktBuildRrAck(
  668. IN PSPX_CONN_FILE pSpxConnFile,
  669. OUT PNDIS_PACKET * ppPkt,
  670. IN USHORT State,
  671. IN USHORT MaxPktSize
  672. )
  673. /*++
  674. Routine Description:
  675. Arguments:
  676. Return Value:
  677. --*/
  678. {
  679. PNDIS_PACKET pPkt;
  680. NDIS_STATUS ndisStatus;
  681. PIPXSPX_HDR pIpxSpxHdr;
  682. PSPX_SEND_RESD pSendResd;
  683. PNDIS_BUFFER NdisBuf, NdisBuf2;
  684. ULONG BufLen = 0;
  685. do
  686. {
  687. *ppPkt = NULL;
  688. // Allocate a ndis packet for the cr.
  689. SpxAllocSendPacket(SpxDevice, &pPkt, &ndisStatus);
  690. if (ndisStatus != NDIS_STATUS_SUCCESS)
  691. {
  692. break;
  693. }
  694. //
  695. // Get the MDL that points to the IPX/SPX header. (the second one)
  696. //
  697. NdisQueryPacket(pPkt, NULL, NULL, &NdisBuf, NULL);
  698. NdisGetNextBuffer(NdisBuf, &NdisBuf2);
  699. NdisQueryBuffer(NdisBuf2, (PUCHAR) &pIpxSpxHdr, &BufLen);
  700. #if OWN_PKT_POOLS
  701. pIpxSpxHdr = (PIPXSPX_HDR)((PBYTE)pPkt +
  702. NDIS_PACKET_SIZE +
  703. sizeof(SPX_SEND_RESD) +
  704. IpxInclHdrOffset);
  705. #endif
  706. SpxBuildIpxHdr(
  707. pIpxSpxHdr,
  708. MIN_IPXSPX2_HDRSIZE,
  709. pSpxConnFile->scf_RemAckAddr,
  710. pSpxConnFile->scf_AddrFile->saf_Addr->sa_Socket);
  711. // Build SPX Header.
  712. pIpxSpxHdr->hdr_ConnCtrl = (SPX_CC_SYS | SPX_CC_NEG | SPX_CC_SPX2);
  713. pIpxSpxHdr->hdr_DataType = 0;
  714. PUTSHORT2SHORT(
  715. &pIpxSpxHdr->hdr_SrcConnId,
  716. pSpxConnFile->scf_LocalConnId);
  717. pIpxSpxHdr->hdr_DestConnId = pSpxConnFile->scf_RemConnId;
  718. PUTSHORT2SHORT(
  719. &pIpxSpxHdr->hdr_SeqNum,
  720. pSpxConnFile->scf_SendSeqNum);
  721. // For the RrAck, ack number will be the appropriate number
  722. // for the last data packet received.
  723. PUTSHORT2SHORT(
  724. &pIpxSpxHdr->hdr_AckNum,
  725. pSpxConnFile->scf_RenegAckAckNum);
  726. PUTSHORT2SHORT(
  727. &pIpxSpxHdr->hdr_AllocNum,
  728. pSpxConnFile->scf_SentAllocNum);
  729. PUTSHORT2SHORT(
  730. &pIpxSpxHdr->hdr_NegSize,
  731. MaxPktSize);
  732. DBGPRINT(SEND, DBG3,
  733. ("SpxPktBuildRrAck: SEQ %lx ACKNUM %lx ALLOCNUM %lx MAXPKT %lx\n",
  734. pSpxConnFile->scf_SendSeqNum,
  735. pSpxConnFile->scf_RenegAckAckNum,
  736. pSpxConnFile->scf_SentAllocNum,
  737. MaxPktSize));
  738. pSendResd = (PSPX_SEND_RESD)(pPkt->ProtocolReserved);
  739. pSendResd->sr_Id = IDENTIFIER_SPX;
  740. pSendResd->sr_Type = SPX_TYPE_RRACK;
  741. pSendResd->sr_Reserved1 = NULL;
  742. pSendResd->sr_Reserved2 = NULL;
  743. pSendResd->sr_State = State;
  744. pSendResd->sr_ConnFile = pSpxConnFile;
  745. pSendResd->sr_Request = NULL;
  746. pSendResd->sr_Next = NULL;
  747. pSendResd->sr_Len = pSendResd->sr_HdrLen = MIN_IPXSPX2_HDRSIZE;
  748. *ppPkt = pPkt;
  749. } while (FALSE);
  750. return;
  751. }
  752. VOID
  753. SpxPktBuildDisc(
  754. IN PSPX_CONN_FILE pSpxConnFile,
  755. IN PREQUEST pRequest,
  756. OUT PNDIS_PACKET * ppPkt,
  757. IN USHORT State,
  758. IN UCHAR DataType
  759. )
  760. /*++
  761. Routine Description:
  762. Arguments:
  763. Return Value:
  764. --*/
  765. {
  766. PSPX_SEND_RESD pSendResd;
  767. PNDIS_PACKET pDiscPkt;
  768. NDIS_STATUS ndisStatus;
  769. PIPXSPX_HDR pIpxSpxHdr;
  770. USHORT hdrLen;
  771. PNDIS_BUFFER pNdisMacHdr, pNdisIpxHdr;
  772. PNDIS_BUFFER NdisBuf, NdisBuf2;
  773. ULONG BufLen = 0;
  774. *ppPkt = NULL;
  775. SpxAllocSendPacket(SpxDevice, &pDiscPkt, &ndisStatus);
  776. if (ndisStatus == NDIS_STATUS_SUCCESS)
  777. {
  778. #if OWN_PKT_POOLS
  779. pIpxSpxHdr = (PIPXSPX_HDR)((PBYTE)pDiscPkt +
  780. NDIS_PACKET_SIZE +
  781. sizeof(SPX_SEND_RESD) +
  782. IpxInclHdrOffset);
  783. #endif
  784. //
  785. // Get the MDL that points to the IPX/SPX header. (the second one)
  786. //
  787. NdisQueryPacket(pDiscPkt, NULL, NULL, &NdisBuf, NULL);
  788. NdisGetNextBuffer(NdisBuf, &NdisBuf2);
  789. NdisQueryBuffer(NdisBuf2, (PUCHAR) &pIpxSpxHdr, &BufLen);
  790. hdrLen = SPX2_CONN(pSpxConnFile) ? MIN_IPXSPX2_HDRSIZE : MIN_IPXSPX_HDRSIZE;
  791. NdisQueryPacket(pDiscPkt, NULL, NULL, &pNdisMacHdr, NULL);
  792. pNdisIpxHdr = NDIS_BUFFER_LINKAGE(pNdisMacHdr);
  793. if (!SPX2_CONN(pSpxConnFile))
  794. {
  795. NdisAdjustBufferLength(pNdisIpxHdr, MIN_IPXSPX_HDRSIZE);
  796. }
  797. SpxBuildIpxHdr(
  798. pIpxSpxHdr,
  799. hdrLen,
  800. pSpxConnFile->scf_RemAddr,
  801. pSpxConnFile->scf_AddrFile->saf_Addr->sa_Socket);
  802. // Build SPX Header.
  803. pIpxSpxHdr->hdr_ConnCtrl =
  804. (SPX_CC_ACK |
  805. (SPX2_CONN(pSpxConnFile) ? SPX_CC_SPX2 : 0) |
  806. ((DataType == SPX2_DT_IDISC) ? 0 : SPX_CC_EOM));
  807. pIpxSpxHdr->hdr_DataType = DataType;
  808. PUTSHORT2SHORT(
  809. &pIpxSpxHdr->hdr_SrcConnId,
  810. pSpxConnFile->scf_LocalConnId);
  811. pIpxSpxHdr->hdr_DestConnId =
  812. *((UNALIGNED USHORT *)&pSpxConnFile->scf_RemConnId);
  813. PUTSHORT2SHORT(
  814. &pIpxSpxHdr->hdr_SeqNum,
  815. pSpxConnFile->scf_SendSeqNum);
  816. PUTSHORT2SHORT(
  817. &pIpxSpxHdr->hdr_AckNum,
  818. pSpxConnFile->scf_RecvSeqNum);
  819. PUTSHORT2SHORT(
  820. &pIpxSpxHdr->hdr_AllocNum,
  821. pSpxConnFile->scf_SentAllocNum);
  822. if (SPX2_CONN(pSpxConnFile))
  823. {
  824. PUTSHORT2SHORT(
  825. &pIpxSpxHdr->hdr_NegSize,
  826. pSpxConnFile->scf_MaxPktSize);
  827. }
  828. pSendResd = (PSPX_SEND_RESD)(pDiscPkt->ProtocolReserved);
  829. pSendResd->sr_Id = IDENTIFIER_SPX;
  830. pSendResd->sr_State = State;
  831. pSendResd->sr_Reserved1 = NULL;
  832. pSendResd->sr_Reserved2 = NULL;
  833. pSendResd->sr_Type =
  834. ((DataType == SPX2_DT_IDISC) ? SPX_TYPE_IDISC : SPX_TYPE_ORDREL);
  835. pSendResd->sr_Next = NULL;
  836. pSendResd->sr_Request = pRequest;
  837. pSendResd->sr_ConnFile = pSpxConnFile;
  838. pSendResd->sr_Offset = 0;
  839. pSendResd->sr_SeqNum = pSpxConnFile->scf_SendSeqNum;
  840. pSendResd->sr_Len =
  841. pSendResd->sr_HdrLen = hdrLen;
  842. *ppPkt = pDiscPkt;
  843. }
  844. return;
  845. }
  846. VOID
  847. SpxPktBuildProbe(
  848. IN PSPX_CONN_FILE pSpxConnFile,
  849. OUT PNDIS_PACKET * ppPkt,
  850. IN USHORT State,
  851. IN BOOLEAN fSpx2
  852. )
  853. /*++
  854. Routine Description:
  855. Arguments:
  856. Return Value:
  857. --*/
  858. {
  859. PSPX_SEND_RESD pSendResd;
  860. PNDIS_PACKET pProbe;
  861. NDIS_STATUS ndisStatus;
  862. PIPXSPX_HDR pIpxSpxHdr;
  863. USHORT hdrLen;
  864. PNDIS_BUFFER pNdisMacHdr, pNdisIpxHdr;
  865. PNDIS_BUFFER NdisBuf, NdisBuf2;
  866. ULONG BufLen = 0;
  867. *ppPkt = NULL;
  868. SpxAllocSendPacket(SpxDevice, &pProbe, &ndisStatus);
  869. if (ndisStatus == NDIS_STATUS_SUCCESS)
  870. {
  871. //
  872. // Get the MDL that points to the IPX/SPX header. (the second one)
  873. //
  874. NdisQueryPacket(pProbe, NULL, NULL, &NdisBuf, NULL);
  875. NdisGetNextBuffer(NdisBuf, &NdisBuf2);
  876. NdisQueryBuffer(NdisBuf2, (PUCHAR) &pIpxSpxHdr, &BufLen);
  877. #if OWN_PKT_POOLS
  878. pIpxSpxHdr = (PIPXSPX_HDR)((PBYTE)pProbe +
  879. NDIS_PACKET_SIZE +
  880. sizeof(SPX_SEND_RESD) +
  881. IpxInclHdrOffset);
  882. #endif
  883. hdrLen = (fSpx2 ? MIN_IPXSPX2_HDRSIZE : MIN_IPXSPX_HDRSIZE);
  884. NdisQueryPacket(pProbe, NULL, NULL, &pNdisMacHdr, NULL);
  885. pNdisIpxHdr = NDIS_BUFFER_LINKAGE(pNdisMacHdr);
  886. if (!fSpx2)
  887. {
  888. NdisAdjustBufferLength(pNdisIpxHdr, MIN_IPXSPX_HDRSIZE);
  889. }
  890. SpxBuildIpxHdr(
  891. pIpxSpxHdr,
  892. hdrLen,
  893. pSpxConnFile->scf_RemAddr,
  894. pSpxConnFile->scf_AddrFile->saf_Addr->sa_Socket);
  895. // Build SPX Header.
  896. pIpxSpxHdr->hdr_ConnCtrl = (SPX_CC_SYS | SPX_CC_ACK |
  897. (fSpx2 ? SPX_CC_SPX2 : 0));
  898. pIpxSpxHdr->hdr_DataType = 0;
  899. PUTSHORT2SHORT(
  900. &pIpxSpxHdr->hdr_SrcConnId,
  901. pSpxConnFile->scf_LocalConnId);
  902. pIpxSpxHdr->hdr_DestConnId =
  903. *((UNALIGNED USHORT *)&pSpxConnFile->scf_RemConnId);
  904. if (fSpx2)
  905. {
  906. pIpxSpxHdr->hdr_SeqNum = 0;
  907. PUTSHORT2SHORT(
  908. &pIpxSpxHdr->hdr_NegSize,
  909. pSpxConnFile->scf_MaxPktSize);
  910. }
  911. else
  912. {
  913. PUTSHORT2SHORT(
  914. &pIpxSpxHdr->hdr_SeqNum,
  915. pSpxConnFile->scf_SendSeqNum);
  916. }
  917. PUTSHORT2SHORT(
  918. &pIpxSpxHdr->hdr_AckNum,
  919. pSpxConnFile->scf_RecvSeqNum);
  920. PUTSHORT2SHORT(
  921. &pIpxSpxHdr->hdr_AllocNum,
  922. pSpxConnFile->scf_SentAllocNum);
  923. pSendResd = (PSPX_SEND_RESD)(pProbe->ProtocolReserved);
  924. pSendResd->sr_Id = IDENTIFIER_SPX;
  925. pSendResd->sr_Type = SPX_TYPE_PROBE;
  926. pSendResd->sr_Reserved1 = NULL;
  927. pSendResd->sr_Reserved2 = NULL;
  928. pSendResd->sr_State = State;
  929. pSendResd->sr_Next = NULL;
  930. pSendResd->sr_Request = NULL;
  931. pSendResd->sr_ConnFile = pSpxConnFile;
  932. pSendResd->sr_Len =
  933. pSendResd->sr_HdrLen = (fSpx2 ? MIN_IPXSPX2_HDRSIZE
  934. : MIN_IPXSPX_HDRSIZE);
  935. *ppPkt = pProbe;
  936. }
  937. return;
  938. }
  939. VOID
  940. SpxPktBuildData(
  941. IN PSPX_CONN_FILE pSpxConnFile,
  942. OUT PNDIS_PACKET * ppPkt,
  943. IN USHORT State,
  944. IN USHORT Length
  945. )
  946. /*++
  947. Routine Description:
  948. Handles zero length sends.
  949. Arguments:
  950. Return Value:
  951. --*/
  952. {
  953. PNDIS_BUFFER pNdisBuffer;
  954. PSPX_SEND_RESD pSendResd;
  955. PNDIS_PACKET pDataPkt;
  956. NDIS_STATUS ndisStatus;
  957. PIPXSPX_HDR pIpxSpxHdr;
  958. USHORT hdrLen;
  959. PNDIS_BUFFER pNdisMacHdr, pNdisIpxHdr;
  960. PNDIS_BUFFER NdisBuf, NdisBuf2;
  961. ULONG BufLen = 0;
  962. *ppPkt = NULL;
  963. SpxAllocSendPacket(SpxDevice, &pDataPkt, &ndisStatus);
  964. if (ndisStatus == NDIS_STATUS_SUCCESS)
  965. {
  966. // Make a ndis buffer descriptor for the data if present.
  967. if (Length > 0)
  968. {
  969. SpxCopyBufferChain(
  970. &ndisStatus,
  971. &pNdisBuffer,
  972. SpxDevice->dev_NdisBufferPoolHandle,
  973. REQUEST_TDI_BUFFER(pSpxConnFile->scf_ReqPkt),
  974. pSpxConnFile->scf_ReqPktOffset,
  975. Length);
  976. if (ndisStatus != NDIS_STATUS_SUCCESS)
  977. {
  978. // Free the send packet
  979. SpxPktSendRelease(pDataPkt);
  980. return;
  981. }
  982. // Chain this in the packet
  983. NdisChainBufferAtBack(pDataPkt, pNdisBuffer);
  984. }
  985. //
  986. // Get the MDL that points to the IPX/SPX header. (the second one)
  987. //
  988. NdisQueryPacket(pDataPkt, NULL, NULL, &NdisBuf, NULL);
  989. NdisGetNextBuffer(NdisBuf, &NdisBuf2);
  990. NdisQueryBuffer(NdisBuf2, (PUCHAR) &pIpxSpxHdr, &BufLen);
  991. #if OWN_PKT_POOLS
  992. pIpxSpxHdr = (PIPXSPX_HDR)((PBYTE)pDataPkt +
  993. NDIS_PACKET_SIZE +
  994. sizeof(SPX_SEND_RESD) +
  995. IpxInclHdrOffset);
  996. #endif
  997. hdrLen = SPX2_CONN(pSpxConnFile) ? MIN_IPXSPX2_HDRSIZE : MIN_IPXSPX_HDRSIZE;
  998. Length += hdrLen;
  999. NdisQueryPacket(pDataPkt, NULL, NULL, &pNdisMacHdr, NULL);
  1000. pNdisIpxHdr = NDIS_BUFFER_LINKAGE(pNdisMacHdr);
  1001. if (!SPX2_CONN(pSpxConnFile))
  1002. {
  1003. NdisAdjustBufferLength(pNdisIpxHdr, MIN_IPXSPX_HDRSIZE);
  1004. }
  1005. SpxBuildIpxHdr(
  1006. pIpxSpxHdr,
  1007. Length,
  1008. pSpxConnFile->scf_RemAddr,
  1009. pSpxConnFile->scf_AddrFile->saf_Addr->sa_Socket);
  1010. // Build SPX Header.
  1011. pIpxSpxHdr->hdr_ConnCtrl =
  1012. (((State & SPX_SENDPKT_ACKREQ) ? SPX_CC_ACK : 0) |
  1013. ((State & SPX_SENDPKT_EOM) ? SPX_CC_EOM : 0) |
  1014. (SPX2_CONN(pSpxConnFile) ? SPX_CC_SPX2 : 0));
  1015. pIpxSpxHdr->hdr_DataType = pSpxConnFile->scf_DataType;
  1016. PUTSHORT2SHORT(
  1017. &pIpxSpxHdr->hdr_SrcConnId,
  1018. pSpxConnFile->scf_LocalConnId);
  1019. pIpxSpxHdr->hdr_DestConnId =
  1020. *((UNALIGNED USHORT *)&pSpxConnFile->scf_RemConnId);
  1021. PUTSHORT2SHORT(
  1022. &pIpxSpxHdr->hdr_SeqNum,
  1023. pSpxConnFile->scf_SendSeqNum);
  1024. PUTSHORT2SHORT(
  1025. &pIpxSpxHdr->hdr_AckNum,
  1026. pSpxConnFile->scf_RecvSeqNum);
  1027. PUTSHORT2SHORT(
  1028. &pIpxSpxHdr->hdr_AllocNum,
  1029. pSpxConnFile->scf_SentAllocNum);
  1030. if (SPX2_CONN(pSpxConnFile))
  1031. {
  1032. PUTSHORT2SHORT(
  1033. &pIpxSpxHdr->hdr_NegSize,
  1034. pSpxConnFile->scf_MaxPktSize);
  1035. }
  1036. pSendResd = (PSPX_SEND_RESD)(pDataPkt->ProtocolReserved);
  1037. pSendResd->sr_Id = IDENTIFIER_SPX;
  1038. pSendResd->sr_State = State;
  1039. pSendResd->sr_Reserved1 = NULL;
  1040. pSendResd->sr_Reserved2 = NULL;
  1041. pSendResd->sr_Type = SPX_TYPE_DATA;
  1042. pSendResd->sr_Next = NULL;
  1043. pSendResd->sr_Request = pSpxConnFile->scf_ReqPkt;
  1044. pSendResd->sr_Offset = pSpxConnFile->scf_ReqPktOffset;
  1045. pSendResd->sr_ConnFile = pSpxConnFile;
  1046. pSendResd->sr_SeqNum = pSpxConnFile->scf_SendSeqNum;
  1047. pSendResd->sr_Len = Length;
  1048. pSendResd->sr_HdrLen = hdrLen;
  1049. if (State & SPX_SENDPKT_ACKREQ)
  1050. {
  1051. KeQuerySystemTime((PLARGE_INTEGER)&pSendResd->sr_SentTime);
  1052. }
  1053. CTEAssert(pSendResd->sr_Len <= pSpxConnFile->scf_MaxPktSize);
  1054. *ppPkt = pDataPkt;
  1055. // Ok, allocation succeeded. Increment send seq.
  1056. pSpxConnFile->scf_SendSeqNum++;
  1057. }
  1058. return;
  1059. }
  1060. VOID
  1061. SpxCopyBufferChain(
  1062. OUT PNDIS_STATUS Status,
  1063. OUT PNDIS_BUFFER * TargetChain,
  1064. IN NDIS_HANDLE PoolHandle,
  1065. IN PNDIS_BUFFER SourceChain,
  1066. IN UINT Offset,
  1067. IN UINT Length
  1068. )
  1069. /*++
  1070. Routine Description:
  1071. Creates a TargetBufferChain from the SourceBufferChain. The copy begins at
  1072. the 'Offset' location in the source chain. It copies 'Length' bytes. It also
  1073. handles Length = 0. If we run out of source chain before copying length amount
  1074. of bytes or run out of memory to create any more buffers for the target chain,
  1075. we clean up the partial chain created so far.
  1076. Arguments:
  1077. Status - Status of the request.
  1078. TargetChain - Pointer to the allocated buffer descriptor.
  1079. PoolHandle - Handle that is used to specify the pool.
  1080. SourceChain - Pointer to the descriptor of the source memory.
  1081. Offset - The Offset in the sources memory from which the copy is to
  1082. begin
  1083. Length - Number of Bytes to copy.
  1084. Return Value:
  1085. None.
  1086. --*/
  1087. {
  1088. UINT BytesBeforeCurBuffer = 0;
  1089. PNDIS_BUFFER CurBuffer = SourceChain;
  1090. UINT BytesLeft;
  1091. UINT AvailableBytes;
  1092. PNDIS_BUFFER NewNdisBuffer, StartTargetChain;
  1093. CTEAssert( SourceChain );
  1094. // First of all find the source buffer that contains data that starts at
  1095. // Offset.
  1096. NdisQueryBuffer( CurBuffer, NULL, &AvailableBytes );
  1097. while ( BytesBeforeCurBuffer + AvailableBytes <= Offset ) {
  1098. BytesBeforeCurBuffer += AvailableBytes;
  1099. CurBuffer = CurBuffer->Next;
  1100. if ( CurBuffer ) {
  1101. NdisQueryBuffer( CurBuffer, NULL, &AvailableBytes );
  1102. } else {
  1103. break;
  1104. }
  1105. }
  1106. if ( ! CurBuffer ) {
  1107. *Status = STATUS_UNSUCCESSFUL;
  1108. return;
  1109. }
  1110. //
  1111. // Copy the first buffer. This takes care of Length = 0.
  1112. //
  1113. BytesLeft = Length;
  1114. //
  1115. // ( Offset - BytesBeforeCurBuffer ) gives us the offset within this buffer.
  1116. //
  1117. AvailableBytes -= ( Offset - BytesBeforeCurBuffer );
  1118. if ( AvailableBytes > BytesLeft ) {
  1119. AvailableBytes = BytesLeft;
  1120. }
  1121. NdisCopyBuffer(
  1122. Status,
  1123. &NewNdisBuffer,
  1124. PoolHandle,
  1125. CurBuffer,
  1126. Offset - BytesBeforeCurBuffer,
  1127. AvailableBytes);
  1128. if ( *Status != NDIS_STATUS_SUCCESS ) {
  1129. return;
  1130. }
  1131. StartTargetChain = NewNdisBuffer;
  1132. BytesLeft -= AvailableBytes;
  1133. //
  1134. // Did the first buffer have enough data. If so, we r done.
  1135. //
  1136. if ( ! BytesLeft ) {
  1137. *TargetChain = StartTargetChain;
  1138. return;
  1139. }
  1140. //
  1141. // Now follow the Mdl chain and copy more buffers.
  1142. //
  1143. CurBuffer = CurBuffer->Next;
  1144. NdisQueryBuffer( CurBuffer, NULL, &AvailableBytes );
  1145. while ( CurBuffer ) {
  1146. if ( AvailableBytes > BytesLeft ) {
  1147. AvailableBytes = BytesLeft;
  1148. }
  1149. NdisCopyBuffer(
  1150. Status,
  1151. &(NDIS_BUFFER_LINKAGE(NewNdisBuffer)),
  1152. PoolHandle,
  1153. CurBuffer,
  1154. 0,
  1155. AvailableBytes);
  1156. if ( *Status != NDIS_STATUS_SUCCESS ) {
  1157. //
  1158. // ran out of resources. put back what we've used in this call and
  1159. // return the error.
  1160. //
  1161. while ( StartTargetChain != NULL) {
  1162. NewNdisBuffer = NDIS_BUFFER_LINKAGE( StartTargetChain );
  1163. NdisFreeBuffer ( StartTargetChain );
  1164. StartTargetChain = NewNdisBuffer;
  1165. }
  1166. return;
  1167. }
  1168. NewNdisBuffer = NDIS_BUFFER_LINKAGE(NewNdisBuffer);
  1169. BytesLeft -= AvailableBytes;
  1170. if ( ! BytesLeft ) {
  1171. *TargetChain = StartTargetChain;
  1172. return;
  1173. }
  1174. CurBuffer = CurBuffer->Next;
  1175. NdisQueryBuffer( CurBuffer, NULL, &AvailableBytes );
  1176. }
  1177. //
  1178. // Ran out of source chain. This should not happen.
  1179. //
  1180. CTEAssert( FALSE );
  1181. // For Retail build we clean up anyways.
  1182. while ( StartTargetChain != NULL) {
  1183. NewNdisBuffer = NDIS_BUFFER_LINKAGE( StartTargetChain );
  1184. NdisFreeBuffer ( StartTargetChain );
  1185. StartTargetChain = NewNdisBuffer;
  1186. }
  1187. *Status = STATUS_UNSUCCESSFUL;
  1188. return;
  1189. }
  1190. VOID
  1191. SpxPktBuildAck(
  1192. IN PSPX_CONN_FILE pSpxConnFile,
  1193. OUT PNDIS_PACKET * ppPkt,
  1194. IN USHORT State,
  1195. IN BOOLEAN fBuildNack,
  1196. IN USHORT NumToResend
  1197. )
  1198. /*++
  1199. Routine Description:
  1200. Arguments:
  1201. Return Value:
  1202. --*/
  1203. {
  1204. PNDIS_PACKET pPkt;
  1205. PSPX_SEND_RESD pSendResd;
  1206. PIPXSPX_HDR pIpxSpxHdr;
  1207. NDIS_STATUS ndisStatus;
  1208. USHORT hdrLen;
  1209. PNDIS_BUFFER pNdisMacHdr, pNdisIpxHdr;
  1210. PNDIS_BUFFER NdisBuf, NdisBuf2;
  1211. ULONG BufLen = 0;
  1212. BOOLEAN fSpx2 = SPX_CONN_FLAG(pSpxConnFile, SPX_CONNFILE_SPX2);
  1213. *ppPkt = NULL;
  1214. SpxAllocSendPacket(SpxDevice, &pPkt, &ndisStatus);
  1215. if (ndisStatus != NDIS_STATUS_SUCCESS)
  1216. {
  1217. DBGPRINT(SEND, ERR,
  1218. ("SpxPktBuildAck: Could not allocate ndis packet\n"));
  1219. return;
  1220. }
  1221. //
  1222. // Get the MDL that points to the IPX/SPX header. (the second one)
  1223. //
  1224. NdisQueryPacket(pPkt, NULL, NULL, &NdisBuf, NULL);
  1225. NdisGetNextBuffer(NdisBuf, &NdisBuf2);
  1226. NdisQueryBuffer(NdisBuf2, (PUCHAR) &pIpxSpxHdr, &BufLen);
  1227. #if OWN_PKT_POOLS
  1228. pIpxSpxHdr = (PIPXSPX_HDR)((PBYTE)pPkt +
  1229. NDIS_PACKET_SIZE +
  1230. sizeof(SPX_SEND_RESD) +
  1231. IpxInclHdrOffset);
  1232. #endif
  1233. hdrLen = SPX2_CONN(pSpxConnFile) ? MIN_IPXSPX2_HDRSIZE : MIN_IPXSPX_HDRSIZE;
  1234. NdisQueryPacket(pPkt, NULL, NULL, &pNdisMacHdr, NULL);
  1235. pNdisIpxHdr = NDIS_BUFFER_LINKAGE(pNdisMacHdr);
  1236. if (!fSpx2)
  1237. {
  1238. NdisAdjustBufferLength(pNdisIpxHdr, MIN_IPXSPX_HDRSIZE);
  1239. }
  1240. // Send where data came from
  1241. SpxBuildIpxHdr(
  1242. pIpxSpxHdr,
  1243. hdrLen,
  1244. pSpxConnFile->scf_RemAckAddr,
  1245. pSpxConnFile->scf_AddrFile->saf_Addr->sa_Socket);
  1246. pIpxSpxHdr->hdr_ConnCtrl = (SPX_CC_SYS | (fSpx2 ? SPX_CC_SPX2 : 0));
  1247. pIpxSpxHdr->hdr_DataType = 0;
  1248. PUTSHORT2SHORT(
  1249. &pIpxSpxHdr->hdr_SrcConnId,
  1250. pSpxConnFile->scf_LocalConnId);
  1251. pIpxSpxHdr->hdr_DestConnId = pSpxConnFile->scf_RemConnId;
  1252. PUTSHORT2SHORT(
  1253. &pIpxSpxHdr->hdr_AckNum,
  1254. pSpxConnFile->scf_RecvSeqNum);
  1255. if (fSpx2)
  1256. {
  1257. pIpxSpxHdr->hdr_SeqNum = 0;
  1258. if (fBuildNack)
  1259. {
  1260. PUTSHORT2SHORT(
  1261. &pIpxSpxHdr->hdr_SeqNum,
  1262. NumToResend);
  1263. }
  1264. PUTSHORT2SHORT(
  1265. &pIpxSpxHdr->hdr_NegSize,
  1266. pSpxConnFile->scf_MaxPktSize);
  1267. }
  1268. else
  1269. {
  1270. // Put current send seq number in packet for spx1
  1271. PUTSHORT2SHORT(
  1272. &pIpxSpxHdr->hdr_SeqNum,
  1273. pSpxConnFile->scf_SendSeqNum);
  1274. }
  1275. PUTSHORT2SHORT(
  1276. &pIpxSpxHdr->hdr_AllocNum,
  1277. pSpxConnFile->scf_SentAllocNum);
  1278. pSendResd = (PSPX_SEND_RESD)(pPkt->ProtocolReserved);
  1279. pSendResd->sr_Id = IDENTIFIER_SPX;
  1280. pSendResd->sr_Type = (fBuildNack ? SPX_TYPE_DATANACK : SPX_TYPE_DATAACK);
  1281. pSendResd->sr_Reserved1 = NULL;
  1282. pSendResd->sr_Reserved2 = NULL;
  1283. pSendResd->sr_State = State;
  1284. pSendResd->sr_ConnFile = pSpxConnFile;
  1285. pSendResd->sr_Request = NULL;
  1286. pSendResd->sr_Next = NULL;
  1287. pSendResd->sr_Len = pSendResd->sr_HdrLen = hdrLen;
  1288. *ppPkt = pPkt;
  1289. return;
  1290. }
  1291. VOID
  1292. SpxPktRecvRelease(
  1293. IN PNDIS_PACKET pPkt
  1294. )
  1295. {
  1296. ((PSPX_RECV_RESD)(pPkt->ProtocolReserved))->rr_State = SPX_RECVPKT_IDLE;
  1297. SpxFreeRecvPacket(SpxDevice, pPkt);
  1298. return;
  1299. }
  1300. VOID
  1301. SpxPktSendRelease(
  1302. IN PNDIS_PACKET pPkt
  1303. )
  1304. {
  1305. PNDIS_BUFFER pBuf, pIpxSpxBuf, pFreeBuf;
  1306. UINT bufCount;
  1307. CTEAssert((((PSPX_SEND_RESD)(pPkt->ProtocolReserved))->sr_State &
  1308. SPX_SENDPKT_IPXOWNS) == 0);
  1309. NdisQueryPacket(pPkt, NULL, &bufCount, &pBuf, NULL);
  1310. // BufCount == 1 for only the header. That's ok, we just reset the length
  1311. // and free the packet to the buffer pools. Else we need to free user buffers
  1312. // before that.
  1313. NdisUnchainBufferAtFront(
  1314. pPkt,
  1315. &pBuf);
  1316. NdisUnchainBufferAtFront(
  1317. pPkt,
  1318. &pIpxSpxBuf);
  1319. //
  1320. // Set the header length to the max. that can be needed.
  1321. //
  1322. NdisAdjustBufferLength(pIpxSpxBuf, MIN_IPXSPX2_HDRSIZE);
  1323. while (bufCount-- > 2)
  1324. {
  1325. PBYTE pData;
  1326. ULONG dataLen;
  1327. NdisUnchainBufferAtBack(
  1328. pPkt,
  1329. &pFreeBuf);
  1330. // See if we free data associated with the buffer
  1331. if ((((PSPX_SEND_RESD)(pPkt->ProtocolReserved))->sr_State &
  1332. SPX_SENDPKT_FREEDATA) != 0)
  1333. {
  1334. NdisQueryBuffer(pFreeBuf, &pData, &dataLen);
  1335. CTEAssert(pData != NULL);
  1336. SpxFreeMemory(pData);
  1337. }
  1338. CTEAssert(pFreeBuf != NULL);
  1339. NdisFreeBuffer(pFreeBuf);
  1340. }
  1341. NdisReinitializePacket(pPkt);
  1342. // Initialize elements of the protocol reserved structure.
  1343. ((PSPX_SEND_RESD)(pPkt->ProtocolReserved))->sr_Id = IDENTIFIER_SPX;
  1344. ((PSPX_SEND_RESD)(pPkt->ProtocolReserved))->sr_State = SPX_SENDPKT_IDLE;
  1345. ((PSPX_SEND_RESD)(pPkt->ProtocolReserved))->sr_Reserved1= NULL;
  1346. ((PSPX_SEND_RESD)(pPkt->ProtocolReserved))->sr_Reserved2= NULL;
  1347. NdisChainBufferAtFront(
  1348. pPkt,
  1349. pBuf);
  1350. NdisChainBufferAtBack(
  1351. pPkt,
  1352. pIpxSpxBuf);
  1353. SpxFreeSendPacket(SpxDevice, pPkt);
  1354. return;
  1355. }