Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

618 lines
15 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. ports.c
  5. Abstract:
  6. This module contains the port management code.
  7. Author:
  8. Jameel Hyder (jameelh@microsoft.com)
  9. Nikhil Kamkolkar (nikhilk@microsoft.com)
  10. Revision History:
  11. 19 Jun 1992 Initial Version
  12. Notes: Tab stop: 4
  13. --*/
  14. #include <atalk.h>
  15. #pragma hdrstop
  16. #define FILENUM PORTS
  17. #ifdef ALLOC_PRAGMA
  18. #pragma alloc_text(PAGEINIT, AtalkPortShutdown)
  19. #pragma alloc_text(PAGEINIT, atalkPortFreeZones)
  20. #endif
  21. VOID FASTCALL
  22. AtalkPortDeref(
  23. IN OUT PPORT_DESCRIPTOR pPortDesc,
  24. IN BOOLEAN AtDpc
  25. )
  26. /*++
  27. Routine Description:
  28. Arguments:
  29. Return Value:
  30. --*/
  31. {
  32. BOOLEAN portDone = FALSE;
  33. BOOLEAN fPnPInProgress;
  34. BOOLEAN fRasPort;
  35. KIRQL OldIrql;
  36. if (AtDpc)
  37. {
  38. ACQUIRE_SPIN_LOCK_DPC(&pPortDesc->pd_Lock);
  39. }
  40. else
  41. {
  42. ACQUIRE_SPIN_LOCK(&pPortDesc->pd_Lock, &OldIrql);
  43. }
  44. ASSERT(pPortDesc->pd_RefCount > 0);
  45. pPortDesc->pd_RefCount--;
  46. if (pPortDesc->pd_RefCount == 0)
  47. {
  48. portDone = TRUE;
  49. ASSERT((pPortDesc->pd_Flags & PD_CLOSING) != 0);
  50. }
  51. fPnPInProgress = (pPortDesc->pd_Flags & PD_PNP_RECONFIGURE)? TRUE : FALSE;
  52. // We hold the lock while freeing up all the stuff, this should
  53. // only happen during unload.
  54. if (portDone)
  55. {
  56. DBGPRINT(DBG_COMP_UNLOAD, DBG_LEVEL_WARN,
  57. ("AtalkPortDeref: Freeing zones and such ...\n"));
  58. // Free up zonelist
  59. atalkPortFreeZones(pPortDesc);
  60. DBGPRINT(DBG_COMP_UNLOAD, DBG_LEVEL_WARN,
  61. ("AtalkPortDeref: Releasing Amt tables ...\n"));
  62. // We do need to free up the AMT.
  63. AtalkAarpReleaseAmt(pPortDesc);
  64. // Free the BRC
  65. AtalkAarpReleaseBrc(pPortDesc);
  66. }
  67. if (AtDpc)
  68. {
  69. RELEASE_SPIN_LOCK_DPC(&pPortDesc->pd_Lock);
  70. }
  71. else
  72. {
  73. RELEASE_SPIN_LOCK(&pPortDesc->pd_Lock, OldIrql);
  74. }
  75. if (portDone)
  76. {
  77. PPORT_DESCRIPTOR *ppTmp;
  78. // Unlink the portdesc from the list and free its memory
  79. ACQUIRE_SPIN_LOCK(&AtalkPortLock, &OldIrql);
  80. for (ppTmp = &AtalkPortList;
  81. *ppTmp != NULL;
  82. ppTmp = &((*ppTmp)->pd_Next))
  83. {
  84. if (*ppTmp == pPortDesc)
  85. {
  86. *ppTmp = pPortDesc->pd_Next;
  87. break;
  88. }
  89. }
  90. ASSERT (*ppTmp == pPortDesc->pd_Next);
  91. // Is the default-port going away ?
  92. if (AtalkDefaultPort == pPortDesc)
  93. {
  94. AtalkDefaultPort = NULL;
  95. KeResetEvent(&AtalkDefaultPortEvent);
  96. }
  97. RELEASE_SPIN_LOCK(&AtalkPortLock, OldIrql);
  98. //
  99. // if we are here becaue of PnP Reconfigure then don't free the memory
  100. // (we haven't closed the adapter with ndis, and we have other useful
  101. // stuff that we must retain). Put the creation refcount and the
  102. // binding refcount back that got taken away when we first got the
  103. // PnP Reconfigure event.
  104. // (no need for spinlock: this was ready for a free!!)
  105. //
  106. if (fPnPInProgress)
  107. {
  108. // 1 binding refcount + 1 creation refcount
  109. pPortDesc->pd_RefCount = 2;
  110. if (pPortDesc->pd_Flags & PD_RAS_PORT)
  111. {
  112. fRasPort = TRUE;
  113. }
  114. else
  115. {
  116. fRasPort = FALSE;
  117. }
  118. // blow away everything on the flag, except these
  119. pPortDesc->pd_Flags = (PD_PNP_RECONFIGURE | PD_BOUND);
  120. if (fRasPort)
  121. {
  122. pPortDesc->pd_Flags |= PD_RAS_PORT;
  123. }
  124. // restore EXT_NET flag if applicable
  125. if (pPortDesc->pd_PortType != ALAP_PORT)
  126. {
  127. pPortDesc->pd_Flags |= PD_EXT_NET;
  128. }
  129. // reset all pointers and other gunk to 0
  130. pPortDesc->pd_Next = NULL;
  131. pPortDesc->pd_Nodes = NULL;
  132. pPortDesc->pd_RouterNode = NULL;
  133. pPortDesc->pd_TentativeNodeAddr.atn_Network = 0;
  134. pPortDesc->pd_TentativeNodeAddr.atn_Node = 0;
  135. pPortDesc->pd_RoutersPramNode.atn_Network = 0;
  136. pPortDesc->pd_RoutersPramNode.atn_Node = 0;
  137. pPortDesc->pd_UsersPramNode1.atn_Network = 0;
  138. pPortDesc->pd_UsersPramNode1.atn_Node = 0;
  139. pPortDesc->pd_UsersPramNode2.atn_Network = 0;
  140. pPortDesc->pd_UsersPramNode2.atn_Node = 0;
  141. pPortDesc->pd_InitialZoneList = NULL;
  142. pPortDesc->pd_InitialDefaultZone = NULL;
  143. pPortDesc->pd_InitialDesiredZone = NULL;
  144. pPortDesc->pd_ZoneList = NULL;
  145. pPortDesc->pd_DefaultZone = NULL;
  146. pPortDesc->pd_DesiredZone = NULL;
  147. pPortDesc->pd_AmtCount = 0;
  148. RtlZeroMemory(&pPortDesc->pd_PortStats, sizeof(ATALK_PORT_STATS));
  149. // Unblock caller now that we are done
  150. KeSetEvent(pPortDesc->pd_ShutDownEvent, IO_NETWORK_INCREMENT, FALSE);
  151. pPortDesc->pd_ShutDownEvent = NULL;
  152. }
  153. else
  154. {
  155. // is the Arap port going away?
  156. if (RasPortDesc == pPortDesc)
  157. {
  158. RasPortDesc = NULL;
  159. }
  160. if (pPortDesc->pd_MulticastList != NULL)
  161. {
  162. AtalkFreeMemory(pPortDesc->pd_MulticastList);
  163. pPortDesc->pd_MulticastList = NULL;
  164. }
  165. // Unblock caller now that we are done
  166. KeSetEvent(pPortDesc->pd_ShutDownEvent, IO_NETWORK_INCREMENT, FALSE);
  167. if (pPortDesc->pd_FriendlyAdapterName.Buffer)
  168. {
  169. AtalkFreeMemory(pPortDesc->pd_FriendlyAdapterName.Buffer);
  170. }
  171. AtalkFreeMemory(pPortDesc);
  172. ACQUIRE_SPIN_LOCK(&AtalkPortLock, &OldIrql);
  173. AtalkNumberOfPorts --;
  174. RELEASE_SPIN_LOCK(&AtalkPortLock, OldIrql);
  175. }
  176. }
  177. }
  178. BOOLEAN
  179. AtalkReferenceDefaultPort(
  180. IN VOID
  181. )
  182. {
  183. KIRQL OldIrql;
  184. BOOLEAN fReferenced = FALSE;
  185. ACQUIRE_SPIN_LOCK(&AtalkPortLock, &OldIrql);
  186. if (AtalkDefaultPort)
  187. {
  188. ACQUIRE_SPIN_LOCK_DPC(&AtalkDefaultPort->pd_Lock);
  189. if ( !(AtalkDefaultPort->pd_Flags & (PD_PNP_RECONFIGURE | PD_CLOSING)) )
  190. {
  191. AtalkDefaultPort->pd_RefCount++;
  192. fReferenced = TRUE;
  193. }
  194. RELEASE_SPIN_LOCK_DPC(&AtalkDefaultPort->pd_Lock);
  195. }
  196. RELEASE_SPIN_LOCK(&AtalkPortLock, OldIrql);
  197. return(fReferenced);
  198. }
  199. VOID
  200. atalkPortFreeZones(
  201. IN PPORT_DESCRIPTOR pPortDesc
  202. )
  203. /*++
  204. Routine Description:
  205. Arguments:
  206. Return Value:
  207. --*/
  208. {
  209. // Dereference initial default and desired zones, and the zone list
  210. if (pPortDesc->pd_InitialDefaultZone != NULL)
  211. AtalkZoneDereference(pPortDesc->pd_InitialDefaultZone);
  212. if (pPortDesc->pd_InitialDesiredZone != NULL)
  213. AtalkZoneDereference(pPortDesc->pd_InitialDesiredZone);
  214. if (pPortDesc->pd_InitialZoneList != NULL)
  215. AtalkZoneFreeList(pPortDesc->pd_InitialZoneList);
  216. // and the current versions of the zones
  217. if (pPortDesc->pd_DefaultZone != NULL)
  218. AtalkZoneDereference(pPortDesc->pd_DefaultZone);
  219. if (pPortDesc->pd_DesiredZone != NULL)
  220. AtalkZoneDereference(pPortDesc->pd_DesiredZone);
  221. if (pPortDesc->pd_ZoneList != NULL)
  222. AtalkZoneFreeList(pPortDesc->pd_ZoneList);
  223. }
  224. VOID FASTCALL
  225. AtalkPortSetResetFlag(
  226. IN PPORT_DESCRIPTOR pPortDesc,
  227. IN BOOLEAN fRemoveBit,
  228. IN DWORD dwBit
  229. )
  230. /*++
  231. Routine Description:
  232. Arguments:
  233. Return Value:
  234. --*/
  235. {
  236. KIRQL OldIrql;
  237. ASSERT(VALID_PORT(pPortDesc));
  238. ACQUIRE_SPIN_LOCK(&pPortDesc->pd_Lock, &OldIrql);
  239. if (fRemoveBit)
  240. {
  241. pPortDesc->pd_Flags &= ~(dwBit);
  242. }
  243. else
  244. {
  245. pPortDesc->pd_Flags |= dwBit;
  246. }
  247. RELEASE_SPIN_LOCK(&pPortDesc->pd_Lock, OldIrql);
  248. }
  249. ATALK_ERROR
  250. AtalkPortShutdown(
  251. IN OUT PPORT_DESCRIPTOR pPortDesc
  252. )
  253. /*++
  254. Routine Description:
  255. Arguments:
  256. Return Value:
  257. --*/
  258. {
  259. PATALK_NODE pAtalkNode;
  260. ATALK_ERROR error = ATALK_NO_ERROR;
  261. BOOLEAN fActive;
  262. BOOLEAN fRasPort=FALSE;
  263. BOOLEAN fPnpReconfigure;
  264. KEVENT ShutdownEvent;
  265. KIRQL OldIrql;
  266. DBGPRINT(DBG_COMP_UNLOAD, DBG_LEVEL_WARN,
  267. ("AtalkPortShutdown: Shutting down port %Z...\n", &pPortDesc->pd_AdapterKey));
  268. KeInitializeEvent(&ShutdownEvent, NotificationEvent, FALSE);
  269. // if this is the default port, tell TDI that we are leaving so server finds out
  270. if (pPortDesc->pd_Flags & PD_DEF_PORT)
  271. {
  272. if (TdiRegistrationHandle)
  273. {
  274. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_INFO,
  275. ("AtalkPortShutdown: deregistering device!!\n"));
  276. TdiDeregisterDeviceObject(TdiRegistrationHandle);
  277. TdiRegistrationHandle = NULL;
  278. }
  279. }
  280. ACQUIRE_SPIN_LOCK(&pPortDesc->pd_Lock, &OldIrql);
  281. // we have already taken care of the Arap port separately: just say done
  282. if (pPortDesc->pd_Flags & PD_RAS_PORT)
  283. {
  284. fRasPort = TRUE;
  285. }
  286. pPortDesc->pd_Flags |= PD_CLOSING;
  287. fActive = (pPortDesc->pd_Flags & PD_BOUND) ? TRUE : FALSE;
  288. fPnpReconfigure = (pPortDesc->pd_Flags & PD_PNP_RECONFIGURE)? TRUE : FALSE;
  289. // Switch off the active flag just in case the unbind fails.
  290. // We arent going to accept any packets anymore.
  291. pPortDesc->pd_Flags &= ~PD_ACTIVE;
  292. pPortDesc->pd_ShutDownEvent = &ShutdownEvent;
  293. DBGPRINT(DBG_COMP_UNLOAD, DBG_LEVEL_WARN,
  294. ("AtalkPortShutdown: Freeing nodes on port ....\n"));
  295. // Release any nodes on this port that are not already closing.
  296. if (!fRasPort)
  297. {
  298. do
  299. {
  300. // Ref the next node.
  301. // ASSERT!! error does not get changed after this statement.
  302. AtalkNodeReferenceNextNc(pPortDesc->pd_Nodes, &pAtalkNode, &error);
  303. if (!ATALK_SUCCESS(error))
  304. {
  305. break;
  306. }
  307. RELEASE_SPIN_LOCK(&pPortDesc->pd_Lock, OldIrql);
  308. DBGPRINT(DBG_COMP_UNLOAD, DBG_LEVEL_ERR,
  309. ("AtalkPortShutdown: Releasing Node\n"));
  310. AtalkNodeReleaseOnPort(pPortDesc, pAtalkNode);
  311. AtalkNodeDereference(pAtalkNode);
  312. ACQUIRE_SPIN_LOCK(&pPortDesc->pd_Lock, &OldIrql);
  313. } while (TRUE);
  314. }
  315. RELEASE_SPIN_LOCK(&pPortDesc->pd_Lock, OldIrql);
  316. // If we are routing, remove the RTEs for this port since each has a reference
  317. // to this port.
  318. if (AtalkRouter & !fRasPort)
  319. {
  320. AtalkRtmpKillPortRtes(pPortDesc);
  321. }
  322. if (EXT_NET(pPortDesc))
  323. {
  324. // cancel the Amt timer and take away the refcount for it
  325. if (AtalkTimerCancelEvent(&pPortDesc->pd_AmtTimer, NULL))
  326. {
  327. AtalkPortDereference(pPortDesc);
  328. }
  329. // cancel the Brc timer and take away the refcount for it
  330. if (AtalkTimerCancelEvent(&pPortDesc->pd_BrcTimer, NULL))
  331. {
  332. AtalkPortDereference(pPortDesc);
  333. }
  334. }
  335. if (!AtalkRouter)
  336. {
  337. // cancel the RtmpAging timer and take away the refcount for it
  338. if (AtalkTimerCancelEvent(&pPortDesc->pd_RtmpAgingTimer, NULL))
  339. {
  340. AtalkPortDereference(pPortDesc);
  341. }
  342. }
  343. //
  344. // if we are currently bound, *and* we are not here because of
  345. // PnPReconfigure, go ahead and unbind from ndis
  346. //
  347. if (fActive && !fPnpReconfigure)
  348. {
  349. // Unbind from the mac
  350. AtalkNdisUnbind(pPortDesc);
  351. }
  352. //
  353. // if are here because of PnpReconfigure, we didn't unbind. But fake
  354. // that we did (from refcount perspective) so that we can proceed!
  355. // (in the PnPReconfigure code path, we don't free this memory when refcount
  356. // goes to 0: we merely use it to trigger some pnp work)
  357. //
  358. if (fPnpReconfigure)
  359. {
  360. AtalkPortDereference(pPortDesc);
  361. }
  362. // Remove the creation reference
  363. AtalkPortDereference(pPortDesc);
  364. // Make sure we are not at or above dispatch level
  365. ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
  366. // Wait for the last reference to go away
  367. KeWaitForSingleObject(&ShutdownEvent,
  368. Executive,
  369. KernelMode,
  370. FALSE,
  371. NULL);
  372. if (fActive)
  373. {
  374. ACQUIRE_SPIN_LOCK(&AtalkPortLock, &OldIrql);
  375. AtalkNumberOfActivePorts--;
  376. RELEASE_SPIN_LOCK(&AtalkPortLock, OldIrql);
  377. ASSERT(AtalkStatistics.stat_NumActivePorts > 0);
  378. AtalkStatistics.stat_NumActivePorts--;
  379. }
  380. DBGPRINT(DBG_COMP_UNLOAD, DBG_LEVEL_ERR,
  381. ("AtalkPortShutdown: shutdown for port %lx completed\n",pPortDesc));
  382. return ATALK_NO_ERROR;
  383. }
  384. #if DBG
  385. VOID
  386. AtalkPortDumpInfo(
  387. VOID
  388. )
  389. {
  390. int i, j;
  391. KIRQL OldIrql;
  392. PPORT_DESCRIPTOR pPortDesc;
  393. PZONE_LIST pZoneList;
  394. ACQUIRE_SPIN_LOCK(&AtalkPortLock, &OldIrql);
  395. for (pPortDesc = AtalkPortList;
  396. pPortDesc != NULL;
  397. pPortDesc = pPortDesc->pd_Next)
  398. {
  399. DBGPRINT(DBG_COMP_DUMP, DBG_LEVEL_FATAL,
  400. ("Port info for port %Z\n", &pPortDesc->pd_AdapterKey));
  401. ACQUIRE_SPIN_LOCK_DPC(&pPortDesc->pd_Lock);
  402. DBGPRINT(DBG_COMP_DUMP, DBG_LEVEL_FATAL,
  403. (" Flags -> %d\n", pPortDesc->pd_Flags));
  404. DBGPRINT(DBG_COMP_DUMP, DBG_LEVEL_FATAL,
  405. (" PortType -> %d\n", pPortDesc->pd_PortType));
  406. DBGPRINT(DBG_COMP_DUMP, DBG_LEVEL_FATAL,
  407. (" PortName -> %s\n", pPortDesc->pd_PortName));
  408. DBGPRINT(DBG_COMP_DUMP, DBG_LEVEL_FATAL,
  409. (" AARP Probes -> %d\n", pPortDesc->pd_AarpProbes));
  410. if (pPortDesc->pd_InitialNetworkRange.anr_FirstNetwork != 0)
  411. {
  412. DBGPRINT(DBG_COMP_DUMP, DBG_LEVEL_FATAL,
  413. (" InitialNwRange -> %lx-%lx\n",
  414. pPortDesc->pd_InitialNetworkRange.anr_FirstNetwork,
  415. pPortDesc->pd_InitialNetworkRange.anr_LastNetwork))
  416. }
  417. DBGPRINT(DBG_COMP_DUMP, DBG_LEVEL_FATAL,
  418. (" NetworkRange -> %x-%x\n",
  419. pPortDesc->pd_NetworkRange.anr_FirstNetwork,
  420. pPortDesc->pd_NetworkRange.anr_LastNetwork))
  421. DBGPRINT(DBG_COMP_DUMP, DBG_LEVEL_FATAL,
  422. (" ARouter Address -> %x.%x\n",
  423. pPortDesc->pd_ARouter.atn_Network,
  424. pPortDesc->pd_ARouter.atn_Node));
  425. DBGPRINT(DBG_COMP_DUMP, DBG_LEVEL_FATAL,
  426. (" Multicast Addr -> "));
  427. for (j = 0; j < MAX_HW_ADDR_LEN; j++)
  428. DBGPRINTSKIPHDR(DBG_COMP_DUMP, DBG_LEVEL_FATAL,
  429. ("%02x", (BYTE)pPortDesc->pd_ZoneMulticastAddr[j]));
  430. DBGPRINTSKIPHDR(DBG_COMP_DUMP, DBG_LEVEL_FATAL,
  431. ("\n"));
  432. if (pPortDesc->pd_InitialZoneList != NULL)
  433. {
  434. DBGPRINT(DBG_COMP_DUMP, DBG_LEVEL_FATAL,
  435. (" Initial zone list:\n"));
  436. for (pZoneList = pPortDesc->pd_InitialZoneList;
  437. pZoneList != NULL; pZoneList = pZoneList->zl_Next)
  438. {
  439. DBGPRINT(DBG_COMP_DUMP, DBG_LEVEL_FATAL,
  440. (" %s\n", pZoneList->zl_pZone->zn_Zone));
  441. }
  442. }
  443. if (pPortDesc->pd_InitialDefaultZone != NULL)
  444. DBGPRINT(DBG_COMP_DUMP, DBG_LEVEL_FATAL,
  445. (" InitialDefZone -> %s\n",
  446. pPortDesc->pd_InitialDefaultZone->zn_Zone));
  447. if (pPortDesc->pd_InitialDesiredZone != NULL)
  448. DBGPRINT(DBG_COMP_DUMP, DBG_LEVEL_FATAL,
  449. (" InitialDesZone -> %s\n",
  450. pPortDesc->pd_InitialDesiredZone->zn_Zone));
  451. if (pPortDesc->pd_ZoneList)
  452. {
  453. DBGPRINT(DBG_COMP_DUMP, DBG_LEVEL_FATAL,
  454. (" Current zone list:\n"));
  455. for (pZoneList = pPortDesc->pd_ZoneList;
  456. pZoneList != NULL; pZoneList = pZoneList->zl_Next)
  457. {
  458. DBGPRINT(DBG_COMP_DUMP, DBG_LEVEL_FATAL,
  459. (" %s\n", pZoneList->zl_pZone->zn_Zone));
  460. }
  461. }
  462. if (pPortDesc->pd_DefaultZone != NULL)
  463. DBGPRINT(DBG_COMP_DUMP, DBG_LEVEL_FATAL,
  464. (" CurrentDefZone -> %s\n",
  465. pPortDesc->pd_DefaultZone->zn_Zone));
  466. if (pPortDesc->pd_DesiredZone != NULL)
  467. DBGPRINT(DBG_COMP_DUMP, DBG_LEVEL_FATAL,
  468. (" CurrentDesZone -> %s\n",
  469. pPortDesc->pd_DesiredZone->zn_Zone));
  470. RELEASE_SPIN_LOCK_DPC(&pPortDesc->pd_Lock);
  471. }
  472. RELEASE_SPIN_LOCK(&AtalkPortLock, OldIrql);
  473. }
  474. #endif