Source code of Windows XP (NT5)
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.

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