adapter.c 53 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717
  1. /*
  2. * TAP-Windows -- A kernel driver to provide virtual tap
  3. * device functionality on Windows.
  4. *
  5. * This code was inspired by the CIPE-Win32 driver by Damion K. Wilson.
  6. *
  7. * This source code is Copyright (C) 2002-2014 OpenVPN Technologies, Inc.,
  8. * and is released under the GPL version 2 (see below).
  9. *
  10. * This program is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License version 2
  12. * as published by the Free Software Foundation.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program (see the file COPYING included with this
  21. * distribution); if not, write to the Free Software Foundation, Inc.,
  22. * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  23. */
  24. //
  25. // Include files.
  26. //
  27. #include "tap.h"
  28. NDIS_OID TAPSupportedOids[] =
  29. {
  30. OID_GEN_HARDWARE_STATUS,
  31. OID_GEN_TRANSMIT_BUFFER_SPACE,
  32. OID_GEN_RECEIVE_BUFFER_SPACE,
  33. OID_GEN_TRANSMIT_BLOCK_SIZE,
  34. OID_GEN_RECEIVE_BLOCK_SIZE,
  35. OID_GEN_VENDOR_ID,
  36. OID_GEN_VENDOR_DESCRIPTION,
  37. OID_GEN_VENDOR_DRIVER_VERSION,
  38. OID_GEN_CURRENT_PACKET_FILTER,
  39. OID_GEN_CURRENT_LOOKAHEAD,
  40. OID_GEN_DRIVER_VERSION,
  41. OID_GEN_MAXIMUM_TOTAL_SIZE,
  42. OID_GEN_XMIT_OK,
  43. OID_GEN_RCV_OK,
  44. OID_GEN_STATISTICS,
  45. #ifdef IMPLEMENT_OPTIONAL_OIDS
  46. OID_GEN_TRANSMIT_QUEUE_LENGTH, // Optional
  47. #endif // IMPLEMENT_OPTIONAL_OIDS
  48. OID_GEN_LINK_PARAMETERS,
  49. OID_GEN_INTERRUPT_MODERATION,
  50. OID_GEN_MEDIA_SUPPORTED,
  51. OID_GEN_MEDIA_IN_USE,
  52. OID_GEN_MAXIMUM_SEND_PACKETS,
  53. OID_GEN_XMIT_ERROR,
  54. OID_GEN_RCV_ERROR,
  55. OID_GEN_RCV_NO_BUFFER,
  56. OID_802_3_PERMANENT_ADDRESS,
  57. OID_802_3_CURRENT_ADDRESS,
  58. OID_802_3_MULTICAST_LIST,
  59. OID_802_3_MAXIMUM_LIST_SIZE,
  60. OID_802_3_RCV_ERROR_ALIGNMENT,
  61. OID_802_3_XMIT_ONE_COLLISION,
  62. OID_802_3_XMIT_MORE_COLLISIONS,
  63. #ifdef IMPLEMENT_OPTIONAL_OIDS
  64. OID_802_3_XMIT_DEFERRED, // Optional
  65. OID_802_3_XMIT_MAX_COLLISIONS, // Optional
  66. OID_802_3_RCV_OVERRUN, // Optional
  67. OID_802_3_XMIT_UNDERRUN, // Optional
  68. OID_802_3_XMIT_HEARTBEAT_FAILURE, // Optional
  69. OID_802_3_XMIT_TIMES_CRS_LOST, // Optional
  70. OID_802_3_XMIT_LATE_COLLISIONS, // Optional
  71. OID_PNP_CAPABILITIES, // Optional
  72. #endif // IMPLEMENT_OPTIONAL_OIDS
  73. };
  74. //======================================================================
  75. // TAP NDIS 6 Miniport Callbacks
  76. //======================================================================
  77. // Returns with reference count initialized to one.
  78. PTAP_ADAPTER_CONTEXT
  79. tapAdapterContextAllocate(
  80. __in NDIS_HANDLE MiniportAdapterHandle
  81. )
  82. {
  83. PTAP_ADAPTER_CONTEXT adapter = NULL;
  84. adapter = (PTAP_ADAPTER_CONTEXT )NdisAllocateMemoryWithTagPriority(
  85. GlobalData.NdisDriverHandle,
  86. sizeof(TAP_ADAPTER_CONTEXT),
  87. TAP_ADAPTER_TAG,
  88. NormalPoolPriority
  89. );
  90. if(adapter)
  91. {
  92. NET_BUFFER_LIST_POOL_PARAMETERS nblPoolParameters = {0};
  93. NdisZeroMemory(adapter,sizeof(TAP_ADAPTER_CONTEXT));
  94. adapter->MiniportAdapterHandle = MiniportAdapterHandle;
  95. // Initialize cancel-safe IRP queue
  96. tapIrpCsqInitialize(&adapter->PendingReadIrpQueue);
  97. // Initialize TAP send packet queue.
  98. tapPacketQueueInitialize(&adapter->SendPacketQueue);
  99. // Allocate the adapter lock.
  100. NdisAllocateSpinLock(&adapter->AdapterLock);
  101. // NBL pool for making TAP receive indications.
  102. NdisZeroMemory(&nblPoolParameters, sizeof(NET_BUFFER_LIST_POOL_PARAMETERS));
  103. // Initialize event used to determine when all receive NBLs have been returned.
  104. NdisInitializeEvent(&adapter->ReceiveNblInFlightCountZeroEvent);
  105. nblPoolParameters.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
  106. nblPoolParameters.Header.Revision = NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1;
  107. nblPoolParameters.Header.Size = NDIS_SIZEOF_NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1;
  108. nblPoolParameters.ProtocolId = NDIS_PROTOCOL_ID_DEFAULT;
  109. nblPoolParameters.ContextSize = 0;
  110. //nblPoolParameters.ContextSize = sizeof(RX_NETBUFLIST_RSVD);
  111. nblPoolParameters.fAllocateNetBuffer = TRUE;
  112. nblPoolParameters.PoolTag = TAP_RX_NBL_TAG;
  113. #pragma warning( suppress : 28197 )
  114. adapter->ReceiveNblPool = NdisAllocateNetBufferListPool(
  115. adapter->MiniportAdapterHandle,
  116. &nblPoolParameters);
  117. if (adapter->ReceiveNblPool == NULL)
  118. {
  119. DEBUGP (("[TAP] Couldn't allocate adapter receive NBL pool\n"));
  120. NdisFreeMemory(adapter,0,0);
  121. }
  122. // Add initial reference. Normally removed in AdapterHalt.
  123. adapter->RefCount = 1;
  124. // Safe for multiple removes.
  125. NdisInitializeListHead(&adapter->AdapterListLink);
  126. //
  127. // The miniport adapter is initially powered up
  128. //
  129. adapter->CurrentPowerState = NdisDeviceStateD0;
  130. }
  131. return adapter;
  132. }
  133. VOID
  134. tapReadPermanentAddress(
  135. __in PTAP_ADAPTER_CONTEXT Adapter,
  136. __in NDIS_HANDLE ConfigurationHandle,
  137. __out MACADDR PermanentAddress
  138. )
  139. {
  140. NDIS_STATUS status;
  141. NDIS_CONFIGURATION_PARAMETER *configParameter;
  142. NDIS_STRING macKey = NDIS_STRING_CONST("MAC");
  143. ANSI_STRING macString;
  144. BOOLEAN macFromRegistry = FALSE;
  145. // Read MAC parameter from registry.
  146. NdisReadConfiguration(
  147. &status,
  148. &configParameter,
  149. ConfigurationHandle,
  150. &macKey,
  151. NdisParameterString
  152. );
  153. if (status == NDIS_STATUS_SUCCESS)
  154. {
  155. if( (configParameter->ParameterType == NdisParameterString)
  156. && (configParameter->ParameterData.StringData.Length >= 12)
  157. )
  158. {
  159. if (RtlUnicodeStringToAnsiString(
  160. &macString,
  161. &configParameter->ParameterData.StringData,
  162. TRUE) == STATUS_SUCCESS
  163. )
  164. {
  165. macFromRegistry = ParseMAC (PermanentAddress, macString.Buffer);
  166. RtlFreeAnsiString (&macString);
  167. }
  168. }
  169. }
  170. if(!macFromRegistry)
  171. {
  172. //
  173. // There is no (valid) address stashed in the registry parameter.
  174. //
  175. // Make up a dummy mac address based on the ANSI representation of the
  176. // NetCfgInstanceId GUID.
  177. //
  178. GenerateRandomMac(PermanentAddress, MINIPORT_INSTANCE_ID(Adapter));
  179. }
  180. }
  181. NDIS_STATUS
  182. tapReadConfiguration(
  183. __in PTAP_ADAPTER_CONTEXT Adapter
  184. )
  185. {
  186. NDIS_STATUS status = NDIS_STATUS_SUCCESS;
  187. NDIS_CONFIGURATION_OBJECT configObject;
  188. NDIS_HANDLE configHandle;
  189. DEBUGP (("[TAP] --> tapReadConfiguration\n"));
  190. //
  191. // Setup defaults in case configuration cannot be opened.
  192. //
  193. Adapter->MtuSize = ETHERNET_MTU;
  194. Adapter->MediaStateAlwaysConnected = FALSE;
  195. Adapter->LogicalMediaState = FALSE;
  196. Adapter->AllowNonAdmin = FALSE;
  197. //
  198. // Open the registry for this adapter to read advanced
  199. // configuration parameters stored by the INF file.
  200. //
  201. NdisZeroMemory(&configObject, sizeof(configObject));
  202. {C_ASSERT(sizeof(configObject) >= NDIS_SIZEOF_CONFIGURATION_OBJECT_REVISION_1);}
  203. configObject.Header.Type = NDIS_OBJECT_TYPE_CONFIGURATION_OBJECT;
  204. configObject.Header.Size = NDIS_SIZEOF_CONFIGURATION_OBJECT_REVISION_1;
  205. configObject.Header.Revision = NDIS_CONFIGURATION_OBJECT_REVISION_1;
  206. configObject.NdisHandle = Adapter->MiniportAdapterHandle;
  207. configObject.Flags = 0;
  208. status = NdisOpenConfigurationEx(
  209. &configObject,
  210. &configHandle
  211. );
  212. // Read on the opened configuration handle.
  213. if(status == NDIS_STATUS_SUCCESS)
  214. {
  215. NDIS_CONFIGURATION_PARAMETER *configParameter;
  216. NDIS_STRING mkey = NDIS_STRING_CONST("NetCfgInstanceId");
  217. //
  218. // Read NetCfgInstanceId from the registry.
  219. // ------------------------------------
  220. // NetCfgInstanceId is required to create device and associated
  221. // symbolic link for the adapter device.
  222. //
  223. // NetCfgInstanceId is a GUID string provided by NDIS that identifies
  224. // the adapter instance. An example is:
  225. //
  226. // NetCfgInstanceId={410EB49D-2381-4FE7-9B36-498E22619DF0}
  227. //
  228. // Other names are derived from NetCfgInstanceId. For example, MiniportName:
  229. //
  230. // MiniportName=\DEVICE\{410EB49D-2381-4FE7-9B36-498E22619DF0}
  231. //
  232. NdisReadConfiguration (
  233. &status,
  234. &configParameter,
  235. configHandle,
  236. &mkey,
  237. NdisParameterString
  238. );
  239. if (status == NDIS_STATUS_SUCCESS)
  240. {
  241. if (configParameter->ParameterType == NdisParameterString
  242. && configParameter->ParameterData.StringData.Length <= sizeof(Adapter->NetCfgInstanceIdBuffer) - sizeof(WCHAR))
  243. {
  244. DEBUGP (("[TAP] NdisReadConfiguration (NetCfgInstanceId=%wZ)\n",
  245. &configParameter->ParameterData.StringData ));
  246. // Save NetCfgInstanceId as UNICODE_STRING.
  247. Adapter->NetCfgInstanceId.Length = Adapter->NetCfgInstanceId.MaximumLength
  248. = configParameter->ParameterData.StringData.Length;
  249. Adapter->NetCfgInstanceId.Buffer = Adapter->NetCfgInstanceIdBuffer;
  250. NdisMoveMemory(
  251. Adapter->NetCfgInstanceId.Buffer,
  252. configParameter->ParameterData.StringData.Buffer,
  253. Adapter->NetCfgInstanceId.Length
  254. );
  255. // Save NetCfgInstanceId as ANSI_STRING as well.
  256. if (RtlUnicodeStringToAnsiString (
  257. &Adapter->NetCfgInstanceIdAnsi,
  258. &configParameter->ParameterData.StringData,
  259. TRUE) != STATUS_SUCCESS
  260. )
  261. {
  262. DEBUGP (("[TAP] NetCfgInstanceId ANSI name conversion failed\n"));
  263. status = NDIS_STATUS_RESOURCES;
  264. }
  265. }
  266. else
  267. {
  268. DEBUGP (("[TAP] NetCfgInstanceId has invalid type\n"));
  269. status = NDIS_STATUS_INVALID_DATA;
  270. }
  271. }
  272. else
  273. {
  274. DEBUGP (("[TAP] NetCfgInstanceId failed\n"));
  275. status = NDIS_STATUS_INVALID_DATA;
  276. }
  277. if (status == NDIS_STATUS_SUCCESS)
  278. {
  279. NDIS_STATUS localStatus; // Use default if these fail.
  280. NDIS_CONFIGURATION_PARAMETER *configParameter;
  281. NDIS_STRING mtuKey = NDIS_STRING_CONST("MTU");
  282. NDIS_STRING mediaStatusKey = NDIS_STRING_CONST("MediaStatus");
  283. #if ENABLE_NONADMIN
  284. NDIS_STRING allowNonAdminKey = NDIS_STRING_CONST("AllowNonAdmin");
  285. #endif
  286. // Read MTU from the registry.
  287. NdisReadConfiguration (
  288. &localStatus,
  289. &configParameter,
  290. configHandle,
  291. &mtuKey,
  292. NdisParameterInteger
  293. );
  294. if (localStatus == NDIS_STATUS_SUCCESS)
  295. {
  296. if (configParameter->ParameterType == NdisParameterInteger)
  297. {
  298. int mtu = configParameter->ParameterData.IntegerData;
  299. if(mtu == 0)
  300. {
  301. mtu = ETHERNET_MTU;
  302. }
  303. // Sanity check
  304. if (mtu < MINIMUM_MTU)
  305. {
  306. mtu = MINIMUM_MTU;
  307. }
  308. else if (mtu > MAXIMUM_MTU)
  309. {
  310. mtu = MAXIMUM_MTU;
  311. }
  312. Adapter->MtuSize = mtu;
  313. }
  314. }
  315. DEBUGP (("[%s] Using MTU %d\n",
  316. MINIPORT_INSTANCE_ID (Adapter),
  317. Adapter->MtuSize
  318. ));
  319. // Read MediaStatus setting from registry.
  320. NdisReadConfiguration (
  321. &localStatus,
  322. &configParameter,
  323. configHandle,
  324. &mediaStatusKey,
  325. NdisParameterInteger
  326. );
  327. if (localStatus == NDIS_STATUS_SUCCESS)
  328. {
  329. if (configParameter->ParameterType == NdisParameterInteger)
  330. {
  331. if(configParameter->ParameterData.IntegerData == 0)
  332. {
  333. // Connect state is appplication controlled.
  334. DEBUGP(("[%s] Initial MediaConnectState: Application Controlled\n",
  335. MINIPORT_INSTANCE_ID (Adapter)));
  336. Adapter->MediaStateAlwaysConnected = FALSE;
  337. Adapter->LogicalMediaState = FALSE;
  338. }
  339. else
  340. {
  341. // Connect state is always connected.
  342. DEBUGP(("[%s] Initial MediaConnectState: Always Connected\n",
  343. MINIPORT_INSTANCE_ID (Adapter)));
  344. Adapter->MediaStateAlwaysConnected = TRUE;
  345. Adapter->LogicalMediaState = TRUE;
  346. }
  347. }
  348. }
  349. // Read MAC PermanentAddress setting from registry.
  350. tapReadPermanentAddress(
  351. Adapter,
  352. configHandle,
  353. Adapter->PermanentAddress
  354. );
  355. DEBUGP (("[%s] Using MAC PermanentAddress %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n",
  356. MINIPORT_INSTANCE_ID (Adapter),
  357. Adapter->PermanentAddress[0],
  358. Adapter->PermanentAddress[1],
  359. Adapter->PermanentAddress[2],
  360. Adapter->PermanentAddress[3],
  361. Adapter->PermanentAddress[4],
  362. Adapter->PermanentAddress[5])
  363. );
  364. // Now seed the current MAC address with the permanent address.
  365. ETH_COPY_NETWORK_ADDRESS(Adapter->CurrentAddress, Adapter->PermanentAddress);
  366. DEBUGP (("[%s] Using MAC CurrentAddress %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n",
  367. MINIPORT_INSTANCE_ID (Adapter),
  368. Adapter->CurrentAddress[0],
  369. Adapter->CurrentAddress[1],
  370. Adapter->CurrentAddress[2],
  371. Adapter->CurrentAddress[3],
  372. Adapter->CurrentAddress[4],
  373. Adapter->CurrentAddress[5])
  374. );
  375. // Read optional AllowNonAdmin setting from registry.
  376. #if ENABLE_NONADMIN
  377. NdisReadConfiguration (
  378. &localStatus,
  379. &configParameter,
  380. configHandle,
  381. &allowNonAdminKey,
  382. NdisParameterInteger
  383. );
  384. if (localStatus == NDIS_STATUS_SUCCESS)
  385. {
  386. if (configParameter->ParameterType == NdisParameterInteger)
  387. {
  388. Adapter->AllowNonAdmin = TRUE;
  389. }
  390. }
  391. #endif
  392. }
  393. // Close the configuration handle.
  394. NdisCloseConfiguration(configHandle);
  395. }
  396. else
  397. {
  398. DEBUGP (("[TAP] Couldn't open adapter registry\n"));
  399. }
  400. DEBUGP (("[TAP] <-- tapReadConfiguration; status = %8.8X\n",status));
  401. return status;
  402. }
  403. VOID
  404. tapAdapterContextAddToGlobalList(
  405. __in PTAP_ADAPTER_CONTEXT Adapter
  406. )
  407. {
  408. LOCK_STATE lockState;
  409. PLIST_ENTRY listEntry = &Adapter->AdapterListLink;
  410. // Acquire global adapter list lock.
  411. NdisAcquireReadWriteLock(
  412. &GlobalData.Lock,
  413. TRUE, // Acquire for write
  414. &lockState
  415. );
  416. // Adapter context should NOT be in any list.
  417. ASSERT( (listEntry->Flink == listEntry) && (listEntry->Blink == listEntry ) );
  418. // Add reference to persist until after removal.
  419. tapAdapterContextReference(Adapter);
  420. // Add the adapter context to the global list.
  421. InsertTailList(&GlobalData.AdapterList,&Adapter->AdapterListLink);
  422. // Release global adapter list lock.
  423. NdisReleaseReadWriteLock(&GlobalData.Lock,&lockState);
  424. }
  425. VOID
  426. tapAdapterContextRemoveFromGlobalList(
  427. __in PTAP_ADAPTER_CONTEXT Adapter
  428. )
  429. {
  430. LOCK_STATE lockState;
  431. // Acquire global adapter list lock.
  432. NdisAcquireReadWriteLock(
  433. &GlobalData.Lock,
  434. TRUE, // Acquire for write
  435. &lockState
  436. );
  437. // Remove the adapter context from the global list.
  438. RemoveEntryList(&Adapter->AdapterListLink);
  439. // Safe for multiple removes.
  440. NdisInitializeListHead(&Adapter->AdapterListLink);
  441. // Remove reference added in tapAdapterContextAddToGlobalList.
  442. tapAdapterContextDereference(Adapter);
  443. // Release global adapter list lock.
  444. NdisReleaseReadWriteLock(&GlobalData.Lock,&lockState);
  445. }
  446. // Returns with added reference on adapter context.
  447. PTAP_ADAPTER_CONTEXT
  448. tapAdapterContextFromDeviceObject(
  449. __in PDEVICE_OBJECT DeviceObject
  450. )
  451. {
  452. LOCK_STATE lockState;
  453. // Acquire global adapter list lock.
  454. NdisAcquireReadWriteLock(
  455. &GlobalData.Lock,
  456. FALSE, // Acquire for read
  457. &lockState
  458. );
  459. if (!IsListEmpty(&GlobalData.AdapterList))
  460. {
  461. PLIST_ENTRY entry = GlobalData.AdapterList.Flink;
  462. PTAP_ADAPTER_CONTEXT adapter;
  463. while (entry != &GlobalData.AdapterList)
  464. {
  465. adapter = CONTAINING_RECORD(entry, TAP_ADAPTER_CONTEXT, AdapterListLink);
  466. // Match on DeviceObject
  467. if(adapter->DeviceObject == DeviceObject )
  468. {
  469. // Add reference to adapter context.
  470. tapAdapterContextReference(adapter);
  471. // Release global adapter list lock.
  472. NdisReleaseReadWriteLock(&GlobalData.Lock,&lockState);
  473. return adapter;
  474. }
  475. // Move to next entry
  476. entry = entry->Flink;
  477. }
  478. }
  479. // Release global adapter list lock.
  480. NdisReleaseReadWriteLock(&GlobalData.Lock,&lockState);
  481. return (PTAP_ADAPTER_CONTEXT )NULL;
  482. }
  483. NDIS_STATUS
  484. AdapterSetOptions(
  485. __in NDIS_HANDLE NdisDriverHandle,
  486. __in NDIS_HANDLE DriverContext
  487. )
  488. /*++
  489. Routine Description:
  490. The MiniportSetOptions function registers optional handlers. For each
  491. optional handler that should be registered, this function makes a call
  492. to NdisSetOptionalHandlers.
  493. MiniportSetOptions runs at IRQL = PASSIVE_LEVEL.
  494. Arguments:
  495. DriverContext The context handle
  496. Return Value:
  497. NDIS_STATUS_xxx code
  498. --*/
  499. {
  500. NDIS_STATUS status;
  501. DEBUGP (("[TAP] --> AdapterSetOptions\n"));
  502. //
  503. // Set any optional handlers by filling out the appropriate struct and
  504. // calling NdisSetOptionalHandlers here.
  505. //
  506. status = NDIS_STATUS_SUCCESS;
  507. DEBUGP (("[TAP] <-- AdapterSetOptions; status = %8.8X\n",status));
  508. return status;
  509. }
  510. NDIS_STATUS
  511. AdapterCreate(
  512. __in NDIS_HANDLE MiniportAdapterHandle,
  513. __in NDIS_HANDLE MiniportDriverContext,
  514. __in PNDIS_MINIPORT_INIT_PARAMETERS MiniportInitParameters
  515. )
  516. {
  517. PTAP_ADAPTER_CONTEXT adapter = NULL;
  518. NDIS_STATUS status;
  519. UNREFERENCED_PARAMETER(MiniportDriverContext);
  520. UNREFERENCED_PARAMETER(MiniportInitParameters);
  521. DEBUGP (("[TAP] --> AdapterCreate\n"));
  522. do
  523. {
  524. NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES regAttributes = {0};
  525. NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES genAttributes = {0};
  526. NDIS_PNP_CAPABILITIES pnpCapabilities = {0};
  527. //
  528. // Allocate adapter context structure and initialize all the
  529. // memory resources for sending and receiving packets.
  530. //
  531. // Returns with reference count initialized to one.
  532. //
  533. adapter = tapAdapterContextAllocate(MiniportAdapterHandle);
  534. if(adapter == NULL)
  535. {
  536. DEBUGP (("[TAP] Couldn't allocate adapter memory\n"));
  537. status = NDIS_STATUS_RESOURCES;
  538. break;
  539. }
  540. // Enter the Initializing state.
  541. DEBUGP (("[TAP] Miniport State: Initializing\n"));
  542. tapAdapterAcquireLock(adapter,FALSE);
  543. adapter->Locked.AdapterState = MiniportInitializingState;
  544. tapAdapterReleaseLock(adapter,FALSE);
  545. //
  546. // First read adapter configuration from registry.
  547. // -----------------------------------------------
  548. // Subsequent device registration will fail if NetCfgInstanceId
  549. // has not been successfully read.
  550. //
  551. status = tapReadConfiguration(adapter);
  552. //
  553. // Set the registration attributes.
  554. //
  555. {C_ASSERT(sizeof(regAttributes) >= NDIS_SIZEOF_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1);}
  556. regAttributes.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES;
  557. regAttributes.Header.Size = NDIS_SIZEOF_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1;
  558. regAttributes.Header.Revision = NDIS_SIZEOF_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1;
  559. regAttributes.MiniportAdapterContext = adapter;
  560. regAttributes.AttributeFlags = TAP_ADAPTER_ATTRIBUTES_FLAGS;
  561. regAttributes.CheckForHangTimeInSeconds = TAP_ADAPTER_CHECK_FOR_HANG_TIME_IN_SECONDS;
  562. regAttributes.InterfaceType = TAP_INTERFACE_TYPE;
  563. //NDIS_DECLARE_MINIPORT_ADAPTER_CONTEXT(TAP_ADAPTER_CONTEXT);
  564. status = NdisMSetMiniportAttributes(
  565. MiniportAdapterHandle,
  566. (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&regAttributes
  567. );
  568. if (status != NDIS_STATUS_SUCCESS)
  569. {
  570. DEBUGP (("[TAP] NdisSetOptionalHandlers failed; Status 0x%08x\n",status));
  571. break;
  572. }
  573. //
  574. // Next, set the general attributes.
  575. //
  576. {C_ASSERT(sizeof(genAttributes) >= NDIS_SIZEOF_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_1);}
  577. genAttributes.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES;
  578. genAttributes.Header.Size = NDIS_SIZEOF_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_1;
  579. genAttributes.Header.Revision = NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_1;
  580. //
  581. // Specify the medium type that the NIC can support but not
  582. // necessarily the medium type that the NIC currently uses.
  583. //
  584. genAttributes.MediaType = TAP_MEDIUM_TYPE;
  585. //
  586. // Specifiy medium type that the NIC currently uses.
  587. //
  588. genAttributes.PhysicalMediumType = TAP_PHYSICAL_MEDIUM;
  589. //
  590. // Specifiy the maximum network frame size, in bytes, that the NIC
  591. // supports excluding the header.
  592. //
  593. genAttributes.MtuSize = TAP_FRAME_MAX_DATA_SIZE;
  594. genAttributes.MaxXmitLinkSpeed = TAP_XMIT_SPEED;
  595. genAttributes.XmitLinkSpeed = TAP_XMIT_SPEED;
  596. genAttributes.MaxRcvLinkSpeed = TAP_RECV_SPEED;
  597. genAttributes.RcvLinkSpeed = TAP_RECV_SPEED;
  598. if(adapter->MediaStateAlwaysConnected)
  599. {
  600. DEBUGP(("[%s] Initial MediaConnectState: Connected\n",
  601. MINIPORT_INSTANCE_ID (adapter)));
  602. genAttributes.MediaConnectState = MediaConnectStateConnected;
  603. }
  604. else
  605. {
  606. DEBUGP(("[%s] Initial MediaConnectState: Disconnected\n",
  607. MINIPORT_INSTANCE_ID (adapter)));
  608. genAttributes.MediaConnectState = MediaConnectStateDisconnected;
  609. }
  610. genAttributes.MediaDuplexState = MediaDuplexStateFull;
  611. //
  612. // The maximum number of bytes the NIC can provide as lookahead data.
  613. // If that value is different from the size of the lookahead buffer
  614. // supported by bound protocols, NDIS will call MiniportOidRequest to
  615. // set the size of the lookahead buffer provided by the miniport driver
  616. // to the minimum of the miniport driver and protocol(s) values. If the
  617. // driver always indicates up full packets with
  618. // NdisMIndicateReceiveNetBufferLists, it should set this value to the
  619. // maximum total frame size, which excludes the header.
  620. //
  621. // Upper-layer drivers examine lookahead data to determine whether a
  622. // packet that is associated with the lookahead data is intended for
  623. // one or more of their clients. If the underlying driver supports
  624. // multipacket receive indications, bound protocols are given full net
  625. // packets on every indication. Consequently, this value is identical
  626. // to that returned for OID_GEN_RECEIVE_BLOCK_SIZE.
  627. //
  628. genAttributes.LookaheadSize = TAP_MAX_LOOKAHEAD;
  629. genAttributes.MacOptions = TAP_MAC_OPTIONS;
  630. genAttributes.SupportedPacketFilters = TAP_SUPPORTED_FILTERS;
  631. //
  632. // The maximum number of multicast addresses the NIC driver can manage.
  633. // This list is global for all protocols bound to (or above) the NIC.
  634. // Consequently, a protocol can receive NDIS_STATUS_MULTICAST_FULL from
  635. // the NIC driver when attempting to set the multicast address list,
  636. // even if the number of elements in the given list is less than the
  637. // number originally returned for this query.
  638. //
  639. genAttributes.MaxMulticastListSize = TAP_MAX_MCAST_LIST;
  640. genAttributes.MacAddressLength = MACADDR_SIZE;
  641. //
  642. // Return the MAC address of the NIC burnt in the hardware.
  643. //
  644. ETH_COPY_NETWORK_ADDRESS(genAttributes.PermanentMacAddress, adapter->PermanentAddress);
  645. //
  646. // Return the MAC address the NIC is currently programmed to use. Note
  647. // that this address could be different from the permananent address as
  648. // the user can override using registry. Read NdisReadNetworkAddress
  649. // doc for more info.
  650. //
  651. ETH_COPY_NETWORK_ADDRESS(genAttributes.CurrentMacAddress, adapter->CurrentAddress);
  652. genAttributes.RecvScaleCapabilities = NULL;
  653. genAttributes.AccessType = TAP_ACCESS_TYPE;
  654. genAttributes.DirectionType = TAP_DIRECTION_TYPE;
  655. genAttributes.ConnectionType = TAP_CONNECTION_TYPE;
  656. genAttributes.IfType = TAP_IFTYPE;
  657. genAttributes.IfConnectorPresent = TAP_HAS_PHYSICAL_CONNECTOR;
  658. genAttributes.SupportedStatistics = TAP_SUPPORTED_STATISTICS;
  659. genAttributes.SupportedPauseFunctions = NdisPauseFunctionsUnsupported; // IEEE 802.3 pause frames
  660. genAttributes.DataBackFillSize = 0;
  661. genAttributes.ContextBackFillSize = 0;
  662. //
  663. // The SupportedOidList is an array of OIDs for objects that the
  664. // underlying driver or its NIC supports. Objects include general,
  665. // media-specific, and implementation-specific objects. NDIS forwards a
  666. // subset of the returned list to protocols that make this query. That
  667. // is, NDIS filters any supported statistics OIDs out of the list
  668. // because protocols never make statistics queries.
  669. //
  670. genAttributes.SupportedOidList = TAPSupportedOids;
  671. genAttributes.SupportedOidListLength = sizeof(TAPSupportedOids);
  672. genAttributes.AutoNegotiationFlags = NDIS_LINK_STATE_DUPLEX_AUTO_NEGOTIATED;
  673. //
  674. // Set power management capabilities
  675. //
  676. NdisZeroMemory(&pnpCapabilities, sizeof(pnpCapabilities));
  677. pnpCapabilities.WakeUpCapabilities.MinMagicPacketWakeUp = NdisDeviceStateUnspecified;
  678. pnpCapabilities.WakeUpCapabilities.MinPatternWakeUp = NdisDeviceStateUnspecified;
  679. genAttributes.PowerManagementCapabilities = &pnpCapabilities;
  680. status = NdisMSetMiniportAttributes(
  681. MiniportAdapterHandle,
  682. (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&genAttributes
  683. );
  684. if (status != NDIS_STATUS_SUCCESS)
  685. {
  686. DEBUGP (("[TAP] NdisMSetMiniportAttributes failed; Status 0x%08x\n",status));
  687. break;
  688. }
  689. //
  690. // Create the Win32 device I/O interface.
  691. //
  692. status = CreateTapDevice(adapter);
  693. if (status == NDIS_STATUS_SUCCESS)
  694. {
  695. // Add this adapter to the global adapter list.
  696. tapAdapterContextAddToGlobalList(adapter);
  697. }
  698. else
  699. {
  700. DEBUGP (("[TAP] CreateTapDevice failed; Status 0x%08x\n",status));
  701. break;
  702. }
  703. } while(FALSE);
  704. if(status == NDIS_STATUS_SUCCESS)
  705. {
  706. // Enter the Paused state if initialization is complete.
  707. DEBUGP (("[TAP] Miniport State: Paused\n"));
  708. tapAdapterAcquireLock(adapter,FALSE);
  709. adapter->Locked.AdapterState = MiniportPausedState;
  710. tapAdapterReleaseLock(adapter,FALSE);
  711. }
  712. else
  713. {
  714. if(adapter != NULL)
  715. {
  716. DEBUGP (("[TAP] Miniport State: Halted\n"));
  717. //
  718. // Remove reference when adapter context was allocated
  719. // ---------------------------------------------------
  720. // This should result in freeing adapter context memory
  721. // and assiciated resources.
  722. //
  723. tapAdapterContextDereference(adapter);
  724. adapter = NULL;
  725. }
  726. }
  727. DEBUGP (("[TAP] <-- AdapterCreate; status = %8.8X\n",status));
  728. return status;
  729. }
  730. VOID
  731. AdapterHalt(
  732. __in NDIS_HANDLE MiniportAdapterContext,
  733. __in NDIS_HALT_ACTION HaltAction
  734. )
  735. /*++
  736. Routine Description:
  737. Halt handler is called when NDIS receives IRP_MN_STOP_DEVICE,
  738. IRP_MN_SUPRISE_REMOVE or IRP_MN_REMOVE_DEVICE requests from the PNP
  739. manager. Here, the driver should free all the resources acquired in
  740. MiniportInitialize and stop access to the hardware. NDIS will not submit
  741. any further request once this handler is invoked.
  742. 1) Free and unmap all I/O resources.
  743. 2) Disable interrupt and deregister interrupt handler.
  744. 3) Deregister shutdown handler regsitered by
  745. NdisMRegisterAdapterShutdownHandler .
  746. 4) Cancel all queued up timer callbacks.
  747. 5) Finally wait indefinitely for all the outstanding receive
  748. packets indicated to the protocol to return.
  749. MiniportHalt runs at IRQL = PASSIVE_LEVEL.
  750. Arguments:
  751. MiniportAdapterContext Pointer to the Adapter
  752. HaltAction The reason for halting the adapter
  753. Return Value:
  754. None.
  755. --*/
  756. {
  757. PTAP_ADAPTER_CONTEXT adapter = (PTAP_ADAPTER_CONTEXT )MiniportAdapterContext;
  758. UNREFERENCED_PARAMETER(HaltAction);
  759. DEBUGP (("[TAP] --> AdapterHalt\n"));
  760. // Enter the Halted state.
  761. DEBUGP (("[TAP] Miniport State: Halted\n"));
  762. tapAdapterAcquireLock(adapter,FALSE);
  763. adapter->Locked.AdapterState = MiniportHaltedState;
  764. tapAdapterReleaseLock(adapter,FALSE);
  765. // Remove this adapter from the global adapter list.
  766. tapAdapterContextRemoveFromGlobalList(adapter);
  767. // BUGBUG!!! Call AdapterShutdownEx to do some of the work of stopping.
  768. // TODO!!! More...
  769. //
  770. // Destroy the TAP Win32 device.
  771. //
  772. DestroyTapDevice(adapter);
  773. //
  774. // Remove initial reference added in AdapterCreate.
  775. // ------------------------------------------------
  776. // This should result in freeing adapter context memory
  777. // and resources allocated in AdapterCreate.
  778. //
  779. tapAdapterContextDereference(adapter);
  780. adapter = NULL;
  781. DEBUGP (("[TAP] <-- AdapterHalt\n"));
  782. }
  783. VOID
  784. tapWaitForReceiveNblInFlightCountZeroEvent(
  785. __in PTAP_ADAPTER_CONTEXT Adapter
  786. )
  787. {
  788. LONG nblCount;
  789. //
  790. // Wait until higher-level protocol has returned all NBLs
  791. // to the driver.
  792. //
  793. // Add one NBL "bias" to insure allow event to be reset safely.
  794. nblCount = NdisInterlockedIncrement(&Adapter->ReceiveNblInFlightCount);
  795. ASSERT(nblCount > 0 );
  796. NdisResetEvent(&Adapter->ReceiveNblInFlightCountZeroEvent);
  797. //
  798. // Now remove the bias and wait for the ReceiveNblInFlightCountZeroEvent
  799. // if the count returned is not zero.
  800. //
  801. nblCount = NdisInterlockedDecrement(&Adapter->ReceiveNblInFlightCount);
  802. ASSERT(nblCount >= 0);
  803. if(nblCount)
  804. {
  805. LARGE_INTEGER startTime, currentTime;
  806. NdisGetSystemUpTimeEx(&startTime);
  807. for (;;)
  808. {
  809. BOOLEAN waitResult = NdisWaitEvent(
  810. &Adapter->ReceiveNblInFlightCountZeroEvent,
  811. TAP_WAIT_POLL_LOOP_TIMEOUT
  812. );
  813. NdisGetSystemUpTimeEx(&currentTime);
  814. if (waitResult)
  815. {
  816. break;
  817. }
  818. DEBUGP (("[%s] Waiting for %d in-flight receive NBLs to be returned.\n",
  819. MINIPORT_INSTANCE_ID (Adapter),
  820. Adapter->ReceiveNblInFlightCount
  821. ));
  822. }
  823. DEBUGP (("[%s] Waited %d ms for all in-flight NBLs to be returned.\n",
  824. MINIPORT_INSTANCE_ID (Adapter),
  825. (currentTime.LowPart - startTime.LowPart)
  826. ));
  827. }
  828. }
  829. NDIS_STATUS
  830. AdapterPause(
  831. __in NDIS_HANDLE MiniportAdapterContext,
  832. __in PNDIS_MINIPORT_PAUSE_PARAMETERS PauseParameters
  833. )
  834. /*++
  835. Routine Description:
  836. When a miniport receives a pause request, it enters into a Pausing state.
  837. The miniport should not indicate up any more network data. Any pending
  838. send requests must be completed, and new requests must be rejected with
  839. NDIS_STATUS_PAUSED.
  840. Once all sends have been completed and all recieve NBLs have returned to
  841. the miniport, the miniport enters the Paused state.
  842. While paused, the miniport can still service interrupts from the hardware
  843. (to, for example, continue to indicate NDIS_STATUS_MEDIA_CONNECT
  844. notifications).
  845. The miniport must continue to be able to handle status indications and OID
  846. requests. MiniportPause is different from MiniportHalt because, in
  847. general, the MiniportPause operation won't release any resources.
  848. MiniportPause must not attempt to acquire any resources where allocation
  849. can fail, since MiniportPause itself must not fail.
  850. MiniportPause runs at IRQL = PASSIVE_LEVEL.
  851. Arguments:
  852. MiniportAdapterContext Pointer to the Adapter
  853. MiniportPauseParameters Additional information about the pause operation
  854. Return Value:
  855. If the miniport is able to immediately enter the Paused state, it should
  856. return NDIS_STATUS_SUCCESS.
  857. If the miniport must wait for send completions or pending receive NBLs, it
  858. should return NDIS_STATUS_PENDING now, and call NDISMPauseComplete when the
  859. miniport has entered the Paused state.
  860. No other return value is permitted. The pause operation must not fail.
  861. --*/
  862. {
  863. PTAP_ADAPTER_CONTEXT adapter = (PTAP_ADAPTER_CONTEXT )MiniportAdapterContext;
  864. NDIS_STATUS status;
  865. UNREFERENCED_PARAMETER(PauseParameters);
  866. DEBUGP (("[TAP] --> AdapterPause\n"));
  867. // Enter the Pausing state.
  868. DEBUGP (("[TAP] Miniport State: Pausing\n"));
  869. tapAdapterAcquireLock(adapter,FALSE);
  870. adapter->Locked.AdapterState = MiniportPausingState;
  871. tapAdapterReleaseLock(adapter,FALSE);
  872. //
  873. // Stop the flow of network data through the receive path
  874. // ------------------------------------------------------
  875. // In the Pausing and Paused state tapAdapterSendAndReceiveReady
  876. // will prevent new calls to NdisMIndicateReceiveNetBufferLists
  877. // to indicate additional receive NBLs to the host.
  878. //
  879. // However, there may be some in-flight NBLs owned by the driver
  880. // that have been indicated to the host but have not yet been
  881. // returned.
  882. //
  883. // Wait here for all in-flight receive indications to be returned.
  884. //
  885. tapWaitForReceiveNblInFlightCountZeroEvent(adapter);
  886. //
  887. // Stop the flow of network data through the send path
  888. // ---------------------------------------------------
  889. // The initial implementation of the NDIS 6 send path follows the
  890. // NDIS 5 pattern. Under this approach every send packet is copied
  891. // into a driver-owned TAP_PACKET structure and the NBL owned by
  892. // higher-level protocol is immediatly completed.
  893. //
  894. // With this deep-copy approach the driver never claims ownership
  895. // of any send NBL.
  896. //
  897. // A future implementation may queue send NBLs and thereby eliminate
  898. // the need for the unnecessary allocation and deep copy of each packet.
  899. //
  900. // So, nothing to do here for the send path for now...
  901. status = NDIS_STATUS_SUCCESS;
  902. // Enter the Paused state.
  903. DEBUGP (("[TAP] Miniport State: Paused\n"));
  904. tapAdapterAcquireLock(adapter,FALSE);
  905. adapter->Locked.AdapterState = MiniportPausedState;
  906. tapAdapterReleaseLock(adapter,FALSE);
  907. DEBUGP (("[TAP] <-- AdapterPause; status = %8.8X\n",status));
  908. return status;
  909. }
  910. NDIS_STATUS
  911. AdapterRestart(
  912. __in NDIS_HANDLE MiniportAdapterContext,
  913. __in PNDIS_MINIPORT_RESTART_PARAMETERS RestartParameters
  914. )
  915. /*++
  916. Routine Description:
  917. When a miniport receives a restart request, it enters into a Restarting
  918. state. The miniport may begin indicating received data (e.g., using
  919. NdisMIndicateReceiveNetBufferLists), handling status indications, and
  920. processing OID requests in the Restarting state. However, no sends will be
  921. requested while the miniport is in the Restarting state.
  922. Once the miniport is ready to send data, it has entered the Running state.
  923. The miniport informs NDIS that it is in the Running state by returning
  924. NDIS_STATUS_SUCCESS from this MiniportRestart function; or if this function
  925. has already returned NDIS_STATUS_PENDING, by calling NdisMRestartComplete.
  926. MiniportRestart runs at IRQL = PASSIVE_LEVEL.
  927. Arguments:
  928. MiniportAdapterContext Pointer to the Adapter
  929. RestartParameters Additional information about the restart operation
  930. Return Value:
  931. If the miniport is able to immediately enter the Running state, it should
  932. return NDIS_STATUS_SUCCESS.
  933. If the miniport is still in the Restarting state, it should return
  934. NDIS_STATUS_PENDING now, and call NdisMRestartComplete when the miniport
  935. has entered the Running state.
  936. Other NDIS_STATUS codes indicate errors. If an error is encountered, the
  937. miniport must return to the Paused state (i.e., stop indicating receives).
  938. --*/
  939. {
  940. PTAP_ADAPTER_CONTEXT adapter = (PTAP_ADAPTER_CONTEXT )MiniportAdapterContext;
  941. NDIS_STATUS status;
  942. UNREFERENCED_PARAMETER(RestartParameters);
  943. DEBUGP (("[TAP] --> AdapterRestart\n"));
  944. // Enter the Restarting state.
  945. DEBUGP (("[TAP] Miniport State: Restarting\n"));
  946. tapAdapterAcquireLock(adapter,FALSE);
  947. adapter->Locked.AdapterState = MiniportRestartingState;
  948. tapAdapterReleaseLock(adapter,FALSE);
  949. status = NDIS_STATUS_SUCCESS;
  950. if(status == NDIS_STATUS_SUCCESS)
  951. {
  952. // Enter the Running state.
  953. DEBUGP (("[TAP] Miniport State: Running\n"));
  954. tapAdapterAcquireLock(adapter,FALSE);
  955. adapter->Locked.AdapterState = MiniportRunning;
  956. tapAdapterReleaseLock(adapter,FALSE);
  957. }
  958. else
  959. {
  960. // Enter the Paused state if restart failed.
  961. DEBUGP (("[TAP] Miniport State: Paused\n"));
  962. tapAdapterAcquireLock(adapter,FALSE);
  963. adapter->Locked.AdapterState = MiniportPausedState;
  964. tapAdapterReleaseLock(adapter,FALSE);
  965. }
  966. DEBUGP (("[TAP] <-- AdapterRestart; status = %8.8X\n",status));
  967. return status;
  968. }
  969. BOOLEAN
  970. tapAdapterReadAndWriteReady(
  971. __in PTAP_ADAPTER_CONTEXT Adapter
  972. )
  973. /*++
  974. Routine Description:
  975. This routine determines whether the adapter device interface can
  976. accept read and write operations.
  977. Arguments:
  978. Adapter Pointer to our adapter context
  979. Return Value:
  980. Returns TRUE if the adapter state allows it to queue IRPs passed to
  981. the device read and write callbacks.
  982. --*/
  983. {
  984. if(!Adapter->TapDeviceCreated)
  985. {
  986. // TAP device not created or is being destroyed.
  987. return FALSE;
  988. }
  989. if(Adapter->TapFileObject == NULL)
  990. {
  991. // TAP application file object not open.
  992. return FALSE;
  993. }
  994. if(!Adapter->TapFileIsOpen)
  995. {
  996. // TAP application file object may be closing.
  997. return FALSE;
  998. }
  999. if(!Adapter->LogicalMediaState)
  1000. {
  1001. // Don't handle read/write if media not connected.
  1002. return FALSE;
  1003. }
  1004. if(Adapter->CurrentPowerState != NdisDeviceStateD0)
  1005. {
  1006. // Don't handle read/write if device is not fully powered.
  1007. return FALSE;
  1008. }
  1009. return TRUE;
  1010. }
  1011. NDIS_STATUS
  1012. tapAdapterSendAndReceiveReady(
  1013. __in PTAP_ADAPTER_CONTEXT Adapter
  1014. )
  1015. /*++
  1016. Routine Description:
  1017. This routine determines whether the adapter NDIS send and receive
  1018. paths are ready.
  1019. This routine examines various adapter state variables and returns
  1020. a value that indicates whether the adapter NDIS interfaces can
  1021. accept send packets or indicate receive packets.
  1022. In normal operation the adapter may temporarily enter and then exit
  1023. a not-ready condition. In particular, the adapter becomes not-ready
  1024. when in the Pausing/Paused states, but may become ready again when
  1025. Restarted.
  1026. Runs at IRQL <= DISPATCH_LEVEL
  1027. Arguments:
  1028. Adapter Pointer to our adapter context
  1029. Return Value:
  1030. Returns NDIS_STATUS_SUCCESS if the adapter state allows it to
  1031. accept send packets and indicate receive packets.
  1032. Otherwise it returns a NDIS_STATUS value other than NDIS_STATUS_SUCCESS.
  1033. These status values can be used directly as the completion status for
  1034. packets that must be completed immediatly in the send path.
  1035. --*/
  1036. {
  1037. NDIS_STATUS status = NDIS_STATUS_SUCCESS;
  1038. //
  1039. // Check various state variables to insure adapter is ready.
  1040. //
  1041. tapAdapterAcquireLock(Adapter,FALSE);
  1042. if(!Adapter->LogicalMediaState)
  1043. {
  1044. status = NDIS_STATUS_MEDIA_DISCONNECTED;
  1045. }
  1046. else if(Adapter->CurrentPowerState != NdisDeviceStateD0)
  1047. {
  1048. status = NDIS_STATUS_LOW_POWER_STATE;
  1049. }
  1050. else if(Adapter->ResetInProgress)
  1051. {
  1052. status = NDIS_STATUS_RESET_IN_PROGRESS;
  1053. }
  1054. else
  1055. {
  1056. switch(Adapter->Locked.AdapterState)
  1057. {
  1058. case MiniportPausingState:
  1059. case MiniportPausedState:
  1060. status = NDIS_STATUS_PAUSED;
  1061. break;
  1062. case MiniportHaltedState:
  1063. status = NDIS_STATUS_INVALID_STATE;
  1064. break;
  1065. default:
  1066. status = NDIS_STATUS_SUCCESS;
  1067. break;
  1068. }
  1069. }
  1070. tapAdapterReleaseLock(Adapter,FALSE);
  1071. return status;
  1072. }
  1073. BOOLEAN
  1074. AdapterCheckForHangEx(
  1075. __in NDIS_HANDLE MiniportAdapterContext
  1076. )
  1077. /*++
  1078. Routine Description:
  1079. The MiniportCheckForHangEx handler is called to report the state of the
  1080. NIC, or to monitor the responsiveness of an underlying device driver.
  1081. This is an optional function. If this handler is not specified, NDIS
  1082. judges the driver unresponsive when the driver holds
  1083. MiniportQueryInformation or MiniportSetInformation requests for a
  1084. time-out interval (deafult 4 sec), and then calls the driver's
  1085. MiniportReset function. A NIC driver's MiniportInitialize function can
  1086. extend NDIS's time-out interval by calling NdisMSetAttributesEx to
  1087. avoid unnecessary resets.
  1088. MiniportCheckForHangEx runs at IRQL <= DISPATCH_LEVEL.
  1089. Arguments:
  1090. MiniportAdapterContext Pointer to our adapter
  1091. Return Value:
  1092. TRUE NDIS calls the driver's MiniportReset function.
  1093. FALSE Everything is fine
  1094. --*/
  1095. {
  1096. PTAP_ADAPTER_CONTEXT adapter = (PTAP_ADAPTER_CONTEXT )MiniportAdapterContext;
  1097. //DEBUGP (("[TAP] --> AdapterCheckForHangEx\n"));
  1098. //DEBUGP (("[TAP] <-- AdapterCheckForHangEx; status = FALSE\n"));
  1099. return FALSE; // Everything is fine
  1100. }
  1101. NDIS_STATUS
  1102. AdapterReset(
  1103. __in NDIS_HANDLE MiniportAdapterContext,
  1104. __out PBOOLEAN AddressingReset
  1105. )
  1106. /*++
  1107. Routine Description:
  1108. MiniportResetEx is a required to issue a hardware reset to the NIC
  1109. and/or to reset the driver's software state.
  1110. 1) The miniport driver can optionally complete any pending
  1111. OID requests. NDIS will submit no further OID requests
  1112. to the miniport driver for the NIC being reset until
  1113. the reset operation has finished. After the reset,
  1114. NDIS will resubmit to the miniport driver any OID requests
  1115. that were pending but not completed by the miniport driver
  1116. before the reset.
  1117. 2) A deserialized miniport driver must complete any pending send
  1118. operations. NDIS will not requeue pending send packets for
  1119. a deserialized driver since NDIS does not maintain the send
  1120. queue for such a driver.
  1121. 3) If MiniportReset returns NDIS_STATUS_PENDING, the driver must
  1122. complete the original request subsequently with a call to
  1123. NdisMResetComplete.
  1124. MiniportReset runs at IRQL <= DISPATCH_LEVEL.
  1125. Arguments:
  1126. AddressingReset - If multicast or functional addressing information
  1127. or the lookahead size, is changed by a reset,
  1128. MiniportReset must set the variable at AddressingReset
  1129. to TRUE before it returns control. This causes NDIS to
  1130. call the MiniportSetInformation function to restore
  1131. the information.
  1132. MiniportAdapterContext - Pointer to our adapter
  1133. Return Value:
  1134. NDIS_STATUS
  1135. --*/
  1136. {
  1137. PTAP_ADAPTER_CONTEXT adapter = (PTAP_ADAPTER_CONTEXT )MiniportAdapterContext;
  1138. NDIS_STATUS status;
  1139. UNREFERENCED_PARAMETER(MiniportAdapterContext);
  1140. UNREFERENCED_PARAMETER(AddressingReset);
  1141. DEBUGP (("[TAP] --> AdapterReset\n"));
  1142. // Indicate that adapter reset is in progress.
  1143. adapter->ResetInProgress = TRUE;
  1144. // See note above...
  1145. *AddressingReset = FALSE;
  1146. // BUGBUG!!! TODO!!! Lots of work here...
  1147. // Indicate that adapter reset has completed.
  1148. adapter->ResetInProgress = FALSE;
  1149. status = NDIS_STATUS_SUCCESS;
  1150. DEBUGP (("[TAP] <-- AdapterReset; status = %8.8X\n",status));
  1151. return status;
  1152. }
  1153. VOID
  1154. AdapterDevicePnpEventNotify(
  1155. __in NDIS_HANDLE MiniportAdapterContext,
  1156. __in PNET_DEVICE_PNP_EVENT NetDevicePnPEvent
  1157. )
  1158. {
  1159. PTAP_ADAPTER_CONTEXT adapter = (PTAP_ADAPTER_CONTEXT )MiniportAdapterContext;
  1160. DEBUGP (("[TAP] --> AdapterDevicePnpEventNotify\n"));
  1161. /*
  1162. switch (NetDevicePnPEvent->DevicePnPEvent)
  1163. {
  1164. case NdisDevicePnPEventSurpriseRemoved:
  1165. //
  1166. // Called when NDIS receives IRP_MN_SUPRISE_REMOVAL.
  1167. // NDIS calls MiniportHalt function after this call returns.
  1168. //
  1169. MP_SET_FLAG(Adapter, fMP_ADAPTER_SURPRISE_REMOVED);
  1170. DEBUGP(MP_INFO, "[%p] MPDevicePnpEventNotify: NdisDevicePnPEventSurpriseRemoved\n", Adapter);
  1171. break;
  1172. case NdisDevicePnPEventPowerProfileChanged:
  1173. //
  1174. // After initializing a miniport driver and after miniport driver
  1175. // receives an OID_PNP_SET_POWER notification that specifies
  1176. // a device power state of NdisDeviceStateD0 (the powered-on state),
  1177. // NDIS calls the miniport's MiniportPnPEventNotify function with
  1178. // PnPEvent set to NdisDevicePnPEventPowerProfileChanged.
  1179. //
  1180. DEBUGP(MP_INFO, "[%p] MPDevicePnpEventNotify: NdisDevicePnPEventPowerProfileChanged\n", Adapter);
  1181. if (NetDevicePnPEvent->InformationBufferLength == sizeof(ULONG))
  1182. {
  1183. ULONG NdisPowerProfile = *((PULONG)NetDevicePnPEvent->InformationBuffer);
  1184. if (NdisPowerProfile == NdisPowerProfileBattery)
  1185. {
  1186. DEBUGP(MP_INFO, "[%p] The host system is running on battery power\n", Adapter);
  1187. }
  1188. if (NdisPowerProfile == NdisPowerProfileAcOnLine)
  1189. {
  1190. DEBUGP(MP_INFO, "[%p] The host system is running on AC power\n", Adapter);
  1191. }
  1192. }
  1193. break;
  1194. default:
  1195. DEBUGP(MP_ERROR, "[%p] MPDevicePnpEventNotify: unknown PnP event 0x%x\n", Adapter, NetDevicePnPEvent->DevicePnPEvent);
  1196. }
  1197. */
  1198. DEBUGP (("[TAP] <-- AdapterDevicePnpEventNotify\n"));
  1199. }
  1200. VOID
  1201. AdapterShutdownEx(
  1202. __in NDIS_HANDLE MiniportAdapterContext,
  1203. __in NDIS_SHUTDOWN_ACTION ShutdownAction
  1204. )
  1205. /*++
  1206. Routine Description:
  1207. The MiniportShutdownEx handler restores hardware to its initial state when
  1208. the system is shut down, whether by the user or because an unrecoverable
  1209. system error occurred. This is to ensure that the NIC is in a known
  1210. state and ready to be reinitialized when the machine is rebooted after
  1211. a system shutdown occurs for any reason, including a crash dump.
  1212. Here just disable the interrupt and stop the DMA engine. Do not free
  1213. memory resources or wait for any packet transfers to complete. Do not call
  1214. into NDIS at this time.
  1215. This can be called at aribitrary IRQL, including in the context of a
  1216. bugcheck.
  1217. Arguments:
  1218. MiniportAdapterContext Pointer to our adapter
  1219. ShutdownAction The reason why NDIS called the shutdown function
  1220. Return Value:
  1221. None.
  1222. --*/
  1223. {
  1224. PTAP_ADAPTER_CONTEXT adapter = (PTAP_ADAPTER_CONTEXT )MiniportAdapterContext;
  1225. UNREFERENCED_PARAMETER(ShutdownAction);
  1226. UNREFERENCED_PARAMETER(MiniportAdapterContext);
  1227. DEBUGP (("[TAP] --> AdapterShutdownEx\n"));
  1228. // Enter the Shutdown state.
  1229. DEBUGP (("[TAP] Miniport State: Shutdown\n"));
  1230. tapAdapterAcquireLock(adapter,FALSE);
  1231. adapter->Locked.AdapterState = MiniportShutdownState;
  1232. tapAdapterReleaseLock(adapter,FALSE);
  1233. //
  1234. // BUGBUG!!! FlushIrpQueues???
  1235. //
  1236. DEBUGP (("[TAP] <-- AdapterShutdownEx\n"));
  1237. }
  1238. // Free adapter context memory and associated resources.
  1239. VOID
  1240. tapAdapterContextFree(
  1241. __in PTAP_ADAPTER_CONTEXT Adapter
  1242. )
  1243. {
  1244. PLIST_ENTRY listEntry = &Adapter->AdapterListLink;
  1245. DEBUGP (("[TAP] --> tapAdapterContextFree\n"));
  1246. // Adapter context should already be removed.
  1247. ASSERT( (listEntry->Flink == listEntry) && (listEntry->Blink == listEntry ) );
  1248. // Insure that adapter context has been removed from global adapter list.
  1249. RemoveEntryList(&Adapter->AdapterListLink);
  1250. // Free the adapter lock.
  1251. NdisFreeSpinLock(&Adapter->AdapterLock);
  1252. // Free the ANSI NetCfgInstanceId buffer.
  1253. if(Adapter->NetCfgInstanceIdAnsi.Buffer != NULL)
  1254. {
  1255. RtlFreeAnsiString(&Adapter->NetCfgInstanceIdAnsi);
  1256. }
  1257. Adapter->NetCfgInstanceIdAnsi.Buffer = NULL;
  1258. // Free the receive NBL pool.
  1259. if(Adapter->ReceiveNblPool != NULL )
  1260. {
  1261. NdisFreeNetBufferListPool(Adapter->ReceiveNblPool);
  1262. }
  1263. Adapter->ReceiveNblPool = NULL;
  1264. NdisFreeMemory(Adapter,0,0);
  1265. DEBUGP (("[TAP] <-- tapAdapterContextFree\n"));
  1266. }
  1267. ULONG
  1268. tapGetNetBufferFrameType(
  1269. __in PNET_BUFFER NetBuffer
  1270. )
  1271. /*++
  1272. Routine Description:
  1273. Reads the network frame's destination address to determine the type
  1274. (broadcast, multicast, etc)
  1275. Runs at IRQL <= DISPATCH_LEVEL.
  1276. Arguments:
  1277. NetBuffer The NB to examine
  1278. Return Value:
  1279. NDIS_PACKET_TYPE_BROADCAST
  1280. NDIS_PACKET_TYPE_MULTICAST
  1281. NDIS_PACKET_TYPE_DIRECTED
  1282. --*/
  1283. {
  1284. PETH_HEADER ethernetHeader;
  1285. ethernetHeader = (PETH_HEADER )NdisGetDataBuffer(
  1286. NetBuffer,
  1287. sizeof(ETH_HEADER),
  1288. NULL,
  1289. 1,
  1290. 0
  1291. );
  1292. ASSERT(ethernetHeader);
  1293. if (ETH_IS_BROADCAST(ethernetHeader->dest))
  1294. {
  1295. return NDIS_PACKET_TYPE_BROADCAST;
  1296. }
  1297. else if(ETH_IS_MULTICAST(ethernetHeader->dest))
  1298. {
  1299. return NDIS_PACKET_TYPE_MULTICAST;
  1300. }
  1301. else
  1302. {
  1303. return NDIS_PACKET_TYPE_DIRECTED;
  1304. }
  1305. }
  1306. ULONG
  1307. tapGetNetBufferCountsFromNetBufferList(
  1308. __in PNET_BUFFER_LIST NetBufferList,
  1309. __inout_opt PULONG TotalByteCount // Of all linked NBs
  1310. )
  1311. /*++
  1312. Routine Description:
  1313. Returns the number of net buffers linked to the net buffer list.
  1314. Optionally retuens the total byte count of all net buffers linked
  1315. to the net buffer list
  1316. Runs at IRQL <= DISPATCH_LEVEL.
  1317. Arguments:
  1318. NetBufferList The NBL to examine
  1319. Return Value:
  1320. The number of net buffers linked to the net buffer list.
  1321. --*/
  1322. {
  1323. ULONG netBufferCount = 0;
  1324. PNET_BUFFER currentNb;
  1325. if(TotalByteCount)
  1326. {
  1327. *TotalByteCount = 0;
  1328. }
  1329. currentNb = NET_BUFFER_LIST_FIRST_NB(NetBufferList);
  1330. while(currentNb)
  1331. {
  1332. ++netBufferCount;
  1333. if(TotalByteCount)
  1334. {
  1335. *TotalByteCount += NET_BUFFER_DATA_LENGTH(currentNb);
  1336. }
  1337. // Move to next NB
  1338. currentNb = NET_BUFFER_NEXT_NB(currentNb);
  1339. }
  1340. return netBufferCount;
  1341. }
  1342. VOID
  1343. tapAdapterAcquireLock(
  1344. __in PTAP_ADAPTER_CONTEXT Adapter,
  1345. __in BOOLEAN DispatchLevel
  1346. )
  1347. {
  1348. ASSERT(!DispatchLevel || (DISPATCH_LEVEL == KeGetCurrentIrql()));
  1349. if (DispatchLevel)
  1350. {
  1351. NdisDprAcquireSpinLock(&Adapter->AdapterLock);
  1352. }
  1353. else
  1354. {
  1355. NdisAcquireSpinLock(&Adapter->AdapterLock);
  1356. }
  1357. }
  1358. VOID
  1359. tapAdapterReleaseLock(
  1360. __in PTAP_ADAPTER_CONTEXT Adapter,
  1361. __in BOOLEAN DispatchLevel
  1362. )
  1363. {
  1364. ASSERT(!DispatchLevel || (DISPATCH_LEVEL == KeGetCurrentIrql()));
  1365. if (DispatchLevel)
  1366. {
  1367. NdisDprReleaseSpinLock(&Adapter->AdapterLock);
  1368. }
  1369. else
  1370. {
  1371. NdisReleaseSpinLock(&Adapter->AdapterLock);
  1372. }
  1373. }