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.

2263 lines
74 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. arap.c
  5. Abstract:
  6. This module implements routines specific to ARAP
  7. Author:
  8. Shirish Koti
  9. Revision History:
  10. 15 Nov 1996 Initial Version
  11. --*/
  12. #include <atalk.h>
  13. #pragma hdrstop
  14. #define FILENUM ARAPNDIS
  15. #ifdef ALLOC_PRAGMA
  16. #pragma alloc_text(PAGE_ARAP, ArapRcvIndication)
  17. #pragma alloc_text(PAGE_ARAP, ArapNdisSend)
  18. #pragma alloc_text(PAGE_ARAP, ArapNdisSendComplete)
  19. #pragma alloc_text(PAGE_ARAP, ArapGetNdisPacket)
  20. #endif
  21. //***
  22. //
  23. // Function: ArapRcvIndication
  24. // This routine is called whenever Ndis calls the stack to indicate
  25. // data on a port. We find out our context (pArapConn) from the
  26. // the 'fake' ethernet header that NdisWan cooks up.
  27. //
  28. // Parameters: pArapConn - connection element for whom data has come in
  29. // LkBuf - buffer containing the (most likely, compressed) data
  30. // LkBufSize - size of the lookahead buffer
  31. //
  32. // Return: none
  33. //
  34. // NOTE: NdisWan always gives the entire buffer as the lookahead buffer,
  35. // and we rely on that fact!
  36. //***$
  37. VOID
  38. ArapRcvIndication(
  39. IN PARAPCONN pArapConn,
  40. IN PVOID LkBuf,
  41. IN UINT LkBufSize
  42. )
  43. {
  44. BYTE MnpFrameType;
  45. BYTE SeqNum = (BYTE)-1;
  46. BYTE LastAckRcvd;
  47. BOOLEAN fCopyPacket;
  48. BOOLEAN fValidPkt;
  49. BOOLEAN fMustAck;
  50. PLIST_ENTRY pSendList;
  51. PLIST_ENTRY pRecvList;
  52. PMNPSENDBUF pMnpSendBuf;
  53. PARAPBUF pArapBuf;
  54. PARAPBUF pFirstArapBuf=NULL;
  55. BOOLEAN fLessOrEqual;
  56. BOOLEAN fAcceptPkt;
  57. BOOLEAN fGreater;
  58. DWORD DecompressedDataLen;
  59. DWORD dwDataOffset=0;
  60. DWORD dwFrameOverhead=0;
  61. DWORD dwMaxAcceptableLen;
  62. DWORD StatusCode;
  63. BOOLEAN fSendLNAck=FALSE;
  64. BYTE ClientCredit;
  65. BYTE AttnType;
  66. BYTE LNSeqToAck;
  67. DWORD BufSizeEstimate;
  68. DWORD DecompSize;
  69. DWORD BytesDecompressed;
  70. DWORD BytesToDecompress;
  71. DWORD BytesRemaining;
  72. PBYTE CompressedDataBuf;
  73. BYTE BitMask;
  74. BYTE RelSeq;
  75. DBG_ARAP_CHECK_PAGED_CODE();
  76. DBGDUMPBYTES("ArapRcvInd pkt rcvd: ",LkBuf,LkBufSize,3);
  77. //
  78. // we're at indicate time, so dpc
  79. //
  80. ACQUIRE_SPIN_LOCK_DPC(&pArapConn->SpinLock);
  81. //
  82. // if the connection is going away, drop the packet
  83. //
  84. if ( (pArapConn->State == MNP_IDLE) || (pArapConn->State > MNP_UP) )
  85. {
  86. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  87. ("ArapRcvIndication: invalid state = %d, returning (%lx %lx)\n",
  88. pArapConn,pArapConn->State));
  89. RELEASE_SPIN_LOCK_DPC(&pArapConn->SpinLock);
  90. return;
  91. }
  92. // one more frame came in
  93. pArapConn->StatInfo.FramesRcvd++;
  94. //
  95. // if a dup LR comes in, SynByte, DleByte etc. aren't set yet, and we hit
  96. // this assert. just check to see if we are in MNP_RESPONSE state
  97. //
  98. ASSERT( ((((PUCHAR)LkBuf)[0] == pArapConn->MnpState.SynByte) &&
  99. (((PUCHAR)LkBuf)[1] == pArapConn->MnpState.DleByte) &&
  100. (((PUCHAR)LkBuf)[2] == pArapConn->MnpState.StxByte) &&
  101. (((PUCHAR)LkBuf)[LkBufSize-4] == pArapConn->MnpState.DleByte) &&
  102. (((PUCHAR)LkBuf)[LkBufSize-3] == pArapConn->MnpState.EtxByte)) ||
  103. (pArapConn->State == MNP_RESPONSE) );
  104. ARAP_DBG_TRACE(pArapConn,30105,LkBuf,LkBufSize,0,0);
  105. // we just heard from the client: "reset" the inactivity timer
  106. pArapConn->InactivityTimer = pArapConn->T403Duration + AtalkGetCurrentTick();
  107. MnpFrameType = ((PUCHAR)LkBuf)[MNP_FRMTYPE_OFFSET];
  108. if ( MnpFrameType == MNP_LT_V20CLIENT )
  109. {
  110. MnpFrameType = (BYTE)MNP_LT;
  111. }
  112. fCopyPacket = FALSE;
  113. fValidPkt = TRUE;
  114. fMustAck = FALSE;
  115. dwDataOffset = 3; // at the least, we'll ignore the 3 start flag bytes
  116. dwFrameOverhead = 7; // at the least, ignore 3 start, 2 stop, 2 crc bytes
  117. switch(MnpFrameType)
  118. {
  119. //
  120. // if this is a duplicate LT frame, don't waste time decompressing and
  121. // copying (also, make sure we have room to accept this packet!)
  122. //
  123. case MNP_LT:
  124. fValidPkt = FALSE;
  125. if (LkBufSize < (UINT)LT_MIN_LENGTH(pArapConn))
  126. {
  127. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  128. ("ArapRcv: (%lx) LT pkt, but length invalid: dropping!\n",pArapConn));
  129. ASSERT(0);
  130. break;
  131. }
  132. SeqNum = LT_SEQ_NUM((PBYTE)LkBuf, pArapConn);
  133. MNP_DBG_TRACE(pArapConn,SeqNum,(0x10|MNP_LT));
  134. dwMaxAcceptableLen = (pArapConn->BlockId == BLKID_MNP_SMSENDBUF) ?
  135. MNP_MINPKT_SIZE : MNP_MAXPKT_SIZE;
  136. if ((pArapConn->State == MNP_UP) &&
  137. (pArapConn->MnpState.RecvCredit > 0) )
  138. {
  139. LT_OK_TO_ACCEPT(SeqNum, pArapConn, fAcceptPkt);
  140. if (fAcceptPkt)
  141. {
  142. fCopyPacket = TRUE;
  143. fValidPkt = TRUE;
  144. dwDataOffset = LT_SRP_OFFSET(pArapConn);
  145. dwFrameOverhead = LT_OVERHEAD(pArapConn);
  146. // make sure the packet isn't too big (in other words,invalid!)
  147. if (LkBufSize-dwFrameOverhead > dwMaxAcceptableLen)
  148. {
  149. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  150. ("ArapInd: (%lx) too big a pkt (%d vs %d), dropped\n",
  151. pArapConn,LkBufSize-dwFrameOverhead,dwMaxAcceptableLen));
  152. fValidPkt = FALSE;
  153. }
  154. pArapConn->MnpState.HoleInSeq = FALSE;
  155. }
  156. else
  157. {
  158. //
  159. // packet is valid, just not in the right sequence (make note
  160. // of that or else we'll send out an ack!)
  161. //
  162. fValidPkt = TRUE;
  163. //
  164. // did we get an out-of-sequence packet (e.g. we lost B5,
  165. // so we're still expecting B5 but B6 came in)
  166. //
  167. LT_GREATER_THAN(SeqNum,
  168. pArapConn->MnpState.NextToReceive,
  169. fGreater);
  170. if (fGreater)
  171. {
  172. //
  173. // we have already sent an ack out when we first got
  174. // this hole: don't send ack again
  175. //
  176. if (pArapConn->MnpState.HoleInSeq)
  177. {
  178. fMustAck = FALSE;
  179. }
  180. else
  181. {
  182. pArapConn->MnpState.HoleInSeq = TRUE;
  183. fMustAck = TRUE;
  184. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_INFO,
  185. ("ArapRcvInd: (%lx) got a hole, dropping seq=%x vs. %x\n",
  186. pArapConn, SeqNum, pArapConn->MnpState.NextToReceive));
  187. }
  188. break;
  189. }
  190. //
  191. // spec says that we must ignore the first duplicate of any
  192. // seq. What happens most often when we receive a duplicate is
  193. // that the Mac sends the whole window full of dups. e.g. if
  194. // seq num B1 is retransmitted then Mac will also retransmit
  195. // B2, .. B8. We should ignore all of them, but if we get B1
  196. // (or anything upto B8) again, then we must send out an ack.
  197. //
  198. //
  199. // is this the first time (since we successfully received a
  200. // new frame) that we are getting a dup? If so, we must find
  201. // out what's the smallest seq number we can get as a dup
  202. //
  203. if (!pArapConn->MnpState.ReceivingDup)
  204. {
  205. //
  206. // e.g. if we're expecting seq 79 then 0x71 is the
  207. // smallest dup that we can get (for window size = 8)
  208. //
  209. if (pArapConn->MnpState.NextToReceive >=
  210. pArapConn->MnpState.WindowSize)
  211. {
  212. pArapConn->MnpState.FirstDupSeq =
  213. (pArapConn->MnpState.NextToReceive -
  214. pArapConn->MnpState.WindowSize);
  215. }
  216. //
  217. // e.g. if we're expecting seq 3 then 0xfb is the
  218. // smallest dup that we can get (for window size = 8)
  219. //
  220. else
  221. {
  222. pArapConn->MnpState.FirstDupSeq =
  223. (0xff -
  224. (pArapConn->MnpState.WindowSize -
  225. pArapConn->MnpState.NextToReceive) +
  226. 1);
  227. }
  228. pArapConn->MnpState.ReceivingDup = TRUE;
  229. pArapConn->MnpState.DupSeqBitMap = 0;
  230. RelSeq = 0;
  231. }
  232. //
  233. // find the relative seq number (relative to the first dup)
  234. //
  235. if (SeqNum >= pArapConn->MnpState.FirstDupSeq)
  236. {
  237. RelSeq = (SeqNum - pArapConn->MnpState.FirstDupSeq);
  238. }
  239. else
  240. {
  241. RelSeq = (0xff - pArapConn->MnpState.FirstDupSeq) +
  242. SeqNum;
  243. }
  244. //
  245. // 8-frame window: relseq can be 0 through 7
  246. //
  247. if (RelSeq >= 8)
  248. {
  249. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  250. ("ArapRcvInd: (%lx) RelSeq > 8!! (%x %x %x)\n",
  251. pArapConn, SeqNum, pArapConn->MnpState.FirstDupSeq,
  252. pArapConn->MnpState.DupSeqBitMap));
  253. fMustAck = TRUE;
  254. break;
  255. }
  256. BitMask = (1 << RelSeq);
  257. //
  258. // is this a second (or more) retransmission of this seq num?
  259. //
  260. if (pArapConn->MnpState.DupSeqBitMap & BitMask)
  261. {
  262. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_INFO,
  263. ("ArapRcvInd: (%lx) dup pkt, seq=%x vs. %x (%x)\n",
  264. pArapConn, SeqNum, pArapConn->MnpState.FirstDupSeq,
  265. pArapConn->MnpState.DupSeqBitMap));
  266. fMustAck = TRUE;
  267. }
  268. //
  269. // no, this is the first time: don't send out an ack
  270. //
  271. else
  272. {
  273. pArapConn->MnpState.DupSeqBitMap |= BitMask;
  274. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_INFO,
  275. ("ArapRcvInd: (%lx) first dup pkt, seq=%x vs. %x (%x)\n",
  276. pArapConn, SeqNum, pArapConn->MnpState.FirstDupSeq,
  277. pArapConn->MnpState.DupSeqBitMap));
  278. }
  279. }
  280. }
  281. else
  282. {
  283. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  284. ("ArapInd: (%lx) pkt dropped (state %ld, credit %ld)\n",
  285. pArapConn,pArapConn->State,pArapConn->MnpState.RecvCredit));
  286. }
  287. break;
  288. //
  289. // we got an ACK: process it
  290. //
  291. case MNP_LA:
  292. if (LkBufSize < (UINT)LA_MIN_LENGTH(pArapConn))
  293. {
  294. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  295. ("ArapRcv: (%lx) LA pkt, but length invalid: dropping!\n",pArapConn));
  296. ASSERT(0);
  297. break;
  298. }
  299. // client's receive credit (it's our send credit)
  300. ClientCredit = LA_CREDIT((PBYTE)LkBuf, pArapConn);
  301. ASSERT((pArapConn->State == MNP_UP) || (pArapConn->State == MNP_RESPONSE));
  302. // last pkt the client recvd successfully from us
  303. LastAckRcvd = LA_SEQ_NUM((PBYTE)LkBuf, pArapConn);
  304. MNP_DBG_TRACE(pArapConn,LastAckRcvd,(0x10|MNP_LA));
  305. //
  306. // in the normal case, the ack we got should be for a bigger seq num
  307. // than the one we got earlier.
  308. // (special case the MNP_RESPONSE state to complete conn setup)
  309. //
  310. LT_GREATER_THAN(LastAckRcvd,pArapConn->MnpState.LastAckRcvd,fGreater);
  311. if (fGreater || (pArapConn->State == MNP_RESPONSE))
  312. {
  313. pArapConn->MnpState.LastAckRcvd = LastAckRcvd;
  314. //
  315. // remove all the sends upto and including LastAckRcvd and put
  316. // them on SendAckedQ so that RcvCompletion can finish up the job
  317. //
  318. ASSERT(!IsListEmpty(&pArapConn->RetransmitQ));
  319. ASSERT(pArapConn->SendsPending > 0);
  320. //
  321. // if we sent a response to LR and were waiting for client's
  322. // ack, this is it! (RcvCompletion will do the remaining work)
  323. //
  324. if (pArapConn->State == MNP_RESPONSE)
  325. {
  326. pArapConn->State = MNP_UP;
  327. pArapConn->MnpState.NextToReceive = 1;
  328. pArapConn->MnpState.NextToProcess = 1;
  329. pArapConn->MnpState.NextToSend = 1;
  330. pArapConn->FlowControlTimer = AtalkGetCurrentTick() +
  331. pArapConn->T404Duration;
  332. }
  333. //
  334. // remove all the sends that are now acked with this ack from the
  335. // retransmit queue
  336. //
  337. while (1)
  338. {
  339. pSendList = pArapConn->RetransmitQ.Flink;
  340. // no more sends left on the retransmit queue? if so, done
  341. if (pSendList == &pArapConn->RetransmitQ)
  342. {
  343. break;
  344. }
  345. pMnpSendBuf = CONTAINING_RECORD(pSendList,MNPSENDBUF,Linkage);
  346. LT_LESS_OR_EQUAL(pMnpSendBuf->SeqNum,LastAckRcvd,fLessOrEqual);
  347. if (fLessOrEqual)
  348. {
  349. ASSERT(pArapConn->SendsPending >= pMnpSendBuf->DataSize);
  350. RemoveEntryList(&pMnpSendBuf->Linkage);
  351. InsertTailList(&pArapConn->SendAckedQ,
  352. &pMnpSendBuf->Linkage);
  353. ASSERT(pArapConn->MnpState.UnAckedSends >= 1);
  354. pArapConn->MnpState.UnAckedSends--;
  355. }
  356. else
  357. {
  358. // all other sends have higher seq nums: done here
  359. break;
  360. }
  361. }
  362. //
  363. // if we were in the retransmit mode and the retransmit Q is
  364. // now empty, get out of retransmit mode!
  365. //
  366. if (pArapConn->MnpState.RetransmitMode)
  367. {
  368. if (pArapConn->MnpState.UnAckedSends == 0)
  369. {
  370. pArapConn->MnpState.RetransmitMode = FALSE;
  371. pArapConn->MnpState.MustRetransmit = FALSE;
  372. // in case we had gone on a "exponential backoff", reset it
  373. pArapConn->SendRetryTime = pArapConn->SendRetryBaseTime;
  374. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_INFO,
  375. ("ArapRcvInd: ack %x for xmitted pkt, out of re-xmit mode\n",
  376. LastAckRcvd));
  377. }
  378. else
  379. {
  380. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_INFO,
  381. ("ArapRcvInd: ack %x for xmitted pkt, still %d more\n",
  382. LastAckRcvd,pArapConn->MnpState.UnAckedSends));
  383. pArapConn->MnpState.MustRetransmit = TRUE;
  384. }
  385. }
  386. }
  387. //
  388. // the ack we got is for the same seq num as we got earlier: we need
  389. // to retransmit the send we were hoping this ack was for!
  390. //
  391. else
  392. {
  393. if (!IsListEmpty(&pArapConn->RetransmitQ))
  394. {
  395. pArapConn->MnpState.RetransmitMode = TRUE;
  396. pArapConn->MnpState.MustRetransmit = TRUE;
  397. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_INFO,
  398. ("\nArapRcvInd: ack %x again, (%d pkts) entering re-xmit mode\n",
  399. LastAckRcvd,pArapConn->MnpState.UnAckedSends));
  400. }
  401. }
  402. ASSERT(pArapConn->MnpState.UnAckedSends <= pArapConn->MnpState.WindowSize);
  403. //
  404. // spec says our credit is what the client tells us minus the number
  405. // of unacked sends on our Q.
  406. //
  407. //
  408. if (ClientCredit > pArapConn->MnpState.UnAckedSends)
  409. {
  410. ASSERT((ClientCredit - pArapConn->MnpState.UnAckedSends) <= pArapConn->MnpState.WindowSize);
  411. pArapConn->MnpState.SendCredit =
  412. (ClientCredit - pArapConn->MnpState.UnAckedSends);
  413. }
  414. //
  415. // But if the client tells us say 3 and we have 4 sends pending,
  416. // be conservative and close the window until sends get cleared up
  417. //
  418. else
  419. {
  420. pArapConn->MnpState.SendCredit = 0;
  421. }
  422. break;
  423. //
  424. // if we sent an LR response, this must be a retry by client: retransmit
  425. // our response. If we sent in the request (in case of callback) then
  426. // this is the response: send the ack
  427. //
  428. case MNP_LR:
  429. MNP_DBG_TRACE(pArapConn,0,(0x10|MNP_LR));
  430. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  431. ("ArapRcvInd: got LR pkt on %lx, state=%d\n",
  432. pArapConn,pArapConn->State));
  433. if (pArapConn->State == MNP_RESPONSE)
  434. {
  435. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  436. ("ArapRcvInd: excuse me? got an LR! (setting reX)\n"));
  437. pArapConn->MnpState.RetransmitMode = TRUE;
  438. pArapConn->MnpState.MustRetransmit = TRUE;
  439. }
  440. else if (pArapConn->State == MNP_REQUEST)
  441. {
  442. //
  443. // we got an LR response to our LR request (we are doing callback)
  444. // Make sure all the parms that the dial-in client gives are ok
  445. // with us, and configure pArapConn appropriately
  446. //
  447. StatusCode = PrepareConnectionResponse( pArapConn,
  448. LkBuf,
  449. LkBufSize,
  450. NULL,
  451. NULL);
  452. if (StatusCode == ARAPERR_NO_ERROR)
  453. {
  454. pArapConn->State = MNP_UP;
  455. pArapConn->MnpState.NextToReceive = 1;
  456. pArapConn->MnpState.NextToProcess = 1;
  457. pArapConn->MnpState.NextToSend = 1;
  458. pArapConn->FlowControlTimer = AtalkGetCurrentTick() +
  459. pArapConn->T404Duration;
  460. pSendList = pArapConn->RetransmitQ.Flink;
  461. // treat the connection request as a send here
  462. if (pSendList != &pArapConn->RetransmitQ)
  463. {
  464. pMnpSendBuf = CONTAINING_RECORD(pSendList,
  465. MNPSENDBUF,
  466. Linkage);
  467. RemoveEntryList(&pMnpSendBuf->Linkage);
  468. InsertTailList(&pArapConn->SendAckedQ,
  469. &pMnpSendBuf->Linkage);
  470. ASSERT(pArapConn->MnpState.UnAckedSends >= 1);
  471. pArapConn->MnpState.UnAckedSends--;
  472. }
  473. else
  474. {
  475. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  476. ("ArapRcvInd: (%lx) can't find LR request\n",pArapConn));
  477. ASSERT(0);
  478. }
  479. fMustAck = TRUE;
  480. }
  481. else
  482. {
  483. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  484. ("ArapRcvInd: (%lx) invalid LR response %ld\n",
  485. pArapConn,StatusCode));
  486. }
  487. }
  488. else
  489. {
  490. fValidPkt = FALSE;
  491. }
  492. break;
  493. //
  494. // remote sent a disconnect request. Though we'll process it at
  495. // RcvCompletion time, mark it so that we don't attempt send/recv anymore
  496. //
  497. case MNP_LD:
  498. MNP_DBG_TRACE(pArapConn,0,(0x10|MNP_LD));
  499. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  500. ("ArapRcvIndication: recvd disconnect from remote on (%lx)\n",pArapConn));
  501. pArapConn->State = MNP_RDISC_RCVD;
  502. fCopyPacket = TRUE;
  503. break;
  504. //
  505. // remote sent a Link Attention request. See what we need to do
  506. //
  507. case MNP_LN:
  508. if (LkBufSize < (dwDataOffset+LN_MIN_LENGTH))
  509. {
  510. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  511. ("ArapRcv: (%lx) LN pkt, but length invalid: dropping!\n",pArapConn));
  512. ASSERT(0);
  513. break;
  514. }
  515. MNP_DBG_TRACE(pArapConn,0,(0x10|MNP_LN));
  516. AttnType = LN_ATTN_TYPE((PBYTE)LkBuf+dwDataOffset);
  517. LNSeqToAck = LN_ATTN_SEQ((PBYTE)LkBuf+dwDataOffset);
  518. //
  519. // is this a destructive type LN frame? Treat this as a LD frame so
  520. // that we disconnect and cleanup the connection
  521. //
  522. if (AttnType == LN_DESTRUCTIVE)
  523. {
  524. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  525. ("ArapRcv: (%lx) got an LN pkt, sending LNAck!\n",pArapConn));
  526. pArapConn->State = MNP_RDISC_RCVD;
  527. }
  528. //
  529. // ok, he just wants to know if we are doing ok: tell him so
  530. //
  531. else
  532. {
  533. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  534. ("ArapRcv: (%lx) got an LN pkt, sending LNAck!\n",pArapConn));
  535. fSendLNAck = TRUE;
  536. }
  537. break;
  538. //
  539. // we only ack an LN packet, but never generate an LN packet
  540. // so we should never get this LNA packet. Quietly drop it.
  541. //
  542. case MNP_LNA:
  543. MNP_DBG_TRACE(pArapConn,0,(0x10|MNP_LNA));
  544. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  545. ("ArapRcv: (%lx) got LNA. Now, when did we send LN??\n",pArapConn));
  546. break;
  547. default:
  548. MNP_DBG_TRACE(pArapConn,0,MnpFrameType);
  549. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  550. ("ArapRcvIndication: (%lx) dropping packet with unknown type %d\n",
  551. pArapConn,MnpFrameType));
  552. break;
  553. }
  554. //
  555. // if it's a packet that we don't need to copy (e.g. ack) then we're done here.
  556. // Also, if it's an invalid pkt (e.g. out of seq packet) then we must send an ack
  557. //
  558. if ((!fCopyPacket) || (!fValidPkt))
  559. {
  560. RELEASE_SPIN_LOCK_DPC(&pArapConn->SpinLock)
  561. //
  562. // if we got an invalid packet or if we have a condition where we must ack,
  563. // do the needful
  564. //
  565. if (!fValidPkt || fMustAck)
  566. {
  567. MnpSendAckIfReqd(pArapConn, TRUE);
  568. }
  569. else if (fSendLNAck)
  570. {
  571. MnpSendLNAck(pArapConn, LNSeqToAck);
  572. }
  573. return;
  574. }
  575. //
  576. // if it's not an LT packet, treat it separately
  577. //
  578. if (MnpFrameType != MNP_LT)
  579. {
  580. // right now LD is the only packet we put on the Misc Q
  581. ASSERT(MnpFrameType == MNP_LD);
  582. ARAP_GET_RIGHTSIZE_RCVBUF((LkBufSize-dwFrameOverhead), &pArapBuf);
  583. if (pArapBuf == NULL)
  584. {
  585. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  586. ("ArapInd: (%lx) alloc failed, dropping packet (type=%x, seq=%x)\n",
  587. pArapConn,MnpFrameType,SeqNum));
  588. RELEASE_SPIN_LOCK_DPC(&pArapConn->SpinLock)
  589. return;
  590. }
  591. TdiCopyLookaheadData( &pArapBuf->Buffer[0],
  592. (PUCHAR)LkBuf+dwDataOffset,
  593. LkBufSize-dwFrameOverhead,
  594. TDI_RECEIVE_COPY_LOOKAHEAD);
  595. pArapBuf->MnpFrameType = MnpFrameType;
  596. pArapBuf->DataSize = (USHORT)(LkBufSize-dwFrameOverhead);
  597. InsertTailList(&pArapConn->MiscPktsQ, &pArapBuf->Linkage);
  598. RELEASE_SPIN_LOCK_DPC(&pArapConn->SpinLock)
  599. return;
  600. }
  601. //
  602. // ok, we're dealing with the LT packet (the most common packet)
  603. //
  604. // reset the flow control timer
  605. pArapConn->FlowControlTimer = AtalkGetCurrentTick() + pArapConn->T404Duration;
  606. // update the receive state...
  607. ASSERT(pArapConn->MnpState.UnAckedRecvs <= pArapConn->MnpState.WindowSize);
  608. pArapConn->MnpState.UnAckedRecvs++;
  609. // set LastSeqRcvd to what we received successfully just now
  610. pArapConn->MnpState.LastSeqRcvd = pArapConn->MnpState.NextToReceive;
  611. // successfully rcvd the expected packet. Update to next expected
  612. ADD_ONE(pArapConn->MnpState.NextToReceive);
  613. //
  614. // if the 402 timer isn't already "running", "start" it
  615. // Also, shut the flow-control timer: starting T402 timer here will ensure
  616. // that ack goes out, and at that time we'll restart the flow-control timer
  617. //
  618. if (pArapConn->LATimer == 0)
  619. {
  620. pArapConn->LATimer = pArapConn->T402Duration + AtalkGetCurrentTick();
  621. pArapConn->FlowControlTimer = 0;
  622. }
  623. //
  624. // 0-length data is not permissible
  625. // (for some reason, Mac sends a 0-datalength frame: for now, we'll
  626. // "accept" the frame, though we can't do anything with it!)
  627. //
  628. if ((LkBufSize-dwFrameOverhead) == 0)
  629. {
  630. ARAP_DBG_TRACE(pArapConn,30106,LkBuf,LkBufSize,0,0);
  631. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_INFO,
  632. ("ArapInd: (%lx) is the client on drugs? it's sending 0-len data!\n",pArapConn));
  633. RELEASE_SPIN_LOCK_DPC(&pArapConn->SpinLock)
  634. return;
  635. }
  636. pFirstArapBuf = NULL;
  637. BytesToDecompress = (DWORD)LkBufSize-dwFrameOverhead;
  638. CompressedDataBuf = (PUCHAR)LkBuf+dwDataOffset;
  639. DecompressedDataLen = 0;
  640. //
  641. // for now, assume decompressed data will be 4 times the compressed size
  642. // (if that assumption isn't true, we'll alloc more again)
  643. //
  644. BufSizeEstimate = (BytesToDecompress << 2);
  645. if (!(pArapConn->Flags & MNP_V42BIS_NEGOTIATED))
  646. {
  647. BufSizeEstimate = BytesToDecompress;
  648. }
  649. while (1)
  650. {
  651. // get a receive buffer for this size
  652. ARAP_GET_RIGHTSIZE_RCVBUF(BufSizeEstimate, &pArapBuf);
  653. if (pArapBuf == NULL)
  654. {
  655. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  656. ("ArapInd: (%lx) %d bytes alloc failed, dropping seq=%x\n",
  657. pArapConn,BufSizeEstimate,SeqNum));
  658. //
  659. // if we put any stuff on the queue for this MNP packet, remove
  660. // them all: we can't have a partially decompressed packet!
  661. //
  662. if (pFirstArapBuf)
  663. {
  664. pRecvList = &pFirstArapBuf->Linkage;
  665. while (pRecvList != &pArapConn->ReceiveQ)
  666. {
  667. RemoveEntryList(pRecvList);
  668. pArapBuf = CONTAINING_RECORD(pRecvList,ARAPBUF,Linkage);
  669. ARAP_FREE_RCVBUF(pArapBuf);
  670. pRecvList = pRecvList->Flink;
  671. }
  672. }
  673. RELEASE_SPIN_LOCK_DPC(&pArapConn->SpinLock)
  674. // force ack so the client gets a hint that we dropped a pkt
  675. MnpSendAckIfReqd(pArapConn, TRUE);
  676. return;
  677. }
  678. if (!pFirstArapBuf)
  679. {
  680. pFirstArapBuf = pArapBuf;
  681. }
  682. //
  683. // ok, do that v42bis decompression thing if v42bis is negotiated
  684. //
  685. if (pArapConn->Flags & MNP_V42BIS_NEGOTIATED)
  686. {
  687. StatusCode = v42bisDecompress(
  688. pArapConn,
  689. CompressedDataBuf,
  690. BytesToDecompress,
  691. pArapBuf->CurrentBuffer,
  692. pArapBuf->BufferSize,
  693. &BytesRemaining,
  694. &DecompSize);
  695. }
  696. //
  697. // v42bis is not negotiated: skip decompression
  698. //
  699. else
  700. {
  701. if (BytesToDecompress)
  702. {
  703. TdiCopyLookaheadData( &pArapBuf->Buffer[0],
  704. (PUCHAR)LkBuf+dwDataOffset,
  705. BytesToDecompress,
  706. TDI_RECEIVE_COPY_LOOKAHEAD);
  707. }
  708. DecompSize = BytesToDecompress;
  709. StatusCode = ARAPERR_NO_ERROR;
  710. }
  711. ASSERT((StatusCode == ARAPERR_NO_ERROR) ||
  712. (StatusCode == ARAPERR_BUF_TOO_SMALL));
  713. if ((StatusCode != ARAPERR_NO_ERROR) &&
  714. (StatusCode != ARAPERR_BUF_TOO_SMALL))
  715. {
  716. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  717. ("ArapInd: (%lx) v42bisDecompress returned %lx, dropping pkt\n",
  718. pArapConn,StatusCode));
  719. ASSERT(0);
  720. RELEASE_SPIN_LOCK_DPC(&pArapConn->SpinLock)
  721. // force ack so the client gets a hint that we dropped a pkt
  722. MnpSendAckIfReqd(pArapConn, TRUE);
  723. return;
  724. }
  725. //
  726. // if we got any bytes decompressed, put them on the queue
  727. //
  728. if (DecompSize > 0)
  729. {
  730. ASSERT(pArapBuf->BufferSize >= DecompSize);
  731. pArapBuf->DataSize = (USHORT)DecompSize;
  732. // Debug only: make sure q looks ok before we put this stuff on the q
  733. ARAP_CHECK_RCVQ_INTEGRITY(pArapConn);
  734. // queue these bytes on to the ReceiveQ
  735. InsertTailList(&pArapConn->ReceiveQ, &pArapBuf->Linkage);
  736. // Debug only: make sure q looks ok after we put this stuff on the q
  737. ARAP_CHECK_RCVQ_INTEGRITY(pArapConn);
  738. }
  739. DecompressedDataLen += DecompSize;
  740. // are we done decompressing?
  741. if (StatusCode == ARAPERR_NO_ERROR)
  742. {
  743. //
  744. // if there was no output data and there was no error, we didn't
  745. // really need this buffer.
  746. //
  747. if (DecompSize == 0)
  748. {
  749. ARAP_FREE_RCVBUF(pArapBuf);
  750. }
  751. break;
  752. }
  753. //
  754. // ok, we're here because our assumption about how big a buffer we
  755. // needed for decompression wasn't quite right: we must decompress the
  756. // remaining bytes now
  757. //
  758. BytesDecompressed = (BytesToDecompress - BytesRemaining);
  759. BytesToDecompress = BytesRemaining;
  760. CompressedDataBuf += BytesDecompressed;
  761. //
  762. // we ran out of room:double our initial estimate
  763. //
  764. BufSizeEstimate <<= 1;
  765. }
  766. ARAP_DBG_TRACE(pArapConn,30110,pFirstArapBuf,DecompressedDataLen,0,0);
  767. // update statitics on incoming bytes:
  768. pArapConn->StatInfo.BytesRcvd += (DWORD)LkBufSize;
  769. pArapConn->StatInfo.BytesReceivedCompressed += ((DWORD)LkBufSize-dwFrameOverhead);
  770. pArapConn->StatInfo.BytesReceivedUncompressed += DecompressedDataLen;
  771. #if DBG
  772. ArapStatistics.RecvPostDecompMax =
  773. (DecompressedDataLen > ArapStatistics.RecvPostDecompMax)?
  774. DecompressedDataLen : ArapStatistics.RecvPostDecompMax;
  775. ArapStatistics.RecvPostDecomMin =
  776. (DecompressedDataLen < ArapStatistics.RecvPostDecomMin)?
  777. DecompressedDataLen : ArapStatistics.RecvPostDecomMin;
  778. #endif
  779. // we successfully received a brand new packet, so we aren't getting dup's
  780. pArapConn->MnpState.ReceivingDup = FALSE;
  781. // we have these many bytes more waiting to be processed
  782. pArapConn->RecvsPending += DecompressedDataLen;
  783. ARAP_ADJUST_RECVCREDIT(pArapConn);
  784. RELEASE_SPIN_LOCK_DPC(&pArapConn->SpinLock);
  785. // see if ack needs to be sent for the packet we just received
  786. MnpSendAckIfReqd(pArapConn, FALSE);
  787. }
  788. //***
  789. //
  790. // Function: ArapRcvComplete
  791. // This is the RcvComplete routine for the Arap port.
  792. // We look through all the clients on this port (i.e. all the
  793. // Arap clients) to see who needs work done, and finish it.
  794. //
  795. // Parameters: none
  796. //
  797. // Return: none
  798. //
  799. //***$
  800. VOID
  801. ArapRcvComplete(
  802. IN VOID
  803. )
  804. {
  805. PARAPCONN pArapConn;
  806. PARAPCONN pPrevArapConn;
  807. PLIST_ENTRY pConnList;
  808. PLIST_ENTRY pSendAckedList;
  809. PLIST_ENTRY pList;
  810. KIRQL OldIrql;
  811. BOOLEAN fRetransmitting;
  812. BOOLEAN fReceiveQEmpty;
  813. PMNPSENDBUF pMnpSendBuf=NULL;
  814. PMNPSENDBUF pRetransmitBuf=NULL;
  815. PARAPBUF pArapBuf=NULL;
  816. DWORD BytesProcessed=0;
  817. BOOLEAN fArapDataWaiting;
  818. BOOLEAN fArapConnUp=FALSE;
  819. //
  820. // walk through all the Arap clients to see if anyone has data to be
  821. // processed.
  822. // Start from the head of the list
  823. // 1 if the connection state is not ok, try the next connection
  824. // else up the refcount (to make sure it stays around until we're done)
  825. // 2 see if we need to disconnect: if yes, do so and move on
  826. // 3 see if retransmits are needed
  827. // 4 see if ack needs to be sent
  828. // 5 see if any sends need to be completed
  829. // 6 see if any receives need to be completed
  830. // 7 Find the next connection which we will move to next
  831. // 8 remove the refcount on the previous connection that we put in step 1
  832. //
  833. pArapConn = NULL;
  834. pPrevArapConn = NULL;
  835. while (1)
  836. {
  837. ACQUIRE_SPIN_LOCK(&RasPortDesc->pd_Lock, &OldIrql);
  838. //
  839. // first, let's find the right connection to work on
  840. //
  841. while (1)
  842. {
  843. // if we're in the middle of the list, get to the next guy
  844. if (pArapConn != NULL)
  845. {
  846. pConnList = pArapConn->Linkage.Flink;
  847. }
  848. // we're just starting: get the guy at the head of the list
  849. else
  850. {
  851. pConnList = RasPortDesc->pd_ArapConnHead.Flink;
  852. }
  853. // finished all?
  854. if (pConnList == &RasPortDesc->pd_ArapConnHead)
  855. {
  856. RELEASE_SPIN_LOCK(&RasPortDesc->pd_Lock, OldIrql);
  857. if (pPrevArapConn)
  858. {
  859. DerefArapConn(pPrevArapConn);
  860. }
  861. return;
  862. }
  863. pArapConn = CONTAINING_RECORD(pConnList, ARAPCONN, Linkage);
  864. // make sure this connection needs rcv processing
  865. ACQUIRE_SPIN_LOCK_DPC(&pArapConn->SpinLock);
  866. //
  867. // if this connection is being disconnected, skip it (unless we
  868. // just received disconnect from remote, in which case we need to
  869. // process that)
  870. //
  871. if ((pArapConn->State >= MNP_LDISCONNECTING) &&
  872. (pArapConn->State != MNP_RDISC_RCVD))
  873. {
  874. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_INFO,
  875. ("ArapRcvComplete: (%lx) invalid state %d, no rcv processing done\n",
  876. pArapConn,pArapConn->State));
  877. RELEASE_SPIN_LOCK_DPC(&pArapConn->SpinLock);
  878. // go try the next connection
  879. continue;
  880. }
  881. // let's make sure this connection stays around till we finish
  882. pArapConn->RefCount++;
  883. RELEASE_SPIN_LOCK_DPC(&pArapConn->SpinLock);
  884. break;
  885. }
  886. RELEASE_SPIN_LOCK(&RasPortDesc->pd_Lock, OldIrql);
  887. //
  888. // remove the refcount on the previous connection we put in for the Rcv
  889. //
  890. if (pPrevArapConn)
  891. {
  892. DerefArapConn(pPrevArapConn);
  893. }
  894. ASSERT(pPrevArapConn != pArapConn);
  895. pPrevArapConn = pArapConn;
  896. fRetransmitting = FALSE;
  897. fArapConnUp = FALSE;
  898. // if our sniff buffer has enough bytes, give them to dll and make room
  899. ARAP_DUMP_DBG_TRACE(pArapConn);
  900. ACQUIRE_SPIN_LOCK(&pArapConn->SpinLock, &OldIrql);
  901. //
  902. // if we got a disconnect from remote (LD frame), we have cleanup to do
  903. //
  904. if (pArapConn->State == MNP_RDISC_RCVD)
  905. {
  906. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  907. ("ArapRcvComplete: (%lx) disconnect rcvd from remote, calling cleanup\n",
  908. pArapConn));
  909. pArapConn->State = MNP_RDISCONNECTING;
  910. RELEASE_SPIN_LOCK(&pArapConn->SpinLock, OldIrql);
  911. ArapCleanup(pArapConn);
  912. // go process the next connection
  913. continue;
  914. }
  915. //
  916. // do we need to retransmit the sends queued up on the retransmit Q?
  917. //
  918. if (pArapConn->MnpState.MustRetransmit)
  919. {
  920. pList = pArapConn->RetransmitQ.Flink;
  921. if (pList != &pArapConn->RetransmitQ)
  922. {
  923. pRetransmitBuf = CONTAINING_RECORD(pList, MNPSENDBUF, Linkage);
  924. fRetransmitting = TRUE;
  925. if (pRetransmitBuf->RetryCount >= ARAP_MAX_RETRANSMITS)
  926. {
  927. RemoveEntryList(&pRetransmitBuf->Linkage);
  928. ASSERT(pArapConn->MnpState.UnAckedSends >= 1);
  929. // not really important, since we're about to disconnect!
  930. pArapConn->MnpState.UnAckedSends--;
  931. ASSERT(pArapConn->SendsPending >= pRetransmitBuf->DataSize);
  932. #if DBG
  933. InitializeListHead(&pRetransmitBuf->Linkage);
  934. #endif
  935. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  936. ("ArapRcvComplete: (%lx) too many retransmits (%lx). Killing %lx\n",
  937. pRetransmitBuf,pArapConn));
  938. RELEASE_SPIN_LOCK(&pArapConn->SpinLock, OldIrql);
  939. (pRetransmitBuf->ComplRoutine)(pRetransmitBuf,ARAPERR_SEND_FAILED);
  940. continue;
  941. }
  942. }
  943. }
  944. //
  945. // See if any sends can be completed as a result of an ack coming in
  946. // (now that we have the spinlock, move the list away and mark the list as
  947. // empty before we release the lock. Idea is to avoid grab-release-grab..
  948. // of spinlock as we complete all the sends).
  949. //
  950. pSendAckedList = pArapConn->SendAckedQ.Flink;
  951. InitializeListHead(&pArapConn->SendAckedQ);
  952. // is ARAP connection up yet? we'll use this fact very soon...
  953. if (pArapConn->Flags & ARAP_CONNECTION_UP)
  954. {
  955. fArapConnUp = TRUE;
  956. }
  957. RELEASE_SPIN_LOCK(&pArapConn->SpinLock, OldIrql);
  958. //
  959. // next, handle any retransmissions if needed
  960. //
  961. if (fRetransmitting)
  962. {
  963. ArapNdisSend(pArapConn, &pArapConn->RetransmitQ);
  964. }
  965. //
  966. // next, complete all our sends for which we received ack(s)
  967. //
  968. while (pSendAckedList != &pArapConn->SendAckedQ)
  969. {
  970. pMnpSendBuf = CONTAINING_RECORD(pSendAckedList,MNPSENDBUF,Linkage);
  971. pSendAckedList = pSendAckedList->Flink;
  972. InitializeListHead(&pMnpSendBuf->Linkage);
  973. //
  974. // call the completion routine for this send buffer
  975. //
  976. (pMnpSendBuf->ComplRoutine)(pMnpSendBuf,ARAPERR_NO_ERROR);
  977. }
  978. // see if ack needs to be sent, for any packets we received
  979. MnpSendAckIfReqd(pArapConn, FALSE);
  980. //
  981. // and finally, process all the packets on the recieve queue!
  982. //
  983. BytesProcessed = 0;
  984. while (1)
  985. {
  986. if ((pArapBuf = ArapExtractAtalkSRP(pArapConn)) == NULL)
  987. {
  988. // no more data left (or no complete SRP yet): done here
  989. break;
  990. }
  991. // is ARAP connection up? route only if it's up, otherwise drop it!
  992. if (fArapConnUp)
  993. {
  994. ArapRoutePacketFromWan( pArapConn, pArapBuf );
  995. }
  996. // we received AppleTalk data but connection wasn't/isn't up! Drop pkt
  997. else
  998. {
  999. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  1000. ("ArapRcvComplete: (%lx) AT data, but conn not up\n",pArapConn));
  1001. }
  1002. BytesProcessed += pArapBuf->DataSize;
  1003. // done with this buffer
  1004. ARAP_FREE_RCVBUF(pArapBuf);
  1005. }
  1006. //
  1007. // ok, we freed up space: update the counters
  1008. //
  1009. ACQUIRE_SPIN_LOCK(&pArapConn->SpinLock, &OldIrql);
  1010. ASSERT(pArapConn->RecvsPending >= BytesProcessed);
  1011. pArapConn->RecvsPending -= BytesProcessed;
  1012. ARAP_ADJUST_RECVCREDIT(pArapConn);
  1013. #if DBG
  1014. if ((IsListEmpty(&pArapConn->RetransmitQ)) &&
  1015. (IsListEmpty(&pArapConn->HighPriSendQ)) &&
  1016. (IsListEmpty(&pArapConn->MedPriSendQ)) &&
  1017. (IsListEmpty(&pArapConn->LowPriSendQ)) &&
  1018. (IsListEmpty(&pArapConn->SendAckedQ)) )
  1019. {
  1020. ASSERT(pArapConn->SendsPending == 0);
  1021. }
  1022. #endif
  1023. RELEASE_SPIN_LOCK(&pArapConn->SpinLock, OldIrql);
  1024. ArapDataToDll(pArapConn);
  1025. //
  1026. // see if any more packets can/should be sent
  1027. //
  1028. ArapNdisSend(pArapConn, &pArapConn->HighPriSendQ);
  1029. }
  1030. }
  1031. //***
  1032. //
  1033. // Function: ArapNdisSend
  1034. // This routine is called when we need to send data out to the
  1035. // client, whether it's a fresh send or a retransmit.
  1036. //
  1037. // Parameters: pArapConn - connection element for whom data has come in
  1038. // pSendHead - from which queue (new send or retransmit) to send
  1039. //
  1040. // Return: none
  1041. //
  1042. //***$
  1043. VOID
  1044. ArapNdisSend(
  1045. IN PARAPCONN pArapConn,
  1046. IN PLIST_ENTRY pSendHead
  1047. )
  1048. {
  1049. KIRQL OldIrql;
  1050. PMNPSENDBUF pMnpSendBuf=NULL;
  1051. PNDIS_PACKET ndisPacket;
  1052. NDIS_STATUS ndisStatus;
  1053. PLIST_ENTRY pSendList;
  1054. BOOLEAN fGreaterThan;
  1055. BYTE SendCredit;
  1056. BYTE PrevSeqNum;
  1057. BOOLEAN fFirstSend=TRUE;
  1058. BOOLEAN fRetransmitQ;
  1059. DWORD StatusCode;
  1060. DBG_ARAP_CHECK_PAGED_CODE();
  1061. //
  1062. // before we begin, let's see if any of the lower priority queue sends
  1063. // can be moved ("refilled") on to the high priority queue (the real queue)
  1064. //
  1065. ArapRefillSendQ(pArapConn);
  1066. fRetransmitQ = (pSendHead == &pArapConn->RetransmitQ);
  1067. //
  1068. // while we have sends queued up and send-credits available,
  1069. // keep sending
  1070. //
  1071. while (1)
  1072. {
  1073. ACQUIRE_SPIN_LOCK(&pArapConn->SpinLock, &OldIrql);
  1074. pSendList = pSendHead->Flink;
  1075. if (pArapConn->MnpState.RetransmitMode)
  1076. {
  1077. //
  1078. // if we are asked to retransmit, we only retransmit the first
  1079. // packet (until it is acked)
  1080. //
  1081. if (!fFirstSend)
  1082. {
  1083. goto ArapNdisSend_Exit;
  1084. }
  1085. //
  1086. // if we are in the retransmit mode, we can't accept any fresh sends
  1087. //
  1088. if (!fRetransmitQ)
  1089. {
  1090. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_INFO,
  1091. ("ArapNdisSend: in retransmit mode, dropping fresh send\n"));
  1092. goto ArapNdisSend_Exit;
  1093. }
  1094. // we will go down and retransmit (if we can): turn this off here
  1095. pArapConn->MnpState.MustRetransmit = FALSE;
  1096. }
  1097. #if 0
  1098. //
  1099. // if this is a retransmit, find the next send that we must retransmit
  1100. //
  1101. if ((fRetransmitQ) && (!fFirstSend))
  1102. {
  1103. while (pSendList != pSendHead)
  1104. {
  1105. pMnpSendBuf = CONTAINING_RECORD(pSendList,MNPSENDBUF,Linkage);
  1106. // find the seq number larger than the one we just retransmitted
  1107. LT_GREATER_THAN(pMnpSendBuf->SeqNum,PrevSeqNum,fGreaterThan);
  1108. if (fGreaterThan)
  1109. {
  1110. break;
  1111. }
  1112. pSendList = pSendList->Flink;
  1113. }
  1114. }
  1115. #endif
  1116. // no more to send? then we're done
  1117. if (pSendList == pSendHead)
  1118. {
  1119. goto ArapNdisSend_Exit;
  1120. }
  1121. pMnpSendBuf = CONTAINING_RECORD(pSendList,MNPSENDBUF,Linkage);
  1122. ASSERT( (pMnpSendBuf->Signature == MNPSMSENDBUF_SIGNATURE) ||
  1123. (pMnpSendBuf->Signature == MNPLGSENDBUF_SIGNATURE) );
  1124. fFirstSend = FALSE;
  1125. PrevSeqNum = pMnpSendBuf->SeqNum;
  1126. SendCredit = pArapConn->MnpState.SendCredit;
  1127. //
  1128. // if we are disconnecting, don't send
  1129. //
  1130. if (pArapConn->State >= MNP_LDISCONNECTING)
  1131. {
  1132. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  1133. ("ArapNdisSend: disconnecting, or link-down: dropping send\n"));
  1134. ARAP_DBG_TRACE(pArapConn,30305,NULL,pArapConn->State,0,0);
  1135. goto ArapNdisSend_Exit;
  1136. }
  1137. //
  1138. // if this is a fresh send (i.e. not a retransmit) then make sure we have
  1139. // send credits available
  1140. //
  1141. if ( (SendCredit == 0) && (!fRetransmitQ) )
  1142. {
  1143. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_INFO,
  1144. ("ArapNdisSend: send credit 0, dropping send\n"));
  1145. ARAP_DBG_TRACE(pArapConn,30310,NULL,0,0,0);
  1146. goto ArapNdisSend_Exit;
  1147. }
  1148. //
  1149. // if this send is already in NDIS (rare case, but can happen) then return
  1150. //
  1151. if (pMnpSendBuf->Flags != 0)
  1152. {
  1153. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_INFO,
  1154. ("ArapNdisSend: send %lx already in NDIS!!! (seq=%x, %d times)\n",
  1155. pMnpSendBuf,pMnpSendBuf->SeqNum,pMnpSendBuf->RetryCount));
  1156. goto ArapNdisSend_Exit;
  1157. }
  1158. // Mark that this send is in Ndis
  1159. pMnpSendBuf->Flags = 1;
  1160. //
  1161. // Move it to the RetransmitQ for that "reliable" thing to work
  1162. // and set the length so that ndis knows how much to send!
  1163. //
  1164. if (!fRetransmitQ)
  1165. {
  1166. ASSERT(pMnpSendBuf->DataSize <= MNP_MAXPKT_SIZE);
  1167. DBGTRACK_SEND_SIZE(pArapConn,pMnpSendBuf->DataSize);
  1168. //
  1169. // get ndis packet for this send, since this is the first time we
  1170. // are sending this send out
  1171. //
  1172. StatusCode = ArapGetNdisPacket(pMnpSendBuf);
  1173. if (StatusCode != ARAPERR_NO_ERROR)
  1174. {
  1175. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  1176. ("ArapNdisSend: (%lx) couldn't alloc NdisPacket\n",pArapConn));
  1177. pMnpSendBuf->Flags = 0;
  1178. goto ArapNdisSend_Exit;
  1179. }
  1180. // one more frame going outcame in
  1181. pArapConn->StatInfo.FramesSent++;
  1182. RemoveEntryList(&pMnpSendBuf->Linkage);
  1183. InsertTailList(&pArapConn->RetransmitQ, &pMnpSendBuf->Linkage);
  1184. pArapConn->MnpState.UnAckedSends++;
  1185. ASSERT(pArapConn->MnpState.UnAckedSends <= pArapConn->MnpState.WindowSize);
  1186. ASSERT( (pArapConn->MnpState.SendCredit > 0) &&
  1187. (pArapConn->MnpState.SendCredit <= pArapConn->MnpState.WindowSize));
  1188. // we are going to use up one send credit now
  1189. pArapConn->MnpState.SendCredit--;
  1190. NdisAdjustBufferLength(pMnpSendBuf->sb_BuffHdr.bh_NdisBuffer,
  1191. (pMnpSendBuf->DataSize + MNP_OVERHD(pArapConn)));
  1192. ASSERT( (pMnpSendBuf->Buffer[14] == pArapConn->MnpState.SynByte) &&
  1193. (pMnpSendBuf->Buffer[15] == pArapConn->MnpState.DleByte) &&
  1194. (pMnpSendBuf->Buffer[16] == pArapConn->MnpState.StxByte));
  1195. ASSERT((pMnpSendBuf->Buffer[20 + pMnpSendBuf->DataSize] ==
  1196. pArapConn->MnpState.DleByte) &&
  1197. (pMnpSendBuf->Buffer[20 + pMnpSendBuf->DataSize+1] ==
  1198. pArapConn->MnpState.EtxByte));
  1199. }
  1200. //
  1201. // this is a retransmit
  1202. //
  1203. else
  1204. {
  1205. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_INFO,
  1206. ("ArapNdisSend: (%lx) retransmitting %x size=%d\n",
  1207. pArapConn,pMnpSendBuf->SeqNum,pMnpSendBuf->DataSize));
  1208. //
  1209. // reset it: it's possible we had changed it for an earlier retransmit
  1210. //
  1211. if (pMnpSendBuf->RetryCount < ARAP_HALF_MAX_RETRANSMITS)
  1212. {
  1213. pArapConn->SendRetryTime = pArapConn->SendRetryBaseTime;
  1214. }
  1215. //
  1216. // hmmm: we have retransmitted quite a few times. Time to increase
  1217. // our retry time so we do some exponential back off. Increase the
  1218. // retry time by 50%, with an upper bound of 5 seconds
  1219. //
  1220. else
  1221. {
  1222. pArapConn->SendRetryTime += (pArapConn->SendRetryTime>>1);
  1223. if (pArapConn->SendRetryTime > ARAP_MAX_RETRY_INTERVAL)
  1224. {
  1225. pArapConn->SendRetryTime = ARAP_MAX_RETRY_INTERVAL;
  1226. }
  1227. }
  1228. }
  1229. // bump this to note our attempt to send this pkt
  1230. pMnpSendBuf->RetryCount++;
  1231. // put an ndis refcount (remove when ndis completes this send)
  1232. pMnpSendBuf->RefCount++;
  1233. // when should we retransmit this pkt?
  1234. pMnpSendBuf->RetryTime = pArapConn->SendRetryTime + AtalkGetCurrentTick();
  1235. // reset the flow-control timer: we're sending something over
  1236. pArapConn->FlowControlTimer = AtalkGetCurrentTick() +
  1237. pArapConn->T404Duration;
  1238. ARAP_DBG_TRACE(pArapConn,30320,pMnpSendBuf,fRetransmitQ,0,0);
  1239. MNP_DBG_TRACE(pArapConn,pMnpSendBuf->SeqNum,MNP_LT);
  1240. RELEASE_SPIN_LOCK(&pArapConn->SpinLock, OldIrql);
  1241. ndisPacket = pMnpSendBuf->sb_BuffHdr.bh_NdisPkt;
  1242. DBGDUMPBYTES("ArapNdisSend sending pkt: ",
  1243. &pMnpSendBuf->Buffer[0],(pMnpSendBuf->DataSize + MNP_OVERHD(pArapConn)),3);
  1244. // Now send the packet descriptor
  1245. NdisSend(&ndisStatus, RasPortDesc->pd_NdisBindingHandle, ndisPacket);
  1246. // if there was a problem sending, call the completion routine here
  1247. if (ndisStatus != NDIS_STATUS_PENDING)
  1248. {
  1249. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  1250. ("ArapNdisSend: NdisSend failed (%lx %lx)\n", pArapConn,ndisStatus));
  1251. ArapNdisSendComplete(ARAPERR_SEND_FAILED, (PBUFFER_DESC)pMnpSendBuf, NULL);
  1252. // might as well stop here for now if we are having trouble sending!
  1253. goto ArapNdisSend_Exit_NoLock;
  1254. }
  1255. }
  1256. ArapNdisSend_Exit:
  1257. RELEASE_SPIN_LOCK(&pArapConn->SpinLock, OldIrql);
  1258. ArapNdisSend_Exit_NoLock:
  1259. ;
  1260. // if our sniff buffer has enough bytes, give them to dll and make room
  1261. ARAP_DUMP_DBG_TRACE(pArapConn);
  1262. }
  1263. //***
  1264. //
  1265. // Function: ArapNdisSendComplete
  1266. // This routine is the completion routine called by Ndis to tell
  1267. // us that the send completed (i.e. just went out on the wire)
  1268. //
  1269. // Parameters: Status - did it go out on wire?
  1270. // pMnpSendBuf - the buffer that was sent out. We dereference the
  1271. // buffer here. When this send gets acked, that's
  1272. // when the other deref happens.
  1273. //
  1274. // Return: none
  1275. //
  1276. //***$
  1277. VOID
  1278. ArapNdisSendComplete(
  1279. IN NDIS_STATUS Status,
  1280. IN PBUFFER_DESC pBufferDesc,
  1281. IN PSEND_COMPL_INFO pSendInfo
  1282. )
  1283. {
  1284. PARAPCONN pArapConn;
  1285. PMNPSENDBUF pMnpSendBuf;
  1286. DBG_ARAP_CHECK_PAGED_CODE();
  1287. pMnpSendBuf = (PMNPSENDBUF)pBufferDesc;
  1288. pArapConn = pMnpSendBuf->pArapConn;
  1289. ARAPTRACE(("Entered ArapNdisSendComplete (%lx %lx %lx)\n",
  1290. Status,pMnpSendBuf,pArapConn));
  1291. if (Status != NDIS_STATUS_SUCCESS)
  1292. {
  1293. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  1294. ("ArapNdisSendComplete (%lx): send failed %lx\n",pArapConn,Status));
  1295. }
  1296. // ndis send completed: take away the ndis refcount
  1297. DerefMnpSendBuf(pMnpSendBuf, TRUE);
  1298. }
  1299. //***
  1300. //
  1301. // Function: ArapGetNdisPacket
  1302. // This function gets an Ndis Packet for the ARAP send buffer
  1303. //
  1304. // Parameters: pMnpSendBuf - the send buffer for which we need Ndis Packet
  1305. //
  1306. // Return: error code
  1307. //
  1308. //***$
  1309. DWORD
  1310. ArapGetNdisPacket(
  1311. IN PMNPSENDBUF pMnpSendBuf
  1312. )
  1313. {
  1314. PBUFFER_HDR pBufHdr;
  1315. NDIS_STATUS ndisStatus;
  1316. DBG_ARAP_CHECK_PAGED_CODE();
  1317. pBufHdr = (PBUFFER_HDR)pMnpSendBuf;
  1318. pBufHdr->bh_NdisPkt = NULL;
  1319. // Allocate an NDIS packet descriptor from the global packet pool
  1320. NdisAllocatePacket(&ndisStatus,
  1321. &pBufHdr->bh_NdisPkt,
  1322. AtalkNdisPacketPoolHandle);
  1323. if (ndisStatus != NDIS_STATUS_SUCCESS)
  1324. {
  1325. LOG_ERROR(EVENT_ATALK_NDISRESOURCES, ndisStatus, NULL, 0);
  1326. DBGPRINT(DBG_COMP_SYSTEM, DBG_LEVEL_ERR,
  1327. ("ArapGetNdisPacket: Ndis Out-of-Resource condition hit\n"));
  1328. ASSERT(0);
  1329. return(ARAPERR_OUT_OF_RESOURCES);
  1330. }
  1331. // Link the buffer descriptor into the packet descriptor
  1332. RtlZeroMemory(pBufHdr->bh_NdisPkt->ProtocolReserved, sizeof(PROTOCOL_RESD));
  1333. NdisChainBufferAtBack(pBufHdr->bh_NdisPkt,
  1334. pBufHdr->bh_NdisBuffer);
  1335. ((PPROTOCOL_RESD)(pBufHdr->bh_NdisPkt->ProtocolReserved))->Receive.pr_BufHdr = pBufHdr;
  1336. ARAP_SET_NDIS_CONTEXT(pMnpSendBuf, NULL);
  1337. return(ARAPERR_NO_ERROR);
  1338. }
  1339. //***
  1340. //
  1341. // Function: RasStatusIndication
  1342. // This is the status indication routine for the Arap port.
  1343. // When line-up, line-down indications come from NdisWan, we
  1344. // execute this routine.
  1345. //
  1346. // Parameters: GeneralStatus - what is this indication for
  1347. // StatusBuf - the buffer containig the indication info
  1348. // StatusBufLen - length of this buffer
  1349. //
  1350. // Return: none
  1351. //
  1352. //***$
  1353. VOID
  1354. RasStatusIndication(
  1355. IN NDIS_STATUS GeneralStatus,
  1356. IN PVOID StatusBuf,
  1357. IN UINT StatusBufLen
  1358. )
  1359. {
  1360. KIRQL OldIrql;
  1361. PNDIS_WAN_LINE_UP pLineUp;
  1362. PNDIS_WAN_LINE_DOWN pLineDown;
  1363. PNDIS_WAN_FRAGMENT pFragment;
  1364. ATALK_NODEADDR ClientNode;
  1365. PARAPCONN pArapConn;
  1366. PATCPCONN pAtcpConn;
  1367. PARAP_BIND_INFO pArapBindInfo;
  1368. PNDIS_WAN_GET_STATS pWanStats;
  1369. DWORD dwFlags;
  1370. BOOLEAN fKillConnection=FALSE;
  1371. switch (GeneralStatus)
  1372. {
  1373. case NDIS_STATUS_WAN_LINE_UP:
  1374. if (StatusBufLen < sizeof(NDIS_WAN_LINE_UP))
  1375. {
  1376. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR, ("RasStatusIndication:\
  1377. line-up buff too small (%ld)\n", StatusBufLen));
  1378. break;
  1379. }
  1380. pLineUp = (PNDIS_WAN_LINE_UP)StatusBuf;
  1381. pArapBindInfo = (PARAP_BIND_INFO)pLineUp->ProtocolBuffer;
  1382. //
  1383. // is this a PPP connection?
  1384. //
  1385. if (pArapBindInfo->fThisIsPPP)
  1386. {
  1387. ClientNode.atn_Network = pArapBindInfo->ClientAddr.ata_Network;
  1388. ClientNode.atn_Node = (BYTE)pArapBindInfo->ClientAddr.ata_Node;
  1389. pAtcpConn = FindAndRefPPPConnByAddr(ClientNode, &dwFlags);
  1390. ASSERT(pAtcpConn == pArapBindInfo->AtalkContext);
  1391. if (pAtcpConn)
  1392. {
  1393. ASSERT(pAtcpConn->Signature == ATCPCONN_SIGNATURE);
  1394. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  1395. ("PPP: Line-Up received on %lx: link-speed = %lx, net addr %x.%x\n",
  1396. pAtcpConn,pLineUp->LinkSpeed,ClientNode.atn_Network,ClientNode.atn_Node));
  1397. if ((dwFlags & ATCP_LINE_UP_DONE) || (dwFlags & ATCP_CONNECTION_UP))
  1398. {
  1399. // remove the refcount put in by FindAndRefPPPConnByAddr
  1400. DerefPPPConn(pAtcpConn);
  1401. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  1402. ("PPP: Line-Up received on connection already up"));
  1403. break;
  1404. }
  1405. ACQUIRE_SPIN_LOCK(&pAtcpConn->SpinLock, &OldIrql);
  1406. ASSERT(!((dwFlags & ATCP_LINE_UP_DONE) || (dwFlags & ATCP_CONNECTION_UP)));
  1407. pAtcpConn->Flags |= ATCP_LINE_UP_DONE;
  1408. pAtcpConn->Flags |= ATCP_CONNECTION_UP;
  1409. // put NDISWAN refcount
  1410. pAtcpConn->RefCount++;
  1411. //
  1412. // put our context for ndiswan
  1413. //
  1414. // mark that this is a PPP connection
  1415. pLineUp->LocalAddress[0] = PPP_ID_BYTE1;
  1416. pLineUp->LocalAddress[1] = PPP_ID_BYTE2;
  1417. pLineUp->LocalAddress[2] = 0x0;
  1418. pLineUp->LocalAddress[3] = ClientNode.atn_Node;
  1419. *((USHORT UNALIGNED *)(&pLineUp->LocalAddress[4])) =
  1420. ClientNode.atn_Network;
  1421. //
  1422. // copy the header since this is what we'll use throughout the
  1423. // life of the connection
  1424. //
  1425. RtlCopyMemory( &pAtcpConn->NdiswanHeader[0],
  1426. pLineUp->RemoteAddress,
  1427. 6 );
  1428. RtlCopyMemory( &pAtcpConn->NdiswanHeader[6],
  1429. pLineUp->LocalAddress,
  1430. 6 );
  1431. // these two bytes don't really mean much, but might as well set'em
  1432. pAtcpConn->NdiswanHeader[12] = 0x80;
  1433. pAtcpConn->NdiswanHeader[13] = 0xf3;
  1434. RELEASE_SPIN_LOCK(&pAtcpConn->SpinLock, OldIrql);
  1435. // remove the refcount put in by FindAndRefPPPConnByAddr
  1436. DerefPPPConn(pAtcpConn);
  1437. // tell dll we bound ok
  1438. pArapBindInfo->ErrorCode = ARAPERR_NO_ERROR;
  1439. }
  1440. else
  1441. {
  1442. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  1443. ("RasStatusIndication: PPP line-up, but no conn for %ld.%ld\n",
  1444. ClientNode.atn_Network,ClientNode.atn_Node));
  1445. ASSERT(0);
  1446. pArapBindInfo->ErrorCode = ARAPERR_NO_SUCH_CONNECTION;
  1447. }
  1448. }
  1449. //
  1450. // nope, this is an ARAP connection!
  1451. //
  1452. else
  1453. {
  1454. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  1455. ("Arap: Line-Up received: link-speed = %lx, dll context = %lx\n",
  1456. pLineUp->LinkSpeed,pArapBindInfo->pDllContext));
  1457. ASSERT(FindArapConnByContx(pArapBindInfo->pDllContext) == NULL);
  1458. //
  1459. // alloc a connection. If we fail, tell dll sorry
  1460. //
  1461. pArapConn = AllocArapConn(pLineUp->LinkSpeed);
  1462. if (pArapConn == NULL)
  1463. {
  1464. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  1465. ("RasStatusIndication: AllocArapConn failed\n"));
  1466. pArapBindInfo->AtalkContext = NULL;
  1467. pArapBindInfo->ErrorCode = ARAPERR_OUT_OF_RESOURCES;
  1468. break;
  1469. }
  1470. // do the legendary "binding" (exchange contexts!)
  1471. pArapConn->pDllContext = pArapBindInfo->pDllContext;
  1472. pArapBindInfo->AtalkContext = pArapConn;
  1473. //
  1474. // insert this connection in the list of all Arap connections
  1475. //
  1476. ACQUIRE_SPIN_LOCK(&RasPortDesc->pd_Lock, &OldIrql);
  1477. InsertTailList(&RasPortDesc->pd_ArapConnHead, &pArapConn->Linkage);
  1478. RELEASE_SPIN_LOCK(&RasPortDesc->pd_Lock, OldIrql);
  1479. // mark that this is an ARAP connection
  1480. pLineUp->LocalAddress[0] = ARAP_ID_BYTE1;
  1481. pLineUp->LocalAddress[1] = ARAP_ID_BYTE2;
  1482. // put our context for ndiswan
  1483. *((ULONG UNALIGNED *)(&pLineUp->LocalAddress[2])) =
  1484. *((ULONG UNALIGNED *)(&pArapConn));
  1485. //
  1486. // copy the header since this is what we'll use throughout the
  1487. // life of the connection
  1488. //
  1489. RtlCopyMemory( &pArapConn->NdiswanHeader[0],
  1490. pLineUp->RemoteAddress,
  1491. 6 );
  1492. RtlCopyMemory( &pArapConn->NdiswanHeader[6],
  1493. pLineUp->LocalAddress,
  1494. 6 );
  1495. // these two bytes don't really mean much, but might as well set'em
  1496. pArapConn->NdiswanHeader[12] = 0x80;
  1497. pArapConn->NdiswanHeader[13] = 0xf3;
  1498. // tell dll we bound ok
  1499. pArapBindInfo->ErrorCode = ARAPERR_NO_ERROR;
  1500. } // if (pArapBindInfo->fThisIsPPP)
  1501. break;
  1502. case NDIS_STATUS_WAN_LINE_DOWN:
  1503. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  1504. ("RasStatusIndication: Line-Down received\n"));
  1505. if (StatusBufLen < sizeof(NDIS_WAN_LINE_DOWN))
  1506. {
  1507. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  1508. ("RasStatusIndication: line-down buff too small (%ld)\n",
  1509. StatusBufLen));
  1510. break;
  1511. }
  1512. pLineDown = (PNDIS_WAN_LINE_DOWN)StatusBuf;
  1513. //
  1514. // is this a PPP connection?
  1515. //
  1516. if ((pLineDown->LocalAddress[0] == PPP_ID_BYTE1) &&
  1517. (pLineDown->LocalAddress[1] == PPP_ID_BYTE2))
  1518. {
  1519. ClientNode.atn_Node = pLineDown->LocalAddress[3];
  1520. ClientNode.atn_Network =
  1521. *((USHORT UNALIGNED *)(&pLineDown->LocalAddress[4]));
  1522. pAtcpConn = FindAndRefPPPConnByAddr(ClientNode, &dwFlags);
  1523. if (pAtcpConn)
  1524. {
  1525. ASSERT(pAtcpConn->Signature == ATCPCONN_SIGNATURE);
  1526. ACQUIRE_SPIN_LOCK(&pAtcpConn->SpinLock, &OldIrql);
  1527. ASSERT(dwFlags & ATCP_LINE_UP_DONE);
  1528. pAtcpConn->Flags &= ~(ATCP_CONNECTION_UP | ATCP_LINE_UP_DONE);
  1529. RELEASE_SPIN_LOCK(&pAtcpConn->SpinLock, OldIrql);
  1530. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  1531. ("PPP line-down: killing %lx in line-down\n",pAtcpConn));
  1532. // line-down: take away the NDISWAN refcount
  1533. DerefPPPConn(pAtcpConn);
  1534. // remove the refcount put in by FindAndRefPPPConnByAddr
  1535. DerefPPPConn(pAtcpConn);
  1536. }
  1537. else
  1538. {
  1539. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  1540. ("RasStatusIndication: PPP line-down, but no conn for %ld.%ld\n",
  1541. ClientNode.atn_Network,ClientNode.atn_Node));
  1542. }
  1543. }
  1544. //
  1545. // no, this is an ARAP connection
  1546. //
  1547. else
  1548. {
  1549. ASSERT((pLineDown->LocalAddress[0] == ARAP_ID_BYTE1) &&
  1550. (pLineDown->LocalAddress[1] == ARAP_ID_BYTE2));
  1551. *((ULONG UNALIGNED *)(&pArapConn)) =
  1552. *((ULONG UNALIGNED *)(&pLineDown->LocalAddress[2]));
  1553. // this had better be a line-down for an existing connection!
  1554. if (ArapConnIsValid(pArapConn))
  1555. {
  1556. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  1557. ("Arap line-down: killing %lx in line-down\n",pArapConn));
  1558. ArapCleanup(pArapConn);
  1559. // remove validation refcount
  1560. DerefArapConn(pArapConn);
  1561. // remove line-up refcount
  1562. DerefArapConn(pArapConn);
  1563. }
  1564. else
  1565. {
  1566. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  1567. ("RasStatusIndication: line-down, can't find pArapConn\n"));
  1568. }
  1569. }
  1570. break;
  1571. case NDIS_STATUS_WAN_GET_STATS:
  1572. if (StatusBufLen < sizeof(NDIS_WAN_GET_STATS))
  1573. {
  1574. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  1575. ("RasStatusIndication: GetStats buff too small (%ld)\n", StatusBufLen));
  1576. break;
  1577. }
  1578. pWanStats = (PNDIS_WAN_GET_STATS)StatusBuf;
  1579. //
  1580. // is this a PPP connection? If so, ignore it: we don't keep stats
  1581. // for PPP connection
  1582. //
  1583. if ((pWanStats->LocalAddress[0] == PPP_ID_BYTE1) &&
  1584. (pWanStats->LocalAddress[1] == PPP_ID_BYTE2))
  1585. {
  1586. break;
  1587. }
  1588. //
  1589. // no, this is an ARAP connection
  1590. //
  1591. else
  1592. {
  1593. ASSERT((pWanStats->LocalAddress[0] == ARAP_ID_BYTE1) &&
  1594. (pWanStats->LocalAddress[1] == ARAP_ID_BYTE2));
  1595. *((ULONG UNALIGNED *)(&pArapConn)) =
  1596. *((ULONG UNALIGNED *)(&pWanStats->LocalAddress[2]));
  1597. // the connection had better be a valid one!
  1598. if (ArapConnIsValid(pArapConn))
  1599. {
  1600. //
  1601. // copy those stats in!
  1602. //
  1603. ACQUIRE_SPIN_LOCK(&pArapConn->SpinLock, &OldIrql);
  1604. pWanStats->BytesSent =
  1605. pArapConn->StatInfo.BytesSent;
  1606. pWanStats->BytesRcvd =
  1607. pArapConn->StatInfo.BytesRcvd;
  1608. pWanStats->FramesSent =
  1609. pArapConn->StatInfo.FramesSent;
  1610. pWanStats->FramesRcvd =
  1611. pArapConn->StatInfo.FramesRcvd;
  1612. pWanStats->BytesTransmittedUncompressed =
  1613. pArapConn->StatInfo.BytesTransmittedUncompressed;
  1614. pWanStats->BytesReceivedUncompressed =
  1615. pArapConn->StatInfo.BytesReceivedUncompressed;
  1616. pWanStats->BytesTransmittedCompressed =
  1617. pArapConn->StatInfo.BytesTransmittedCompressed;
  1618. pWanStats->BytesReceivedCompressed =
  1619. pArapConn->StatInfo.BytesReceivedCompressed;
  1620. RELEASE_SPIN_LOCK(&pArapConn->SpinLock, OldIrql);
  1621. // remove validation refcount
  1622. DerefArapConn(pArapConn);
  1623. }
  1624. else
  1625. {
  1626. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  1627. ("RasStatusIndication: GetStats on bad connection %lx\n",pArapConn));
  1628. }
  1629. }
  1630. break;
  1631. case NDIS_STATUS_WAN_FRAGMENT:
  1632. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  1633. ("RasStatusIndication: Wan-Fragment received\n"));
  1634. if (StatusBufLen < sizeof(NDIS_WAN_FRAGMENT))
  1635. {
  1636. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR, ("RasStatusIndication:\
  1637. fragment: buff too small (%ld)\n", StatusBufLen));
  1638. break;
  1639. }
  1640. pFragment = (PNDIS_WAN_FRAGMENT)StatusBuf;
  1641. *((ULONG UNALIGNED *)(&pArapConn)) =
  1642. *((ULONG UNALIGNED *)(&pFragment->LocalAddress[2]));
  1643. if (pArapConn == NULL)
  1644. {
  1645. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR, ("RasStatusIndication:\
  1646. fragment, can't find pArapConn\n"));
  1647. break;
  1648. }
  1649. //
  1650. // a frame got fragmented (wrong crc or resync or something bad)
  1651. // Send an ack to the remote client so he might recover quickly
  1652. //
  1653. MnpSendAckIfReqd(pArapConn, TRUE);
  1654. default:
  1655. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  1656. ("RasStatusIndication: unknown status %lx\n", GeneralStatus));
  1657. break;
  1658. }
  1659. }
  1660. //***
  1661. //
  1662. // Function: ArapAdapterInit
  1663. // This routine, called at init time, sets up protocol type info
  1664. // etc. with ndiswan
  1665. //
  1666. // Parameters: pPortDesc - the port descriptor corresponding to the "Adapter"
  1667. //
  1668. // Return: none
  1669. //
  1670. //***$
  1671. ATALK_ERROR
  1672. ArapAdapterInit(
  1673. IN OUT PPORT_DESCRIPTOR pPortDesc
  1674. )
  1675. {
  1676. ATALK_ERROR error;
  1677. NDIS_REQUEST request;
  1678. NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS;
  1679. UCHAR WanProtocolId[6] = { 0x80, 0x00, 0x00, 0x00, 0x80, 0xf3 };
  1680. ULONG WanHeaderFormat;
  1681. NDIS_WAN_PROTOCOL_CAPS WanProtCap;
  1682. //
  1683. // set the protocol info
  1684. //
  1685. request.RequestType = NdisRequestSetInformation;
  1686. request.DATA.QUERY_INFORMATION.Oid = OID_WAN_PROTOCOL_TYPE;
  1687. request.DATA.QUERY_INFORMATION.InformationBuffer = WanProtocolId;
  1688. request.DATA.QUERY_INFORMATION.InformationBufferLength = 6;
  1689. ndisStatus = AtalkNdisSubmitRequest(pPortDesc,
  1690. &request,
  1691. TRUE,
  1692. NULL,
  1693. NULL);
  1694. if (ndisStatus != NDIS_STATUS_SUCCESS)
  1695. {
  1696. LOG_ERRORONPORT(pPortDesc,
  1697. EVENT_ARAP_BIND_FAIL,
  1698. ndisStatus,
  1699. NULL,
  1700. 0);
  1701. }
  1702. //
  1703. // set the protocol caps
  1704. //
  1705. WanProtCap.Flags = WAN_PROTOCOL_KEEPS_STATS;
  1706. request.RequestType = NdisRequestSetInformation;
  1707. request.DATA.QUERY_INFORMATION.Oid = OID_WAN_PROTOCOL_CAPS;
  1708. request.DATA.QUERY_INFORMATION.InformationBuffer = &WanProtCap;
  1709. request.DATA.QUERY_INFORMATION.InformationBufferLength = sizeof(NDIS_WAN_PROTOCOL_CAPS);
  1710. ndisStatus = AtalkNdisSubmitRequest(pPortDesc,
  1711. &request,
  1712. TRUE,
  1713. NULL,
  1714. NULL);
  1715. if (ndisStatus != NDIS_STATUS_SUCCESS)
  1716. {
  1717. LOG_ERRORONPORT(pPortDesc,
  1718. EVENT_ARAP_BIND_FAIL,
  1719. ndisStatus,
  1720. NULL,
  1721. 0);
  1722. }
  1723. //
  1724. // set the header info
  1725. //
  1726. WanHeaderFormat = NdisWanHeaderEthernet;
  1727. request.RequestType = NdisRequestSetInformation;
  1728. request.DATA.QUERY_INFORMATION.Oid = OID_WAN_HEADER_FORMAT;
  1729. request.DATA.QUERY_INFORMATION.InformationBuffer = &WanHeaderFormat;
  1730. request.DATA.QUERY_INFORMATION.InformationBufferLength = 4;
  1731. ndisStatus = AtalkNdisSubmitRequest(pPortDesc,
  1732. &request,
  1733. TRUE,
  1734. NULL,
  1735. NULL);
  1736. if (ndisStatus != NDIS_STATUS_SUCCESS)
  1737. {
  1738. LOG_ERRORONPORT(pPortDesc,
  1739. EVENT_ARAP_BIND_FAIL,
  1740. ndisStatus,
  1741. NULL,
  1742. 0);
  1743. }
  1744. //
  1745. // Now query the line count.
  1746. //
  1747. request.RequestType = NdisRequestQueryInformation;
  1748. request.DATA.QUERY_INFORMATION.Oid = OID_WAN_LINE_COUNT;
  1749. request.DATA.QUERY_INFORMATION.InformationBuffer = &pPortDesc->pd_RasLines,
  1750. request.DATA.QUERY_INFORMATION.InformationBufferLength = 4;
  1751. ndisStatus = AtalkNdisSubmitRequest(pPortDesc,
  1752. &request,
  1753. TRUE,
  1754. NULL,
  1755. NULL);
  1756. if (ndisStatus != NDIS_STATUS_SUCCESS)
  1757. {
  1758. pPortDesc->pd_RasLines = 1;
  1759. }
  1760. if (pPortDesc->pd_RasLines == 0) {
  1761. LOG_ERRORONPORT(pPortDesc,
  1762. EVENT_ARAP_NO_RESRC,
  1763. ndisStatus,
  1764. NULL,
  1765. 0);
  1766. }
  1767. return AtalkNdisToAtalkError(ndisStatus);
  1768. }