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