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.

1751 lines
56 KiB

  1. // Copyright (c) 1997, Microsoft Corporation, all rights reserved
  2. //
  3. // mp.c
  4. // RAS L2TP WAN mini-port/call-manager driver
  5. // Mini-port routines
  6. //
  7. // 01/07/97 Steve Cobb
  8. #include "l2tpp.h"
  9. #include "mp.tmh"
  10. // The adapter control block address is recorded in this global as a debugging
  11. // aid. This global must not be read by any code.
  12. //
  13. ADAPTERCB* g_pDebugAdapter;
  14. // The number of packets indicated up to and returned from the driver above.
  15. //
  16. LONG g_lPacketsIndicated = 0;
  17. LONG g_lPacketsReturned = 0;
  18. // Call statistics totals for all calls since loading, calls and the lock
  19. // protecting access to them. For this global only, the 'ullCallUp' field is
  20. // the number of calls recorded, rather than a time.
  21. //
  22. CALLSTATS g_stats;
  23. NDIS_SPIN_LOCK g_lockStats;
  24. // Default settings for the NDIS_WAN_CO_INFO capabilities of an adapter.
  25. //
  26. static NDIS_WAN_CO_INFO g_infoDefaults =
  27. {
  28. L2TP_MaxFrameSize, // MaxFrameSize
  29. 0, // MaxSendWindow (placeholder)
  30. PPP_FRAMING // FramingBits
  31. | PPP_COMPRESS_ADDRESS_CONTROL
  32. | PPP_COMPRESS_PROTOCOL_FIELD,
  33. 0, // DesiredACCM
  34. };
  35. //-----------------------------------------------------------------------------
  36. // Local prototypes (alphabetically)
  37. //-----------------------------------------------------------------------------
  38. VOID
  39. FreeAdapter(
  40. IN ADAPTERCB* pAdapter );
  41. NDIS_STATUS
  42. GetRegistrySettings(
  43. IN NDIS_HANDLE WrapperConfigurationContext,
  44. OUT USHORT* pusMaxVcs,
  45. OUT TDIXMEDIATYPE* pMediaType,
  46. OUT L2TPROLE* pOutgoingRole,
  47. OUT ULONG* pulMaxSendTimeoutMs,
  48. OUT ULONG* pulInitialSendTimeoutMs,
  49. OUT ULONG* pulMaxRetransmits,
  50. OUT ULONG* pulHelloMs,
  51. OUT ULONG* pulMaxAckDelayMs,
  52. OUT SHORT* psMaxOutOfOrder,
  53. OUT USHORT* pusControlReceiveWindow,
  54. OUT USHORT* pusPayloadReceiveWindow,
  55. OUT ULONG* pulPayloadSendWindow,
  56. OUT USHORT* pusLlistDepth,
  57. OUT CHAR** ppszHostName,
  58. OUT CHAR** ppszPassword,
  59. OUT BOOLEAN* pfIgnoreFramingMismatch,
  60. OUT BOOLEAN* pfExclusiveTunnels,
  61. OUT HOSTROUTEEXISTS* phre,
  62. OUT BOOLEAN* pfDisableUdpXsums,
  63. OUT WCHAR** ppszDriverDesc );
  64. NDIS_STATUS
  65. QueryInformation(
  66. IN ADAPTERCB* pAdapter,
  67. IN VCCB* pLink,
  68. IN NDIS_OID Oid,
  69. IN PVOID InformationBuffer,
  70. IN ULONG InformationBufferLength,
  71. OUT PULONG BytesWritten,
  72. OUT PULONG BytesNeeded );
  73. NDIS_STATUS
  74. SetInformation(
  75. IN ADAPTERCB* pAdapter,
  76. IN VCCB* pLink,
  77. IN NDIS_OID Oid,
  78. IN PVOID InformationBuffer,
  79. IN ULONG InformationBufferLength,
  80. OUT PULONG BytesRead,
  81. OUT PULONG BytesNeeded );
  82. //-----------------------------------------------------------------------------
  83. // Mini-port handlers
  84. //-----------------------------------------------------------------------------
  85. NDIS_STATUS
  86. LmpInitialize(
  87. OUT PNDIS_STATUS OpenErrorStatus,
  88. OUT PUINT SelectedMediumIndex,
  89. IN PNDIS_MEDIUM MediumArray,
  90. IN UINT MediumArraySize,
  91. IN NDIS_HANDLE MiniportAdapterHandle,
  92. IN NDIS_HANDLE WrapperConfigurationContext )
  93. // Standard 'MiniportInitialize' routine called by NDIS to initialize a
  94. // new WAN adapter. See DDK doc. The driver will receive no requests
  95. // until this initialization has completed.
  96. //
  97. {
  98. NDIS_STATUS status;
  99. ADAPTERCB* pAdapter;
  100. TRACE( TL_I, TM_Init, ( "LmpInit" ) );
  101. status = *OpenErrorStatus = NDIS_STATUS_SUCCESS;
  102. // Find the medium index in the array of media, looking for the only one
  103. // we support, 'NdisMediumCoWan'.
  104. //
  105. {
  106. UINT i;
  107. for (i = 0; i < MediumArraySize; ++i)
  108. {
  109. if (MediumArray[ i ] == NdisMediumCoWan)
  110. {
  111. break;
  112. }
  113. }
  114. if (i >= MediumArraySize)
  115. {
  116. TRACE( TL_A, TM_Init, ( "medium?" ) );
  117. return NDIS_STATUS_FAILURE;
  118. }
  119. *SelectedMediumIndex = i;
  120. }
  121. // Allocate and zero a control block for the new adapter.
  122. //
  123. pAdapter = ALLOC_NONPAGED( sizeof(*pAdapter), MTAG_ADAPTERCB );
  124. TRACE( TL_N, TM_Init, ( "Acb=$%p", pAdapter ) );
  125. if (!pAdapter)
  126. {
  127. return NDIS_STATUS_RESOURCES;
  128. }
  129. NdisZeroMemory( pAdapter, sizeof(*pAdapter) );
  130. // The adapter control block address is recorded in 'g_pDebugAdapter' as a
  131. // debugging aid only. This global is not to be read by any code.
  132. //
  133. g_pDebugAdapter = pAdapter;
  134. // Set a marker for easier memory dump browsing and future assertions.
  135. //
  136. pAdapter->ulTag = MTAG_ADAPTERCB;
  137. // Save the NDIS handle associated with this adapter for use in future
  138. // NdisXxx calls.
  139. //
  140. pAdapter->MiniportAdapterHandle = MiniportAdapterHandle;
  141. // Initialize the list of active tunnels and it's lock.
  142. //
  143. InitializeListHead( &pAdapter->listTunnels );
  144. NdisAllocateSpinLock( &pAdapter->lockTunnels );
  145. // Copy default NDISWAN information. Some of these are updated below.
  146. //
  147. NdisMoveMemory( &pAdapter->info, &g_infoDefaults, sizeof(pAdapter->info) );
  148. pAdapter->info.MaxFrameSize = 1400;
  149. do
  150. {
  151. TDIXMEDIATYPE tmt;
  152. L2TPROLE role;
  153. USHORT usLlistDepth;
  154. BOOLEAN fIgnoreFramingMismatch;
  155. BOOLEAN fExclusiveTunnels;
  156. HOSTROUTEEXISTS hre;
  157. BOOLEAN fDisableUdpXsums;
  158. // Read this adapter's registry settings.
  159. //
  160. status = GetRegistrySettings(
  161. WrapperConfigurationContext,
  162. &pAdapter->usMaxVcs,
  163. &tmt,
  164. &role,
  165. &pAdapter->ulMaxSendTimeoutMs,
  166. &pAdapter->ulInitialSendTimeoutMs,
  167. &pAdapter->ulMaxRetransmits,
  168. &pAdapter->ulHelloMs,
  169. &pAdapter->ulMaxAckDelayMs,
  170. &pAdapter->sMaxOutOfOrder,
  171. &pAdapter->usControlReceiveWindow,
  172. &pAdapter->usPayloadReceiveWindow,
  173. &pAdapter->info.MaxSendWindow,
  174. &usLlistDepth,
  175. &pAdapter->pszHostName,
  176. &pAdapter->pszPassword,
  177. &fIgnoreFramingMismatch,
  178. &fExclusiveTunnels,
  179. &hre,
  180. &fDisableUdpXsums,
  181. &pAdapter->pszDriverDesc );
  182. if (status != NDIS_STATUS_SUCCESS)
  183. {
  184. // Set 'usMaxVcs' to 0 as an indication to FreeAdapter that the
  185. // lookaside lists and pools were not initialized.
  186. //
  187. pAdapter->usMaxVcs = 0;
  188. break;
  189. }
  190. // Convert the outgoing call role and mismatch flags to the equivalent
  191. // control block flag settings.
  192. //
  193. if (role == LR_Lac)
  194. {
  195. pAdapter->ulFlags |= ACBF_OutgoingRoleLac;
  196. }
  197. if (fIgnoreFramingMismatch)
  198. {
  199. pAdapter->ulFlags |= ACBF_IgnoreFramingMismatch;
  200. }
  201. if (fExclusiveTunnels)
  202. {
  203. pAdapter->ulFlags |= ACBF_ExclusiveTunnels;
  204. }
  205. // Initialize our framing and bearer capability bit masks. NDISWAN
  206. // supports only synchronous framing. Until we add the full LAC
  207. // support, we have no bearer capabilities for both the LAC and LNS
  208. // roles.
  209. //
  210. pAdapter->ulFramingCaps = FBM_Sync;
  211. pAdapter->ulBearerCaps = 0;
  212. // Initialize lookaside lists, buffer pools, and packet pool. On NT,
  213. // lookaside depths are optimized by the system based on usage
  214. // regardless of the depth set, but choose something reasonable
  215. // anyway.
  216. //
  217. {
  218. if (pAdapter->usMaxVcs < usLlistDepth)
  219. {
  220. usLlistDepth = pAdapter->usMaxVcs;
  221. }
  222. NdisInitializeNPagedLookasideList(
  223. &pAdapter->llistWorkItems,
  224. NULL, NULL, 0,
  225. sizeof(NDIS_WORK_ITEM),
  226. MTAG_WORKITEM,
  227. usLlistDepth );
  228. NdisInitializeNPagedLookasideList(
  229. &pAdapter->llistTimerQItems,
  230. NULL, NULL, 0,
  231. sizeof(TIMERQITEM),
  232. MTAG_TIMERQITEM,
  233. usLlistDepth );
  234. NdisInitializeNPagedLookasideList(
  235. &pAdapter->llistControlSents,
  236. NULL, NULL, 0,
  237. sizeof(CONTROLSENT),
  238. MTAG_CTRLSENT,
  239. usLlistDepth );
  240. NdisInitializeNPagedLookasideList(
  241. &pAdapter->llistPayloadSents,
  242. NULL, NULL, 0,
  243. sizeof(PAYLOADSENT),
  244. MTAG_PAYLSENT,
  245. usLlistDepth );
  246. NdisInitializeNPagedLookasideList(
  247. &pAdapter->llistTunnelWorks,
  248. NULL, NULL, 0,
  249. sizeof(TUNNELWORK),
  250. MTAG_TUNNELWORK,
  251. usLlistDepth );
  252. NdisInitializeNPagedLookasideList(
  253. &pAdapter->llistControlMsgInfos,
  254. NULL, NULL, 0,
  255. sizeof(CONTROLMSGINFO),
  256. MTAG_CTRLMSGINFO,
  257. usLlistDepth );
  258. #if LLISTALL
  259. NdisInitializeNPagedLookasideList(
  260. &pAdapter->llistTunnels,
  261. NULL, NULL, 0,
  262. sizeof(TUNNELCB),
  263. MTAG_TUNNELCB,
  264. usLlistDepth );
  265. NdisInitializeNPagedLookasideList(
  266. &pAdapter->llistVcs,
  267. NULL, NULL, 0,
  268. sizeof(VCCB),
  269. MTAG_VCCB,
  270. usLlistDepth );
  271. NdisInitializeNPagedLookasideList(
  272. &pAdapter->llistTimerQs,
  273. NULL, NULL, 0,
  274. sizeof(TIMERQ),
  275. MTAG_TIMERQ,
  276. usLlistDepth );
  277. NdisInitializeNPagedLookasideList(
  278. &pAdapter->llistControlReceiveds,
  279. NULL, NULL, 0,
  280. sizeof(CONTROLRECEIVED),
  281. MTAG_CTRLRECD,,
  282. usLlistDepth );
  283. NdisInitializeNPagedLookasideList(
  284. &pAdapter->llistPayloadReceiveds,
  285. NULL, NULL, 0,
  286. sizeof(PAYLOADRECEIVED),
  287. MTAG_PAYLRECD,
  288. usLlistDepth );
  289. NdisInitializeNPagedLookasideList(
  290. &pAdapter->llistInCallSetups,
  291. NULL, NULL, 0,
  292. sizeof(INCALLSETUP),
  293. MTAG_INCALL,
  294. usLlistDepth );
  295. #endif
  296. InitBufferPool(
  297. &pAdapter->poolFrameBuffers,
  298. L2TP_FrameBufferSize
  299. + ((tmt == TMT_RawIp) ? IpFixedHeaderSize : 0),
  300. 0, 10, 0,
  301. TRUE, MTAG_FBUFPOOL );
  302. InitBufferPool(
  303. &pAdapter->poolHeaderBuffers,
  304. L2TP_HeaderBufferSize,
  305. 0, 20, 0,
  306. TRUE, MTAG_HBUFPOOL );
  307. InitPacketPool(
  308. &pAdapter->poolPackets,
  309. 0, 0, 30, 0,
  310. MTAG_PACKETPOOL );
  311. }
  312. // Initialize the TDI extension context.
  313. //
  314. TdixInitialize(
  315. tmt,
  316. hre,
  317. ((fDisableUdpXsums) ? TDIXF_DisableUdpXsums : 0),
  318. L2tpReceive,
  319. &pAdapter->poolFrameBuffers,
  320. &pAdapter->tdix );
  321. // Allocate and zero the VC control block address array.
  322. //
  323. {
  324. ULONG ulSize;
  325. ulSize = pAdapter->usMaxVcs * sizeof(VCCB*);
  326. pAdapter->ppVcs = ALLOC_NONPAGED( ulSize, MTAG_VCTABLE );
  327. TRACE( TL_V, TM_Init, ( "VcTable=$%p", pAdapter->ppVcs ) );
  328. if (!pAdapter->ppVcs)
  329. {
  330. status = NDIS_STATUS_RESOURCES;
  331. break;
  332. }
  333. NdisZeroMemory( pAdapter->ppVcs, ulSize );
  334. // Allocate the lock that guards the table.
  335. //
  336. NdisAllocateSpinLock( &pAdapter->lockVcs );
  337. // At this point, all VC slots in the table are available.
  338. //
  339. pAdapter->lAvailableVcSlots = (LONG )pAdapter->usMaxVcs;
  340. // Set the initial value of the termination call ID counter. See
  341. // GetNextTerminationCallId.
  342. //
  343. pAdapter->usNextTerminationCallId = pAdapter->usMaxVcs + 1;
  344. }
  345. // Inform NDIS of the attributes of our adapter. Set the
  346. // 'MiniportAdapterContext' returned to us by NDIS when it calls our
  347. // handlers to the address of our adapter control block. Turn off
  348. // hardware oriented timeouts.
  349. //
  350. NdisMSetAttributesEx(
  351. MiniportAdapterHandle,
  352. (NDIS_HANDLE)pAdapter,
  353. (UINT)-1,
  354. NDIS_ATTRIBUTE_IGNORE_PACKET_TIMEOUT
  355. | NDIS_ATTRIBUTE_IGNORE_REQUEST_TIMEOUT,
  356. NdisInterfaceInternal );
  357. // Register the address family of our call manager with NDIS for the
  358. // newly bound adapter. We use the mini-port form of
  359. // RegisterAddressFamily instead of the protocol form, though that
  360. // would also work. With the protocol form, our internal call manager
  361. // would have to go thru NDIS to talk to the mini-port instead of just
  362. // calling directly. Since the L2TP call manager is not likely to be
  363. // useful with anything but the L2TP mini-port, this would be a waste.
  364. // The mini-port form also causes the call manager VC context to
  365. // automatically map to the mini-port VC context, which is exactly
  366. // what we want.
  367. //
  368. // NDIS notifies all call manager clients of the new family we
  369. // register. The TAPI proxy is the only client expected to be
  370. // interested. NDISWAN will receive the notification, but ignore it
  371. // and wait for the TAPI proxy to notify it of the proxied version.
  372. //
  373. {
  374. NDIS_CALL_MANAGER_CHARACTERISTICS ncmc;
  375. CO_ADDRESS_FAMILY family;
  376. NdisZeroMemory( &family, sizeof(family) );
  377. family.MajorVersion = NDIS_MajorVersion;
  378. family.MinorVersion = NDIS_MinorVersion;
  379. family.AddressFamily = CO_ADDRESS_FAMILY_TAPI_PROXY;
  380. NdisZeroMemory( &ncmc, sizeof(ncmc) );
  381. ncmc.MajorVersion = NDIS_MajorVersion;
  382. ncmc.MinorVersion = NDIS_MinorVersion;
  383. ncmc.CmCreateVcHandler = LcmCmCreateVc;
  384. ncmc.CmDeleteVcHandler = LcmCmDeleteVc;
  385. ncmc.CmOpenAfHandler = LcmCmOpenAf;
  386. ncmc.CmCloseAfHandler = LcmCmCloseAf;
  387. ncmc.CmRegisterSapHandler = LcmCmRegisterSap;
  388. ncmc.CmDeregisterSapHandler = LcmCmDeregisterSap;
  389. ncmc.CmMakeCallHandler = LcmCmMakeCall;
  390. ncmc.CmCloseCallHandler = LcmCmCloseCall;
  391. ncmc.CmIncomingCallCompleteHandler = LcmCmIncomingCallComplete;
  392. // no CmAddPartyHandler
  393. // no CmDropPartyHandler
  394. ncmc.CmActivateVcCompleteHandler = LcmCmActivateVcComplete;
  395. ncmc.CmDeactivateVcCompleteHandler = LcmCmDeactivateVcComplete;
  396. ncmc.CmModifyCallQoSHandler = LcmCmModifyCallQoS;
  397. ncmc.CmRequestHandler = LcmCmRequest;
  398. // no CmRequestCompleteHandler
  399. TRACE( TL_I, TM_Cm, ( "NdisMCmRegAf" ) );
  400. status = NdisMCmRegisterAddressFamily(
  401. MiniportAdapterHandle, &family, &ncmc, sizeof(ncmc) );
  402. TRACE( TL_I, TM_Cm, ( "NdisMCmRegAf=$%x", status ) );
  403. }
  404. }
  405. while (FALSE);
  406. if (status == NDIS_STATUS_SUCCESS)
  407. {
  408. // Add a reference that will eventually be removed by an NDIS call to
  409. // the LmpHalt handler.
  410. //
  411. ReferenceAdapter( pAdapter );
  412. }
  413. else
  414. {
  415. // Failed, so undo whatever portion succeeded.
  416. //
  417. if (pAdapter)
  418. {
  419. FreeAdapter( pAdapter );
  420. }
  421. }
  422. TRACE( TL_V, TM_Init, ( "LmpInit=$%08x", status ) );
  423. return status;
  424. }
  425. VOID
  426. LmpHalt(
  427. IN NDIS_HANDLE MiniportAdapterContext )
  428. // Standard 'MiniportHalt' routine called by NDIS to deallocate all
  429. // resources attached to the adapter. NDIS does not make any other calls
  430. // for this mini-port adapter during or after this call. NDIS will not
  431. // call this routine when packets indicated as received have not been
  432. // returned, or when any VC is created and known to NDIS. Runs at PASSIVE
  433. // IRQL.
  434. //
  435. {
  436. ADAPTERCB* pAdapter;
  437. TRACE( TL_I, TM_Mp, ( "LmpHalt" ) );
  438. pAdapter = (ADAPTERCB* )MiniportAdapterContext;
  439. if (!pAdapter || pAdapter->ulTag != MTAG_ADAPTERCB)
  440. {
  441. ASSERT( !"Atag?" );
  442. return;
  443. }
  444. // Don't allow the halt to complete before all timers have completed as
  445. // this can result in a 0xC7 bugcheck if the driver is immediately
  446. // unloaded. All timers should be in the process of terminating before
  447. // NDIS calls this handler, so this should occur very quickly.
  448. //
  449. while (pAdapter->ulTimers)
  450. {
  451. TRACE( TL_A, TM_Mp, ( "LmpHalt timers=%d", pAdapter->ulTimers ) );
  452. WPLOG( LL_A, LM_Mp, ( "LmpHalt timers=%d", pAdapter->ulTimers ) );
  453. NdisMSleep( 100000 );
  454. }
  455. DereferenceAdapter( pAdapter );
  456. TRACE( TL_V, TM_Mp, ( "LmpHalt done" ) );
  457. }
  458. NDIS_STATUS
  459. LmpReset(
  460. OUT PBOOLEAN AddressingReset,
  461. IN NDIS_HANDLE MiniportAdapterContext )
  462. // Standard 'MiniportReset' routine called by NDIS to reset the driver's
  463. // software state.
  464. //
  465. {
  466. TRACE( TL_I, TM_Mp, ( "LmpReset" ) );
  467. return NDIS_STATUS_NOT_RESETTABLE;
  468. }
  469. VOID
  470. LmpReturnPacket(
  471. IN NDIS_HANDLE MiniportAdapterContext,
  472. IN PNDIS_PACKET Packet )
  473. // Standard 'MiniportReturnPacket' routine called by NDIS when a packet
  474. // used to indicate a receive has been released by the driver above.
  475. //
  476. {
  477. VCCB* pVc;
  478. CHAR* pBuffer;
  479. ADAPTERCB* pAdapter;
  480. NDIS_BUFFER* pTrimmedBuffer;
  481. PACKETHEAD* pHead;
  482. PACKETPOOL* pPool;
  483. TRACE( TL_N, TM_Mp, ( "LmpReturnPacket" ) );
  484. // Unpack the context information we stashed earlier.
  485. //
  486. pHead = *((PACKETHEAD** )(&Packet->MiniportReserved[ 0 ]));
  487. pBuffer = *((CHAR** )(&Packet->MiniportReserved[ sizeof(VOID*) ]));
  488. // Find the adapter from the PACKETHEAD address.
  489. //
  490. pPool = PacketPoolFromPacketHead( pHead );
  491. pAdapter = CONTAINING_RECORD( pPool, ADAPTERCB, poolPackets );
  492. ASSERT( pAdapter->ulTag == MTAG_ADAPTERCB );
  493. // Free the descriptor created by NdisCopyBuffer.
  494. //
  495. NdisUnchainBufferAtFront( Packet, &pTrimmedBuffer );
  496. if (pTrimmedBuffer)
  497. {
  498. extern ULONG g_ulNdisFreeBuffers;
  499. NdisFreeBuffer( pTrimmedBuffer );
  500. NdisInterlockedIncrement( &g_ulNdisFreeBuffers );
  501. }
  502. // Free the buffer and packet back to the pools.
  503. //
  504. FreeBufferToPool( &pAdapter->poolFrameBuffers, pBuffer, TRUE );
  505. FreePacketToPool( &pAdapter->poolPackets, pHead, TRUE );
  506. NdisInterlockedIncrement( &g_lPacketsReturned );
  507. TRACE( TL_V, TM_Mp, ( "LmpReturnPacket done" ) );
  508. }
  509. NDIS_STATUS
  510. LmpCoActivateVc(
  511. IN NDIS_HANDLE MiniportVcContext,
  512. IN OUT PCO_CALL_PARAMETERS CallParameters )
  513. // Standard 'MiniportCoActivateVc' routine called by NDIS in response to a
  514. // protocol's request to activate a virtual circuit.
  515. //
  516. {
  517. ASSERT( !"LmpCoActVc?" );
  518. return NDIS_STATUS_SUCCESS;
  519. }
  520. NDIS_STATUS
  521. LmpCoDeactivateVc(
  522. IN NDIS_HANDLE MiniportVcContext )
  523. // Standard 'MiniportCoDeactivateVc' routine called by NDIS in response to
  524. // a protocol's request to de-activate a virtual circuit.
  525. //
  526. {
  527. ASSERT( !"LmpCoDeactVc?" );
  528. return NDIS_STATUS_SUCCESS;
  529. }
  530. VOID
  531. LmpCoSendPackets(
  532. IN NDIS_HANDLE MiniportVcContext,
  533. IN PPNDIS_PACKET PacketArray,
  534. IN UINT NumberOfPackets )
  535. // Standard 'MiniportCoDeactivateVc' routine called by NDIS in response to
  536. // a protocol's request to send packets on a virtual circuit.
  537. //
  538. {
  539. UINT i;
  540. NDIS_STATUS status;
  541. NDIS_PACKET** ppPacket;
  542. VCCB* pVc;
  543. TRACE( TL_N, TM_Send, ( "LmpCoSendPackets(%d)", NumberOfPackets ) );
  544. pVc = (VCCB* )MiniportVcContext;
  545. ASSERT( pVc->ulTag == MTAG_VCCB );
  546. for (i = 0, ppPacket = PacketArray;
  547. i < NumberOfPackets;
  548. ++i, ++ppPacket)
  549. {
  550. NDIS_PACKET* pPacket = *ppPacket;
  551. // SendPayload sends the packet and eventually calls
  552. // NdisMCoSendComplete to notify caller of the result.
  553. //
  554. NDIS_SET_PACKET_STATUS( pPacket, NDIS_STATUS_PENDING );
  555. SendPayload( pVc, pPacket );
  556. }
  557. TRACE( TL_V, TM_Send, ( "LmpCoSendPackets done" ) );
  558. }
  559. NDIS_STATUS
  560. LmpCoRequest(
  561. IN NDIS_HANDLE MiniportAdapterContext,
  562. IN NDIS_HANDLE MiniportVcContext,
  563. IN OUT PNDIS_REQUEST NdisRequest )
  564. // Standard 'MiniportCoRequestHandler' routine called by NDIS in response
  565. // to a protocol's request information from the mini-port. Unlike the
  566. // Query/SetInformation handlers that this routine obsoletes, requests are
  567. // not serialized.
  568. //
  569. {
  570. ADAPTERCB* pAdapter;
  571. VCCB* pVc;
  572. NDIS_STATUS status;
  573. TRACE( TL_N, TM_Mp, ( "LmpCoReq" ) );
  574. pAdapter = (ADAPTERCB* )MiniportAdapterContext;
  575. if (pAdapter->ulTag != MTAG_ADAPTERCB)
  576. {
  577. ASSERT( !"Atag?" );
  578. return NDIS_STATUS_INVALID_DATA;
  579. }
  580. pVc = (VCCB* )MiniportVcContext;
  581. if (pVc && pVc->ulTag != MTAG_VCCB)
  582. {
  583. ASSERT( !"Vtag?" );
  584. return NDIS_STATUS_INVALID_DATA;
  585. }
  586. switch (NdisRequest->RequestType)
  587. {
  588. case NdisRequestQueryInformation:
  589. {
  590. status = QueryInformation(
  591. pAdapter,
  592. pVc,
  593. NdisRequest->DATA.QUERY_INFORMATION.Oid,
  594. NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer,
  595. NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength,
  596. &NdisRequest->DATA.QUERY_INFORMATION.BytesWritten,
  597. &NdisRequest->DATA.QUERY_INFORMATION.BytesNeeded );
  598. break;
  599. }
  600. case NdisRequestSetInformation:
  601. {
  602. status = SetInformation(
  603. pAdapter,
  604. pVc,
  605. NdisRequest->DATA.SET_INFORMATION.Oid,
  606. NdisRequest->DATA.SET_INFORMATION.InformationBuffer,
  607. NdisRequest->DATA.SET_INFORMATION.InformationBufferLength,
  608. &NdisRequest->DATA.SET_INFORMATION.BytesRead,
  609. &NdisRequest->DATA.SET_INFORMATION.BytesNeeded );
  610. break;
  611. }
  612. default:
  613. {
  614. status = NDIS_STATUS_NOT_SUPPORTED;
  615. TRACE( TL_A, TM_Mp, ( "type=%d?", NdisRequest->RequestType ) );
  616. break;
  617. }
  618. }
  619. TRACE( TL_V, TM_Mp, ( "LmpCoReq=$%x", status ) );
  620. return status;
  621. }
  622. //-----------------------------------------------------------------------------
  623. // Mini-port utility routines (alphabetically)
  624. // Some are used externally
  625. //-----------------------------------------------------------------------------
  626. VOID
  627. DereferenceAdapter(
  628. IN ADAPTERCB* pAdapter )
  629. // Removes a reference from the adapter control block 'pAdapter', and when
  630. // frees the adapter resources when the last reference is removed.
  631. //
  632. {
  633. LONG lRef;
  634. lRef = NdisInterlockedDecrement( &pAdapter->lRef );
  635. TRACE( TL_N, TM_Ref, ( "DerefA to %d", lRef ) );
  636. ASSERT( lRef >= 0 );
  637. if (lRef == 0)
  638. {
  639. FreeAdapter( pAdapter );
  640. }
  641. }
  642. VOID
  643. FreeAdapter(
  644. IN ADAPTERCB* pAdapter )
  645. // Frees all resources allocated for adapter 'pAdapter', including
  646. // 'pAdapter' itself.
  647. //
  648. {
  649. BOOLEAN fSuccess;
  650. ASSERT( IsListEmpty( &pAdapter->listTunnels ) );
  651. if (pAdapter->ppVcs)
  652. {
  653. FREE_NONPAGED( pAdapter->ppVcs );
  654. }
  655. // Setting 'usMaxVcs' to 0 is LmpInitialize's way of telling us that the
  656. // lookaside lists and pools were not initialized.
  657. //
  658. if (pAdapter->usMaxVcs)
  659. {
  660. NdisDeleteNPagedLookasideList( &pAdapter->llistWorkItems );
  661. NdisDeleteNPagedLookasideList( &pAdapter->llistTimerQItems );
  662. NdisDeleteNPagedLookasideList( &pAdapter->llistControlSents );
  663. NdisDeleteNPagedLookasideList( &pAdapter->llistPayloadSents );
  664. NdisDeleteNPagedLookasideList( &pAdapter->llistTunnelWorks );
  665. NdisDeleteNPagedLookasideList( &pAdapter->llistControlMsgInfos );
  666. #if LLISTALL
  667. NdisDeleteNPagedLookasideList( &pAdapter->llistTunnels );
  668. NdisDeleteNPagedLookasideList( &pAdapter->llistVcs );
  669. NdisDeleteNPagedLookasideList( &pAdapter->llistTimerQs );
  670. NdisDeleteNPagedLookasideList( &pAdapter->llistControlReceiveds );
  671. NdisDeleteNPagedLookasideList( &pAdapter->llistPayloadReceiveds );
  672. NdisDeleteNPagedLookasideList( &pAdapter->llistInCallSetups );
  673. #endif
  674. fSuccess = FreeBufferPool( &pAdapter->poolFrameBuffers );
  675. ASSERT( fSuccess );
  676. fSuccess = FreeBufferPool( &pAdapter->poolHeaderBuffers );
  677. ASSERT( fSuccess );
  678. fSuccess = FreePacketPool( &pAdapter->poolPackets );
  679. ASSERT( fSuccess );
  680. }
  681. if (pAdapter->pszPassword)
  682. {
  683. FREE_NONPAGED( pAdapter->pszPassword );
  684. }
  685. if (pAdapter->pszDriverDesc)
  686. {
  687. FREE_NONPAGED( pAdapter->pszDriverDesc );
  688. }
  689. if (pAdapter->pszHostName)
  690. {
  691. FREE_NONPAGED( pAdapter->pszHostName );
  692. }
  693. pAdapter->ulTag = MTAG_FREED;
  694. FREE_NONPAGED( pAdapter );
  695. }
  696. NDIS_STATUS
  697. GetRegistrySettings(
  698. IN NDIS_HANDLE WrapperConfigurationContext,
  699. OUT USHORT* pusMaxVcs,
  700. OUT TDIXMEDIATYPE* pMediaType,
  701. OUT L2TPROLE* pOutgoingRole,
  702. OUT ULONG* pulMaxSendTimeoutMs,
  703. OUT ULONG* pulInitialSendTimeoutMs,
  704. OUT ULONG* pulMaxRetransmits,
  705. OUT ULONG* pulHelloMs,
  706. OUT ULONG* pulMaxAckDelayMs,
  707. OUT SHORT* psMaxOutOfOrder,
  708. OUT USHORT* pusControlReceiveWindow,
  709. OUT USHORT* pusPayloadReceiveWindow,
  710. OUT ULONG* pulPayloadSendWindow,
  711. OUT USHORT* pusLlistDepth,
  712. OUT CHAR** ppszHostName,
  713. OUT CHAR** ppszPassword,
  714. OUT BOOLEAN* pfIgnoreFramingMismatch,
  715. OUT BOOLEAN* pfExclusiveTunnels,
  716. OUT HOSTROUTEEXISTS* phre,
  717. OUT BOOLEAN* pfDisableUdpXsums,
  718. OUT WCHAR** ppszDriverDesc )
  719. // Read this mini-port's registry settings into caller's output variables.
  720. // 'WrapperConfigurationContext' is the handle to passed to
  721. // MiniportInitialize.
  722. //
  723. {
  724. NDIS_STATUS status;
  725. NDIS_HANDLE hCfg;
  726. NDIS_CONFIGURATION_PARAMETER* pncp;
  727. NdisOpenConfiguration( &status, &hCfg, WrapperConfigurationContext );
  728. if (status != NDIS_STATUS_SUCCESS)
  729. return status;
  730. do
  731. {
  732. // (recommended) The number of VCs we must be able to provide.
  733. //
  734. {
  735. NDIS_STRING nstr = NDIS_STRING_CONST( "MaxWanEndpoints" );
  736. NdisReadConfiguration(
  737. &status, &pncp, hCfg, &nstr, NdisParameterInteger );
  738. if (status == NDIS_STATUS_SUCCESS)
  739. {
  740. *pusMaxVcs = (USHORT )pncp->ParameterData.IntegerData;
  741. // Make sure it's a valid value. The implicit upper bound
  742. // imposed by the protocol's Tunnel-Id/Call-ID sizes is 65535.
  743. // Settings above 1000 are not recommended, but will work if
  744. // huge amounts of memory and bandwidth are available.
  745. //
  746. if (*pusMaxVcs < 1)
  747. {
  748. status = NDIS_STATUS_INVALID_DATA;
  749. break;
  750. }
  751. }
  752. else
  753. {
  754. *pusMaxVcs = 1000;
  755. status = NDIS_STATUS_SUCCESS;
  756. }
  757. }
  758. // (recommended) The media type to run L2TP over.
  759. //
  760. {
  761. NDIS_STRING nstr = NDIS_STRING_CONST( "VpnMediaType" );
  762. NdisReadConfiguration(
  763. &status, &pncp, hCfg, &nstr, NdisParameterInteger );
  764. if (status == NDIS_STATUS_SUCCESS)
  765. {
  766. *pMediaType = (TDIXMEDIATYPE )pncp->ParameterData.IntegerData;
  767. // Make sure it's a valid type.
  768. //
  769. if (*pMediaType != TMT_Udp && *pMediaType != TMT_RawIp)
  770. {
  771. status = NDIS_STATUS_INVALID_DATA;
  772. break;
  773. }
  774. }
  775. else
  776. {
  777. // No media type in registry. Default to UDP.
  778. //
  779. *pMediaType = TMT_Udp;
  780. status = NDIS_STATUS_SUCCESS;
  781. }
  782. }
  783. // (optional) The maximum send timeout in milliseconds.
  784. //
  785. {
  786. NDIS_STRING nstr = NDIS_STRING_CONST( "MaxSendTimeoutMs" );
  787. NdisReadConfiguration(
  788. &status, &pncp, hCfg, &nstr, NdisParameterInteger );
  789. if (status == NDIS_STATUS_SUCCESS)
  790. {
  791. *pulMaxSendTimeoutMs = pncp->ParameterData.IntegerData;
  792. // Make sure it's a valid value.
  793. //
  794. if (*pulMaxSendTimeoutMs == 0)
  795. {
  796. *pulMaxSendTimeoutMs = 0x7FFFFFFF;
  797. }
  798. }
  799. else
  800. {
  801. // No value in registry. Set a reasonable default.
  802. //
  803. *pulMaxSendTimeoutMs = L2TP_DefaultMaxSendTimeoutMs;
  804. status = NDIS_STATUS_SUCCESS;
  805. }
  806. }
  807. // (optional) The initial send timeout in milliseconds.
  808. //
  809. {
  810. NDIS_STRING nstr = NDIS_STRING_CONST( "InitialSendTimeoutMs" );
  811. NdisReadConfiguration(
  812. &status, &pncp, hCfg, &nstr, NdisParameterInteger );
  813. if (status == NDIS_STATUS_SUCCESS)
  814. {
  815. *pulInitialSendTimeoutMs = pncp->ParameterData.IntegerData;
  816. // Make sure it's a valid value.
  817. //
  818. if (*pulInitialSendTimeoutMs == 0)
  819. {
  820. *pulInitialSendTimeoutMs = 0x7FFFFFFF;
  821. }
  822. if (*pulInitialSendTimeoutMs > *pulMaxSendTimeoutMs)
  823. *pulInitialSendTimeoutMs = *pulMaxSendTimeoutMs;
  824. }
  825. else
  826. {
  827. // No value in registry. Set a reasonable default.
  828. //
  829. *pulInitialSendTimeoutMs = L2TP_DefaultSendTimeoutMs;
  830. status = NDIS_STATUS_SUCCESS;
  831. }
  832. }
  833. // (optional) The maximum number of control message retransmissions
  834. // before the tunnel is reset.
  835. //
  836. {
  837. NDIS_STRING nstr = NDIS_STRING_CONST( "MaxRetransmits" );
  838. NdisReadConfiguration(
  839. &status, &pncp, hCfg, &nstr, NdisParameterInteger );
  840. if (status == NDIS_STATUS_SUCCESS)
  841. {
  842. *pulMaxRetransmits = pncp->ParameterData.IntegerData;
  843. }
  844. else
  845. {
  846. // No value in registry. Set a reasonable default.
  847. //
  848. *pulMaxRetransmits = L2TP_DefaultMaxRetransmits;
  849. status = NDIS_STATUS_SUCCESS;
  850. }
  851. }
  852. // (optional) The control Hello timeout in milliseconds.
  853. //
  854. {
  855. NDIS_STRING nstr = NDIS_STRING_CONST( "HelloMs" );
  856. NdisReadConfiguration(
  857. &status, &pncp, hCfg, &nstr, NdisParameterInteger );
  858. if (status == NDIS_STATUS_SUCCESS)
  859. {
  860. *pulHelloMs = pncp->ParameterData.IntegerData;
  861. }
  862. else
  863. {
  864. // No value in registry. Set a reasonable default.
  865. //
  866. *pulHelloMs = L2TP_HelloMs;
  867. status = STATUS_SUCCESS;
  868. }
  869. }
  870. // (optional) The maximum piggyback delay in milliseconds before
  871. // sending a zero payload acknowledgement.
  872. //
  873. {
  874. NDIS_STRING nstr = NDIS_STRING_CONST( "MaxAckDelayMs" );
  875. NdisReadConfiguration(
  876. &status, &pncp, hCfg, &nstr, NdisParameterInteger );
  877. if (status == NDIS_STATUS_SUCCESS)
  878. {
  879. *pulMaxAckDelayMs = pncp->ParameterData.IntegerData;
  880. }
  881. else
  882. {
  883. // No value in registry. Set a reasonable default.
  884. //
  885. *pulMaxAckDelayMs = L2TP_MaxAckDelay;
  886. status = NDIS_STATUS_SUCCESS;
  887. }
  888. }
  889. // (optional) The maximum number of out-of-order packets to queue.
  890. //
  891. {
  892. NDIS_STRING nstr = NDIS_STRING_CONST( "MaxOutOfOrder" );
  893. NdisReadConfiguration(
  894. &status, &pncp, hCfg, &nstr, NdisParameterInteger );
  895. if (status == NDIS_STATUS_SUCCESS)
  896. {
  897. *psMaxOutOfOrder = (SHORT )pncp->ParameterData.IntegerData;
  898. // Make sure it's not negative and within 1/4 of the possible
  899. // sequence values to avoid aliasing. Zero effectively
  900. // disables out of order handling.
  901. //
  902. if (*psMaxOutOfOrder < 0 || *psMaxOutOfOrder > 0x4000)
  903. {
  904. status = NDIS_STATUS_INVALID_DATA;
  905. break;
  906. }
  907. }
  908. else
  909. {
  910. // No value in registry. Set a reasonable default.
  911. //
  912. *psMaxOutOfOrder = 100;
  913. status = NDIS_STATUS_SUCCESS;
  914. }
  915. }
  916. // (optional) The role (LNS or LAC) that the adapter will play in
  917. // outgoing calls. The role played for incoming calls is
  918. // determined by the role the peer plays in his call
  919. // request.
  920. //
  921. {
  922. NDIS_STRING nstr = NDIS_STRING_CONST( "OutgoingRole" );
  923. NdisReadConfiguration(
  924. &status, &pncp, hCfg, &nstr, NdisParameterInteger );
  925. if (status == NDIS_STATUS_SUCCESS)
  926. {
  927. *pOutgoingRole = (L2TPROLE )pncp->ParameterData.IntegerData;
  928. // Make sure it's a valid role.
  929. //
  930. if (*pOutgoingRole != LR_Lac && *pOutgoingRole != LR_Lns)
  931. {
  932. status = NDIS_STATUS_INVALID_DATA;
  933. break;
  934. }
  935. }
  936. else
  937. {
  938. // No role in registry. Default to LAC.
  939. //
  940. *pOutgoingRole = LR_Lac;
  941. status = NDIS_STATUS_SUCCESS;
  942. }
  943. }
  944. // (optional) The control receive window sent to peer to indicate how
  945. // many sent control messages peer may have outstanding.
  946. //
  947. {
  948. NDIS_STRING nstr = NDIS_STRING_CONST( "ControlReceiveWindow" );
  949. NdisReadConfiguration(
  950. &status, &pncp, hCfg, &nstr, NdisParameterInteger );
  951. if (status == NDIS_STATUS_SUCCESS)
  952. {
  953. *pusControlReceiveWindow =
  954. (USHORT )pncp->ParameterData.IntegerData;
  955. }
  956. else
  957. {
  958. // No setting in registry. Set a reasonable default.
  959. //
  960. *pusControlReceiveWindow = 8;
  961. status = NDIS_STATUS_SUCCESS;
  962. }
  963. }
  964. // (optional) The payload receive window sent to peer to indicate how
  965. // many send payloads peer may have outstanding on any one
  966. // call. A value of 0 disables all Ns/Nr sequencing on the
  967. // payload channel for locally requested calls.
  968. //
  969. {
  970. NDIS_STRING nstr = NDIS_STRING_CONST( "PayloadReceiveWindow" );
  971. NdisReadConfiguration(
  972. &status, &pncp, hCfg, &nstr, NdisParameterInteger );
  973. if (status == NDIS_STATUS_SUCCESS)
  974. {
  975. *pusPayloadReceiveWindow =
  976. (USHORT )pncp->ParameterData.IntegerData;
  977. }
  978. else
  979. {
  980. // No setting in registry. Set a reasonable default.
  981. //
  982. // Note: Default changed to 0 (off) from 16 due to performance
  983. // study that shows significantly better results without
  984. // flow control, presumably due to interference with
  985. // higher level timers.
  986. //
  987. *pusPayloadReceiveWindow = 0;
  988. status = NDIS_STATUS_SUCCESS;
  989. }
  990. }
  991. // (optional) The maximum payload send window size reported to
  992. // NDISWAN. Peer may set the actual send window higher or
  993. // lower, but if higher this is the actual maximum.
  994. //
  995. {
  996. NDIS_STRING nstr = NDIS_STRING_CONST( "PayloadSendWindow" );
  997. NdisReadConfiguration(
  998. &status, &pncp, hCfg, &nstr, NdisParameterInteger );
  999. if (status == NDIS_STATUS_SUCCESS)
  1000. {
  1001. *pulPayloadSendWindow =
  1002. (ULONG )pncp->ParameterData.IntegerData;
  1003. }
  1004. else
  1005. {
  1006. // No setting in registry. Set a reasonable default.
  1007. //
  1008. *pulPayloadSendWindow = 16;
  1009. status = NDIS_STATUS_SUCCESS;
  1010. }
  1011. }
  1012. // (optional) The lookaside list depth ceiling, where higher values
  1013. // allow this driver to consume more non-paged pool in
  1014. // return for performance gain at high volumes. Setting
  1015. // this value above 'MaxVcs' has no effect.
  1016. //
  1017. {
  1018. NDIS_STRING nstr = NDIS_STRING_CONST( "LookasideDepth" );
  1019. NdisReadConfiguration(
  1020. &status, &pncp, hCfg, &nstr, NdisParameterInteger );
  1021. if (status == NDIS_STATUS_SUCCESS)
  1022. {
  1023. *pusLlistDepth = (USHORT )pncp->ParameterData.IntegerData;
  1024. }
  1025. else
  1026. {
  1027. // No setting in registry. Set a reasonable default.
  1028. //
  1029. *pusLlistDepth = 30;
  1030. status = NDIS_STATUS_SUCCESS;
  1031. }
  1032. }
  1033. // The host name passed to peer and used as the base of the
  1034. // call serial number.
  1035. // Host name is required as this is used in hostname MUST AVP.
  1036. {
  1037. NDIS_STRING nstr = NDIS_STRING_CONST( "HostName" );
  1038. NdisReadConfiguration(
  1039. &status, &pncp, hCfg, &nstr, NdisParameterString );
  1040. if (status == NDIS_STATUS_SUCCESS)
  1041. {
  1042. *ppszHostName =
  1043. StrDupNdisStringToA( &pncp->ParameterData.StringData );
  1044. if(!*ppszHostName)
  1045. {
  1046. status = NDIS_STATUS_RESOURCES;
  1047. }
  1048. }
  1049. else
  1050. {
  1051. // No setting in registry, so use a default.
  1052. //
  1053. *ppszHostName = GetFullHostNameFromRegistry();
  1054. if (!*ppszHostName)
  1055. {
  1056. *ppszHostName = StrDupSized("NONE", sizeof("NONE"), 0);
  1057. }
  1058. if(*ppszHostName)
  1059. {
  1060. status = NDIS_STATUS_SUCCESS;
  1061. }
  1062. else
  1063. {
  1064. status = NDIS_STATUS_RESOURCES;
  1065. }
  1066. }
  1067. if(status != NDIS_STATUS_SUCCESS)
  1068. {
  1069. break;
  1070. }
  1071. }
  1072. // (optional) The single password shared with peer for use in
  1073. // verifying peer's identity. If specified, authentication
  1074. // of peer is required, and if not, authentication is not
  1075. // provided.
  1076. //
  1077. {
  1078. NDIS_STRING nstr = NDIS_STRING_CONST( "Password" );
  1079. NdisReadConfiguration(
  1080. &status, &pncp, hCfg, &nstr, NdisParameterString );
  1081. if (status == NDIS_STATUS_SUCCESS)
  1082. {
  1083. *ppszPassword =
  1084. StrDupNdisStringToA( &pncp->ParameterData.StringData );
  1085. }
  1086. else
  1087. {
  1088. // No setting in registry...and no default.
  1089. //
  1090. *ppszPassword = NULL;
  1091. status = NDIS_STATUS_SUCCESS;
  1092. }
  1093. }
  1094. // (optional) Buggy peer hedge flag to ignore framing mismatches.
  1095. //
  1096. {
  1097. NDIS_STRING nstr = NDIS_STRING_CONST( "IgnoreFramingMismatch" );
  1098. NdisReadConfiguration(
  1099. &status, &pncp, hCfg, &nstr, NdisParameterInteger );
  1100. if (status == NDIS_STATUS_SUCCESS)
  1101. {
  1102. *pfIgnoreFramingMismatch =
  1103. (BOOLEAN )!!(pncp->ParameterData.IntegerData);
  1104. }
  1105. else
  1106. {
  1107. // No value in registry. Set a reasonable default.
  1108. //
  1109. *pfIgnoreFramingMismatch = TRUE;
  1110. status = NDIS_STATUS_SUCCESS;
  1111. }
  1112. }
  1113. // (optional) Flag indicating whether, by default, separate tunnels
  1114. // are to be created for each outgoing call even if a
  1115. // tunnel already exists to the same peer. This setting
  1116. // can be overridden via L2TP-specific call parameters.
  1117. //
  1118. {
  1119. NDIS_STRING nstr = NDIS_STRING_CONST( "ExclusiveTunnels" );
  1120. NdisReadConfiguration(
  1121. &status, &pncp, hCfg, &nstr, NdisParameterInteger );
  1122. if (status == NDIS_STATUS_SUCCESS)
  1123. {
  1124. *pfExclusiveTunnels =
  1125. (BOOLEAN )!!(pncp->ParameterData.IntegerData);
  1126. }
  1127. else
  1128. {
  1129. // No value in registry. Set a default.
  1130. //
  1131. *pfExclusiveTunnels = FALSE;
  1132. status = NDIS_STATUS_SUCCESS;
  1133. }
  1134. }
  1135. // (optional) Flag indicating whether routes created outside this
  1136. // driver may be used as L2TP host routes. If the flag is
  1137. // not set, the pre-existing host routes will cause the
  1138. // tunnel to close.
  1139. //
  1140. {
  1141. NDIS_STRING nstr = NDIS_STRING_CONST( "UseExistingRoutes" );
  1142. BOOLEAN fDefault;
  1143. fDefault = FALSE;
  1144. NdisReadConfiguration(
  1145. &status, &pncp, hCfg, &nstr, NdisParameterInteger );
  1146. if (status == NDIS_STATUS_SUCCESS)
  1147. {
  1148. *phre = (HOSTROUTEEXISTS )pncp->ParameterData.IntegerData;
  1149. if (*phre != HRE_Use
  1150. && *phre != HRE_Fail
  1151. #if ROUTEWITHREF
  1152. && *phre != HRE_Reference
  1153. #endif
  1154. )
  1155. {
  1156. // Bad value in registry.
  1157. //
  1158. fDefault = TRUE;
  1159. }
  1160. }
  1161. else
  1162. {
  1163. // No value in registry.
  1164. //
  1165. status = NDIS_STATUS_SUCCESS;
  1166. fDefault = TRUE;
  1167. }
  1168. if (fDefault)
  1169. {
  1170. #if ROUTEWITHREF
  1171. // Set default to "reference" as this allows simultaneous L2TP
  1172. // and PPTP connections between the same two peers without
  1173. // host route trashing.
  1174. //
  1175. *phre = HRE_Reference;
  1176. #else
  1177. // Set default to "fail" to prevent L2TP from stomping on a
  1178. // PPTP host route.
  1179. //
  1180. *phre = HRE_Fail;
  1181. #endif
  1182. }
  1183. }
  1184. // (optional) Flag indicating whether UDP checksums should be disabled
  1185. // on L2TP payload traffic.
  1186. //
  1187. {
  1188. NDIS_STRING nstr = NDIS_STRING_CONST( "DisableUdpChecksums" );
  1189. NdisReadConfiguration(
  1190. &status, &pncp, hCfg, &nstr, NdisParameterInteger );
  1191. if (status == NDIS_STATUS_SUCCESS)
  1192. {
  1193. *pfDisableUdpXsums =
  1194. (BOOLEAN )!!(pncp->ParameterData.IntegerData);
  1195. }
  1196. else
  1197. {
  1198. // No value in registry. Set a default. The L2TP draft says
  1199. // implementation MUST default to "enabled".
  1200. //
  1201. *pfDisableUdpXsums = TRUE;
  1202. status = NDIS_STATUS_SUCCESS;
  1203. }
  1204. }
  1205. // (required) The driver description string, which is reported to TAPI
  1206. // as the L2TP line name.
  1207. //
  1208. {
  1209. NDIS_STRING nstr = NDIS_STRING_CONST( "DriverDesc" );
  1210. NdisReadConfiguration(
  1211. &status, &pncp, hCfg, &nstr, NdisParameterString );
  1212. if (status == NDIS_STATUS_SUCCESS)
  1213. {
  1214. *ppszDriverDesc =
  1215. StrDupNdisString( &pncp->ParameterData.StringData );
  1216. }
  1217. else
  1218. {
  1219. // No setting in registry...and no default.
  1220. //
  1221. *ppszDriverDesc = NULL;
  1222. status = NDIS_STATUS_SUCCESS;
  1223. }
  1224. }
  1225. }
  1226. while (FALSE);
  1227. NdisCloseConfiguration( hCfg );
  1228. TRACE( TL_N, TM_Init,
  1229. ( "Reg: vcs=%d mt=%d or=%d lld=%d hto=%d ooo=%d mad=%d dx=%d",
  1230. *pusMaxVcs,
  1231. *pMediaType,
  1232. *pOutgoingRole,
  1233. (ULONG )*pusLlistDepth,
  1234. *pulHelloMs,
  1235. (INT )*psMaxOutOfOrder,
  1236. *pulMaxAckDelayMs,
  1237. (UINT )*pfDisableUdpXsums ) );
  1238. TRACE( TL_N, TM_Init,
  1239. ( "Reg: mto=%d ito=%d mrt=%d crw=%d prw=%d psw=%d ifm=%d xt=%d xr=%d",
  1240. *pulMaxSendTimeoutMs,
  1241. *pulInitialSendTimeoutMs,
  1242. *pulMaxRetransmits,
  1243. (UINT )*pusControlReceiveWindow,
  1244. (UINT )*pusPayloadReceiveWindow,
  1245. (UINT )*pulPayloadSendWindow,
  1246. (UINT )*pfIgnoreFramingMismatch,
  1247. (UINT )*pfExclusiveTunnels,
  1248. (UINT )*phre));
  1249. TRACE( TL_N, TM_Init,
  1250. ( "Reg: hn=\"%s\" pw=\"%s\"",
  1251. ((*ppszHostName) ? *ppszHostName : ""),
  1252. ((*ppszPassword) ? *ppszPassword : "") ) );
  1253. return status;
  1254. }
  1255. NDIS_STATUS
  1256. QueryInformation(
  1257. IN ADAPTERCB* pAdapter,
  1258. IN VCCB* pVc,
  1259. IN NDIS_OID Oid,
  1260. IN PVOID InformationBuffer,
  1261. IN ULONG InformationBufferLength,
  1262. OUT PULONG BytesWritten,
  1263. OUT PULONG BytesNeeded )
  1264. // Handle QueryInformation requests. Arguments are as for the standard
  1265. // NDIS 'MiniportQueryInformation' handler except this routine does not
  1266. // count on being serialized with respect to other requests.
  1267. //
  1268. {
  1269. NDIS_STATUS status;
  1270. ULONG ulInfo;
  1271. VOID* pInfo;
  1272. ULONG ulInfoLen;
  1273. status = NDIS_STATUS_SUCCESS;
  1274. // The cases in this switch statement find or create a buffer containing
  1275. // the requested information and point 'pInfo' at it, noting it's length
  1276. // in 'ulInfoLen'. Since many of the OIDs return a ULONG, a 'ulInfo'
  1277. // buffer is set up as the default.
  1278. //
  1279. ulInfo = 0;
  1280. pInfo = &ulInfo;
  1281. ulInfoLen = sizeof(ulInfo);
  1282. switch (Oid)
  1283. {
  1284. case OID_GEN_MAXIMUM_LOOKAHEAD:
  1285. {
  1286. // Report the maximum number of bytes we can always provide as
  1287. // lookahead data on receive indications. We always indicate full
  1288. // packets so this is the same as the receive block size. And
  1289. // since we always allocate enough for a full packet, the receive
  1290. // block size is the same as the frame size.
  1291. //
  1292. TRACE( TL_N, TM_Mp, ( "QInfo(OID_GEN_MAXIMUM_LOOKAHEAD)" ) );
  1293. ulInfo = L2TP_MaxFrameSize;
  1294. break;
  1295. }
  1296. case OID_GEN_MAC_OPTIONS:
  1297. {
  1298. // Report a bitmask defining optional properties of the driver.
  1299. //
  1300. // NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA promises that our receive
  1301. // buffer is not on a device-specific card.
  1302. //
  1303. // NDIS_MAC_OPTION_TRANSFERS_NOT_PEND promises we won't return
  1304. // NDIS_STATUS_PENDING from our TransferData handler which is true
  1305. // since we don't have one.
  1306. //
  1307. TRACE( TL_N, TM_Mp, ( "QInfo(OID_GEN_MAC_OPTIONS)" ) );
  1308. ulInfo = NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA
  1309. | NDIS_MAC_OPTION_TRANSFERS_NOT_PEND;
  1310. break;
  1311. }
  1312. case OID_WAN_MEDIUM_SUBTYPE:
  1313. {
  1314. // Report the media subtype we support. NDISWAN may use this in
  1315. // the future (doesn't now) to provide framing differences for
  1316. // different media.
  1317. //
  1318. TRACE( TL_N, TM_Mp, ( "QInfo(OID_WAN_MEDIUM_SUBTYPE)" ) );
  1319. ulInfo = NdisWanMediumL2TP;
  1320. break;
  1321. }
  1322. case OID_WAN_CO_GET_INFO:
  1323. {
  1324. // Report the capabilities of the adapter.
  1325. //
  1326. TRACE( TL_N, TM_Mp, ( "QInfo(OID_WAN_CO_GET_INFO)" ) );
  1327. pInfo = &pAdapter->info;
  1328. ulInfoLen = sizeof(NDIS_WAN_CO_INFO);
  1329. break;
  1330. }
  1331. case OID_WAN_CO_GET_LINK_INFO:
  1332. {
  1333. // Report the current state of the link.
  1334. //
  1335. TRACE( TL_N, TM_Mp, ( "QInfo(OID_WAN_CO_GET_LINK_INFO)" ) );
  1336. if (!pVc)
  1337. {
  1338. return NDIS_STATUS_INVALID_DATA;
  1339. }
  1340. pInfo = &pVc->linkinfo;
  1341. ulInfoLen = sizeof(NDIS_WAN_CO_GET_LINK_INFO);
  1342. break;
  1343. }
  1344. case OID_WAN_CO_GET_COMP_INFO:
  1345. {
  1346. // Report the type of compression we provide, which is none.
  1347. //
  1348. TRACE( TL_N, TM_Mp, ( "QInfo(OID_WAN_CO_GET_COMP_INFO)" ) );
  1349. status = NDIS_STATUS_NOT_SUPPORTED;
  1350. ulInfoLen = 0;
  1351. break;
  1352. }
  1353. case OID_WAN_CO_GET_STATS_INFO:
  1354. {
  1355. // Because L2TP doesn't do compression, NDISWAN will use it's own
  1356. // statistics and not query ours.
  1357. //
  1358. ASSERT( !"OID_WAN_CO_GET_STATS_INFO?" );
  1359. status = NDIS_STATUS_NOT_SUPPORTED;
  1360. ulInfoLen = 0;
  1361. break;
  1362. }
  1363. case OID_GEN_SUPPORTED_LIST:
  1364. {
  1365. static ULONG aulSupportedOids[] = {
  1366. OID_GEN_SUPPORTED_LIST,
  1367. OID_GEN_MAXIMUM_LOOKAHEAD,
  1368. OID_GEN_MAC_OPTIONS,
  1369. OID_WAN_MEDIUM_SUBTYPE,
  1370. OID_WAN_CO_GET_INFO,
  1371. OID_WAN_CO_GET_LINK_INFO,
  1372. OID_WAN_CO_SET_LINK_INFO,
  1373. OID_CO_TAPI_CM_CAPS,
  1374. OID_CO_TAPI_LINE_CAPS,
  1375. OID_CO_TAPI_ADDRESS_CAPS,
  1376. OID_CO_TAPI_GET_CALL_DIAGNOSTICS
  1377. };
  1378. TRACE( TL_N, TM_Mp, ( "QInfo(OID_GEN_SUPPORTED_LIST)" ) );
  1379. pInfo = aulSupportedOids;
  1380. ulInfoLen = sizeof(aulSupportedOids);
  1381. break;
  1382. }
  1383. #if 0
  1384. // These OIDs are mandatory according to current doc, but since
  1385. // NDISWAN never requests them they are omitted.
  1386. //
  1387. case OID_GEN_HARDWARE_STATUS:
  1388. case OID_GEN_MEDIA_SUPPORTED:
  1389. case OID_GEN_MEDIA_IN_USE:
  1390. case OID_GEN_MEDIA_IN_USE:
  1391. case OID_GEN_MAXIMUM_FRAME_SIZE:
  1392. case OID_GEN_LINK_SPEED:
  1393. case OID_GEN_TRANSMIT_BUFFER_SPACE:
  1394. case OID_GEN_RECEIVE_BUFFER_SPACE:
  1395. case OID_GEN_TRANSMIT_BLOCK_SIZE:
  1396. case OID_GEN_RECEIVE_BLOCK_SIZE:
  1397. case OID_GEN_VENDOR_ID:
  1398. case OID_GEN_VENDOR_DESCRIPTION:
  1399. case OID_GEN_VENDOR_DRIVER_VERSION:
  1400. case OID_GEN_CURRENT_PACKET_FILTER:
  1401. case OID_GEN_CURRENT_LOOKAHEAD:
  1402. case OID_GEN_DRIVER_VERSION:
  1403. case OID_GEN_MAXIMUM_TOTAL_SIZE:
  1404. case OID_GEN_MAC_OPTIONS:
  1405. case OID_GEN_MEDIA_CONNECT_STATUS:
  1406. case OID_GEN_MAXIMUM_SEND_PACKETS:
  1407. case OID_WAN_PERMANENT_ADDRESS:
  1408. case OID_WAN_CURRENT_ADDRESS:
  1409. case OID_WAN_QUALITY_OF_SERVICE:
  1410. case OID_WAN_LINE_COUNT:
  1411. #endif
  1412. default:
  1413. {
  1414. TRACE( TL_A, TM_Mp, ( "Q-OID=$%08x?", Oid ) );
  1415. status = NDIS_STATUS_NOT_SUPPORTED;
  1416. ulInfoLen = 0;
  1417. break;
  1418. }
  1419. }
  1420. if (ulInfoLen > InformationBufferLength)
  1421. {
  1422. // Caller's buffer is too small. Tell him what he needs.
  1423. //
  1424. *BytesNeeded = ulInfoLen;
  1425. status = NDIS_STATUS_INVALID_LENGTH;
  1426. }
  1427. else
  1428. {
  1429. // Copy the found result to caller's buffer.
  1430. //
  1431. if (ulInfoLen > 0)
  1432. {
  1433. NdisMoveMemory( InformationBuffer, pInfo, ulInfoLen );
  1434. DUMPDW( TL_N, TM_Mp, pInfo, ulInfoLen );
  1435. }
  1436. *BytesNeeded = *BytesWritten = ulInfoLen;
  1437. }
  1438. return status;
  1439. }
  1440. VOID
  1441. ReferenceAdapter(
  1442. IN ADAPTERCB* pAdapter )
  1443. // Adds areference to the adapter block, 'pAdapter'.
  1444. //
  1445. {
  1446. LONG lRef;
  1447. lRef = NdisInterlockedIncrement( &pAdapter->lRef );
  1448. TRACE( TL_N, TM_Ref, ( "RefA to %d", lRef ) );
  1449. }
  1450. NDIS_STATUS
  1451. SetInformation(
  1452. IN ADAPTERCB* pAdapter,
  1453. IN VCCB* pVc,
  1454. IN NDIS_OID Oid,
  1455. IN PVOID InformationBuffer,
  1456. IN ULONG InformationBufferLength,
  1457. OUT PULONG BytesRead,
  1458. OUT PULONG BytesNeeded )
  1459. // Handle SetInformation requests. Arguments are as for the standard NDIS
  1460. // 'MiniportQueryInformation' handler except this routine does not count
  1461. // on being serialized with respect to other requests.
  1462. //
  1463. {
  1464. NDIS_STATUS status;
  1465. status = NDIS_STATUS_SUCCESS;
  1466. switch (Oid)
  1467. {
  1468. case OID_WAN_CO_SET_LINK_INFO:
  1469. {
  1470. // Read new link state settings.
  1471. //
  1472. TRACE( TL_N, TM_Mp, ( "SInfo(OID_WAN_CO_SET_LINK_INFO)" ) );
  1473. if (InformationBufferLength < sizeof(NDIS_WAN_CO_SET_LINK_INFO))
  1474. {
  1475. status = NDIS_STATUS_INVALID_LENGTH;
  1476. *BytesRead = 0;
  1477. }
  1478. else
  1479. {
  1480. if (!pVc)
  1481. return NDIS_STATUS_INVALID_DATA;
  1482. ASSERT( sizeof(pVc->linkinfo)
  1483. == sizeof(NDIS_WAN_CO_SET_LINK_INFO) );
  1484. NdisMoveMemory( &pVc->linkinfo, InformationBuffer,
  1485. sizeof(pVc->linkinfo) );
  1486. DUMPB( TL_N, TM_Mp, &pVc->linkinfo, sizeof(pVc->linkinfo) );
  1487. *BytesRead = sizeof(NDIS_WAN_CO_SET_LINK_INFO);
  1488. }
  1489. *BytesNeeded = sizeof(NDIS_WAN_CO_SET_LINK_INFO);
  1490. }
  1491. break;
  1492. case OID_WAN_CO_SET_COMP_INFO:
  1493. {
  1494. // L2TP doesn't provide compression.
  1495. //
  1496. TRACE( TL_N, TM_Mp, ( "SInfo(OID_WAN_CO_SET_COMP_INFO)" ) );
  1497. status = NDIS_STATUS_NOT_SUPPORTED;
  1498. *BytesRead = *BytesNeeded = 0;
  1499. break;
  1500. }
  1501. #if 0
  1502. // These OIDs are mandatory according to current doc, but since
  1503. // NDISWAN never requests them they are omitted.
  1504. //
  1505. case OID_GEN_CURRENT_PACKET_FILTER:
  1506. case OID_GEN_CURRENT_LOOKAHEAD:
  1507. case OID_GEN_PROTOCOL_OPTIONS:
  1508. case OID_WAN_PROTOCOL_TYPE:
  1509. case OID_WAN_HEADER_FORMAT:
  1510. #endif
  1511. default:
  1512. {
  1513. TRACE( TL_A, TM_Mp, ( "S-OID=$%08x?", Oid ) );
  1514. status = NDIS_STATUS_NOT_SUPPORTED;
  1515. *BytesRead = *BytesNeeded = 0;
  1516. break;
  1517. }
  1518. }
  1519. return status;
  1520. }