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.

3189 lines
87 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. araputil.c
  5. Abstract:
  6. This module implements utility routines needed for the ARAP functionality
  7. Author:
  8. Shirish Koti
  9. Revision History:
  10. 15 Nov 1996 Initial Version
  11. --*/
  12. #include <atalk.h>
  13. #pragma hdrstop
  14. // File module number for errorlogging
  15. #define FILENUM ARAPUTIL
  16. #ifdef ALLOC_PRAGMA
  17. #pragma alloc_text(PAGE_ARAP, DerefMnpSendBuf)
  18. #pragma alloc_text(PAGE_ARAP, DerefArapConn)
  19. #pragma alloc_text(PAGE_ARAP, ArapReleaseAddr)
  20. #pragma alloc_text(PAGE_ARAP, ArapCleanup)
  21. #pragma alloc_text(PAGE_ARAP, PrepareConnectionResponse)
  22. #pragma alloc_text(PAGE_ARAP, ArapExtractAtalkSRP)
  23. #pragma alloc_text(PAGE_ARAP, ArapQueueSendBytes)
  24. #pragma alloc_text(PAGE_ARAP, ArapGetSendBuf)
  25. #pragma alloc_text(PAGE_ARAP, ArapRefillSendQ)
  26. #endif
  27. //***
  28. //
  29. // Function: AllocArapConn
  30. // Allocate a connection element and initialize fields
  31. //
  32. // Parameters: none
  33. //
  34. // Return: pointer to a newly allocated connection element
  35. //
  36. //***$
  37. PARAPCONN
  38. AllocArapConn(
  39. IN ULONG LinkSpeed
  40. )
  41. {
  42. PARAPCONN pArapConn;
  43. v42bis_connection_t *pV42bis;
  44. PUCHAR pBuf;
  45. LONG RetryTime;
  46. if ( (pArapConn = AtalkAllocZeroedMemory(sizeof(ARAPCONN))) == NULL)
  47. {
  48. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR, ("AllocArapConn: alloc failed\n"));
  49. return(NULL);
  50. }
  51. //
  52. // allocate v42bis buffers (it v42bis is enabled that is)
  53. //
  54. if (ArapGlobs.V42bisEnabled)
  55. {
  56. pV42bis = AtalkAllocZeroedMemory(sizeof(v42bis_connection_t));
  57. if (pV42bis == NULL)
  58. {
  59. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  60. ("AllocArapConn: alloc for v42 failed\n"));
  61. AtalkFreeMemory(pArapConn);
  62. return(NULL);
  63. }
  64. //
  65. // allocate overflow buffer for the decode side
  66. //
  67. if ((pBuf = AtalkAllocZeroedMemory(MAX_P2)) == NULL)
  68. {
  69. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  70. ("AllocArapConn: alloc for v42-2 failed\n"));
  71. AtalkFreeMemory(pArapConn);
  72. AtalkFreeMemory(pV42bis);
  73. return(NULL);
  74. }
  75. pV42bis->decode.OverFlowBuf = pBuf;
  76. pV42bis->decode.OverFlowBytes = 0;
  77. pV42bis->encode.OverFlowBuf = pBuf;
  78. pV42bis->encode.OverFlowBytes = 0;
  79. pArapConn->pV42bis = pV42bis;
  80. }
  81. //
  82. // if v42bis is not enabled, don't need no buffers!
  83. //
  84. else
  85. {
  86. pArapConn->pV42bis = NULL;
  87. }
  88. #if DBG
  89. pArapConn->Signature = ARAPCONN_SIGNATURE;
  90. //
  91. // for debug builds, we can set registry parm to keep a trace of events
  92. // If that setting is enabled, alloc a buffer to store the trace
  93. //
  94. if (ArapGlobs.SniffMode)
  95. {
  96. pBuf = AtalkAllocZeroedMemory(ARAP_SNIFF_BUFF_SIZE);
  97. if (pBuf == NULL)
  98. {
  99. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  100. ("AllocArapConn: alloc for trace buffer failed\n"));
  101. // don't fail the call if this alloc fails
  102. }
  103. pArapConn->pDbgTraceBuffer = pArapConn->pDbgCurrPtr = pBuf;
  104. // put in a guard signature, to catch overrun
  105. if (pArapConn->pDbgTraceBuffer)
  106. {
  107. *((DWORD *)&(pArapConn->pDbgTraceBuffer[ARAP_SNIFF_BUFF_SIZE-4])) = 0xcafebeef;
  108. }
  109. }
  110. #endif
  111. pArapConn->State = MNP_IDLE;
  112. // Creation refcount and a line-up refcount
  113. pArapConn->RefCount = 2;
  114. pArapConn->MnpState.WindowSize = ArapGlobs.MaxLTFrames;
  115. pArapConn->MnpState.RecvCredit = pArapConn->MnpState.WindowSize;
  116. pArapConn->LinkSpeed = LinkSpeed;
  117. //
  118. // T401 timer value in tick counts (1 tick = 100ms).
  119. // we'll keep this at 1 second (i.e. 10 ticks) for a 33.6 (and faster) modem.
  120. // If we are on a slower modem, increase it proportionately. So, a 28.8 modem
  121. // would get RetryTime=2.0sec, 14.4 would get 3.7sec, 9600 baud would get 4.2sec etc.
  122. //
  123. RetryTime = 15;
  124. if (LinkSpeed < 336)
  125. {
  126. RetryTime += (((336 - LinkSpeed) + 5)/10);
  127. }
  128. // make sure our calculation didn't go haywire...
  129. if (RetryTime < ARAP_MIN_RETRY_INTERVAL)
  130. {
  131. RetryTime = ARAP_MIN_RETRY_INTERVAL;
  132. }
  133. else if (RetryTime > ARAP_MAX_RETRY_INTERVAL)
  134. {
  135. RetryTime = ARAP_MAX_RETRY_INTERVAL;
  136. }
  137. pArapConn->SendRetryTime = RetryTime;
  138. pArapConn->SendRetryBaseTime = RetryTime;
  139. // T402 is 0.5 times T401 value
  140. pArapConn->T402Duration = (pArapConn->SendRetryTime/2);
  141. //
  142. // T403 should be at least 59 seconds. We don't really kill after this
  143. // period of inactivity. We simply tell the dll and it does whatever is the
  144. // policy: so just use whatever time period the dll tells us
  145. //
  146. pArapConn->T403Duration = ArapGlobs.MnpInactiveTime;
  147. //
  148. // T404: spec says 3 sec for 2400 baud and faster, 7 sec for anything slower
  149. // Let's use 4 seconds here
  150. //
  151. pArapConn->T404Duration = 30;
  152. // initialize all the timer values
  153. pArapConn->LATimer = 0;
  154. pArapConn->InactivityTimer = pArapConn->T403Duration + AtalkGetCurrentTick();
  155. // set this to a high value for now: we'll set it when the conn is up
  156. pArapConn->FlowControlTimer = AtalkGetCurrentTick() + 36000;
  157. InitializeListHead(&pArapConn->MiscPktsQ);
  158. InitializeListHead(&pArapConn->ReceiveQ);
  159. InitializeListHead(&pArapConn->ArapDataQ);
  160. InitializeListHead(&pArapConn->RetransmitQ);
  161. InitializeListHead(&pArapConn->HighPriSendQ);
  162. InitializeListHead(&pArapConn->MedPriSendQ);
  163. InitializeListHead(&pArapConn->LowPriSendQ);
  164. InitializeListHead(&pArapConn->SendAckedQ);
  165. INITIALIZE_SPIN_LOCK(&pArapConn->SpinLock);
  166. // start the retransmit timer for this connection
  167. AtalkTimerInitialize( &pArapConn->RetryTimer,
  168. (TIMER_ROUTINE)ArapRetryTimer,
  169. ARAP_TIMER_INTERVAL) ;
  170. AtalkTimerScheduleEvent(&pArapConn->RetryTimer);
  171. pArapConn->Flags |= RETRANSMIT_TIMER_ON;
  172. // put a timer refcount
  173. pArapConn->RefCount++;
  174. return( pArapConn );
  175. }
  176. //***
  177. //
  178. // Function: ArapAcceptIrp
  179. // Determine if the irp submitted by the dll is acceptable now
  180. //
  181. // Parameters: pIrp - the incoming irp
  182. // IoControlCode - the control code (what's the irp for?)
  183. // pfDerefDefPort - was default adapter referenced?
  184. //
  185. // Return: TRUE if the irp is acceptable, FALSE otherwise
  186. //
  187. //***$
  188. BOOLEAN
  189. ArapAcceptIrp(
  190. IN PIRP pIrp,
  191. IN ULONG IoControlCode,
  192. IN BOOLEAN *pfDerefDefPort
  193. )
  194. {
  195. KIRQL OldIrql;
  196. PARAP_SEND_RECV_INFO pSndRcvInfo=NULL;
  197. PARAPCONN pArapConn;
  198. BOOLEAN fAccept=FALSE;
  199. BOOLEAN fUnblockPnP=FALSE;
  200. *pfDerefDefPort = FALSE;
  201. //
  202. // we allow these ioctls to come in any time
  203. //
  204. if ((IoControlCode == IOCTL_ARAP_SELECT) ||
  205. (IoControlCode == IOCTL_ARAP_DISCONNECT) ||
  206. (IoControlCode == IOCTL_ARAP_CONTINUE_SHUTDOWN) )
  207. {
  208. return(TRUE);
  209. }
  210. pSndRcvInfo = (PARAP_SEND_RECV_INFO)pIrp->AssociatedIrp.SystemBuffer;
  211. pArapConn = pSndRcvInfo->AtalkContext;
  212. //
  213. // put a IrpProcess refcount on the default port so it won't go away via pnp etc.
  214. //
  215. if (!AtalkReferenceRasDefPort())
  216. {
  217. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  218. ("ArapProcessIoctl: Default port gone, or going %lx not accepted (%lx)\n",
  219. pIrp,IoControlCode));
  220. pSndRcvInfo->StatusCode = ARAPERR_STACK_IS_NOT_ACTIVE;
  221. return(FALSE);
  222. }
  223. // note the fact that we have referenced the default adapter
  224. *pfDerefDefPort = TRUE;
  225. //
  226. // now it's simple to decide whether we want to accept this irp or not
  227. //
  228. ACQUIRE_SPIN_LOCK(&ArapSpinLock, &OldIrql);
  229. fAccept = (ArapStackState == ARAP_STATE_ACTIVE) ? TRUE : FALSE;
  230. RELEASE_SPIN_LOCK(&ArapSpinLock, OldIrql);
  231. return(fAccept);
  232. }
  233. //***
  234. //
  235. // Function: ArapCancelIrp
  236. // Cancel the irp. Currently, only select irps are cancellable
  237. //
  238. // Parameters: pIrp - the incoming irp
  239. //
  240. // Return: none
  241. //
  242. //***$
  243. VOID
  244. ArapCancelIrp(
  245. IN PIRP pIrp
  246. )
  247. {
  248. KIRQL OldIrql;
  249. PLIST_ENTRY pList;
  250. PARAPCONN pArapConn;
  251. NTSTATUS ReturnStatus=STATUS_SUCCESS;
  252. //
  253. // kill all connections and don't accept any more irps:
  254. // cancelling a select irp is a blasphemy!
  255. //
  256. ACQUIRE_SPIN_LOCK(&ArapSpinLock, &OldIrql);
  257. if (ArapSelectIrp == NULL)
  258. {
  259. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_ERR,("ArapCancelIrp: weird race condition!\n"));
  260. RELEASE_SPIN_LOCK(&ArapSpinLock, OldIrql);
  261. return;
  262. }
  263. ASSERT (pIrp == ArapSelectIrp);
  264. ArapSelectIrp = NULL;
  265. if (ArapStackState == ARAP_STATE_ACTIVE)
  266. {
  267. ArapStackState = ARAP_STATE_ACTIVE_WAITING;
  268. }
  269. else if (ArapStackState == ARAP_STATE_INACTIVE)
  270. {
  271. ArapStackState = ARAP_STATE_INACTIVE_WAITING;
  272. }
  273. RELEASE_SPIN_LOCK(&ArapSpinLock, OldIrql);
  274. if (RasPortDesc == NULL)
  275. {
  276. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_ERR,("ArapCancelIrp: RasPortDesc is null!\n"));
  277. ARAP_COMPLETE_IRP(pIrp, 0, STATUS_CANCELLED, &ReturnStatus);
  278. return;
  279. }
  280. //
  281. // now, go kill all the arap connections
  282. //
  283. ACQUIRE_SPIN_LOCK(&RasPortDesc->pd_Lock, &OldIrql);
  284. pList = RasPortDesc->pd_ArapConnHead.Flink;
  285. while (pList != &RasPortDesc->pd_ArapConnHead)
  286. {
  287. pArapConn = CONTAINING_RECORD(pList, ARAPCONN, Linkage);
  288. ASSERT(pArapConn->Signature == ARAPCONN_SIGNATURE);
  289. // if this connection is already disconnected, skip it
  290. ACQUIRE_SPIN_LOCK_DPC(&pArapConn->SpinLock);
  291. if (pArapConn->State == MNP_DISCONNECTED)
  292. {
  293. pList = pArapConn->Linkage.Flink;
  294. RELEASE_SPIN_LOCK_DPC(&pArapConn->SpinLock);
  295. continue;
  296. }
  297. RELEASE_SPIN_LOCK_DPC(&pArapConn->SpinLock);
  298. RELEASE_SPIN_LOCK(&RasPortDesc->pd_Lock, OldIrql);
  299. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_ERR,
  300. ("ArapCancelIrp: killing ARAP connection %lx\n",pArapConn));
  301. ArapCleanup(pArapConn);
  302. ACQUIRE_SPIN_LOCK(&RasPortDesc->pd_Lock, &OldIrql);
  303. pList = RasPortDesc->pd_ArapConnHead.Flink;
  304. }
  305. //
  306. // walk through the list to see if any connection(s) disconnected but is
  307. // waiting for a select irp to come down. We know the select irp is never
  308. // going to come down, so pretend that dll has been told and deref the puppy
  309. // for telling the dll (which will probably free the connection)
  310. //
  311. pList = RasPortDesc->pd_ArapConnHead.Flink;
  312. while (pList != &RasPortDesc->pd_ArapConnHead)
  313. {
  314. pArapConn = CONTAINING_RECORD(pList, ARAPCONN, Linkage);
  315. ASSERT(pArapConn->Signature == ARAPCONN_SIGNATURE);
  316. ACQUIRE_SPIN_LOCK_DPC(&pArapConn->SpinLock);
  317. if (pArapConn->Flags & DISCONNECT_NO_IRP)
  318. {
  319. pArapConn->Flags &= ~DISCONNECT_NO_IRP;
  320. RELEASE_SPIN_LOCK_DPC(&pArapConn->SpinLock);
  321. RELEASE_SPIN_LOCK(&RasPortDesc->pd_Lock, OldIrql);
  322. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_ERR,
  323. ("ArapCancelIrp: faking dll-completion for dead connection %lx\n",pArapConn));
  324. DerefArapConn(pArapConn);
  325. ACQUIRE_SPIN_LOCK(&RasPortDesc->pd_Lock, &OldIrql);
  326. pList = RasPortDesc->pd_ArapConnHead.Flink;
  327. }
  328. else
  329. {
  330. pList = pArapConn->Linkage.Flink;
  331. RELEASE_SPIN_LOCK_DPC(&pArapConn->SpinLock);
  332. }
  333. }
  334. RELEASE_SPIN_LOCK(&RasPortDesc->pd_Lock, OldIrql);
  335. // finally, complete that cancelled irp!
  336. ARAP_COMPLETE_IRP(pIrp, 0, STATUS_CANCELLED, &ReturnStatus);
  337. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  338. ("ArapCancelIrp: select irp cancelled and completed (%lx)\n",pIrp));
  339. }
  340. //***
  341. //
  342. // Function: ArapGetSelectIrp
  343. // Get the select irp, after some checks
  344. //
  345. // Parameters: ppIrp - pointer to irp pointer, contains select irp on return
  346. //
  347. // Return: none
  348. //
  349. //***$
  350. VOID
  351. ArapGetSelectIrp(
  352. IN PIRP *ppIrp
  353. )
  354. {
  355. KIRQL OldIrql;
  356. KIRQL OldIrql2;
  357. *(ppIrp) = NULL;
  358. IoAcquireCancelSpinLock(&OldIrql);
  359. ACQUIRE_SPIN_LOCK(&ArapSpinLock, &OldIrql2);
  360. if (ArapSelectIrp && (!ArapSelectIrp->Cancel))
  361. {
  362. ArapSelectIrp->CancelRoutine = NULL;
  363. *(ppIrp) = ArapSelectIrp;
  364. ArapSelectIrp = NULL;
  365. }
  366. RELEASE_SPIN_LOCK(&ArapSpinLock, OldIrql2);
  367. IoReleaseCancelSpinLock(OldIrql);
  368. }
  369. //***
  370. //
  371. // Function: FindArapConnByContx
  372. // Finds the corresponding connection element, given the dll's
  373. // context
  374. //
  375. // Parameters: pDllContext - the dll context for the connection
  376. //
  377. // Return: pointer to the corresponding connection element, if found
  378. //
  379. //***$
  380. PARAPCONN
  381. FindArapConnByContx(
  382. IN PVOID pDllContext
  383. )
  384. {
  385. PARAPCONN pArapConn=NULL;
  386. PARAPCONN pWalker;
  387. PLIST_ENTRY pList;
  388. KIRQL OldIrql;
  389. // ARAP not configured?
  390. if (!RasPortDesc)
  391. {
  392. return(NULL);
  393. }
  394. ACQUIRE_SPIN_LOCK(&RasPortDesc->pd_Lock, &OldIrql);
  395. if (!(RasPortDesc->pd_Flags & PD_ACTIVE))
  396. {
  397. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  398. ("FindArapConnByContx: ArapPort not active, ignoring\n"));
  399. RELEASE_SPIN_LOCK(&RasPortDesc->pd_Lock, OldIrql);
  400. return(NULL);
  401. }
  402. pList = RasPortDesc->pd_ArapConnHead.Flink;
  403. //
  404. // walk through all the Arap clients to see if we find ours
  405. //
  406. while (pList != &RasPortDesc->pd_ArapConnHead)
  407. {
  408. pWalker = CONTAINING_RECORD(pList, ARAPCONN, Linkage);
  409. pList = pWalker->Linkage.Flink;
  410. if (pWalker->pDllContext == pDllContext)
  411. {
  412. pArapConn = pWalker;
  413. break;
  414. }
  415. }
  416. RELEASE_SPIN_LOCK(&RasPortDesc->pd_Lock, OldIrql);
  417. return( pArapConn );
  418. }
  419. //***
  420. //
  421. // Function: FindAndRefArapConnByAddr
  422. // Finds the corresponding connection element, given the network
  423. // address (of the remote client)
  424. //
  425. // Parameters: destNode - network addr of the destination (remote client)
  426. // pdwFlags - pointer to a dword to return Flags field
  427. //
  428. // Return: pointer to the corresponding connection element, if found
  429. //
  430. //***$
  431. PARAPCONN
  432. FindAndRefArapConnByAddr(
  433. IN ATALK_NODEADDR destNode,
  434. OUT DWORD *pdwFlags
  435. )
  436. {
  437. PARAPCONN pArapConn=NULL;
  438. PARAPCONN pWalker;
  439. PLIST_ENTRY pList;
  440. KIRQL OldIrql;
  441. // ARAP not configured?
  442. if (!RasPortDesc)
  443. {
  444. return(NULL);
  445. }
  446. ACQUIRE_SPIN_LOCK(&RasPortDesc->pd_Lock, &OldIrql);
  447. if (!(RasPortDesc->pd_Flags & PD_ACTIVE))
  448. {
  449. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  450. ("FindAndRefArapConnByAddr: ArapPort not active, ignoring\n"));
  451. RELEASE_SPIN_LOCK(&RasPortDesc->pd_Lock, OldIrql);
  452. return(NULL);
  453. }
  454. pList = RasPortDesc->pd_ArapConnHead.Flink;
  455. //
  456. // walk through all the Arap clients to see if we find ours
  457. //
  458. while (pList != &RasPortDesc->pd_ArapConnHead)
  459. {
  460. pWalker = CONTAINING_RECORD(pList, ARAPCONN, Linkage);
  461. pList = pWalker->Linkage.Flink;
  462. if (ATALK_NODES_EQUAL(&pWalker->NetAddr, &destNode))
  463. {
  464. ACQUIRE_SPIN_LOCK_DPC(&pWalker->SpinLock);
  465. //
  466. // we return the pArapConn only if the MNP connection is up and
  467. // and the ARAP connection is also up (or, if ARAP connection isn't
  468. // up yet then only if we are searching for a node)
  469. //
  470. //
  471. if ((pWalker->State == MNP_UP) &&
  472. ((pWalker->Flags & ARAP_CONNECTION_UP) ||
  473. (pWalker->Flags & ARAP_FINDING_NODE)) )
  474. {
  475. pArapConn = pWalker;
  476. pArapConn->RefCount++;
  477. *pdwFlags = pWalker->Flags;
  478. }
  479. else if (pWalker->Flags & ARAP_CONNECTION_UP)
  480. {
  481. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  482. ("FindAndRefArapConnByAddr: found pArapConn (%lx), but state=%ld,Flags=%lx\n",
  483. pWalker,pWalker->State,pWalker->Flags));
  484. }
  485. RELEASE_SPIN_LOCK_DPC(&pWalker->SpinLock);
  486. break;
  487. }
  488. }
  489. RELEASE_SPIN_LOCK(&RasPortDesc->pd_Lock, OldIrql);
  490. return(pArapConn);
  491. }
  492. //***
  493. //
  494. // Function: FindAndRefRasConnByAddr
  495. // Finds the corresponding connection element, given the network
  496. // address (of the remote client)
  497. //
  498. // Parameters: destNode - network addr of the destination (remote client)
  499. // pdwFlags - pointer to a dword to return Flags field
  500. // pfThisIsPPP - pointer to a bool: is this PPP or ARAP connection?
  501. //
  502. // Return: pointer to the corresponding connection element, if found
  503. //
  504. //***$
  505. PVOID
  506. FindAndRefRasConnByAddr(
  507. IN ATALK_NODEADDR destNode,
  508. OUT DWORD *pdwFlags,
  509. OUT BOOLEAN *pfThisIsPPP
  510. )
  511. {
  512. PVOID pRasConn;
  513. // RAS not configured?
  514. if (!RasPortDesc)
  515. {
  516. return(NULL);
  517. }
  518. pRasConn = (PVOID)FindAndRefPPPConnByAddr(destNode,pdwFlags);
  519. if (pRasConn)
  520. {
  521. *pfThisIsPPP = TRUE;
  522. return(pRasConn);
  523. }
  524. pRasConn = FindAndRefArapConnByAddr(destNode, pdwFlags);
  525. *pfThisIsPPP = FALSE;
  526. return(pRasConn);
  527. }
  528. //***
  529. //
  530. // Function: ArapConnIsValid
  531. // Make sure that what we think is a connection is indeed a
  532. // connection (i.e., it's there in our list of connections)
  533. //
  534. // Parameters: pArapConn - the connection in question
  535. //
  536. // Return: TRUE if the connection is valid, FALSE otherwise
  537. //
  538. //***$
  539. BOOLEAN
  540. ArapConnIsValid(
  541. IN PARAPCONN pArapConn
  542. )
  543. {
  544. PARAPCONN pWalker;
  545. PLIST_ENTRY pList;
  546. KIRQL OldIrql;
  547. BOOLEAN fIsValid=FALSE;
  548. // ARAP not configured?
  549. if (!RasPortDesc)
  550. {
  551. return(FALSE);
  552. }
  553. ACQUIRE_SPIN_LOCK(&RasPortDesc->pd_Lock, &OldIrql);
  554. pList = RasPortDesc->pd_ArapConnHead.Flink;
  555. //
  556. // walk through all the Arap conns and see if we find the given conn
  557. //
  558. while (pList != &RasPortDesc->pd_ArapConnHead)
  559. {
  560. pWalker = CONTAINING_RECORD(pList, ARAPCONN, Linkage);
  561. pList = pWalker->Linkage.Flink;
  562. if (pWalker == pArapConn)
  563. {
  564. ACQUIRE_SPIN_LOCK_DPC(&pWalker->SpinLock);
  565. ASSERT(pWalker->Signature == ARAPCONN_SIGNATURE);
  566. if (!(pWalker->Flags & ARAP_GOING_AWAY))
  567. {
  568. // put a validation refcount
  569. pWalker->RefCount++;
  570. fIsValid = TRUE;
  571. }
  572. RELEASE_SPIN_LOCK_DPC(&pWalker->SpinLock);
  573. break;
  574. }
  575. }
  576. RELEASE_SPIN_LOCK(&RasPortDesc->pd_Lock, OldIrql);
  577. return( fIsValid );
  578. }
  579. //***
  580. //
  581. // Function: DerefMnpSendBuf
  582. // This routine dereferences the MNP send. When the refcount
  583. // goes to zero, we free it
  584. //
  585. // Parameters: pMnpSendBuf - the MNP send to be dereferenced
  586. //
  587. // Return: Nothing
  588. //
  589. //***$
  590. VOID
  591. DerefMnpSendBuf(
  592. IN PMNPSENDBUF pMnpSendBuf,
  593. IN BOOLEAN fNdisSendComplete
  594. )
  595. {
  596. KIRQL OldIrql;
  597. PARAPCONN pArapConn;
  598. BOOLEAN fFreeIt=FALSE;
  599. DBG_ARAP_CHECK_PAGED_CODE();
  600. pArapConn = pMnpSendBuf->pArapConn;
  601. ARAPTRACE(("Entered DerefMnpSendBuf (%lx %lx refcount=%d ComplFn=%lx)\n",
  602. pArapConn,pMnpSendBuf,pMnpSendBuf->RefCount,pMnpSendBuf->ComplRoutine));
  603. ACQUIRE_SPIN_LOCK(&pArapConn->SpinLock, &OldIrql);
  604. //
  605. // catch weird things like freeing twice
  606. // (we subtract 0x100 in completion routine, to mark that it has run)
  607. //
  608. ASSERT((pMnpSendBuf->Signature == MNPSMSENDBUF_SIGNATURE) ||
  609. (pMnpSendBuf->Signature == MNPSMSENDBUF_SIGNATURE-0x100) ||
  610. (pMnpSendBuf->Signature == MNPLGSENDBUF_SIGNATURE) ||
  611. (pMnpSendBuf->Signature == MNPLGSENDBUF_SIGNATURE-0x100));
  612. ASSERT(pMnpSendBuf->RefCount > 0);
  613. // Mark that Ndis completed our send
  614. if (fNdisSendComplete)
  615. {
  616. pMnpSendBuf->Flags = 0;
  617. }
  618. pMnpSendBuf->RefCount--;
  619. if (pMnpSendBuf->RefCount == 0)
  620. {
  621. fFreeIt = TRUE;
  622. }
  623. RELEASE_SPIN_LOCK(&pArapConn->SpinLock, OldIrql);
  624. if (!fFreeIt)
  625. {
  626. return;
  627. }
  628. // make sure it's not still sitting on retransmit queue
  629. ASSERT(IsListEmpty(&pMnpSendBuf->Linkage));
  630. #if DBG
  631. pMnpSendBuf->Signature--;
  632. #endif
  633. ArapNdisFreeBuf(pMnpSendBuf);
  634. // remove that MNPSend refcount
  635. DerefArapConn(pArapConn);
  636. }
  637. //***
  638. //
  639. // Function: DerefArapConn
  640. // Decrements the refcount of the connection element by 1. If the
  641. // refcount goes to 0, releases network addr and frees it
  642. //
  643. // Parameters: pArapConn - connection element in question
  644. //
  645. // Return: none
  646. //
  647. //***$
  648. VOID
  649. DerefArapConn(
  650. IN PARAPCONN pArapConn
  651. )
  652. {
  653. KIRQL OldIrql;
  654. BOOLEAN fKill = FALSE;
  655. DBG_ARAP_CHECK_PAGED_CODE();
  656. ARAPTRACE(("Entered DerefArapConn (%lx refcount=%d)\n",pArapConn,pArapConn->RefCount));
  657. ACQUIRE_SPIN_LOCK(&pArapConn->SpinLock, &OldIrql);
  658. ASSERT(pArapConn->Signature == ARAPCONN_SIGNATURE);
  659. ASSERT(pArapConn->RefCount > 0);
  660. pArapConn->RefCount--;
  661. if (pArapConn->RefCount == 0)
  662. {
  663. fKill = TRUE;
  664. pArapConn->Flags |= ARAP_GOING_AWAY;
  665. }
  666. RELEASE_SPIN_LOCK(&pArapConn->SpinLock, OldIrql);
  667. if (!fKill)
  668. {
  669. return;
  670. }
  671. ASSERT(pArapConn->pRecvIoctlIrp == NULL);
  672. ASSERT(pArapConn->pIoctlIrp == NULL);
  673. ASSERT(IsListEmpty(&pArapConn->HighPriSendQ));
  674. ASSERT(IsListEmpty(&pArapConn->MedPriSendQ));
  675. ASSERT(IsListEmpty(&pArapConn->LowPriSendQ));
  676. ASSERT(IsListEmpty(&pArapConn->SendAckedQ));
  677. ASSERT(IsListEmpty(&pArapConn->ReceiveQ));
  678. ASSERT(IsListEmpty(&pArapConn->ArapDataQ));
  679. ASSERT(IsListEmpty(&pArapConn->RetransmitQ));
  680. /* ASSERT(pArapConn->SendsPending == 0); */
  681. ASSERT(!(pArapConn->Flags & RETRANSMIT_TIMER_ON));
  682. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  683. ("DerefArapConn: refcount 0, freeing %lx\n", pArapConn));
  684. ACQUIRE_SPIN_LOCK(&RasPortDesc->pd_Lock, &OldIrql);
  685. RemoveEntryList(&pArapConn->Linkage);
  686. RELEASE_SPIN_LOCK(&RasPortDesc->pd_Lock, OldIrql);
  687. #if ARAP_STATIC_MODE
  688. // "release" the network addr used by this client
  689. ArapReleaseAddr(pArapConn);
  690. #endif //ARAP_STATIC_MODE
  691. // free that v42bis buffer
  692. if (pArapConn->pV42bis)
  693. {
  694. // free the decode-side overflow buffer
  695. AtalkFreeMemory(pArapConn->pV42bis->decode.OverFlowBuf);
  696. AtalkFreeMemory(pArapConn->pV42bis);
  697. }
  698. #if DBG
  699. ArapDbgDumpMnpHist(pArapConn);
  700. // if we had allocated a sniff buffer, free it
  701. if (pArapConn->pDbgTraceBuffer)
  702. {
  703. AtalkFreeMemory(pArapConn->pDbgTraceBuffer);
  704. }
  705. //
  706. // let's catch if someone tries to access this after a free
  707. //
  708. RtlFillMemory(pArapConn,sizeof(ARAPCONN),0x7);
  709. pArapConn->Signature = 0xDEADBEEF;
  710. #endif
  711. // and finally, we say good bye
  712. AtalkFreeMemory(pArapConn);
  713. ACQUIRE_SPIN_LOCK(&ArapSpinLock, &OldIrql);
  714. ArapConnections--;
  715. RELEASE_SPIN_LOCK(&ArapSpinLock, OldIrql);
  716. #if ARAP_STATIC_MODE
  717. // This will delete a route if this is the last connection that vanished
  718. ArapDeleteArapRoute();
  719. #endif //ARAP_STATIC_MODE
  720. // connection is completely gone: see if arap pages can be unlocked
  721. AtalkUnlockArapIfNecessary();
  722. }
  723. //***
  724. //
  725. // Function: ArapCleanup
  726. // Once the client goes into the disconnecting state (as a result
  727. // of either local side or remote side initiating the disconnect)
  728. // this routine gets called. This does all the cleanup, such as
  729. // completing all unacked sends, uncompleted receives, stopping
  730. // retransmit timers, completing any irp in progress.
  731. //
  732. // Parameters: pArapConn - connection element being cleaned up
  733. //
  734. // Return: none
  735. //
  736. //***$
  737. VOID
  738. ArapCleanup(
  739. IN PARAPCONN pArapConn
  740. )
  741. {
  742. KIRQL OldIrql;
  743. PIRP pIrp;
  744. PIRP pRcvIrp;
  745. PIRP pDiscIrp;
  746. PARAP_SEND_RECV_INFO pSndRcvInfo;
  747. PARAP_SEND_RECV_INFO pDiscSndRcvInfo;
  748. PLIST_ENTRY pSendHighList;
  749. PLIST_ENTRY pSendMedList;
  750. PLIST_ENTRY pSendLowList;
  751. PLIST_ENTRY pSendAckList;
  752. PLIST_ENTRY pRcvList;
  753. PLIST_ENTRY pArapList;
  754. PLIST_ENTRY pReXmitList;
  755. PLIST_ENTRY pMiscPktList;
  756. PMNPSENDBUF pMnpSendBuf;
  757. PARAPBUF pArapBuf;
  758. DWORD StatusCode;
  759. BOOLEAN fStopTimer=FALSE;
  760. BOOLEAN fArapConnUp=FALSE;
  761. DWORD dwBytesToDll;
  762. NTSTATUS ReturnStatus=STATUS_SUCCESS;
  763. DBG_ARAP_CHECK_PAGED_CODE();
  764. // first thing, see if we should send out a disconnect message
  765. // we make this check without holding the lock because ArapSendLDPacket does
  766. // the right thing. If, due to an extremely tiny window, we don't call
  767. // ArapSendLDPacket, no big deal!
  768. if (pArapConn->State < MNP_LDISCONNECTING)
  769. {
  770. ArapSendLDPacket(pArapConn, 0xFF);
  771. }
  772. ACQUIRE_SPIN_LOCK(&pArapConn->SpinLock, &OldIrql);
  773. ASSERT(pArapConn->Signature == ARAPCONN_SIGNATURE);
  774. // if we have already run the cleanup, nothing to do!
  775. if (pArapConn->State == MNP_DISCONNECTED)
  776. {
  777. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  778. ("ArapCleanup: cleanup already done once on (%lx)\n",pArapConn));
  779. RELEASE_SPIN_LOCK(&pArapConn->SpinLock, OldIrql);
  780. return;
  781. }
  782. pSendHighList = pArapConn->HighPriSendQ.Flink;
  783. InitializeListHead(&pArapConn->HighPriSendQ);
  784. pSendMedList = pArapConn->MedPriSendQ.Flink;
  785. InitializeListHead(&pArapConn->MedPriSendQ);
  786. pSendLowList = pArapConn->LowPriSendQ.Flink;
  787. InitializeListHead(&pArapConn->LowPriSendQ);
  788. pSendAckList = pArapConn->SendAckedQ.Flink;
  789. InitializeListHead(&pArapConn->SendAckedQ);
  790. pRcvList = pArapConn->ReceiveQ.Flink;
  791. InitializeListHead(&pArapConn->ReceiveQ);
  792. pArapList = pArapConn->ArapDataQ.Flink;
  793. InitializeListHead(&pArapConn->ArapDataQ);
  794. pReXmitList = pArapConn->RetransmitQ.Flink;
  795. InitializeListHead(&pArapConn->RetransmitQ);
  796. pMiscPktList = pArapConn->MiscPktsQ.Flink;
  797. InitializeListHead(&pArapConn->MiscPktsQ);
  798. pIrp = pArapConn->pIoctlIrp;
  799. pArapConn->pIoctlIrp = NULL;
  800. pRcvIrp = pArapConn->pRecvIoctlIrp;
  801. pArapConn->pRecvIoctlIrp = NULL;
  802. if (pArapConn->State == MNP_RDISCONNECTING)
  803. {
  804. pArapConn->Flags |= ARAP_REMOTE_DISCONN;
  805. StatusCode = ARAPERR_RDISCONNECT_COMPLETE;
  806. }
  807. else
  808. {
  809. StatusCode = ARAPERR_LDISCONNECT_COMPLETE;
  810. }
  811. pArapConn->State = MNP_DISCONNECTED;
  812. pArapConn->Flags &= ~ARAP_DATA_WAITING;
  813. // if the timer is running, stop it
  814. if (pArapConn->Flags & RETRANSMIT_TIMER_ON)
  815. {
  816. fStopTimer = TRUE;
  817. pArapConn->Flags &= ~RETRANSMIT_TIMER_ON;
  818. // creation refcount and timer refcount better be on here
  819. ASSERT(pArapConn->RefCount >= 2);
  820. }
  821. fArapConnUp = FALSE;
  822. // was ARAP connection up?
  823. if (pArapConn->Flags & ARAP_CONNECTION_UP)
  824. {
  825. fArapConnUp = TRUE;
  826. }
  827. #if DBG
  828. //
  829. // if we are sniffing, mark the sniff to indicate the end (so dll knows it
  830. // got all the sniff info)
  831. //
  832. if (pArapConn->pDbgCurrPtr)
  833. {
  834. PSNIFF_INFO pSniff;
  835. pSniff = (PSNIFF_INFO)(pArapConn->pDbgCurrPtr);
  836. pSniff->Signature = ARAP_SNIFF_SIGNATURE;
  837. pSniff->TimeStamp = (DWORD)AtalkGetCurrentTick();
  838. pSniff->Location = 0xfedc;
  839. pSniff->FrameLen = 0;
  840. pArapConn->SniffedBytes += sizeof(SNIFF_INFO);
  841. pArapConn->pDbgCurrPtr += sizeof(SNIFF_INFO);
  842. }
  843. #endif
  844. RELEASE_SPIN_LOCK(&pArapConn->SpinLock, OldIrql);
  845. if (fStopTimer)
  846. {
  847. if (AtalkTimerCancelEvent(&pArapConn->RetryTimer, NULL))
  848. {
  849. // remove the timer refcount
  850. DerefArapConn(pArapConn);
  851. }
  852. }
  853. //
  854. // call completion routine for all the sends that have been acked
  855. //
  856. while (pSendAckList != &pArapConn->SendAckedQ)
  857. {
  858. pMnpSendBuf = CONTAINING_RECORD(pSendAckList,MNPSENDBUF,Linkage);
  859. pSendAckList = pSendAckList->Flink;
  860. #if DBG
  861. InitializeListHead(&pMnpSendBuf->Linkage);
  862. #endif
  863. // call the completion routine which will do cleanup for this buffer
  864. (pMnpSendBuf->ComplRoutine)(pMnpSendBuf,ARAPERR_NO_ERROR);
  865. }
  866. // whatever is on the ReceiveQ, try and send it off to the destination
  867. // since this data came before the disconnect came in
  868. while (1)
  869. {
  870. if ((pArapBuf = ArapExtractAtalkSRP(pArapConn)) == NULL)
  871. {
  872. // no more data left (or no complete SRP): done here
  873. break;
  874. }
  875. // was ARAP connection up? route only if it's up, otherwise drop it!
  876. if (fArapConnUp)
  877. {
  878. ArapRoutePacketFromWan( pArapConn, pArapBuf );
  879. }
  880. // we received AppleTalk data but connection wasn't up! Drop pkt
  881. else
  882. {
  883. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  884. ("ArapCleanup: (%lx) AT data, but conn not up\n",pArapConn));
  885. }
  886. #if DBG
  887. //
  888. // yeah, there is no spinlock: given our state, no one else will be
  889. // touching this field. Besides, this is debug-only!
  890. //
  891. pArapConn->RecvsPending -= pArapBuf->DataSize;
  892. #endif
  893. // done with this buffer
  894. ARAP_FREE_RCVBUF(pArapBuf);
  895. }
  896. //
  897. // if there are any buffers left on the ReceiveQ, they are basically
  898. // incomplete SRP's: throw them away
  899. //
  900. while (pRcvList != &pArapConn->ReceiveQ)
  901. {
  902. pArapBuf = CONTAINING_RECORD(pRcvList, ARAPBUF, Linkage);
  903. pRcvList = pRcvList->Flink;
  904. #if DBG
  905. // same deal again with spinlock again...
  906. pArapConn->RecvsPending -= pArapBuf->DataSize;
  907. #endif
  908. ARAP_FREE_RCVBUF(pArapBuf);
  909. }
  910. //
  911. // free up all the packets on ArapDataQ: these are not going to be of
  912. // any use, whether or not the connection was up, so best just to throw
  913. // them away (why complicate life?)
  914. //
  915. while (pArapList != &pArapConn->ArapDataQ)
  916. {
  917. pArapBuf = CONTAINING_RECORD(pArapList, ARAPBUF, Linkage);
  918. pArapList = pArapList->Flink;
  919. #if DBG
  920. // same deal again with spinlock again...
  921. pArapConn->RecvsPending -= pArapBuf->DataSize;
  922. #endif
  923. ARAP_FREE_RCVBUF(pArapBuf);
  924. }
  925. //
  926. // free up all the packets on the MiscPktsQ
  927. //
  928. while (pMiscPktList != &pArapConn->MiscPktsQ)
  929. {
  930. pArapBuf = CONTAINING_RECORD(pMiscPktList, ARAPBUF, Linkage);
  931. pMiscPktList = pMiscPktList->Flink;
  932. ARAP_FREE_RCVBUF(pArapBuf);
  933. }
  934. //
  935. // call completion routine for all the sends that were waiting to be sent
  936. // on the high priority Q
  937. //
  938. while (pSendHighList != &pArapConn->HighPriSendQ)
  939. {
  940. pMnpSendBuf = CONTAINING_RECORD(pSendHighList,MNPSENDBUF,Linkage);
  941. pSendHighList = pSendHighList->Flink;
  942. #if DBG
  943. InitializeListHead(&pMnpSendBuf->Linkage);
  944. #endif
  945. // call the completion routine which will do cleanup for this buffer
  946. (pMnpSendBuf->ComplRoutine)(pMnpSendBuf,ARAPERR_DISCONNECT_IN_PROGRESS);
  947. }
  948. //
  949. // call completion routine for all the sends that were waiting to be sent
  950. // on the Med priority Q
  951. //
  952. while (pSendMedList != &pArapConn->MedPriSendQ)
  953. {
  954. pMnpSendBuf = CONTAINING_RECORD(pSendMedList,MNPSENDBUF,Linkage);
  955. pSendMedList = pSendMedList->Flink;
  956. #if DBG
  957. InitializeListHead(&pMnpSendBuf->Linkage);
  958. #endif
  959. // call the completion routine which will do cleanup for this buffer
  960. (pMnpSendBuf->ComplRoutine)(pMnpSendBuf,ARAPERR_DISCONNECT_IN_PROGRESS);
  961. }
  962. //
  963. // call completion routine for all the sends that were waiting to be sent
  964. // on the Low priority Q
  965. //
  966. while (pSendLowList != &pArapConn->LowPriSendQ)
  967. {
  968. pMnpSendBuf = CONTAINING_RECORD(pSendLowList,MNPSENDBUF,Linkage);
  969. pSendLowList = pSendLowList->Flink;
  970. #if DBG
  971. InitializeListHead(&pMnpSendBuf->Linkage);
  972. #endif
  973. // call the completion routine which will do cleanup for this buffer
  974. (pMnpSendBuf->ComplRoutine)(pMnpSendBuf,ARAPERR_DISCONNECT_IN_PROGRESS);
  975. }
  976. //
  977. // free up all the packets on RetransmitQ that were waiting to be acked
  978. //
  979. while (pReXmitList != &pArapConn->RetransmitQ)
  980. {
  981. pMnpSendBuf = CONTAINING_RECORD(pReXmitList, MNPSENDBUF, Linkage);
  982. pReXmitList = pReXmitList->Flink;
  983. #if DBG
  984. InitializeListHead(&pMnpSendBuf->Linkage);
  985. #endif
  986. // call the completion routine which will do cleanup for this buffer
  987. (pMnpSendBuf->ComplRoutine)(pMnpSendBuf,ARAPERR_DISCONNECT_IN_PROGRESS);
  988. }
  989. // if there was an irp in progress, complete it first!
  990. if (pIrp)
  991. {
  992. pSndRcvInfo = (PARAP_SEND_RECV_INFO)pIrp->AssociatedIrp.SystemBuffer;
  993. pSndRcvInfo->StatusCode = ARAPERR_DISCONNECT_IN_PROGRESS;
  994. ARAP_COMPLETE_IRP(pIrp, sizeof(ARAP_SEND_RECV_INFO), STATUS_SUCCESS,
  995. &ReturnStatus);
  996. }
  997. // if there was an irp in progress, complete it first!
  998. if (pRcvIrp)
  999. {
  1000. pSndRcvInfo = (PARAP_SEND_RECV_INFO)pRcvIrp->AssociatedIrp.SystemBuffer;
  1001. pSndRcvInfo->StatusCode = ARAPERR_DISCONNECT_IN_PROGRESS;
  1002. ARAP_COMPLETE_IRP(pRcvIrp, sizeof(ARAP_SEND_RECV_INFO), STATUS_SUCCESS,
  1003. &ReturnStatus);
  1004. }
  1005. // if we have any sniff info, give it to dll.
  1006. ARAP_DUMP_DBG_TRACE(pArapConn);
  1007. //
  1008. // now, try telling the dll that the connection went away. (We can do this
  1009. // only using a "select" irp)
  1010. //
  1011. ACQUIRE_SPIN_LOCK(&pArapConn->SpinLock, &OldIrql);
  1012. ArapGetSelectIrp(&pDiscIrp);
  1013. // no select irp? just mark that fact, so on next select we'll tell dll
  1014. if (!pDiscIrp)
  1015. {
  1016. pArapConn->Flags |= DISCONNECT_NO_IRP;
  1017. }
  1018. RELEASE_SPIN_LOCK(&pArapConn->SpinLock, OldIrql);
  1019. //
  1020. // if we did find select irp, go ahead and tell the dll
  1021. //
  1022. if (pDiscIrp)
  1023. {
  1024. dwBytesToDll = 0;
  1025. #if DBG
  1026. //
  1027. // if we have some sniff info that we couldn't deliver earlier through
  1028. // the sniff irp, then give them through this irp: it's going back
  1029. // "empty" anyway!
  1030. //
  1031. if (pArapConn->pDbgTraceBuffer && pArapConn->SniffedBytes > 0)
  1032. {
  1033. dwBytesToDll = ArapFillIrpWithSniffInfo(pArapConn,pDiscIrp);
  1034. }
  1035. #endif
  1036. pDiscSndRcvInfo = (PARAP_SEND_RECV_INFO)pDiscIrp->AssociatedIrp.SystemBuffer;
  1037. pDiscSndRcvInfo->pDllContext = pArapConn->pDllContext;
  1038. pDiscSndRcvInfo->AtalkContext = ARAP_INVALID_CONTEXT;
  1039. pDiscSndRcvInfo->DataLen = dwBytesToDll;
  1040. pDiscSndRcvInfo->StatusCode = StatusCode;
  1041. dwBytesToDll += sizeof(ARAP_SEND_RECV_INFO);
  1042. ARAP_COMPLETE_IRP(pDiscIrp, dwBytesToDll, STATUS_SUCCESS,
  1043. &ReturnStatus);
  1044. // we told dll: remove this link
  1045. pArapConn->pDllContext = NULL;
  1046. // we told the dll, remove the connect refcount
  1047. DerefArapConn(pArapConn);
  1048. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  1049. ("ArapCleanup: told dll (%lx refcount=%d)\n",pArapConn,pArapConn->RefCount));
  1050. }
  1051. else
  1052. {
  1053. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  1054. ("ArapCleanup: no select irp, dll doesn't yet know (%lx) died\n", pArapConn));
  1055. }
  1056. // remove the creation refcount
  1057. DerefArapConn(pArapConn);
  1058. }
  1059. //***
  1060. //
  1061. // Function: PrepareConnectionResponse
  1062. // This routine parses the connect request that is first sent by
  1063. // the remote client and forms a connection response (LR frame)
  1064. // based on the options negotiated.
  1065. // This routine basically does the MNP negotiation.
  1066. //
  1067. // Parameters: pArapConn - connection element being cleaned up
  1068. // pReq - buffer containting client's original connect request
  1069. // pFrame - buffer in which we put the response
  1070. // BytesWritten - how big is the connection response
  1071. //
  1072. // Return: result of the operation (ARAPERR_....)
  1073. //
  1074. //***$
  1075. DWORD
  1076. PrepareConnectionResponse(
  1077. IN PARAPCONN pArapConn,
  1078. IN PBYTE pReq, // buffer with client's request
  1079. IN DWORD ReqLen, // how big is the request
  1080. OUT PBYTE pFrame, // buffer with our response to the client
  1081. OUT USHORT * pMnpLen
  1082. )
  1083. {
  1084. PBYTE pReqEnd;
  1085. PBYTE pFrameStart;
  1086. BYTE VarLen;
  1087. KIRQL OldIrql;
  1088. BYTE NumLTFrames=0;
  1089. USHORT MaxInfoLen=0;
  1090. USHORT FrameLen;
  1091. BYTE Mandatory[5];
  1092. BOOLEAN fOptimized=FALSE;
  1093. BOOLEAN fMaxLen256=FALSE;
  1094. BOOLEAN fV42Bis=FALSE;
  1095. BOOLEAN fArapV20=TRUE;
  1096. DWORD dwReqToSkip;
  1097. DWORD dwFrameToSkip;
  1098. BYTE JunkBuffer[MNP_MINPKT_SIZE+1];
  1099. DWORD i;
  1100. BOOLEAN fNonStd=FALSE;
  1101. DBG_ARAP_CHECK_PAGED_CODE();
  1102. #if DBG
  1103. //
  1104. // validate our assumption that all the clients always send out the same
  1105. // LR request packet
  1106. //
  1107. for (i=0; i<sizeof(ArapDbgLRPacket); i++ )
  1108. {
  1109. if (pReq[3+i] != ArapDbgLRPacket[i])
  1110. {
  1111. fNonStd = TRUE;
  1112. }
  1113. }
  1114. if (fNonStd)
  1115. {
  1116. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  1117. ("Arap Prepare..Response: non-standard LR-request packet\n"));
  1118. DbgPrint(" Std : ");
  1119. for (i=0; i<sizeof(ArapDbgLRPacket); i++)
  1120. {
  1121. DbgPrint("%2X ",ArapDbgLRPacket[i]);
  1122. }
  1123. DbgPrint("\n");
  1124. DbgPrint(" This: ");
  1125. for (i=0; i<sizeof(ArapDbgLRPacket); i++)
  1126. {
  1127. DbgPrint("%2X ",pReq[3+i]);
  1128. }
  1129. DbgPrint("\n");
  1130. }
  1131. #endif
  1132. for (i=0; i<5; i++)
  1133. {
  1134. Mandatory[i] = 0;
  1135. }
  1136. //
  1137. // in case of callback, we get an LR response from the dial-in client. When
  1138. // that happens, we still want to run through this routine to make sure all
  1139. // parameters are legal, etc., and also to "configure" the connection based
  1140. // on the parms negotiated. In that case, however, there is no output frame
  1141. // needed. So, we just write the output frame to junkbuffer
  1142. // which is obviously never used.
  1143. //
  1144. if (pFrame == NULL)
  1145. {
  1146. pFrame = &JunkBuffer[0];
  1147. }
  1148. pFrameStart = pFrame;
  1149. //
  1150. // see if this is ARAP v2.0 or v1.0 connection: we know the frame is good,
  1151. // so just look at the first byte
  1152. //
  1153. if (*pReq == MNP_SYN)
  1154. {
  1155. fArapV20 = FALSE;
  1156. }
  1157. // now copy those three start flag bytes
  1158. *pFrame++ = *pReq++;
  1159. *pFrame++ = *pReq++;
  1160. *pFrame++ = *pReq++;
  1161. // first byte (after the start flag, that is) is the length byte
  1162. FrameLen = *pReq;
  1163. if ((FrameLen > ReqLen) || (FrameLen > MNP_MINPKT_SIZE))
  1164. {
  1165. ASSERT(0);
  1166. return(ARAPERR_BAD_FORMAT);
  1167. }
  1168. pReqEnd = pReq + FrameLen;
  1169. pReq += 2; // skip over length ind. and type ind.
  1170. // Constant parameter 1 must have a value of 2
  1171. if ((*pReq++) != MNP_LR_CONST1 )
  1172. {
  1173. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  1174. ("Error: MNP_LR_CONST1 missing in conn req %lx:\n",pArapConn));
  1175. return(ARAPERR_BAD_FORMAT);
  1176. }
  1177. // we build the return frame as we parse the incoming frame: we are supposed
  1178. // to return only those options that we both receive and understand.
  1179. //
  1180. pFrame++; // we'll put the length byte at the end
  1181. *pFrame++ = MNP_LR;
  1182. *pFrame++ = MNP_LR_CONST1;
  1183. // parse all the "variable" parms until we reach end of the frame
  1184. //
  1185. while (pReq < pReqEnd)
  1186. {
  1187. switch (*pReq++)
  1188. {
  1189. //
  1190. // nothing to do here, other than verify it's valid
  1191. //
  1192. case MNP_LR_CONST2:
  1193. VarLen = *pReq++;
  1194. if ( (VarLen == 6) &&
  1195. (*(pReq ) == 1) && (*(pReq+1) == 0) &&
  1196. (*(pReq+2) == 0) && (*(pReq+3) == 0) &&
  1197. (*(pReq+4) == 0) && (*(pReq+5) == 255) )
  1198. {
  1199. *pFrame++ = MNP_LR_CONST2;
  1200. *pFrame++ = VarLen;
  1201. RtlCopyMemory(pFrame, pReq, VarLen);
  1202. pFrame += VarLen;
  1203. pReq += VarLen;
  1204. }
  1205. else
  1206. {
  1207. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  1208. ("Error: bad MNP_LR_CONST2 in conn req %lx:\n",pArapConn));
  1209. return(ARAPERR_BAD_FORMAT);
  1210. }
  1211. Mandatory[0] = 1;
  1212. break;
  1213. //
  1214. // octet-oriented or bit-oriented framing
  1215. //
  1216. case MNP_LR_FRAMING:
  1217. pReq++; // skip over length byte
  1218. //
  1219. // we only support octet-oriented framing mode
  1220. //
  1221. if (*pReq++ < MNP_FRMMODE_OCTET)
  1222. {
  1223. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  1224. ("Error: (%lx) unsupported framing mode %d requested:\n",
  1225. pArapConn,*(pReq-1)));
  1226. ASSERT(0);
  1227. return(ARAPERR_BAD_FORMAT);
  1228. }
  1229. *pFrame++ = MNP_LR_FRAMING;
  1230. *pFrame++ = 1;
  1231. *pFrame++ = MNP_FRMMODE_OCTET;
  1232. Mandatory[1] = 1;
  1233. break;
  1234. //
  1235. // Max. number of outstanding LT frames, k
  1236. //
  1237. case MNP_LR_NUMLTFRMS:
  1238. pReq++; // skip over length byte
  1239. NumLTFrames = *pReq++;
  1240. if (NumLTFrames > ArapGlobs.MaxLTFrames)
  1241. {
  1242. NumLTFrames = ArapGlobs.MaxLTFrames;
  1243. }
  1244. *pFrame++ = MNP_LR_NUMLTFRMS;
  1245. *pFrame++ = 1;
  1246. *pFrame++ = NumLTFrames;
  1247. Mandatory[2] = 1;
  1248. break;
  1249. //
  1250. // Max. information field length, N401
  1251. //
  1252. case MNP_LR_INFOLEN:
  1253. pReq++; // skip over length byte
  1254. MaxInfoLen = *((USHORT *)pReq);
  1255. ASSERT(MaxInfoLen <= 256);
  1256. *pFrame++ = MNP_LR_INFOLEN;
  1257. *pFrame++ = 2;
  1258. // we are just copying whatever client gave
  1259. *pFrame++ = *pReq++;
  1260. *pFrame++ = *pReq++;
  1261. Mandatory[3] = 1;
  1262. break;
  1263. //
  1264. // data optimization info
  1265. //
  1266. case MNP_LR_DATAOPT:
  1267. pReq++; // skip over length byte
  1268. if ((*pReq) & 0x1)
  1269. {
  1270. fMaxLen256 = TRUE;
  1271. }
  1272. if ((*pReq) & 0x2)
  1273. {
  1274. fOptimized = TRUE;
  1275. }
  1276. *pFrame++ = MNP_LR_DATAOPT;
  1277. *pFrame++ = 1;
  1278. *pFrame++ = *pReq++;
  1279. Mandatory[4] = 1;
  1280. break;
  1281. //
  1282. // v42 parameter negotiation
  1283. //
  1284. case MNP_LR_V42BIS:
  1285. fV42Bis = v42bisInit( pArapConn,
  1286. pReq,
  1287. &dwReqToSkip,
  1288. pFrame,
  1289. &dwFrameToSkip );
  1290. pReq += dwReqToSkip;
  1291. pFrame += dwFrameToSkip;
  1292. break;
  1293. //
  1294. // what the heck is this option? just skip over it!
  1295. //
  1296. default:
  1297. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  1298. ("Prepare..Response (%lx): unknown option %lx len=%ld type=%ld\n",
  1299. pArapConn, *(pReq-1), *pReq, *(pReq+1)));
  1300. VarLen = *pReq++;
  1301. pReq += VarLen;
  1302. break;
  1303. }
  1304. }
  1305. //
  1306. // make sure we got all the mandatory parameters
  1307. //
  1308. for (i=0; i<5; i++)
  1309. {
  1310. if (Mandatory[i] == 0)
  1311. {
  1312. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  1313. ("PrepareConnectionResponse: parm %d missing (%lx):\n",i,pArapConn));
  1314. return(ARAPERR_BAD_FORMAT);
  1315. }
  1316. }
  1317. // copy the stop flag
  1318. *pFrame++ = (fArapV20)? MNP_ESC : MNP_DLE;
  1319. *pFrame++ = MNP_ETX;
  1320. // store all the negotiated info
  1321. pArapConn->BlockId = (fMaxLen256)? BLKID_MNP_LGSENDBUF : BLKID_MNP_SMSENDBUF;
  1322. if (fOptimized)
  1323. {
  1324. pArapConn->Flags |= MNP_OPTIMIZED_DATA;
  1325. }
  1326. if (fV42Bis)
  1327. {
  1328. pArapConn->Flags |= MNP_V42BIS_NEGOTIATED;
  1329. }
  1330. else
  1331. {
  1332. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  1333. ("Prepare..Response: WARNING!! v42bis NOT negotiated on (%lx):\n",pArapConn));
  1334. }
  1335. if (fArapV20)
  1336. {
  1337. pArapConn->Flags |= ARAP_V20_CONNECTION;
  1338. // save the Syn,Dle,Stx,Etx bytes depeding on what connection this is
  1339. pArapConn->MnpState.SynByte = MNP_SOH;
  1340. pArapConn->MnpState.DleByte = MNP_ESC;
  1341. pArapConn->MnpState.StxByte = MNP_STX;
  1342. pArapConn->MnpState.EtxByte = MNP_ETX;
  1343. }
  1344. else
  1345. {
  1346. pArapConn->MnpState.SynByte = MNP_SYN;
  1347. pArapConn->MnpState.DleByte = MNP_DLE;
  1348. pArapConn->MnpState.StxByte = MNP_STX;
  1349. pArapConn->MnpState.EtxByte = MNP_ETX;
  1350. }
  1351. //
  1352. // if we are doing callback, we should act like the client
  1353. //
  1354. if ((pArapConn->Flags & ARAP_CALLBACK_MODE) && fArapV20)
  1355. {
  1356. pArapConn->MnpState.LTByte = MNP_LT_V20CLIENT;
  1357. }
  1358. else
  1359. {
  1360. pArapConn->MnpState.LTByte = MNP_LT;
  1361. }
  1362. pArapConn->MnpState.WindowSize = NumLTFrames;
  1363. pArapConn->MnpState.UnAckedLimit = (NumLTFrames/2);
  1364. if (pArapConn->MnpState.UnAckedLimit == 0)
  1365. {
  1366. pArapConn->MnpState.UnAckedLimit = 1;
  1367. }
  1368. pArapConn->MnpState.MaxPktSize = MaxInfoLen;
  1369. pArapConn->MnpState.SendCredit = NumLTFrames;
  1370. // how big is the mnp frame
  1371. if (pMnpLen)
  1372. {
  1373. *pMnpLen = (USHORT)(pFrame - pFrameStart);
  1374. // write the length byte
  1375. // (length byte is after the 3 start flag bytes: that's why (pFrameStart+3))
  1376. // (and exclude (3 start + 2 stop + 1 len bytes):that's why (*pMnpLen) - 6)
  1377. *(pFrameStart+3) = (*pMnpLen) - 6;
  1378. }
  1379. return( ARAPERR_NO_ERROR );
  1380. }
  1381. //***
  1382. //
  1383. // Function: ArapExtractAtalkSRP
  1384. // This routine extracts one complete SRP out of the receive
  1385. // buffer queue. One SRP could be split up into multiple receive
  1386. // buffers, or one receive buffer could contain several SRPs: it
  1387. // depends on how the client sent the data.
  1388. //
  1389. // Parameters: pArapConn - connection element in question
  1390. //
  1391. // Return: Pointer to a buffer containing one complete SRP
  1392. // NULL if there is no data, or if a complete SRP hasn't yet arrived
  1393. //
  1394. //***$
  1395. PARAPBUF
  1396. ArapExtractAtalkSRP(
  1397. IN PARAPCONN pArapConn
  1398. )
  1399. {
  1400. KIRQL OldIrql;
  1401. USHORT BytesInThisBuffer;
  1402. USHORT SrpLen;
  1403. USHORT SrpModLen;
  1404. PARAPBUF pArapBuf=NULL;
  1405. PARAPBUF pRecvBufNew=NULL;
  1406. PARAPBUF pReturnBuf=NULL;
  1407. PARAPBUF pNextRecvBuf=NULL;
  1408. PLIST_ENTRY pRcvList;
  1409. DWORD BytesOnQ;
  1410. USHORT BytesRemaining;
  1411. USHORT BytesToCopy;
  1412. BYTE DGroupByte;
  1413. BYTE TmpArray[4];
  1414. USHORT i;
  1415. DBG_ARAP_CHECK_PAGED_CODE();
  1416. ACQUIRE_SPIN_LOCK(&pArapConn->SpinLock, &OldIrql);
  1417. ARAP_CHECK_RCVQ_INTEGRITY(pArapConn);
  1418. ArapSRP_TryNext:
  1419. // list is empty?
  1420. if ((pRcvList = pArapConn->ReceiveQ.Flink) == &pArapConn->ReceiveQ)
  1421. {
  1422. RELEASE_SPIN_LOCK(&pArapConn->SpinLock, OldIrql);
  1423. return(NULL);
  1424. }
  1425. pArapBuf = CONTAINING_RECORD(pRcvList, ARAPBUF, Linkage);
  1426. // Debug only: make sure first few bytes are right...
  1427. ARAP_CHECK_RCVQ_INTEGRITY(pArapConn);
  1428. BytesInThisBuffer = pArapBuf->DataSize;
  1429. //
  1430. // if datasize goes to 0, we free the buffer right away. Also, at indicate time
  1431. // if datasize is 0, we never insert a buffer: so this had better be non-zero!
  1432. //
  1433. ASSERT(BytesInThisBuffer > 0);
  1434. //
  1435. // most common case: we at least have the 2 length bytes in the first buffer
  1436. //
  1437. if (BytesInThisBuffer >= sizeof(USHORT))
  1438. {
  1439. // get the SRP length from the length field (network to host order)
  1440. GETSHORT2SHORT(&SrpLen, pArapBuf->CurrentBuffer);
  1441. }
  1442. //
  1443. // alright, last byte of the first buffer is the 1st length byte.
  1444. // pick up the 2nd length byte from the next buffer
  1445. //
  1446. else
  1447. {
  1448. ARAP_BYTES_ON_RECVQ(pArapConn, &BytesOnQ);
  1449. if (BytesOnQ < sizeof(USHORT))
  1450. {
  1451. RELEASE_SPIN_LOCK(&pArapConn->SpinLock, OldIrql);
  1452. return(NULL);
  1453. }
  1454. pRcvList = pArapBuf->Linkage.Flink;
  1455. ASSERT(pRcvList != &pArapConn->ReceiveQ);
  1456. pNextRecvBuf = CONTAINING_RECORD(pRcvList, ARAPBUF, Linkage);
  1457. TmpArray[0] = pArapBuf->CurrentBuffer[0];
  1458. TmpArray[1] = pNextRecvBuf->CurrentBuffer[0];
  1459. GETSHORT2SHORT(&SrpLen, &TmpArray[0]);
  1460. }
  1461. if (SrpLen > ARAP_MAXPKT_SIZE_INCOMING)
  1462. {
  1463. RELEASE_SPIN_LOCK(&pArapConn->SpinLock, OldIrql);
  1464. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  1465. ("ArapExtractSRP: (%lx) too big a packet (%ld)\n",pArapConn,SrpLen));
  1466. // can't recover! kill connection here
  1467. ArapCleanup(pArapConn);
  1468. return(NULL);
  1469. }
  1470. // add the 2 len bytes. We will always deal with an SRP along
  1471. // with these 2 len bytes
  1472. SrpModLen = SrpLen + sizeof(USHORT);
  1473. //
  1474. // let's deal with the simplest case first
  1475. // (the whole pkt is just one complete SRP):
  1476. //
  1477. if (SrpModLen == BytesInThisBuffer)
  1478. {
  1479. RemoveEntryList(&pArapBuf->Linkage);
  1480. // length of the SRP pkt, plus the 2 length bytes
  1481. pArapBuf->DataSize = SrpModLen;
  1482. pReturnBuf = pArapBuf;
  1483. }
  1484. //
  1485. // The packet contains more than one SRP
  1486. // allocate a new buffer and copy the SRP, leaving remaining bytes behind
  1487. //
  1488. else if (SrpModLen < BytesInThisBuffer)
  1489. {
  1490. ARAP_GET_RIGHTSIZE_RCVBUF(SrpModLen, &pRecvBufNew);
  1491. if (pRecvBufNew == NULL)
  1492. {
  1493. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  1494. ("ArapExtractSRP: (%lx) mem alloc failed\n",pArapConn));
  1495. return(NULL);
  1496. }
  1497. RtlCopyMemory( &pRecvBufNew->Buffer[0],
  1498. pArapBuf->CurrentBuffer,
  1499. SrpModLen);
  1500. pRecvBufNew->DataSize = SrpModLen;
  1501. // changes to reflect the bytes we 'removed' in the original buffer
  1502. pArapBuf->DataSize -= SrpModLen;
  1503. pArapBuf->CurrentBuffer = pArapBuf->CurrentBuffer + SrpModLen;
  1504. pReturnBuf = pRecvBufNew;
  1505. // Debug only: make sure what we're leaving behind is good...
  1506. ARAP_CHECK_RCVQ_INTEGRITY(pArapConn);
  1507. }
  1508. //
  1509. // packet contains a partial SRP (this is a rare case, but possible)
  1510. // we must traverse the queue until we "collect" the whole SRP. If we still
  1511. // can't get one complete SRP, it's not arrived yet!
  1512. //
  1513. else // if (SrpModLen > BytesInThisBuffer)
  1514. {
  1515. ARAP_BYTES_ON_RECVQ(pArapConn, &BytesOnQ);
  1516. //
  1517. // if we have a full srp (split up across multiple buffers on the Q)
  1518. //
  1519. if (BytesOnQ >= SrpModLen)
  1520. {
  1521. //
  1522. // allocate a new buffer to hold this fragmented SRP
  1523. //
  1524. ARAP_GET_RIGHTSIZE_RCVBUF(SrpModLen, &pRecvBufNew);
  1525. if (pRecvBufNew == NULL)
  1526. {
  1527. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  1528. ("ArapExtractSRP: (%lx) mem alloc failed at II\n",pArapConn));
  1529. return(NULL);
  1530. }
  1531. pRecvBufNew->DataSize = SrpModLen;
  1532. pNextRecvBuf = pArapBuf;
  1533. BytesRemaining = SrpModLen;
  1534. while (BytesRemaining)
  1535. {
  1536. BytesToCopy = (BytesRemaining > pNextRecvBuf->DataSize) ?
  1537. pNextRecvBuf->DataSize : BytesRemaining;
  1538. RtlCopyMemory( pRecvBufNew->CurrentBuffer,
  1539. pNextRecvBuf->CurrentBuffer,
  1540. BytesToCopy );
  1541. pRecvBufNew->CurrentBuffer += BytesToCopy;
  1542. pNextRecvBuf->CurrentBuffer += BytesToCopy;
  1543. pNextRecvBuf->DataSize -= BytesToCopy;
  1544. BytesRemaining -= BytesToCopy;
  1545. pRcvList = pNextRecvBuf->Linkage.Flink;
  1546. // are we done with this buffer? if so, unlink it and free it
  1547. if (pNextRecvBuf->DataSize == 0)
  1548. {
  1549. RemoveEntryList(&pNextRecvBuf->Linkage);
  1550. ARAP_FREE_RCVBUF(pNextRecvBuf);
  1551. }
  1552. else
  1553. {
  1554. // didn't free up the buffer? we had better be done!
  1555. ASSERT(BytesRemaining == 0);
  1556. // Debug only: make sure what we're leaving behind is good...
  1557. ARAP_CHECK_RCVQ_INTEGRITY(pArapConn);
  1558. }
  1559. // there should be more data on the queue or we should be done
  1560. ASSERT(pRcvList != &pArapConn->ReceiveQ || BytesRemaining == 0);
  1561. pNextRecvBuf = CONTAINING_RECORD(pRcvList, ARAPBUF, Linkage);
  1562. }
  1563. pRecvBufNew->CurrentBuffer = &pRecvBufNew->Buffer[0];
  1564. pReturnBuf = pRecvBufNew;
  1565. }
  1566. else
  1567. {
  1568. pReturnBuf = NULL;
  1569. }
  1570. }
  1571. if (pReturnBuf)
  1572. {
  1573. DGroupByte = pReturnBuf->CurrentBuffer[ARAP_DGROUP_OFFSET];
  1574. #if DBG
  1575. ARAP_DBG_TRACE(pArapConn,21105,pReturnBuf,0,0,0);
  1576. GETSHORT2SHORT(&SrpLen, pReturnBuf->CurrentBuffer);
  1577. ASSERT(pReturnBuf->DataSize == SrpLen+2);
  1578. ASSERT(SrpLen <= ARAP_MAXPKT_SIZE_INCOMING);
  1579. if (DGroupByte != 0x10 && DGroupByte != 0x50 &&
  1580. (pArapConn->Flags & ARAP_CONNECTION_UP))
  1581. {
  1582. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  1583. ("ArapExtract: DGrpByte %x\n",DGroupByte));
  1584. ASSERT(0);
  1585. }
  1586. //
  1587. // see if we have an arap packet embedded inside another arap packet
  1588. // This is an expensive way, but it's debug only: who cares!
  1589. //
  1590. for (i=6; i<(pReturnBuf->DataSize-6); i++)
  1591. {
  1592. if ((pReturnBuf->CurrentBuffer[i] == 0x10) ||
  1593. (pReturnBuf->CurrentBuffer[i] == 0x50))
  1594. {
  1595. if (pReturnBuf->CurrentBuffer[i+1] == 0)
  1596. {
  1597. if (pReturnBuf->CurrentBuffer[i+2] == 0)
  1598. {
  1599. if (pReturnBuf->CurrentBuffer[i+3] == 0x2)
  1600. {
  1601. if (pReturnBuf->CurrentBuffer[i+4] == 0)
  1602. {
  1603. if (pReturnBuf->CurrentBuffer[i+5] == 0)
  1604. {
  1605. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  1606. ("ArapExtract: ERROR?: embedded arap packet at %lx? (%lx)\n",
  1607. &pReturnBuf->CurrentBuffer[i],pReturnBuf));
  1608. }
  1609. }
  1610. }
  1611. }
  1612. }
  1613. }
  1614. }
  1615. #endif
  1616. //
  1617. // is it out-of-band ARAP data? If so, put it on its own queue, and
  1618. // try to extract another SRP
  1619. //
  1620. if (!(DGroupByte & ARAP_SFLAG_PKT_DATA))
  1621. {
  1622. InsertTailList(&pArapConn->ArapDataQ, &pReturnBuf->Linkage);
  1623. goto ArapSRP_TryNext;
  1624. }
  1625. }
  1626. RELEASE_SPIN_LOCK(&pArapConn->SpinLock, OldIrql);
  1627. return(pReturnBuf);
  1628. }
  1629. //***
  1630. //
  1631. // Function: ArapQueueSendBytes
  1632. // This routine takes compressed data and puts it into MNP packets
  1633. // ready to be sent out. If the last unsent buffer on the queue
  1634. // has some room left, it first stuffs as many bytes as possible
  1635. // in that buffer. After that, if necessary, it allocates a new
  1636. // buffer and puts the remaining bytes in that buffer.
  1637. // The max data in any buffer can only be the negotiated maximum
  1638. // MNP data length (64 or 256 bytes)
  1639. //
  1640. // Parameters: pArapConn - connection element in question
  1641. // pCompressedDataBuffer - pointer to the data to be sent out
  1642. // CompressedDataLen - size of the outgoing data
  1643. // Priority - priority of the send
  1644. //
  1645. // Return: Error code
  1646. //
  1647. //
  1648. // NOTES: IMPORTANT: spinlock must be held before calling this routine
  1649. //
  1650. //***$
  1651. DWORD
  1652. ArapQueueSendBytes(
  1653. IN PARAPCONN pArapConn,
  1654. IN PBYTE pCompressedDataBuffer,
  1655. IN DWORD CompressedDataLen,
  1656. IN DWORD Priority
  1657. )
  1658. {
  1659. DWORD StatusCode;
  1660. PLIST_ENTRY pSendQHead;
  1661. PMNPSENDBUF pMnpSendBuf=NULL;
  1662. PBYTE pFrame, pFrameStart;
  1663. DWORD dwRemainingBytes;
  1664. PMNPSENDBUF pTailMnpSendBuf=NULL;
  1665. PMNPSENDBUF pFirstMnpSendBuf=NULL;
  1666. USHORT DataLenInThisPkt;
  1667. PLIST_ENTRY pList;
  1668. USHORT DataSizeOfOrgTailSend;
  1669. PBYTE FreeBufferOfOrgTailSend;
  1670. BYTE NumSendsOfOrgTailSend;
  1671. BOOLEAN fNeedNewBuffer;
  1672. PLIST_ENTRY pSendList;
  1673. USHORT BytesFree;
  1674. PBYTE pCompressedData;
  1675. BYTE DbgStartSeq;
  1676. DBG_ARAP_CHECK_PAGED_CODE();
  1677. if (Priority == ARAP_SEND_PRIORITY_HIGH)
  1678. {
  1679. pSendQHead = &pArapConn->HighPriSendQ;
  1680. }
  1681. else if (Priority == ARAP_SEND_PRIORITY_MED)
  1682. {
  1683. pSendQHead = &pArapConn->MedPriSendQ;
  1684. }
  1685. else
  1686. {
  1687. pSendQHead = &pArapConn->LowPriSendQ;
  1688. }
  1689. #if DBG
  1690. DbgStartSeq = pArapConn->MnpState.NextToSend;
  1691. #endif
  1692. //
  1693. // first, find the last send-buffer on the queue and see if its buffer has
  1694. // any bytes free that we can use
  1695. //
  1696. fNeedNewBuffer = TRUE;
  1697. if (!IsListEmpty(pSendQHead))
  1698. {
  1699. pList = pSendQHead->Blink;
  1700. pTailMnpSendBuf = CONTAINING_RECORD(pList, MNPSENDBUF, Linkage);
  1701. BytesFree = pTailMnpSendBuf->BytesFree;
  1702. //
  1703. // if there are more than 3 bytes free, we will use the part of this
  1704. // buffer that's free: otherwise, let's go for a new one
  1705. //
  1706. if (BytesFree > ARAP_HDRSIZE)
  1707. {
  1708. pMnpSendBuf = pTailMnpSendBuf;
  1709. pFrame = pTailMnpSendBuf->FreeBuffer;
  1710. pFrameStart = pFrame;
  1711. fNeedNewBuffer = FALSE;
  1712. // save these, in case we have to bail out
  1713. DataSizeOfOrgTailSend = pTailMnpSendBuf->DataSize;
  1714. FreeBufferOfOrgTailSend = pTailMnpSendBuf->FreeBuffer;
  1715. NumSendsOfOrgTailSend = pMnpSendBuf->NumSends;
  1716. // mark that we are stuffing one more send into this buffer
  1717. pMnpSendBuf->NumSends++;
  1718. }
  1719. else
  1720. {
  1721. pTailMnpSendBuf = NULL;
  1722. }
  1723. }
  1724. dwRemainingBytes = CompressedDataLen;
  1725. pCompressedData = pCompressedDataBuffer;
  1726. // we are adding so many more bytes to our send queue
  1727. pArapConn->SendsPending += CompressedDataLen;
  1728. while (dwRemainingBytes)
  1729. {
  1730. if (fNeedNewBuffer)
  1731. {
  1732. pMnpSendBuf = ArapGetSendBuf(pArapConn, Priority);
  1733. if (pMnpSendBuf == NULL)
  1734. {
  1735. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  1736. ("ArapQueueSendBytes: ArapGetSendBuf failed (%lx)\n", pArapConn));
  1737. StatusCode = ARAPERR_OUT_OF_RESOURCES;
  1738. goto ArapQueueSendBytes_ErrExit;
  1739. }
  1740. // put MNPSend refcount
  1741. pArapConn->RefCount++;
  1742. BytesFree = pMnpSendBuf->BytesFree;
  1743. pFrameStart = pFrame = pMnpSendBuf->FreeBuffer;
  1744. //
  1745. // remeber the first buffer, in case we have to bail out!
  1746. //
  1747. if (!pFirstMnpSendBuf)
  1748. {
  1749. pFirstMnpSendBuf = pMnpSendBuf;
  1750. }
  1751. // put this send on the appropriate send queue
  1752. InsertTailList(pSendQHead, &pMnpSendBuf->Linkage);
  1753. pMnpSendBuf->NumSends = 1;
  1754. }
  1755. if (dwRemainingBytes > BytesFree)
  1756. {
  1757. DataLenInThisPkt = BytesFree;
  1758. }
  1759. else
  1760. {
  1761. DataLenInThisPkt = (USHORT)dwRemainingBytes;
  1762. }
  1763. ASSERT(DataLenInThisPkt <= MNP_MAXPKT_SIZE);
  1764. ASSERT(DataLenInThisPkt <= pMnpSendBuf->BytesFree);
  1765. RtlCopyMemory(pFrame, pCompressedData, DataLenInThisPkt);
  1766. dwRemainingBytes -= DataLenInThisPkt;
  1767. pCompressedData += DataLenInThisPkt;
  1768. ASSERT(pCompressedData <= pCompressedDataBuffer + CompressedDataLen);
  1769. pMnpSendBuf->BytesFree -= DataLenInThisPkt;
  1770. pMnpSendBuf->DataSize += DataLenInThisPkt;
  1771. ASSERT(pMnpSendBuf->DataSize <= MNP_MAXPKT_SIZE);
  1772. pFrame += DataLenInThisPkt;
  1773. // buffer from this point on is free: we could (in a subsequent call)
  1774. // stuff more bytes, starting from this point
  1775. pMnpSendBuf->FreeBuffer = pFrame;
  1776. //
  1777. // we are either done with copying the entire send, or done with this
  1778. // buffer: in either case, put those stop flag bytes
  1779. //
  1780. *pFrame++ = pArapConn->MnpState.DleByte;
  1781. *pFrame++ = pArapConn->MnpState.EtxByte;
  1782. ASSERT(pMnpSendBuf->FreeBuffer <=
  1783. (&pMnpSendBuf->Buffer[0] + 20 + MNP_MAXPKT_SIZE));
  1784. AtalkSetSizeOfBuffDescData(&pMnpSendBuf->sb_BuffDesc,
  1785. (pMnpSendBuf->DataSize + MNP_OVERHD(pArapConn)));
  1786. fNeedNewBuffer = TRUE;
  1787. }
  1788. ARAP_DBG_TRACE(pArapConn,21205,pCompressedDataBuffer,CompressedDataLen,
  1789. Priority,DbgStartSeq);
  1790. return( ARAPERR_NO_ERROR );
  1791. ArapQueueSendBytes_ErrExit:
  1792. //
  1793. // we failed somewhere. Undo whatever we did, to restore the original
  1794. // state and free up whatever resources were allocated.
  1795. //
  1796. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  1797. ("ArapQueueSendBytes_ErrExit (%lx): taking _ErrExit! %ld\n",
  1798. pArapConn,StatusCode));
  1799. pArapConn->SendsPending -= CompressedDataLen;
  1800. // did we fill any bytes in the older buf before allocating new one?
  1801. if (pTailMnpSendBuf)
  1802. {
  1803. pTailMnpSendBuf->DataSize = DataSizeOfOrgTailSend;
  1804. pTailMnpSendBuf->FreeBuffer = pFrame = FreeBufferOfOrgTailSend;
  1805. pTailMnpSendBuf->NumSends = NumSendsOfOrgTailSend;
  1806. // and don't forget those stop flag bytes we overwrote
  1807. *pFrame++ = pArapConn->MnpState.DleByte;
  1808. *pFrame++ = pArapConn->MnpState.EtxByte;
  1809. }
  1810. // did we allocate any new buffers? if so, remove and free them
  1811. if (pFirstMnpSendBuf)
  1812. {
  1813. // restore the next-to-send seq num
  1814. pArapConn->MnpState.NextToSend = pFirstMnpSendBuf->SeqNum;
  1815. while (1)
  1816. {
  1817. // get the next guy first
  1818. pSendList = pFirstMnpSendBuf->Linkage.Flink;
  1819. // remove this one
  1820. RemoveEntryList(&pFirstMnpSendBuf->Linkage);
  1821. ArapNdisFreeBuf(pFirstMnpSendBuf);
  1822. // the guy we thought was next might be the head of list: is he?
  1823. if (pSendList == pSendQHead)
  1824. {
  1825. break;
  1826. }
  1827. pFirstMnpSendBuf = CONTAINING_RECORD(pSendList, MNPSENDBUF, Linkage);
  1828. }
  1829. }
  1830. return(StatusCode);
  1831. }
  1832. //***
  1833. //
  1834. // Function: ArapGetSendBuf
  1835. // This routine allocates a buffer for MNP send and sets it up
  1836. // sending.
  1837. // The max data in any buffer can only be the negotiated maximum
  1838. // MNP data length (64 or 256 bytes)
  1839. //
  1840. // Parameters: pArapConn - connection element in question
  1841. // Priority - priority of the send
  1842. //
  1843. // Return: Pointer to the newly allocated send buffer
  1844. //
  1845. //
  1846. // NOTES: IMPORTANT: spinlock must be held before calling this routine
  1847. //
  1848. //***$
  1849. PMNPSENDBUF
  1850. ArapGetSendBuf(
  1851. IN PARAPCONN pArapConn,
  1852. IN DWORD Priority
  1853. )
  1854. {
  1855. PBYTE pFrame;
  1856. PBYTE pFrameStart;
  1857. BYTE SeqNum;
  1858. PMNPSENDBUF pMnpSendBuf;
  1859. DBG_ARAP_CHECK_PAGED_CODE();
  1860. // allocate an arap send buffer
  1861. pMnpSendBuf = AtalkBPAllocBlock(pArapConn->BlockId);
  1862. if (pMnpSendBuf == NULL)
  1863. {
  1864. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  1865. ("ArapGetSendBuf: alloc failed (%lx)\n", pArapConn));
  1866. ASSERT(0);
  1867. return( NULL );
  1868. }
  1869. #if DBG
  1870. pMnpSendBuf->Signature = (pArapConn->BlockId == BLKID_MNP_LGSENDBUF)?
  1871. MNPLGSENDBUF_SIGNATURE : MNPSMSENDBUF_SIGNATURE;
  1872. InitializeListHead(&pMnpSendBuf->Linkage);
  1873. #endif
  1874. pFrameStart = pFrame = &pMnpSendBuf->Buffer[0];
  1875. AtalkNdisBuildARAPHdr(pFrame, pArapConn);
  1876. pFrame += WAN_LINKHDR_LEN;
  1877. // put the start flag bytes
  1878. *pFrame++ = pArapConn->MnpState.SynByte;
  1879. *pFrame++ = pArapConn->MnpState.DleByte;
  1880. *pFrame++ = pArapConn->MnpState.StxByte;
  1881. //
  1882. // find out what's going to be the seq num for this send if this is a high
  1883. // priority send.
  1884. //
  1885. //
  1886. if (Priority == ARAP_SEND_PRIORITY_HIGH)
  1887. {
  1888. SeqNum = pArapConn->MnpState.NextToSend;
  1889. ADD_ONE(pArapConn->MnpState.NextToSend);
  1890. }
  1891. //
  1892. // For the medium and low priority send, we'll put the seq number when we
  1893. // move it to the high-priority queue
  1894. //
  1895. else
  1896. {
  1897. SeqNum = 0;
  1898. }
  1899. // Optimized? put the header-length, type indication and the seq num
  1900. if (pArapConn->Flags & MNP_OPTIMIZED_DATA)
  1901. {
  1902. *pFrame++ = 2;
  1903. *pFrame++ = pArapConn->MnpState.LTByte;
  1904. *pFrame++ = SeqNum;
  1905. }
  1906. // ok, non-optimized. put the header-length, type indication, type+len for
  1907. // the variable parm and then the seq num
  1908. else
  1909. {
  1910. *pFrame++ = 4;
  1911. *pFrame++ = pArapConn->MnpState.LTByte;
  1912. *pFrame++ = 1;
  1913. *pFrame++ = 1;
  1914. *pFrame++ = SeqNum;
  1915. }
  1916. pMnpSendBuf->BytesFree = (pArapConn->BlockId == BLKID_MNP_SMSENDBUF) ?
  1917. MNP_MINPKT_SIZE : MNP_MAXPKT_SIZE;
  1918. pMnpSendBuf->DataSize = 0;
  1919. pMnpSendBuf->FreeBuffer = pFrame;
  1920. // store info that's used in retransmission and send completion
  1921. pMnpSendBuf->SeqNum = SeqNum;
  1922. pMnpSendBuf->RetryCount = 0;
  1923. pMnpSendBuf->pArapConn = pArapConn;
  1924. pMnpSendBuf->ComplRoutine = ArapMnpSendComplete;
  1925. pMnpSendBuf->TimeAlloced = AtalkGetCurrentTick();
  1926. pMnpSendBuf->Flags = 0;
  1927. // MNP refcount: removed when this MNP pkt is acked
  1928. pMnpSendBuf->RefCount = 1;
  1929. ((PBUFFER_HDR)pMnpSendBuf)->bh_NdisPkt = NULL;
  1930. pArapConn->StatInfo.BytesSent += LT_OVERHEAD(pArapConn);
  1931. return(pMnpSendBuf);
  1932. }
  1933. //***
  1934. //
  1935. // Function: ArapRefillSendQ
  1936. // This routine removes bytes accumulated in the medium and the
  1937. // low-priority send queues, and puts them on to the high priority
  1938. // queue from where bytes are actually sent out. If sufficient
  1939. // bytes haven't accumulated as yet on either of the queus and we
  1940. // haven't waited long enough as yet, then we skip that queue (to
  1941. // allow more bytes to accumulate)
  1942. // The idea behind this is: there are just too many NBP packets
  1943. // - directed as well as broadcast - going toward the remote client.
  1944. // If we send such a packet as soon as it arrives, we end up sending
  1945. // numerous small sized (like 6 or 8 byte) sends to the client and
  1946. // that really hurts throughput as typically the max size is 256!
  1947. //
  1948. // Parameters: pArapConn - connection element in question
  1949. //
  1950. // Return: TRUE if we moved any data to the higher priority queue
  1951. //
  1952. //***$
  1953. BOOLEAN
  1954. ArapRefillSendQ(
  1955. IN PARAPCONN pArapConn
  1956. )
  1957. {
  1958. KIRQL OldIrql;
  1959. PMNPSENDBUF pMnpSendBuf=NULL;
  1960. PLIST_ENTRY pSendHead;
  1961. PLIST_ENTRY pSendList;
  1962. LONG TimeWaited;
  1963. BYTE SeqNum;
  1964. BOOLEAN fMovedSomething=FALSE;
  1965. BOOLEAN fWaitLonger=FALSE;
  1966. DWORD SeqOffset;
  1967. DBG_ARAP_CHECK_PAGED_CODE();
  1968. ACQUIRE_SPIN_LOCK(&pArapConn->SpinLock, &OldIrql);
  1969. pSendHead = &pArapConn->MedPriSendQ;
  1970. while (1)
  1971. {
  1972. pSendList = pSendHead->Flink;
  1973. //
  1974. // if the list is not empty, take a look at the first send. If we have
  1975. // accumulated enough bytes, or if we have waited long enough, then it's
  1976. // time has come to be moved to the HighPriSendQ. Otherwise, we let it
  1977. // stay on the queue for some more coalescing
  1978. //
  1979. if (pSendList != pSendHead)
  1980. {
  1981. pMnpSendBuf = CONTAINING_RECORD(pSendList,MNPSENDBUF,Linkage);
  1982. TimeWaited = AtalkGetCurrentTick() - pMnpSendBuf->TimeAlloced;
  1983. fWaitLonger =
  1984. ((pMnpSendBuf->DataSize < ARAP_SEND_COALESCE_SIZE_LIMIT) &&
  1985. (pMnpSendBuf->NumSends < ARAP_SEND_COALESCE_SRP_LIMIT) &&
  1986. (TimeWaited < ARAP_SEND_COALESCE_TIME_LIMIT) );
  1987. }
  1988. //
  1989. // if this list is empty or if this send must wait for some more time
  1990. // then we must move to the LOW pri queue. If that's also done, quit
  1991. //
  1992. if ((pSendList == pSendHead) || fWaitLonger )
  1993. {
  1994. // if we were on MedPriSendQ, go to the LowPriSendQ
  1995. if (pSendHead == &pArapConn->MedPriSendQ)
  1996. {
  1997. pSendHead = &pArapConn->LowPriSendQ;
  1998. continue;
  1999. }
  2000. else
  2001. {
  2002. break;
  2003. }
  2004. }
  2005. ASSERT(!fWaitLonger);
  2006. //
  2007. // time to move this send over to the high pri queue:
  2008. // put that seq number we had postponed putting earlier
  2009. //
  2010. SeqNum = pArapConn->MnpState.NextToSend;
  2011. ADD_ONE(pArapConn->MnpState.NextToSend);
  2012. SeqOffset = WAN_LINKHDR_LEN + LT_SEQ_OFFSET(pArapConn);
  2013. pMnpSendBuf->Buffer[SeqOffset] = SeqNum;
  2014. pMnpSendBuf->SeqNum = SeqNum;
  2015. RemoveEntryList(&pMnpSendBuf->Linkage);
  2016. InsertTailList(&pArapConn->HighPriSendQ, &pMnpSendBuf->Linkage);
  2017. fMovedSomething = TRUE;
  2018. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  2019. ("ArapRefill: moved %s seq %lx size = %d wait = %d (%d SRPs)\n",
  2020. (pSendHead == &pArapConn->MedPriSendQ)? "MED":"LOW",
  2021. pMnpSendBuf->SeqNum,pMnpSendBuf->DataSize,TimeWaited,
  2022. pMnpSendBuf->NumSends));
  2023. }
  2024. RELEASE_SPIN_LOCK(&pArapConn->SpinLock, OldIrql);
  2025. return(fMovedSomething);
  2026. }
  2027. //***
  2028. //
  2029. // Function: ArapUnblockSelect
  2030. // This function is called when the DLL (ARAP Engine) tells us that
  2031. // it's going away. In ideal world, select irp is the only thing
  2032. // that should get completed here. If any connection was left
  2033. // or any irp wasn't complete yet, this is where we would cleanup!
  2034. //
  2035. // Parameters: None
  2036. //
  2037. // Return: result of the operation (ARAPERR_....)
  2038. //
  2039. //***$
  2040. DWORD
  2041. ArapUnblockSelect(
  2042. IN VOID
  2043. )
  2044. {
  2045. KIRQL OldIrql;
  2046. PIRP pIrp;
  2047. PIRP pSniffIrp;
  2048. PARAP_SEND_RECV_INFO pSndRcvInfo;
  2049. NTSTATUS ReturnStatus=STATUS_SUCCESS;
  2050. ARAPTRACE(("Entered ArapUnblockSelect\n"));
  2051. ACQUIRE_SPIN_LOCK(&ArapSpinLock, &OldIrql);
  2052. pIrp = ArapSelectIrp;
  2053. ArapSelectIrp = NULL;
  2054. #if DBG
  2055. pSniffIrp = ArapSniffIrp;
  2056. ArapSniffIrp = NULL;
  2057. #endif
  2058. if (ArapStackState == ARAP_STATE_ACTIVE)
  2059. {
  2060. ArapStackState = ARAP_STATE_ACTIVE_WAITING;
  2061. }
  2062. else if (ArapStackState == ARAP_STATE_INACTIVE)
  2063. {
  2064. ArapStackState = ARAP_STATE_INACTIVE_WAITING;
  2065. }
  2066. RELEASE_SPIN_LOCK(&ArapSpinLock, OldIrql);
  2067. #if DBG
  2068. //
  2069. // if we had sniffing going, complete the sniff irp since dll is shutting down
  2070. //
  2071. if (pSniffIrp)
  2072. {
  2073. pSndRcvInfo = (PARAP_SEND_RECV_INFO)pSniffIrp->AssociatedIrp.SystemBuffer;
  2074. pSndRcvInfo->StatusCode = ARAPERR_SHUTDOWN_COMPLETE;
  2075. // complete the irp
  2076. ARAP_COMPLETE_IRP(pSniffIrp, sizeof(ARAP_SEND_RECV_INFO),
  2077. STATUS_SUCCESS, &ReturnStatus);
  2078. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  2079. ("ArapUnblockSelect: unblocked the sniff irp\n"));
  2080. }
  2081. #endif
  2082. //
  2083. // complete the select irp, now that the engine tells us that it wants to
  2084. // shutdown
  2085. //
  2086. if (pIrp)
  2087. {
  2088. pSndRcvInfo = (PARAP_SEND_RECV_INFO)pIrp->AssociatedIrp.SystemBuffer;
  2089. pSndRcvInfo->StatusCode = ARAPERR_SHUTDOWN_COMPLETE;
  2090. // complete the irp
  2091. ARAP_COMPLETE_IRP(pIrp, sizeof(ARAP_SEND_RECV_INFO), STATUS_SUCCESS,
  2092. &ReturnStatus);
  2093. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  2094. ("ArapUnblockSelect: unblocked the select irp\n"));
  2095. }
  2096. else
  2097. {
  2098. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  2099. ("ArapUnblockSelect: select irp not yet unblocked\n"));
  2100. }
  2101. return(ARAPERR_NO_ERROR);
  2102. }
  2103. //***
  2104. //
  2105. // Function: ArapReleaseResources
  2106. // This routine frees up any global resources we had allocated
  2107. //
  2108. // Parameters: None
  2109. //
  2110. // Return: result of the operation (ARAPERR_....)
  2111. //
  2112. //***$
  2113. DWORD
  2114. ArapReleaseResources(
  2115. IN VOID
  2116. )
  2117. {
  2118. KIRQL OldIrql;
  2119. PLIST_ENTRY pList;
  2120. PADDRMGMT pAddrMgmt;
  2121. PADDRMGMT pNextAddrMgmt;
  2122. PARAPCONN pArapConn;
  2123. ARAPTRACE(("Entered ArapReleaseResources\n"));
  2124. if (RasPortDesc == NULL)
  2125. {
  2126. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  2127. ("ArapReleaseResources: arap engine never initialized; returning\n"));
  2128. return(ARAPERR_NO_ERROR);
  2129. }
  2130. #if ARAP_STATIC_MODE
  2131. //
  2132. // if we were in the static mode of network address allocation, we
  2133. // allocated memory for our network address "bitmap": free that here.
  2134. //
  2135. if (!(ArapGlobs.DynamicMode))
  2136. {
  2137. pAddrMgmt = ArapGlobs.pAddrMgmt;
  2138. ASSERT(pAddrMgmt);
  2139. while (pAddrMgmt)
  2140. {
  2141. pNextAddrMgmt = pAddrMgmt->Next;
  2142. AtalkFreeMemory(pAddrMgmt);
  2143. pAddrMgmt = pNextAddrMgmt;
  2144. }
  2145. }
  2146. #endif
  2147. //
  2148. // By the time this routine is called, all the connections should have been
  2149. // completely closed. If, however, some connection got stuck in some weird
  2150. // state, at least make sure that we don't have a memory leak
  2151. //
  2152. ASSERT(IsListEmpty(&RasPortDesc->pd_ArapConnHead));
  2153. while (1)
  2154. {
  2155. ACQUIRE_SPIN_LOCK(&RasPortDesc->pd_Lock, &OldIrql);
  2156. if (IsListEmpty(&RasPortDesc->pd_ArapConnHead))
  2157. {
  2158. RELEASE_SPIN_LOCK(&RasPortDesc->pd_Lock, OldIrql);
  2159. break;
  2160. }
  2161. pList = RasPortDesc->pd_ArapConnHead.Flink;
  2162. pArapConn = CONTAINING_RECORD(pList, ARAPCONN, Linkage);
  2163. ACQUIRE_SPIN_LOCK_DPC(&pArapConn->SpinLock);
  2164. // protect against it going away while we do this
  2165. pArapConn->RefCount++;
  2166. RELEASE_SPIN_LOCK_DPC(&pArapConn->SpinLock);
  2167. RELEASE_SPIN_LOCK(&RasPortDesc->pd_Lock, OldIrql);
  2168. ArapCleanup(pArapConn);
  2169. ACQUIRE_SPIN_LOCK(&RasPortDesc->pd_Lock, &OldIrql);
  2170. ACQUIRE_SPIN_LOCK_DPC(&pArapConn->SpinLock);
  2171. RemoveEntryList(&pArapConn->Linkage);
  2172. InitializeListHead(&pArapConn->Linkage);
  2173. // force this connection to be freed
  2174. pArapConn->RefCount = 1;
  2175. RELEASE_SPIN_LOCK_DPC(&pArapConn->SpinLock);
  2176. RELEASE_SPIN_LOCK(&RasPortDesc->pd_Lock, OldIrql);
  2177. DerefArapConn(pArapConn);
  2178. }
  2179. return(ARAPERR_NO_ERROR);
  2180. }
  2181. //***
  2182. //
  2183. // Function: AtalkReferenceRasDefPort
  2184. // This routine puts a refcount on the Default adapter so it doesn't go away
  2185. // with PnP while we are busy doing some ARAP/PPP connection setup
  2186. // It also makes sure that RasPortDesc is indeed present
  2187. //
  2188. // Parameters: None
  2189. //
  2190. // Return: TRUE (most cases) if port is all ok, FALSE if PnP in progress or something
  2191. //
  2192. //***$
  2193. BOOLEAN
  2194. AtalkReferenceRasDefPort(
  2195. IN VOID
  2196. )
  2197. {
  2198. KIRQL OldIrql;
  2199. BOOLEAN fDefPortOk = FALSE;
  2200. ACQUIRE_SPIN_LOCK(&AtalkPortLock, &OldIrql);
  2201. if ((RasPortDesc != NULL) && (!(RasPortDesc->pd_Flags & PD_PNP_RECONFIGURE)))
  2202. {
  2203. if (AtalkDefaultPort)
  2204. {
  2205. ACQUIRE_SPIN_LOCK_DPC(&AtalkDefaultPort->pd_Lock);
  2206. if ((AtalkDefaultPort->pd_Flags &
  2207. (PD_ACTIVE | PD_PNP_RECONFIGURE | PD_CLOSING)) == PD_ACTIVE)
  2208. {
  2209. // put a IrpProcess refcount, so AtalkDefaultPort doesn't go away in PnP
  2210. AtalkDefaultPort->pd_RefCount++;
  2211. fDefPortOk = TRUE;
  2212. }
  2213. else
  2214. {
  2215. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_ERR,
  2216. ("AtalkReferenceRasDefPort: port going away, no can do (%lx)\n",
  2217. AtalkDefaultPort->pd_Flags));
  2218. }
  2219. RELEASE_SPIN_LOCK_DPC(&AtalkDefaultPort->pd_Lock);
  2220. }
  2221. else
  2222. {
  2223. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_ERR,
  2224. ("AtalkReferenceRasDefPort: no default adapter configured!\n"));
  2225. }
  2226. }
  2227. else
  2228. {
  2229. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_ERR,
  2230. ("AtalkReferenceRasDefPort: RasPortDesc not configured\n"));
  2231. }
  2232. RELEASE_SPIN_LOCK(&AtalkPortLock, OldIrql);
  2233. return(fDefPortOk);
  2234. }
  2235. VOID
  2236. AtalkPnPInformRas(
  2237. IN BOOLEAN fEnableRas
  2238. )
  2239. {
  2240. PIRP pIrp=NULL;
  2241. PARAP_SEND_RECV_INFO pSndRcvInfo;
  2242. DWORD StatusCode;
  2243. KIRQL OldIrql;
  2244. NTSTATUS ReturnStatus=STATUS_SUCCESS;
  2245. //
  2246. // fEnableRas = TRUE: we are asked to inform RAS (aka dll, engine) that the stack
  2247. // is now "active" (i.e. available for RAS connections)
  2248. //
  2249. if (fEnableRas)
  2250. {
  2251. //
  2252. // make sure both the adapters are ready. We don't really need spinlock to
  2253. // check the flag since all PnP operations are guaranteed to be serialized
  2254. //
  2255. if ( (AtalkDefaultPort == NULL) ||
  2256. (AtalkDefaultPort->pd_Flags & PD_PNP_RECONFIGURE) ||
  2257. (RasPortDesc == NULL) ||
  2258. (RasPortDesc->pd_Flags & PD_PNP_RECONFIGURE) )
  2259. {
  2260. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  2261. ("AtalkPnPInformRas: not both adapters are ready %lx %lx, returning\n",
  2262. AtalkDefaultPort,RasPortDesc));
  2263. return;
  2264. }
  2265. ACQUIRE_SPIN_LOCK(&ArapSpinLock, &OldIrql);
  2266. //
  2267. // if we are already active, nothing to do!
  2268. //
  2269. if (ArapStackState == ARAP_STATE_ACTIVE)
  2270. {
  2271. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  2272. ("AtalkPnPInformRas: stack already active, nothing to do\n"));
  2273. RELEASE_SPIN_LOCK(&ArapSpinLock, OldIrql);
  2274. return;
  2275. }
  2276. pIrp = ArapSelectIrp;
  2277. ArapSelectIrp = NULL;
  2278. if (pIrp)
  2279. {
  2280. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  2281. ("AtalkPnPInformRas: informing dll that stack is ready\n"));
  2282. ArapStackState = ARAP_STATE_ACTIVE;
  2283. StatusCode = ARAPERR_STACK_IS_ACTIVE;
  2284. }
  2285. else
  2286. {
  2287. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  2288. ("AtalkPnPInformRas: no select irp. stack ready, but dll not knoweth\n"));
  2289. ArapStackState = ARAP_STATE_ACTIVE_WAITING;
  2290. }
  2291. RELEASE_SPIN_LOCK(&ArapSpinLock, OldIrql);
  2292. }
  2293. //
  2294. // fEnableRas = FALSE: we are asked to inform RAS (aka dll, engine) that the stack
  2295. // is now "inactive" (i.e. not available for RAS connections)
  2296. //
  2297. else
  2298. {
  2299. ACQUIRE_SPIN_LOCK(&ArapSpinLock, &OldIrql);
  2300. //
  2301. // if we are already inactive, nothing to do!
  2302. //
  2303. if (ArapStackState == ARAP_STATE_INACTIVE)
  2304. {
  2305. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  2306. ("AtalkPnPInformRas: stack already inactive, nothing to do\n"));
  2307. RELEASE_SPIN_LOCK(&ArapSpinLock, OldIrql);
  2308. return;
  2309. }
  2310. pIrp = ArapSelectIrp;
  2311. ArapSelectIrp = NULL;
  2312. if (pIrp)
  2313. {
  2314. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  2315. ("AtalkPnPInformRas: informing dll that stack is unavailable\n"));
  2316. ArapStackState = ARAP_STATE_INACTIVE;
  2317. StatusCode = ARAPERR_STACK_IS_NOT_ACTIVE;
  2318. }
  2319. else
  2320. {
  2321. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  2322. ("AtalkPnPInformRas: no select irp. stack unavailable, but dll not knoweth\n"));
  2323. ArapStackState = ARAP_STATE_INACTIVE_WAITING;
  2324. }
  2325. RELEASE_SPIN_LOCK(&ArapSpinLock, OldIrql);
  2326. }
  2327. if (pIrp)
  2328. {
  2329. pSndRcvInfo = (PARAP_SEND_RECV_INFO)pIrp->AssociatedIrp.SystemBuffer;
  2330. pSndRcvInfo->StatusCode = StatusCode;
  2331. // complete the irp
  2332. ARAP_COMPLETE_IRP(pIrp, sizeof(ARAP_SEND_RECV_INFO), STATUS_SUCCESS,
  2333. &ReturnStatus);
  2334. }
  2335. }
  2336. #if ARAP_STATIC_MODE
  2337. //***
  2338. //
  2339. // Function: ArapReleaseAddr
  2340. // This routine releases the network address that was being used
  2341. // by the client (corresponding to this connection). In case of
  2342. // dynamic mode, we don't do anything.
  2343. // In case of static mode, we clear the bit corresponding to this
  2344. // particular network address.
  2345. //
  2346. // Parameters: pArapConn - connection element in question
  2347. //
  2348. // Return: none
  2349. //
  2350. //***$
  2351. VOID
  2352. ArapReleaseAddr(
  2353. IN PARAPCONN pArapConn
  2354. )
  2355. {
  2356. KIRQL OldIrql;
  2357. PADDRMGMT pAddrMgmt;
  2358. BYTE Node;
  2359. BYTE ByteNum;
  2360. BYTE BitMask;
  2361. DWORD i;
  2362. DBG_ARAP_CHECK_PAGED_CODE();
  2363. //
  2364. // if we are in static mode, we need to "release" the node so that someone
  2365. // else can use it. Find the bit for this node and clear it (i.e. "release")
  2366. //
  2367. if (!(ArapGlobs.DynamicMode))
  2368. {
  2369. ACQUIRE_SPIN_LOCK(&ArapSpinLock, &OldIrql);
  2370. // first, find the right pAddrMgmt (1st one if we have <255 clients)
  2371. pAddrMgmt = ArapGlobs.pAddrMgmt;
  2372. ASSERT(pAddrMgmt);
  2373. while (pAddrMgmt->Network != pArapConn->NetAddr.atn_Network)
  2374. {
  2375. pAddrMgmt = pAddrMgmt->Next;
  2376. ASSERT(pAddrMgmt);
  2377. }
  2378. Node = pArapConn->NetAddr.atn_Node;
  2379. // find out which of the 32 bytes we should be looking at
  2380. ByteNum = Node/8;
  2381. Node -= (ByteNum*8);
  2382. // generate the bitmask to represent the node
  2383. BitMask = 0x1;
  2384. for (i=0; i<Node; i++ )
  2385. {
  2386. BitMask <<= 1;
  2387. }
  2388. // now, clear that bit!
  2389. pAddrMgmt->NodeBitMap[ByteNum] &= ~BitMask;
  2390. RELEASE_SPIN_LOCK(&ArapSpinLock, OldIrql);
  2391. }
  2392. }
  2393. #endif //ARAP_STATIC_MODE
  2394. //
  2395. // not used anymore: leave them in, in case we need to use them sometime...
  2396. //
  2397. #if 0
  2398. DWORD
  2399. ArapScheduleWorkerEvent(
  2400. IN DWORD Action,
  2401. IN PVOID Context1,
  2402. IN PVOID Context2
  2403. )
  2404. {
  2405. PARAPQITEM pArapQItem;
  2406. if ((pArapQItem = AtalkAllocMemory(sizeof(ARAPQITEM))) == NULL)
  2407. {
  2408. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  2409. ("ArapScheduleWorkerEvent: mem alloc failed!\n"));
  2410. return(ARAPERR_OUT_OF_RESOURCES);
  2411. }
  2412. pArapQItem->Action = Action;
  2413. pArapQItem->Context1 = Context1;
  2414. pArapQItem->Context2 = Context2;
  2415. ExInitializeWorkItem(&pArapQItem->WorkQItem,
  2416. (PWORKER_THREAD_ROUTINE)ArapDelayedEventHandler,
  2417. pArapQItem);
  2418. ExQueueWorkItem(&pArapQItem->WorkQItem, CriticalWorkQueue);
  2419. return(ARAPERR_NO_ERROR);
  2420. }
  2421. VOID
  2422. ArapDelayedEventHandler(
  2423. IN PARAPQITEM pArapQItem
  2424. )
  2425. {
  2426. DWORD Action;
  2427. PIRP pIrp;
  2428. PIO_STACK_LOCATION pIrpSp;
  2429. ULONG IoControlCode;
  2430. PMNPSENDBUF pMnpSendBuf;
  2431. DWORD StatusCode;
  2432. NTSTATUS status;
  2433. KIRQL OldIrq;
  2434. Action = pArapQItem->Action;
  2435. switch (Action)
  2436. {
  2437. case ARAPACTION_COMPLETE_IRP:
  2438. pIrp = (PIRP)pArapQItem->Context1;
  2439. status = (NTSTATUS)pArapQItem->Context2;
  2440. ASSERT(pIrp != NULL);
  2441. #if DBG
  2442. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  2443. IoControlCode = pIrpSp->Parameters.DeviceIoControl.IoControlCode;
  2444. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  2445. ("ArapDelayedEventHandler: completing irp %lx, Ioctl %lx, Status=%lx at irql=%d\n",
  2446. pIrp,IoControlCode,status,KeGetCurrentIrql()));
  2447. #endif
  2448. //TdiCompleteRequest(pIrp, status);
  2449. pIrp->IoStatus.Status = status;
  2450. IoCompleteRequest(pIrp,IO_NETWORK_INCREMENT);
  2451. break;
  2452. case ARAPACTION_CALL_COMPLETION:
  2453. pMnpSendBuf = (PMNPSENDBUF )pArapQItem->Context1;
  2454. StatusCode = (DWORD)pArapQItem->Context2;
  2455. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  2456. ("ArapDelayedEventHandler: calling compl. %lx with %lx, %ld\n",
  2457. pMnpSendBuf->ComplRoutine,pMnpSendBuf, StatusCode));
  2458. (pMnpSendBuf->ComplRoutine)(pMnpSendBuf, StatusCode);
  2459. break;
  2460. default:
  2461. DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR,
  2462. ("ArapDelayedEventHandler: invalid action %ld\n",Action));
  2463. }
  2464. AtalkFreeMemory(pArapQItem);
  2465. }
  2466. #endif // #if 0