Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

586 lines
17 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. adptmgr.c
  5. Abstract:
  6. This module contains the adapter management functions
  7. Author:
  8. Stefan Solomon 03/07/1995
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. //
  14. // Adapter Manager Globals
  15. //
  16. HANDLE AdapterConfigPortHandle;
  17. HANDLE AdapterNotificationThreadHandle;
  18. // Counter of created adapters
  19. ULONG AdaptersCount = 0;
  20. PICB
  21. GetInterfaceByAdptNameAndPktType(LPWSTR AdapterName, DWORD dwType);
  22. DWORD
  23. PnpAdapterConfigHandler(ADAPTER_INFO * pAdapterInfo,
  24. ULONG AdapterIndex,
  25. ULONG AdapterConfigurationStatus);
  26. DWORD
  27. ReConfigureAdapter(IN DWORD dwAdapterIndex,
  28. IN PWSTR pszAdapterName,
  29. IN PADAPTER_INFO pAdapter);
  30. VOID
  31. CreateAdapter(ULONG AdapterIndex,
  32. PWSTR AdapterNamep,
  33. PADAPTER_INFO adptip);
  34. VOID
  35. DeleteAdapter(ULONG AdapterIndex);
  36. VOID
  37. AdapterUp(ULONG AdapterIndex);
  38. VOID
  39. AdapterDown(ULONG AdapterIndex);
  40. /*++
  41. Function: StartAdapterManager
  42. Descr: opens the IPX stack notification port
  43. --*/
  44. DWORD
  45. StartAdapterManager(VOID)
  46. {
  47. ADAPTERS_GLOBAL_PARAMETERS AdptGlobalParameters;
  48. DWORD threadid;
  49. Trace(ADAPTER_TRACE, "StartAdapterManager: Entered\n");
  50. // create adapter config port
  51. if((AdapterConfigPortHandle = IpxCreateAdapterConfigurationPort(
  52. g_hEvents[ADAPTER_NOTIFICATION_EVENT],
  53. &AdptGlobalParameters)) == INVALID_HANDLE_VALUE) {
  54. // can't create config port
  55. return (1);
  56. }
  57. return (0);
  58. }
  59. /*++
  60. Function: StopAdapterManager
  61. Descr: Closes the IPX notification port
  62. --*/
  63. VOID
  64. StopAdapterManager(VOID)
  65. {
  66. DWORD rc;
  67. ULONG AdapterIndex;
  68. Trace(ADAPTER_TRACE, "StopAdapterManager: Entered\n");
  69. // Close the IPX stack notification port
  70. IpxDeleteAdapterConfigurationPort(AdapterConfigPortHandle);
  71. }
  72. // Debugging functions
  73. char * DbgTypeToString(DWORD dwType) {
  74. switch (dwType) {
  75. case MISN_FRAME_TYPE_ETHERNET_II:
  76. return "EthII";
  77. case MISN_FRAME_TYPE_802_3:
  78. return "802.3";
  79. case MISN_FRAME_TYPE_802_2:
  80. return "802.2";
  81. case MISN_FRAME_TYPE_SNAP:
  82. return "SNAP";
  83. case MISN_FRAME_TYPE_ARCNET:
  84. return "Arcnet";
  85. case ISN_FRAME_TYPE_AUTO:
  86. return "Autodetect";
  87. }
  88. return "Unknown";
  89. }
  90. // Helper debug function traces out information about a given interface
  91. VOID DbgTraceAdapterInfo(IN PADAPTER_INFO pAdapter, DWORD dwIndex, LPSTR pszTitle) {
  92. Trace(ADAPTER_TRACE, "%s: Ind=%d IfInd=%d Net=%x Lcl=%x Rmt=%x Spd=%d Type=%d",
  93. pszTitle,
  94. dwIndex,
  95. pAdapter->InterfaceIndex,
  96. *((LONG*)(pAdapter->Network)),
  97. *((LONG*)(pAdapter->LocalNode)),
  98. *((LONG*)(pAdapter->RemoteNode)),
  99. pAdapter->LinkSpeed,
  100. pAdapter->NdisMedium);
  101. }
  102. // Outputs the current status of an adapter to the trace window
  103. VOID DbgTraceAdapter(PACB acbp) {
  104. Trace(ADAPTER_TRACE, "[%d] Interface: %d, Network: %x, Type: %s",
  105. acbp->AdapterIndex,
  106. (acbp->icbp) ? acbp->icbp->InterfaceIndex : -1,
  107. *((LONG*)(acbp->AdapterInfo.Network)),
  108. DbgTypeToString(acbp->AdapterInfo.PacketType));
  109. }
  110. // Outputs the current list of adapters to the trace window
  111. VOID DbgTraceAdapterList() {
  112. PLIST_ENTRY lep;
  113. DWORD i;
  114. PACB acbp;
  115. ACQUIRE_DATABASE_LOCK;
  116. Trace(ADAPTER_TRACE, "List of current adapters:");
  117. Trace(ADAPTER_TRACE, "=========================");
  118. // Loop through the adapter hash table, printing as we go
  119. for (i = 0; i < ADAPTER_HASH_TABLE_SIZE; i++) {
  120. lep = IndexAdptHt[i].Flink;
  121. while(lep != &IndexAdptHt[i]) {
  122. acbp = CONTAINING_RECORD(lep, ACB, IndexHtLinkage);
  123. DbgTraceAdapter(acbp);
  124. lep = acbp->IndexHtLinkage.Flink;
  125. }
  126. }
  127. Trace(ADAPTER_TRACE, "\n");
  128. RELEASE_DATABASE_LOCK;
  129. }
  130. /*++
  131. Function: AdapterNotification
  132. Descr: Processes adapter notification events
  133. --*/
  134. VOID
  135. AdapterNotification(VOID)
  136. {
  137. ADAPTER_INFO AdapterInfo;
  138. ULONG AdapterIndex;
  139. ULONG AdapterConfigurationStatus;
  140. DWORD rc;
  141. Trace(ADAPTER_TRACE, "AdapterNotification: Entered");
  142. // Adaptif manages the adapter information. Get the next piece of
  143. // information that adptif has queued for us.
  144. while((rc = IpxGetQueuedAdapterConfigurationStatus(
  145. AdapterConfigPortHandle,
  146. &AdapterIndex,
  147. &AdapterConfigurationStatus,
  148. &AdapterInfo)) == NO_ERROR)
  149. {
  150. switch(AdapterConfigurationStatus) {
  151. // An adapter is being created. This is happening either
  152. // because we are receiving the list of current adapters
  153. // at initialization time or as a result of a PnP event.
  154. // Either way, the smarts to deal with the situation are built
  155. // into our PnP handler.
  156. //
  157. // This message is also sent when an existing adapter is
  158. // being configured.
  159. case ADAPTER_CREATED:
  160. PnpAdapterConfigHandler(&AdapterInfo,
  161. AdapterIndex,
  162. AdapterConfigurationStatus);
  163. break;
  164. // Handle an adapter being deleted -- this can happen as a result of
  165. // pcmcia removing the adapter or as a result of a binding change
  166. // or a wan link removal.
  167. case ADAPTER_DELETED:
  168. DeleteAdapter(AdapterIndex);
  169. break;
  170. // A wan line came up.
  171. case ADAPTER_UP:
  172. AdapterUp(AdapterIndex);
  173. break;
  174. // A wan line went down
  175. case ADAPTER_DOWN:
  176. AdapterDown(AdapterIndex);
  177. break;
  178. // Some internal error has occured.
  179. default:
  180. SS_ASSERT(FALSE);
  181. break;
  182. }
  183. }
  184. DbgTraceAdapterList();
  185. }
  186. // Handles adapter creation and configuration notifications.
  187. DWORD PnpAdapterConfigHandler(ADAPTER_INFO * pAdapterInfo,
  188. ULONG AdapterIndex,
  189. ULONG AdapterConfigurationStatus)
  190. {
  191. ULONG AdapterNameSize;
  192. LPWSTR AdapterNameBuffer;
  193. DWORD dwErr;
  194. Trace(ADAPTER_TRACE, "PnpAdapterConfigHandler: Entered for adpt #%d", AdapterIndex);
  195. // If this is the internal adapter, we don't need an adapter name
  196. if (AdapterIndex == 0)
  197. AdapterNameBuffer = L"";
  198. // Otherwise, get the adapter name from the stack
  199. else {
  200. AdapterNameSize = wcslen(pAdapterInfo->pszAdpName) * sizeof (WCHAR) + sizeof(WCHAR);
  201. //Allocate the memory to hold the name of the adapter
  202. if((AdapterNameBuffer = GlobalAlloc(GPTR, AdapterNameSize)) == NULL)
  203. return ERROR_NOT_ENOUGH_MEMORY;
  204. wcscpy(AdapterNameBuffer, pAdapterInfo->pszAdpName);
  205. }
  206. // Either create or configure the adapter depending on whether
  207. // it has already exists in the adapter database.
  208. ACQUIRE_DATABASE_LOCK;
  209. if(GetAdapterByIndex(AdapterIndex))
  210. ReConfigureAdapter(AdapterIndex, AdapterNameBuffer, pAdapterInfo);
  211. else
  212. CreateAdapter(AdapterIndex, AdapterNameBuffer, pAdapterInfo);
  213. RELEASE_DATABASE_LOCK;
  214. // Cleanup
  215. if (AdapterIndex != 0)
  216. GlobalFree(AdapterNameBuffer);
  217. return NO_ERROR;
  218. }
  219. // Attempt to bind an unbound adapter
  220. DWORD AttemptAdapterBinding (PACB acbp) {
  221. PICB icbp;
  222. // Make sure we aren't already bound
  223. if (acbp->icbp)
  224. return NO_ERROR;
  225. if(acbp->AdapterInfo.NdisMedium != NdisMediumWan) {
  226. // this is a DEDICATED (e.g LAN) adapter. If an interface already exists for it,
  227. // bind it to its interface and notify the other modules
  228. if(acbp->AdapterIndex != 0) {
  229. icbp = GetInterfaceByAdptNameAndPktType(acbp->AdapterNamep,
  230. acbp->AdapterInfo.PacketType);
  231. if (icbp)
  232. BindInterfaceToAdapter(icbp, acbp);
  233. }
  234. else {
  235. // This is the internal adapter
  236. InternalAdapterp = acbp;
  237. // If the internal network number was set to zero (nullnet), then
  238. // we have a configuration problem -- don't barf on this, just log
  239. // the fact.
  240. if(!memcmp(acbp->AdapterInfo.Network, nullnet, 4)) {
  241. IF_LOG (EVENTLOG_ERROR_TYPE) {
  242. RouterLogErrorDataA (RMEventLogHdl,
  243. ROUTERLOG_IPX_NO_VIRTUAL_NET_NUMBER,
  244. 0, NULL, 0, NULL);
  245. }
  246. Trace(ADAPTER_TRACE, "CreateAdapter: Internal net number is not configured !");
  247. // [pmay] now when we get a bad internal net number, we re-configure.
  248. // SS_ASSERT(FALSE);
  249. PnpAutoSelectInternalNetNumber(ADAPTER_TRACE);
  250. }
  251. // if the internal interface already exists, bind to it
  252. if(icbp = InternalInterfacep) {
  253. BindInterfaceToAdapter(icbp, acbp);
  254. }
  255. }
  256. }
  257. else {
  258. // this is a connected WAN adapter
  259. SS_ASSERT(acbp->icbp == NULL);
  260. // bind to corresponding interface
  261. if(icbp = GetInterfaceByIndex(acbp->AdapterInfo.InterfaceIndex)) {
  262. // bind all interfaces to this adapter
  263. BindInterfaceToAdapter(icbp, acbp);
  264. }
  265. }
  266. return NO_ERROR;
  267. }
  268. // Resets the configuration of the given adapter. This function assumes that
  269. // the database is locked and that the given adapter index references an
  270. // adapter in the database. Furthermore this function assumes that it does
  271. // not need to release its lock on the database.
  272. DWORD ReConfigureAdapter(IN DWORD dwAdapterIndex,
  273. IN PWSTR pszAdapterName,
  274. IN PADAPTER_INFO pAdapter)
  275. {
  276. PACB acbp;
  277. PICB icbp;
  278. Trace(
  279. ADAPTER_TRACE,
  280. "ReConfigureAdapter: Entered for %d: %S: %x, %d",
  281. dwAdapterIndex,
  282. pszAdapterName,
  283. *((DWORD*)(pAdapter->Network)),
  284. pAdapter->InterfaceIndex
  285. );
  286. // If the adapter being configured is the internal adapter and if it is to be
  287. // re-configured to a zero net number, that is to be a signal to automatically
  288. // assign a new network number.
  289. if ((dwAdapterIndex == 0) && (*((DWORD*)pAdapter->Network) == 0)) {
  290. DWORD dwErr;
  291. Trace(ADAPTER_TRACE, "ReConfigureAdapter: Internal Net = 0, selecting new number");
  292. if ((dwErr = PnpAutoSelectInternalNetNumber(ADAPTER_TRACE)) != NO_ERROR)
  293. Trace(ADAPTER_TRACE, "ReConfigureAdapter: Auto-select of new net number FAILED!");
  294. return dwErr;
  295. }
  296. // Get a reference to the adapter and the interface
  297. if (dwAdapterIndex == 0)
  298. acbp = InternalAdapterp;
  299. else
  300. acbp = GetAdapterByIndex(dwAdapterIndex);
  301. if (!acbp) {
  302. Trace(ADAPTER_TRACE, "ReConfigureAdapter: Invalid adapter %d!", dwAdapterIndex);
  303. return ERROR_CAN_NOT_COMPLETE;
  304. }
  305. icbp = acbp->icbp;
  306. // If this adapter isn't bound yet, update it and then
  307. // try to bind it.
  308. if (!icbp) {
  309. acbp->AdapterInfo = *pAdapter;
  310. AttemptAdapterBinding (acbp);
  311. }
  312. // Otherwise, unbind and then re-bind the adapter
  313. else {
  314. // Unbind the interface from the adapter
  315. UnbindInterfaceFromAdapter(icbp);
  316. // Update the information
  317. acbp->AdapterInfo = *pAdapter;
  318. // Rebind the interface to the adapter
  319. AttemptAdapterBinding(acbp);
  320. }
  321. return NO_ERROR;
  322. }
  323. /*++
  324. Function: CreateAdapter
  325. Descr: creates the adapter control block
  326. Modification:
  327. [pmay] Assume the database lock is aquired before this function enters
  328. and that the given adapter index has not already been added
  329. to the adapter database.
  330. --*/
  331. VOID
  332. CreateAdapter(ULONG AdapterIndex,
  333. PWSTR AdapterNamep,
  334. PADAPTER_INFO adptip)
  335. {
  336. PACB acbp;
  337. PICB icbp;
  338. ULONG namelen;
  339. PUCHAR ln = adptip->LocalNode;
  340. Trace(
  341. ADAPTER_TRACE,
  342. "CreateAdapter: Entered for %d (%x%x%x%x%x%x)(%S), %d",
  343. AdapterIndex,
  344. ln[0], ln[1], ln[2], ln[3], ln[4], ln[5],
  345. AdapterNamep,
  346. adptip->InterfaceIndex);
  347. // adapter name len including the unicode null
  348. namelen = (wcslen(AdapterNamep) + 1) * sizeof(WCHAR);
  349. // new adapter, try to get an ACB
  350. if((acbp = GlobalAlloc(GPTR, sizeof(ACB) + namelen)) == NULL) {
  351. Trace(ADAPTER_TRACE, "CreateAdapter: RETURNING BECAUSE INSUFFICIENT MEMORY TO ALLOCATE ADAPTER");
  352. // [pmay] PnP handler takes care of aquiring and releasing the database lock.
  353. // RELEASE_DATABASE_LOCK;
  354. SS_ASSERT(FALSE);
  355. return;
  356. }
  357. // make the ACB
  358. acbp->AdapterIndex = AdapterIndex;
  359. AddToAdapterHt(acbp);
  360. memcpy(acbp->Signature, AdapterSignature, 4);
  361. // We haven't bound to any interface at this point
  362. acbp->icbp = NULL;
  363. // Store the adapter information pertinent to this adapter
  364. acbp->AdapterInfo = *adptip;
  365. // Copy of the adapter name
  366. acbp->AdapterNamep = (LPWSTR)((PUCHAR)acbp + sizeof(ACB));
  367. wcscpy(acbp->AdapterNamep, AdapterNamep);
  368. acbp->AdapterNameLen = namelen - 1; // without the unicode null
  369. // Attempt to bind the adapter
  370. AttemptAdapterBinding (acbp);
  371. AdaptersCount++;
  372. if(acbp->AdapterInfo.NdisMedium != NdisMediumWan) {
  373. if(acbp->AdapterIndex == 0) {
  374. Trace(ADAPTER_TRACE, "CreateAdapter: Created INTERNAL adapter index 0");
  375. }
  376. else {
  377. Trace(ADAPTER_TRACE, "CreateAdapter: Created LAN adapter # %d name %S",
  378. acbp->AdapterIndex,
  379. acbp->AdapterNamep);
  380. }
  381. }
  382. else {
  383. Trace(ADAPTER_TRACE, "CreateAdapter: created WAN adapter # %d", acbp->AdapterIndex);
  384. }
  385. // [pmay] PnP handler takes care of aquiring and releasing the database lock.
  386. // RELEASE_DATABASE_LOCK;
  387. }
  388. /*++
  389. Function: DeleteAdapter
  390. Descr:
  391. --*/
  392. VOID
  393. DeleteAdapter(ULONG AdapterIndex)
  394. {
  395. PACB acbp, acbp2;
  396. PICB icbp;
  397. WCHAR pszAdapterName[MAX_ADAPTER_NAME_LEN];
  398. Trace(ADAPTER_TRACE, "DeleteAdapter: Entered for adapter # %d", AdapterIndex);
  399. ACQUIRE_DATABASE_LOCK;
  400. // Get the adapter
  401. if((acbp = GetAdapterByIndex(AdapterIndex)) == NULL) {
  402. RELEASE_DATABASE_LOCK;
  403. Trace(ADAPTER_TRACE, "DeleteAdapter: Ignored. There is no adapter # %d to be deleted !\n", AdapterIndex);
  404. return;
  405. }
  406. // 1. if the adapter is bound to an interface -> unbind it. Also, save the adapter name.
  407. if((icbp = acbp->icbp) != NULL) {
  408. wcscpy(pszAdapterName, acbp->AdapterNamep);
  409. UnbindInterfaceFromAdapter(acbp->icbp);
  410. }
  411. // Remove the adapter from the database
  412. RemoveFromAdapterHt(acbp);
  413. AdaptersCount--;
  414. // [pmay]
  415. // Since pnp can cause adapters to be added and removed from the database
  416. // in unpredictable orders, see if there is already another adapter in the
  417. // database with which the bound interface can immediately re-bind.
  418. if (icbp) {
  419. if((acbp2 = GetAdapterByNameAndPktType (pszAdapterName, icbp->PacketType)) != NULL)
  420. BindInterfaceToAdapter(icbp, acbp2);
  421. }
  422. RELEASE_DATABASE_LOCK;
  423. Trace(ADAPTER_TRACE, "DeleteAdapter: deleted adapter # %d", acbp->AdapterIndex);
  424. GlobalFree(acbp);
  425. return;
  426. }
  427. /*++
  428. Function: AdapterDown
  429. Descr: Called if the LAN adapter isn't functional.
  430. It calls back into the SNMP Agent with a trap - AdapterDown
  431. --*/
  432. VOID
  433. AdapterDown(ULONG AdapterIndex)
  434. {
  435. // Call AdapterDownTrap
  436. }
  437. /*++
  438. Function: AdapterUp
  439. Descr: Called if the LAN adapter isn't functional.
  440. It calls back into the SNMP Agent with a trap - AdapterUP
  441. --*/
  442. VOID
  443. AdapterUp(ULONG AdapterIndex)
  444. {
  445. // Call AdapterUpTrap
  446. }
  447. VOID
  448. DestroyAllAdapters(VOID)
  449. {
  450. PLIST_ENTRY IfHtBucketp, lep;
  451. PACB acbp;
  452. ULONG AdapterIndex;
  453. int i;
  454. for(i=0, IfHtBucketp = IndexAdptHt; i<ADAPTER_HASH_TABLE_SIZE; i++, IfHtBucketp++) {
  455. if (!IsListEmpty(IfHtBucketp)) {
  456. acbp = CONTAINING_RECORD(IfHtBucketp->Flink, ACB, IndexHtLinkage);
  457. RemoveFromAdapterHt(acbp);
  458. AdaptersCount--;
  459. Trace(ADAPTER_TRACE, "DestroyAllAdapters: destroyed adapter # %d\n", acbp->AdapterIndex);
  460. GlobalFree(acbp);
  461. }
  462. }
  463. }