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.

2275 lines
57 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. wanarp\conn.c
  5. Abstract:
  6. The file contains the code needed for connection management
  7. Revision History:
  8. AmritanR
  9. --*/
  10. #define __FILE_SIG__ CONN_SIG
  11. #include "inc.h"
  12. #if DBG
  13. DWORD g_dwSendsOnDeletedLink = 0;
  14. #endif
  15. VOID
  16. WanNdisStatus(
  17. NDIS_HANDLE nhHandle,
  18. NDIS_STATUS nsNdisStatus,
  19. PVOID pvStatusInfo,
  20. UINT uiStatusInfoSize
  21. )
  22. /*++
  23. Routine Description:
  24. Status handler for NDIS. we simply pass the buffer on to our private
  25. handlers
  26. Locks:
  27. None needed
  28. Arguments:
  29. nhHandle
  30. nsNdisStatus
  31. pvStatusInfo
  32. uiSatusInfoSize
  33. Return Value:
  34. None
  35. --*/
  36. {
  37. UNREFERENCED_PARAMETER(uiStatusInfoSize);
  38. UNREFERENCED_PARAMETER(nhHandle);
  39. switch(nsNdisStatus)
  40. {
  41. case NDIS_STATUS_WAN_LINE_UP:
  42. {
  43. PNDIS_WAN_LINE_UP pLineUp;
  44. pLineUp = (PNDIS_WAN_LINE_UP)pvStatusInfo;
  45. WanpLinkUpIndication(pLineUp);
  46. break;
  47. }
  48. case NDIS_STATUS_WAN_LINE_DOWN:
  49. {
  50. PNDIS_WAN_LINE_DOWN pLineDown;
  51. pLineDown = (PNDIS_WAN_LINE_DOWN)pvStatusInfo;
  52. WanpLinkDownIndication(pLineDown);
  53. break;
  54. }
  55. case NDIS_STATUS_WAN_FRAGMENT:
  56. default:
  57. {
  58. //
  59. // Ignore all other indications
  60. //
  61. break;
  62. }
  63. }
  64. }
  65. VOID
  66. WanNdisStatusComplete(
  67. NDIS_HANDLE nhHandle
  68. )
  69. /*++
  70. Routine Description:
  71. Called after the driver is done indicating a set of status
  72. indications
  73. We dont do anything
  74. Locks:
  75. None
  76. Arguments:
  77. nhHandle
  78. Return Value:
  79. None
  80. --*/
  81. {
  82. UNREFERENCED_PARAMETER(nhHandle);
  83. return;
  84. }
  85. NDIS_STATUS
  86. WanpLinkUpIndication(
  87. PNDIS_WAN_LINE_UP pInfoBuffer
  88. )
  89. /*++
  90. Routine Description:
  91. The routine that handles a new connection. We also get this when a
  92. link in a multi-linked bundle comes up or goes down.
  93. If this is a new connection, we allocate a CONN_ENTRY for this.
  94. Then, if this is a dial in connection, we lock and ref the server
  95. adapter and interface. If this is a router connection, we see if
  96. we already have a mapped adapter. If we do, we lock the adapter
  97. otherwise, we find a free adapter to map for the linkup.
  98. If this is a dial out connection, we create an interface and find a
  99. free adapter to map for the connection.
  100. We set up the needed cross mappings between the conn entry, adapter
  101. and interface and initialize the conn entry
  102. If this is a router connection, we drain all packets, and complete
  103. an IRP to tell router manager about it.
  104. For non dial in connections we indicate a Status change to IP, while
  105. for dial in, we add a link to IP for the client.
  106. Locks:
  107. MUST be called at PASSIVE because we call IPAddInterface.
  108. We acquire the g_rlConnTableLock, g_rwlAdapterLock, g_rwlIfLock
  109. in addition to locking down the adapter and the interface
  110. Arguments:
  111. Return Value:
  112. NDIS_STATUS_SUCCESS
  113. NDIS_STATUS_ADAPTER_NOT_READY
  114. STATUS_INVALID_PARAMETER
  115. NDIS_STATUS_RESOURCES
  116. STATUS_OBJECT_NAME_NOT_FOUND
  117. STATUS_INVALID_DEVICE_STATE
  118. --*/
  119. {
  120. PADAPTER pAdapter;
  121. PCONN_ENTRY pConnEntry;
  122. ULONG ulConnIndex;
  123. KIRQL kiIrql;
  124. LLIPMTUChange mtuChangeInfo;
  125. LLIPSpeedChange speedChangeInfo;
  126. IP_STATUS isStatus;
  127. ULONG ulIndex;
  128. UNICODE_STRING usTempName;
  129. WCHAR rgwcGuid[GUID_STR_LEN + 1];
  130. PUMODE_INTERFACE pInterface;
  131. PIP_WAN_LINKUP_INFO pLinkInfo;
  132. PPENDING_NOTIFICATION pMsg;
  133. //
  134. // This must be at PASSIVE (because we may need to drive a
  135. // IPAddInterface from here)
  136. //
  137. TraceEnter(CONN, "LinkUpIndication");
  138. pLinkInfo = (PIP_WAN_LINKUP_INFO)pInfoBuffer->ProtocolBuffer;
  139. Trace(CONN, INFO,
  140. ("HandleLinkUpIndication: %d.%d.%d.%d/%d.%d.%d.%d - %d.%d.%d.%d\n",
  141. PRINT_IPADDR(pLinkInfo->dwLocalAddr),
  142. PRINT_IPADDR(pLinkInfo->dwLocalMask),
  143. PRINT_IPADDR(pLinkInfo->dwRemoteAddr)));
  144. if(!EnterDriverCode())
  145. {
  146. return NDIS_STATUS_ADAPTER_NOT_READY;
  147. }
  148. ulConnIndex = GetConnIndexFromAddr(pInfoBuffer->LocalAddress);
  149. if(ulConnIndex isnot 0)
  150. {
  151. PVOID pvLinkContext;
  152. //
  153. // This is not the first lineup for this entry
  154. // We should find the entry (if it is on this interface)
  155. // and update speed and mtu info
  156. //
  157. RtAcquireSpinLock(&g_rlConnTableLock,
  158. &kiIrql);
  159. pConnEntry = GetConnEntryGivenIndex(ulConnIndex);
  160. if((pConnEntry is NULL) or
  161. (pConnEntry->byState isnot CS_CONNECTED))
  162. {
  163. RtAssert(FALSE);
  164. RtReleaseSpinLock(&g_rlConnTableLock,
  165. kiIrql);
  166. ExitDriverCode();
  167. return NDIS_STATUS_SUCCESS;
  168. }
  169. RtAssert(pConnEntry->pAdapter);
  170. //
  171. // Lock the conn entry or the adapter
  172. //
  173. RtAcquireSpinLockAtDpcLevel(pConnEntry->prlLock);
  174. RtReleaseSpinLockFromDpcLevel(&g_rlConnTableLock);
  175. if(pInfoBuffer->MaximumTotalSize isnot pConnEntry->ulMtu)
  176. {
  177. pConnEntry->ulMtu = pInfoBuffer->MaximumTotalSize;
  178. mtuChangeInfo.lmc_mtu = pConnEntry->ulMtu;
  179. }
  180. else
  181. {
  182. mtuChangeInfo.lmc_mtu = 0;
  183. }
  184. if((pInfoBuffer->LinkSpeed * 100L) isnot pConnEntry->ulSpeed)
  185. {
  186. pConnEntry->ulSpeed = pInfoBuffer->LinkSpeed * 100L;
  187. speedChangeInfo.lsc_speed = pConnEntry->ulSpeed;
  188. }
  189. else
  190. {
  191. speedChangeInfo.lsc_speed = 0;
  192. }
  193. RtReleaseSpinLock(pConnEntry->prlLock,
  194. kiIrql);
  195. if(mtuChangeInfo.lmc_mtu isnot 0)
  196. {
  197. g_pfnIpStatus(pConnEntry->pAdapter->pvIpContext,
  198. LLIP_STATUS_MTU_CHANGE,
  199. &mtuChangeInfo,
  200. sizeof(LLIPMTUChange),
  201. pConnEntry->pvIpLinkContext);
  202. }
  203. if(speedChangeInfo.lsc_speed isnot 0)
  204. {
  205. g_pfnIpStatus(pConnEntry->pAdapter->pvIpContext,
  206. LLIP_STATUS_SPEED_CHANGE,
  207. &speedChangeInfo,
  208. sizeof(LLIPSpeedChange),
  209. pConnEntry->pvIpLinkContext);
  210. }
  211. DereferenceConnEntry(pConnEntry);
  212. TraceLeave(CONN, "LinkUpIndication");
  213. ExitDriverCode();
  214. return NDIS_STATUS_SUCCESS;
  215. }
  216. PASSIVE_ENTRY();
  217. if((pLinkInfo->duUsage isnot DU_CALLIN) and
  218. (pLinkInfo->duUsage isnot DU_CALLOUT) and
  219. (pLinkInfo->duUsage isnot DU_ROUTER))
  220. {
  221. RtAssert(FALSE);
  222. Trace(CONN,ERROR,
  223. ("LinkUpIndication: Invalid usage %d\n", pLinkInfo->duUsage));
  224. TraceLeave(CONN, "LinkUpIndication");
  225. ExitDriverCode();
  226. return STATUS_INVALID_PARAMETER;
  227. }
  228. RtlZeroMemory(pInfoBuffer->LocalAddress,
  229. ARP_802_ADDR_LENGTH);
  230. //
  231. // Get a connection entry for this connection
  232. // This function finds a free slot in the connection table and puts
  233. // the conn entry into the slot. It sets the ulSlot field in the
  234. // conn entry to be the index of the slot
  235. //
  236. RtAcquireSpinLock(&g_rlConnTableLock,
  237. &kiIrql);
  238. pConnEntry = WanpCreateConnEntry(pLinkInfo->duUsage);
  239. if(pConnEntry is NULL)
  240. {
  241. RtReleaseSpinLock(&g_rlConnTableLock,
  242. kiIrql);
  243. Trace(CONN,ERROR,
  244. ("LinkUpIndication: Couldnt allocate conn entry\n"));
  245. TraceLeave(CONN, "LinkUpIndication");
  246. ExitDriverCode();
  247. return NDIS_STATUS_RESOURCES;
  248. }
  249. RtReleaseSpinLock(&g_rlConnTableLock,
  250. kiIrql);
  251. //
  252. // Create a GUID from a name
  253. //
  254. usTempName.MaximumLength = (GUID_STR_LEN + 1) * sizeof(WCHAR);
  255. usTempName.Length = GUID_STR_LEN * sizeof(WCHAR);
  256. usTempName.Buffer = rgwcGuid;
  257. ConvertGuidToString((GUID *)(pInfoBuffer->DeviceName.Buffer),
  258. rgwcGuid);
  259. rgwcGuid[GUID_STR_LEN] = UNICODE_NULL;
  260. pAdapter = NULL;
  261. //
  262. // Do this usage specific thing. At the end of this switch statement
  263. // we have a locked and referenced Adapter and Interface for the
  264. // connection
  265. //
  266. switch(pLinkInfo->duUsage)
  267. {
  268. case DU_CALLIN:
  269. {
  270. //
  271. // Just get the server adapter and interface
  272. //
  273. Trace(CONN, INFO,
  274. ("LinkUpIndication: Linkup Usage is CALLIN\n"));
  275. //
  276. // Just use 0 as adapter index, since it is not really needed
  277. // for the CALLIN case
  278. //
  279. pAdapter = WanpFindAdapterToMap(DU_CALLIN,
  280. &kiIrql,
  281. 0,
  282. NULL);
  283. if(pAdapter is NULL)
  284. {
  285. WanpDeleteConnEntry(pConnEntry);
  286. ExitDriverCode();
  287. return NDIS_STATUS_RESOURCES;
  288. }
  289. RtAssert(pAdapter is g_pServerAdapter);
  290. //
  291. // clients lock the connection entry
  292. //
  293. RtInitializeSpinLock(&(pConnEntry->rlLock));
  294. pConnEntry->prlLock = &(pConnEntry->rlLock);
  295. RtAssert(pAdapter->pInterface is g_pServerInterface);
  296. RtAssert(pAdapter->byState is AS_MAPPED);
  297. //
  298. // Lock the server interface. We have to have a server interface.
  299. //
  300. pInterface = g_pServerInterface;
  301. //
  302. // Lock and reference the interface
  303. //
  304. RtAcquireSpinLockAtDpcLevel(&(pInterface->rlLock));
  305. ReferenceInterface(pInterface);
  306. break;
  307. }
  308. case DU_CALLOUT:
  309. {
  310. Trace(CONN, INFO,
  311. ("LinkUpIndication: Linkup Usage is CALLOUT\n"));
  312. //
  313. // Allocate a notification for informing the router manager
  314. // of this connection
  315. //
  316. pMsg = AllocateNotification();
  317. if(pMsg is NULL)
  318. {
  319. Trace(CONN, ERROR,
  320. ("LinkUpIndication: Couldnt allocate msg\n"));
  321. TraceLeave(CONN, "LinkUpIndication");
  322. WanpDeleteConnEntry(pConnEntry);
  323. ExitDriverCode();
  324. return NDIS_STATUS_RESOURCES;
  325. }
  326. //
  327. // For dial out, we dynamically create an interface
  328. //
  329. pInterface = RtAllocate(NonPagedPool,
  330. sizeof(UMODE_INTERFACE),
  331. WAN_INTERFACE_TAG);
  332. if(pInterface is NULL)
  333. {
  334. Trace(CONN, ERROR,
  335. ("LinkUpIndication: Couldnt allocate I/f\n"));
  336. TraceLeave(CONN, "LinkUpIndication");
  337. WanpDeleteConnEntry(pConnEntry);
  338. FreeNotification(pMsg);
  339. ExitDriverCode();
  340. return NDIS_STATUS_RESOURCES;
  341. }
  342. RtlZeroMemory(pInterface,
  343. sizeof(UMODE_INTERFACE));
  344. //
  345. // Get a new index from IP for this
  346. // This sets the value to INVALID_IF_INDEX if it fails
  347. //
  348. isStatus = WanpGetNewIndex(&(pInterface->dwRsvdAdapterIndex));
  349. if(isStatus isnot STATUS_SUCCESS)
  350. {
  351. RtFree(pInterface);
  352. Trace(CONN, ERROR,
  353. ("LinkUpIndication: Couldnt get index for I/f\n"));
  354. TraceLeave(CONN, "LinkUpIndication");
  355. WanpDeleteConnEntry(pConnEntry);
  356. FreeNotification(pMsg);
  357. ExitDriverCode();
  358. return NDIS_STATUS_RESOURCES;
  359. }
  360. Trace(CONN, INFO,
  361. ("LinkUpIndication: DialOut name is %S %d\n",
  362. rgwcGuid, pInterface->dwRsvdAdapterIndex));
  363. //
  364. // Find an adapter
  365. //
  366. pAdapter = WanpFindAdapterToMap(DU_CALLOUT,
  367. &kiIrql,
  368. pInterface->dwRsvdAdapterIndex,
  369. &usTempName);
  370. if(pAdapter is NULL)
  371. {
  372. WanpFreeIndex(pInterface->dwRsvdAdapterIndex);
  373. RtFree(pInterface);
  374. WanpDeleteConnEntry(pConnEntry);
  375. FreeNotification(pMsg);
  376. ExitDriverCode();
  377. return NDIS_STATUS_RESOURCES;
  378. }
  379. //
  380. // Initialize the interface block
  381. //
  382. RtInitializeSpinLock(&(pInterface->rlLock));
  383. //
  384. // Structure copy
  385. //
  386. pInterface->Guid = *((GUID *)(pInfoBuffer->DeviceName.Buffer));
  387. pInterface->dwAdminState = IF_ADMIN_STATUS_UP;
  388. pInterface->dwOperState = IF_OPER_STATUS_CONNECTING;
  389. pInterface->dwLastChange = GetTimeTicks();
  390. pInterface->dwIfIndex = INVALID_IF_INDEX;
  391. pInterface->duUsage = DU_CALLOUT;
  392. InitInterfaceRefCount(pInterface);
  393. //
  394. // Reference and lock the interface because the code after
  395. // the switch statement expects pInterface to be locked and
  396. // ref'ed
  397. //
  398. ReferenceInterface(pInterface);
  399. RtAcquireSpinLockAtDpcLevel(&(pInterface->rlLock));
  400. EnterWriterAtDpcLevel(&g_rwlIfLock);
  401. InsertHeadList(&g_leIfList,
  402. &(pInterface->leIfLink));
  403. //
  404. // No need to insert this in the quick lookup table since
  405. // this interface is never accessed by the index
  406. //
  407. InterlockedIncrement(&g_ulNumDialOutInterfaces);
  408. ExitWriterFromDpcLevel(&g_rwlIfLock);
  409. //
  410. // Initialize the message
  411. //
  412. pMsg->wnMsg.ddeEvent = DDE_CALLOUT_LINKUP;
  413. pMsg->wnMsg.dwUserIfIndex = INVALID_IF_INDEX;
  414. pMsg->wnMsg.dwAdapterIndex = pInterface->dwRsvdAdapterIndex;
  415. pMsg->wnMsg.dwLocalMask = pLinkInfo->dwLocalMask;
  416. pMsg->wnMsg.dwLocalAddr = pLinkInfo->dwLocalAddr;
  417. pMsg->wnMsg.dwRemoteAddr = pLinkInfo->dwRemoteAddr;
  418. pMsg->wnMsg.fDefaultRoute = pLinkInfo->fDefaultRoute;
  419. RtAssert(pInfoBuffer->DeviceName.Length <= WANARP_MAX_DEVICE_NAME_LEN);
  420. RtAssert((pInfoBuffer->DeviceName.Length % sizeof(WCHAR)) is 0)
  421. RtlCopyMemory(pMsg->wnMsg.rgwcName,
  422. usTempName.Buffer,
  423. usTempName.Length);
  424. pMsg->wnMsg.rgwcName[usTempName.Length/sizeof(WCHAR)] = UNICODE_NULL;
  425. break;
  426. }
  427. case DU_ROUTER:
  428. {
  429. pMsg = AllocateNotification();
  430. if(pMsg is NULL)
  431. {
  432. Trace(CONN, ERROR,
  433. ("LinkUpIndication: Couldnt allocate msg\n"));
  434. TraceLeave(CONN, "LinkUpIndication");
  435. WanpDeleteConnEntry(pConnEntry);
  436. ExitDriverCode();
  437. return NDIS_STATUS_RESOURCES;
  438. }
  439. //
  440. // Get the interface
  441. //
  442. EnterReader(&g_rwlIfLock,
  443. &kiIrql);
  444. pInterface = WanpFindInterfaceGivenIndex(
  445. pLinkInfo->dwUserIfIndex
  446. );
  447. if(pInterface is NULL)
  448. {
  449. ExitReader(&g_rwlIfLock,
  450. kiIrql);
  451. Trace(CONN, ERROR,
  452. ("LinkUpIndication: No interface %d\n",
  453. pLinkInfo->dwUserIfIndex));
  454. WanpDeleteConnEntry(pConnEntry);
  455. FreeNotification(pMsg);
  456. TraceLeave(CONN, "LinkUpIndication");
  457. ExitDriverCode();
  458. return STATUS_OBJECT_NAME_NOT_FOUND;
  459. }
  460. ExitReaderFromDpcLevel(&g_rwlIfLock);
  461. if((pInterface->dwOperState isnot IF_OPER_STATUS_CONNECTING) and
  462. (pInterface->dwOperState isnot IF_OPER_STATUS_DISCONNECTED))
  463. {
  464. Trace(CONN, ERROR,
  465. ("LinkUpIndication: Interface %p is in state %d\n",
  466. pInterface,
  467. pInterface->dwOperState));
  468. RtReleaseSpinLock(&(pInterface->rlLock),
  469. kiIrql);
  470. WanpDeleteConnEntry(pConnEntry);
  471. FreeNotification(pMsg);
  472. TraceLeave(CONN, "LinkUpIndication");
  473. ExitDriverCode();
  474. return STATUS_INVALID_DEVICE_STATE;
  475. }
  476. pInterface->Guid = *((GUID *)(pInfoBuffer->DeviceName.Buffer));
  477. Trace(CONN, TRACE,
  478. ("LinkUpIndication: For interface %p\n",
  479. pInterface));
  480. //
  481. // See if the interface is mapped to an adapter. This happens
  482. // if this connection is being brought up due to a DODCallout
  483. //
  484. pAdapter = pInterface->pAdapter;
  485. if(pAdapter isnot NULL)
  486. {
  487. //
  488. // We have an adapter and we need to lock it. However
  489. // we cant lock it till we unlock the interface
  490. // So we let go of the interface lock, but dont deref
  491. //
  492. RtReleaseSpinLockFromDpcLevel(&(pInterface->rlLock));
  493. //
  494. // Acquire the adapter lock
  495. //
  496. RtAcquireSpinLockAtDpcLevel(&(pAdapter->rlLock));
  497. //
  498. // This adapter better be mapped to the above interface
  499. // because the only way to unmap an adapter is to delete it
  500. // or to get a LinkDown or a ConnFailure. All these cases are
  501. // mutually exclusive with LinkUp
  502. //
  503. RtAssert(pAdapter->pInterface is pInterface);
  504. RtAssert(pAdapter->byState is AS_MAPPED);
  505. ReferenceAdapter(pAdapter);
  506. //
  507. // Go back and lock the interface
  508. //
  509. RtAcquireSpinLockAtDpcLevel(&(pInterface->rlLock));
  510. RtAssert(pInterface->dwOperState is IF_OPER_STATUS_CONNECTING);
  511. }
  512. else
  513. {
  514. //
  515. // So we dont have an adapter...
  516. // This function MUST be called at PASSIVE
  517. //
  518. RtReleaseSpinLock(&(pInterface->rlLock),
  519. kiIrql);
  520. pAdapter = WanpFindAdapterToMap(DU_ROUTER,
  521. &kiIrql,
  522. pInterface->dwRsvdAdapterIndex,
  523. &usTempName);
  524. if(pAdapter is NULL)
  525. {
  526. DereferenceInterface(pInterface);
  527. WanpDeleteConnEntry(pConnEntry);
  528. FreeNotification(pMsg);
  529. ExitDriverCode();
  530. return NDIS_STATUS_RESOURCES;
  531. }
  532. //
  533. // Got the adapter, lock the interface. We are at
  534. // DPC since the adapter is locked
  535. //
  536. RtAcquireSpinLockAtDpcLevel(&(pInterface->rlLock));
  537. }
  538. //
  539. // Interface and adapter refcounted and locked
  540. //
  541. pMsg->wnMsg.ddeEvent = DDE_INTERFACE_CONNECTED;
  542. pMsg->wnMsg.dwUserIfIndex = pInterface->dwIfIndex;
  543. pMsg->wnMsg.dwAdapterIndex = pInterface->dwRsvdAdapterIndex;
  544. pMsg->wnMsg.dwLocalMask = pLinkInfo->dwLocalMask;
  545. pMsg->wnMsg.dwLocalAddr = pLinkInfo->dwLocalAddr;
  546. pMsg->wnMsg.dwRemoteAddr = pLinkInfo->dwRemoteAddr;
  547. pMsg->wnMsg.fDefaultRoute = pLinkInfo->fDefaultRoute;
  548. break;
  549. }
  550. default:
  551. {
  552. RtAssert(FALSE);
  553. WanpDeleteConnEntry(pConnEntry);
  554. ExitDriverCode();
  555. return STATUS_INVALID_PARAMETER;
  556. }
  557. }
  558. //
  559. // At this point we have a locked and refcounted adapter
  560. // The adapter has been moved to the MAPPED adapter list
  561. // We also have a locked and recfounted interface
  562. // pConnEntry points to a CONN_ENTRY which is in the table but
  563. // is neither locked nor refcounted
  564. //
  565. Trace(CONN, INFO,
  566. ("LinkUpIndication: Found adapter %x to map to i/f %x %d\n",
  567. pAdapter, pInterface, pInterface->dwIfIndex));
  568. #if DBG
  569. Trace(CONN, INFO,
  570. ("LinkUpIndication: Adapter Name is %s\n",
  571. pAdapter->asDeviceNameA.Buffer));
  572. #endif
  573. if(pLinkInfo->duUsage isnot DU_CALLIN)
  574. {
  575. //
  576. // Set the cross mappings between the interface and the adapter
  577. //
  578. pAdapter->pInterface = pInterface;
  579. pInterface->pAdapter = pAdapter;
  580. pAdapter->byState = AS_MAPPED;
  581. pInterface->dwOperState = IF_OPER_STATUS_CONNECTED;
  582. pInterface->dwLastChange= GetTimeTicks();
  583. //
  584. // Put a refcount on both the adapter and the interface
  585. // because the mapping stored pointers to them
  586. //
  587. ReferenceAdapter(pAdapter);
  588. ReferenceInterface(pInterface);
  589. //
  590. // Set the lock in the conn entry
  591. //
  592. pConnEntry->prlLock = &(pAdapter->rlLock);
  593. //
  594. // Non Client adapters store a pointer to the connection entry
  595. // However we dont ref the conn entry for that
  596. //
  597. pAdapter->pConnEntry = pConnEntry;
  598. }
  599. else
  600. {
  601. //
  602. // For callin, the mappings are already set up
  603. //
  604. RtAssert(pAdapter->pInterface is pInterface);
  605. RtAssert(pInterface->pAdapter is pAdapter);
  606. RtAssert(pInterface->dwOperState is IF_OPER_STATUS_CONNECTED);
  607. }
  608. RtlZeroMemory(pInfoBuffer->DeviceName.Buffer,
  609. pInfoBuffer->DeviceName.MaximumLength);
  610. //
  611. // Copy the adapter(device) name into the buffer.
  612. //
  613. RtAssert(pAdapter->usDeviceNameW.Length <= pInfoBuffer->DeviceName.MaximumLength);
  614. pInfoBuffer->DeviceName.Length = pAdapter->usDeviceNameW.Length;
  615. RtlCopyMemory(pInfoBuffer->DeviceName.Buffer,
  616. pAdapter->usDeviceNameW.Buffer,
  617. pAdapter->usDeviceNameW.Length);
  618. //
  619. // Copy out the connection index for this connection into NDISWAN's
  620. // LocalAddress - this will then be put in the DestAddr field by
  621. // NDISWAN in all the receive indications, and in the linkdown
  622. //
  623. InsertConnIndexInAddr(pInfoBuffer->LocalAddress,
  624. pConnEntry->ulSlotIndex);
  625. //
  626. // Set up the connection entry
  627. //
  628. pConnEntry->dwLocalMask = pLinkInfo->dwLocalMask;
  629. pConnEntry->dwLocalAddr = pLinkInfo->dwLocalAddr;
  630. pConnEntry->dwRemoteAddr = pLinkInfo->dwRemoteAddr;
  631. pConnEntry->ulMtu = pInfoBuffer->MaximumTotalSize;
  632. pConnEntry->ulSpeed = pInfoBuffer->LinkSpeed * 100L;
  633. pConnEntry->bFilterNetBios = (pLinkInfo->fFilterNetBios == 1);
  634. pConnEntry->byState = CS_CONNECTED;
  635. RtAssert(pConnEntry->duUsage is pLinkInfo->duUsage);
  636. pConnEntry->pvIpLinkContext = NULL;
  637. //
  638. // Map the entry to the adapter
  639. // Because of the stored pointer, refcount the adapter
  640. //
  641. pConnEntry->pAdapter = pAdapter;
  642. ReferenceAdapter(pAdapter);
  643. //
  644. // Initialize the prebuilt ethernet header
  645. // First zero out the source address in the ethernet header
  646. //
  647. RtlZeroMemory(pConnEntry->ehHeader.rgbySourceAddr,
  648. ARP_802_ADDR_LENGTH);
  649. //
  650. // Put our context in the right place in the ethernet source
  651. // address
  652. //
  653. InsertConnIndexInAddr(pConnEntry->ehHeader.rgbySourceAddr,
  654. pConnEntry->ulSlotIndex);
  655. //
  656. // Refcount the connentry because it lies in the connection table,
  657. // NDISWAN has a "pointer" to it and because pAdapter->pConnEntry
  658. // may have a pointer to it.
  659. // NOTE: since we keep only one ref for all these conditions, all the
  660. // pointer must be cleared in the same function with the connection
  661. // locked
  662. //
  663. ReferenceConnEntry(pConnEntry);
  664. pConnEntry->ehHeader.wType = RtlUshortByteSwap(ARP_ETYPE_IP);
  665. //
  666. // A send is from WANARP -> NDISWAN so put the NDISWAN context in
  667. // the DEST address of our prebuilt ethernet header
  668. //
  669. RtlCopyMemory(pConnEntry->ehHeader.rgbyDestAddr,
  670. pInfoBuffer->RemoteAddress,
  671. ARP_802_ADDR_LENGTH);
  672. //
  673. // For a router connection, tell router manager about it
  674. //
  675. if(pLinkInfo->duUsage is DU_ROUTER)
  676. {
  677. //
  678. // If there are packets queued to the interface, drain them now
  679. //
  680. WanpTransmitQueuedPackets(pAdapter,
  681. pInterface,
  682. pConnEntry,
  683. kiIrql);
  684. //
  685. // Let Router Manager know of a new connection
  686. //
  687. WanpCompleteIrp(pMsg);
  688. }
  689. else
  690. {
  691. //
  692. // Done with the interfaces. We can unlock them now
  693. // Router interfaces are unlocked in WanpSendPackets which
  694. // is called from WanpTransmitQueuedPackets
  695. //
  696. RtReleaseSpinLockFromDpcLevel(&(pInterface->rlLock));
  697. RtReleaseSpinLock(&(pAdapter->rlLock),
  698. kiIrql);
  699. if(pLinkInfo->duUsage is DU_CALLOUT)
  700. {
  701. //
  702. // Complete the IRP to the router manager (or queue if no IRPs
  703. // are pending)
  704. //
  705. WanpCompleteIrp(pMsg);
  706. }
  707. }
  708. //
  709. // Need to make this call without holding locks.
  710. // We can let go of the locks since we wont get any NDIS layer
  711. // calls for this connection till this function completes and
  712. // the IP and IOCTL interface functions can be handled with no
  713. // consistency problems
  714. //
  715. if(pLinkInfo->duUsage isnot DU_CALLIN)
  716. {
  717. //
  718. // Notify upper layer of mtu change
  719. //
  720. mtuChangeInfo.lmc_mtu = pConnEntry->ulMtu;
  721. speedChangeInfo.lsc_speed = pConnEntry->ulSpeed;
  722. g_pfnIpStatus(pAdapter->pvIpContext,
  723. LLIP_STATUS_MTU_CHANGE,
  724. &mtuChangeInfo,
  725. sizeof(LLIPMTUChange),
  726. NULL);
  727. g_pfnIpStatus(pConnEntry->pAdapter->pvIpContext,
  728. LLIP_STATUS_SPEED_CHANGE,
  729. &speedChangeInfo,
  730. sizeof(LLIPSpeedChange),
  731. pConnEntry->pvIpLinkContext);
  732. }
  733. else
  734. {
  735. isStatus = g_pfnIpAddLink(pAdapter->pvIpContext,
  736. pConnEntry->dwRemoteAddr,
  737. pConnEntry,
  738. &(pConnEntry->pvIpLinkContext),
  739. pConnEntry->ulMtu);
  740. if(isStatus isnot IP_SUCCESS)
  741. {
  742. Trace(CONN, ERROR,
  743. ("LinkUpIndication: IpAddLink returned %x\n",
  744. isStatus));
  745. RtlZeroMemory(pInfoBuffer->DeviceName.Buffer,
  746. pInfoBuffer->DeviceName.MaximumLength);
  747. pInfoBuffer->DeviceName.Length = 0;
  748. RtlZeroMemory(pInfoBuffer->LocalAddress,
  749. ARP_802_ADDR_LENGTH);
  750. //
  751. // Just deref the connection entry
  752. // This will clear up everything
  753. //
  754. DereferenceConnEntry(pConnEntry);
  755. }
  756. else
  757. {
  758. //
  759. // Reference it once for the fact that we now have this entry
  760. // with IP
  761. //
  762. ReferenceConnEntry(pConnEntry);
  763. }
  764. }
  765. //
  766. // Done with the interface and adapter. Dereference them now because
  767. // the Find..() functions put a reference on them
  768. //
  769. DereferenceAdapter(pAdapter);
  770. DereferenceInterface(pInterface);
  771. ExitDriverCode();
  772. return NDIS_STATUS_SUCCESS;
  773. }
  774. NDIS_STATUS
  775. WanpLinkDownIndication(
  776. PNDIS_WAN_LINE_DOWN pInfoBuffer
  777. )
  778. /*++
  779. Routine Description:
  780. Locks:
  781. Arguments:
  782. Return Value:
  783. --*/
  784. {
  785. PADAPTER pAdapter;
  786. PUMODE_INTERFACE pInterface;
  787. KIRQL kiIrql;
  788. PCONN_ENTRY pConnEntry;
  789. ULONG ulIndex;
  790. PPENDING_NOTIFICATION pMsg;
  791. TraceEnter(CONN, "LinkDownIndication");
  792. ulIndex = GetConnIndexFromAddr(pInfoBuffer->LocalAddress);
  793. Trace(CONN, INFO,
  794. ("WanpLinkDowIndication: index %d\n", ulIndex));
  795. //
  796. // Lock out the connection entry
  797. //
  798. RtAcquireSpinLock(&g_rlConnTableLock,
  799. &kiIrql);
  800. pConnEntry = GetConnEntryGivenIndex(ulIndex);
  801. if(pConnEntry is NULL)
  802. {
  803. Trace(CONN, ERROR,
  804. ("LinkDownIndication: No entry in slot %d\n",
  805. ulIndex));
  806. RtReleaseSpinLock(&g_rlConnTableLock,
  807. kiIrql);
  808. return NDIS_STATUS_SUCCESS;
  809. }
  810. //
  811. // Lock the connection entry or adapter
  812. //
  813. RtAcquireSpinLockAtDpcLevel(pConnEntry->prlLock);
  814. //
  815. // Done with the connection table
  816. //
  817. RtReleaseSpinLockFromDpcLevel(&g_rlConnTableLock);
  818. //
  819. // Mark this connection/adapter as disconnecting
  820. // We can reference these field of the CONN_ENTRY since they cant
  821. // change during its lifetime
  822. //
  823. pAdapter = pConnEntry->pAdapter;
  824. RtAssert(pAdapter);
  825. RtAssert(pAdapter->byState is AS_MAPPED);
  826. pInterface = pAdapter->pInterface;
  827. pMsg = NULL;
  828. if(pInterface->duUsage is DU_CALLIN)
  829. {
  830. IP_STATUS isStatus;
  831. //
  832. // Client connection. This means we have the connection entry
  833. // locked, but the adapter is unlocked
  834. //
  835. pConnEntry->byState = CS_DISCONNECTING;
  836. RtReleaseSpinLock(pConnEntry->prlLock,
  837. kiIrql);
  838. isStatus = g_pfnIpDeleteLink(g_pServerAdapter->pvIpContext,
  839. pConnEntry->pvIpLinkContext);
  840. if(isStatus isnot IP_SUCCESS)
  841. {
  842. Trace(CONN, ERROR,
  843. ("LinkDownIndication: IpDeleteLink returned %x\n",
  844. isStatus));
  845. //
  846. // This is really bad
  847. //
  848. RtAssert(FALSE);
  849. }
  850. }
  851. else
  852. {
  853. //
  854. // Here we have the adapter locked
  855. // The connection entry is protected by the same lock
  856. //
  857. pConnEntry->byState = CS_DISCONNECTING;
  858. //
  859. // Free the interface mapping
  860. //
  861. pAdapter->pInterface = NULL;
  862. pAdapter->byState = AS_UNMAPPING;
  863. //
  864. // Lock the interface list and the interface
  865. // The interface has to be present since it is ref counted
  866. //
  867. EnterWriterAtDpcLevel(&g_rwlIfLock);
  868. RtAcquireSpinLockAtDpcLevel(&(pInterface->rlLock));
  869. //
  870. // Clear out the adapter field.
  871. //
  872. pInterface->pAdapter = NULL;
  873. pInterface->dwOperState = IF_OPER_STATUS_DISCONNECTED;
  874. pInterface->dwLastChange= GetTimeTicks();
  875. pMsg = AllocateNotification();
  876. if(pMsg is NULL)
  877. {
  878. Trace(CONN, ERROR,
  879. ("LinkDownIndication: Couldnt allocate msg\n"));
  880. //
  881. // Really no failure path here
  882. //
  883. RtAssert(FALSE);
  884. }
  885. if(pInterface->duUsage is DU_CALLOUT)
  886. {
  887. if(pMsg)
  888. {
  889. //
  890. // Setup the message
  891. //
  892. pMsg->wnMsg.ddeEvent = DDE_CALLOUT_LINKDOWN;
  893. pMsg->wnMsg.dwAdapterIndex = pInterface->dwRsvdAdapterIndex;
  894. pMsg->wnMsg.dwUserIfIndex = INVALID_IF_INDEX;
  895. pMsg->wnMsg.dwAdapterIndex = pAdapter->dwAdapterIndex;
  896. pMsg->wnMsg.dwLocalAddr = pConnEntry->dwLocalAddr;
  897. pMsg->wnMsg.dwLocalMask = pConnEntry->dwLocalMask;
  898. pMsg->wnMsg.dwRemoteAddr = pConnEntry->dwRemoteAddr;
  899. }
  900. //
  901. // Remove from list and dereference the interface
  902. //
  903. RemoveEntryList(&(pInterface->leIfLink));
  904. InterlockedDecrement(&g_ulNumDialOutInterfaces);
  905. //
  906. // Done with the interface list
  907. //
  908. ExitWriterFromDpcLevel(&g_rwlIfLock);
  909. //
  910. // One ref kept for being on list
  911. // The final deletion will free the index
  912. //
  913. DereferenceInterface(pInterface);
  914. }
  915. else
  916. {
  917. //
  918. // Dont need the interface list lock
  919. //
  920. ExitWriterFromDpcLevel(&g_rwlIfLock);
  921. Trace(CONN, TRACE,
  922. ("LinkDownIndication: For interface %p\n",
  923. pInterface));
  924. //
  925. // For ROUTER interfaces notify user mode of the connection
  926. // going down
  927. //
  928. if(pMsg)
  929. {
  930. //
  931. // Setup the message
  932. //
  933. pMsg->wnMsg.ddeEvent = DDE_INTERFACE_DISCONNECTED;
  934. pMsg->wnMsg.dwAdapterIndex = pInterface->dwRsvdAdapterIndex;
  935. pMsg->wnMsg.dwUserIfIndex = pInterface->dwIfIndex;
  936. pMsg->wnMsg.dwAdapterIndex = pAdapter->dwAdapterIndex;
  937. pMsg->wnMsg.dwLocalAddr = pConnEntry->dwLocalAddr;
  938. pMsg->wnMsg.dwLocalMask = pConnEntry->dwLocalMask;
  939. pMsg->wnMsg.dwRemoteAddr = pConnEntry->dwRemoteAddr;
  940. }
  941. }
  942. //
  943. // Done with the interface and adapter
  944. //
  945. RtReleaseSpinLockFromDpcLevel(&(pInterface->rlLock));
  946. RtReleaseSpinLock(&(pAdapter->rlLock),
  947. kiIrql);
  948. //
  949. // Deref the adapter because it was mapped to the interface
  950. //
  951. DereferenceAdapter(pAdapter);
  952. //
  953. // Deref the interface because it was mapped to the adapter
  954. //
  955. DereferenceInterface(pInterface);
  956. }
  957. //
  958. // Dereference the connection entry twice. Once because NDISWAN is
  959. // removing the connection, and again because GetConnEntry put a
  960. // reference on it
  961. //
  962. DereferenceConnEntry(pConnEntry);
  963. DereferenceConnEntry(pConnEntry);
  964. if(pMsg)
  965. {
  966. //
  967. // Will be non null only for callout where allocation succeeded
  968. //
  969. WanpCompleteIrp(pMsg);
  970. }
  971. return NDIS_STATUS_SUCCESS;
  972. }
  973. UINT
  974. WanDemandDialRequest(
  975. ROUTE_CONTEXT Context,
  976. IPAddr dwDest,
  977. IPAddr dwSource,
  978. BYTE byProtocol,
  979. PBYTE pbyBuffer,
  980. UINT uiLength,
  981. IPAddr dwHdrSrc
  982. )
  983. /*++
  984. Routine Description:
  985. This function services the request by IP to dial out an interface.
  986. IP passes us the context stored within the route. This context is
  987. nothing but the index of the interface to dial.
  988. We first find the interface. If found, we see if the interface is
  989. already mapped. This can happen in some window of time. In such a case
  990. we simply return the adapter mapped to the interface. Otherwise, we
  991. find a free adapter. We map this adapter to the interface and
  992. complete an IRP to the router manager to ask it to connect the interface.
  993. We set the state on the interface and the adapter to reflect the fact
  994. that they are mapped and awaiting connection.
  995. If we dont find a free adapter, we nevertheless ask the router manager
  996. to dial out the interface, but we fail the demand dial request to IP.
  997. We return the adapter (IP) index of the adapter that was mapped.
  998. Locks:
  999. Acquires the g_rwlIfLock as READER to lock out the interface
  1000. The release the g_rwlIfLock and acquires the g_rwlAdapterlock to
  1001. lock out a free adapter. (NOTE: DOES NOT FOLLOW adapter->interface
  1002. hierarchy)
  1003. Arguments:
  1004. Context
  1005. dwDest
  1006. dwSource
  1007. byProtocol
  1008. pbyBuffer
  1009. uiLength
  1010. Return Value:
  1011. The adapter of the index mapped
  1012. INVALID_IF_INDEX on failure
  1013. --*/
  1014. {
  1015. PADAPTER pAdapter;
  1016. PPENDING_NOTIFICATION pMsg;
  1017. PUMODE_INTERFACE pInterface;
  1018. KIRQL kiIrql;
  1019. DWORD dwAdapterIndex;
  1020. PLIST_ENTRY pleNode;
  1021. TraceEnter(CONN, "DemandDialRequest");
  1022. EnterWriter(&g_rwlAdapterLock,
  1023. &kiIrql);
  1024. EnterReaderAtDpcLevel(&g_rwlIfLock);
  1025. pInterface = WanpFindInterfaceGivenIndex(Context);
  1026. if(pInterface is NULL)
  1027. {
  1028. ExitReaderFromDpcLevel(&g_rwlIfLock);
  1029. ExitWriter(&g_rwlAdapterLock,
  1030. kiIrql);
  1031. Trace(CONN, ERROR,
  1032. ("DemandDialRequest: Couldnt find interface %d\n",
  1033. Context));
  1034. TraceLeave(CONN, "DemandDialRequest");
  1035. return INVALID_IF_INDEX;
  1036. }
  1037. ExitReaderFromDpcLevel(&g_rwlIfLock);
  1038. Trace(CONN, TRACE,
  1039. ("DemandDialRequest: For interface %p\n",
  1040. pInterface));
  1041. //
  1042. // If the interface is already connected, this is just race condition
  1043. //
  1044. if(pInterface->dwOperState >= IF_OPER_STATUS_CONNECTING)
  1045. {
  1046. Trace(CONN, WARN,
  1047. ("DemandDialRequest: I/f state %d, returning old adapter %p\n",
  1048. pInterface->dwOperState,
  1049. pInterface->pAdapter));
  1050. if(pInterface->pAdapter)
  1051. {
  1052. //
  1053. // We can get the adapter index without the holding the adapter
  1054. // lock , because it is a read-only field once the adapter has
  1055. // been added to IP, and can not change while the adapter is
  1056. // is mapped to the interface
  1057. //
  1058. RtAssert(pInterface->pAdapter->dwAdapterIndex is pInterface->dwRsvdAdapterIndex);
  1059. dwAdapterIndex = pInterface->dwRsvdAdapterIndex;
  1060. }
  1061. else
  1062. {
  1063. dwAdapterIndex = INVALID_IF_INDEX;
  1064. }
  1065. RtReleaseSpinLockFromDpcLevel(&(pInterface->rlLock));
  1066. ExitWriter(&g_rwlAdapterLock,
  1067. kiIrql);
  1068. DereferenceInterface(pInterface);
  1069. TraceLeave(CONN, "DemandDialRequest");
  1070. return dwAdapterIndex;
  1071. }
  1072. //
  1073. // We will need to connect this. If we cant get the memory
  1074. // needed for the connection message, bail out
  1075. //
  1076. pMsg = AllocateNotification();
  1077. if(pMsg is NULL)
  1078. {
  1079. Trace(CONN, ERROR,
  1080. ("DemandDialRequest: Couldnt allocate notification\n"));
  1081. RtReleaseSpinLockFromDpcLevel(&(pInterface->rlLock));
  1082. ExitWriter(&g_rwlAdapterLock,
  1083. kiIrql);
  1084. DereferenceInterface(pInterface);
  1085. TraceLeave(CONN, "DemandDialRequest");
  1086. return INVALID_IF_INDEX;
  1087. }
  1088. pInterface->dwOperState = IF_OPER_STATUS_CONNECTING;
  1089. pInterface->dwLastChange= GetTimeTicks();
  1090. //
  1091. // So we dont have an adapter mapped to the interface. Try and find one
  1092. // We dont call FindAdapterToMap because that needs to be at passive
  1093. //
  1094. if(IsListEmpty(&g_leAddedAdapterList))
  1095. {
  1096. Trace(CONN, INFO,
  1097. ("DemandDialRequest: Couldnt find an adapter already added to IP\n"));
  1098. ExitWriterFromDpcLevel(&g_rwlAdapterLock);
  1099. pAdapter = NULL;
  1100. dwAdapterIndex = INVALID_IF_INDEX;
  1101. }
  1102. else
  1103. {
  1104. pleNode = RemoveHeadList(&g_leAddedAdapterList);
  1105. pAdapter = CONTAINING_RECORD(pleNode,
  1106. ADAPTER,
  1107. leAdapterLink);
  1108. RtAcquireSpinLockAtDpcLevel(&(pAdapter->rlLock));
  1109. InsertHeadList(&g_leMappedAdapterList,
  1110. &(pAdapter->leAdapterLink));
  1111. ExitWriterFromDpcLevel(&g_rwlAdapterLock);
  1112. RtAssert(pAdapter->byState is AS_ADDED);
  1113. //
  1114. // So we have a locked adapter
  1115. //
  1116. dwAdapterIndex = pAdapter->dwAdapterIndex;
  1117. //
  1118. // Map the adapter to the interface and refcount the adapter
  1119. // to account for the fact that there is a stored pointer to it
  1120. //
  1121. pInterface->pAdapter = pAdapter;
  1122. ReferenceAdapter(pAdapter);
  1123. //
  1124. // Setup the cross mapping
  1125. //
  1126. pAdapter->pInterface = pInterface;
  1127. pAdapter->byState = AS_MAPPED;
  1128. ReferenceInterface(pInterface);
  1129. Trace(CONN, INFO,
  1130. ("DemandDialRequest: Found adapter %d free for %d\n",
  1131. pAdapter->dwAdapterIndex,
  1132. pInterface->dwIfIndex));
  1133. #if DBG
  1134. Trace(CONN, INFO,
  1135. ("DemandDialRequest: Adapter Index is %d. Name is %s\n",
  1136. pAdapter->dwAdapterIndex,
  1137. pAdapter->asDeviceNameA.Buffer));
  1138. #endif
  1139. }
  1140. //
  1141. // Initialize the info to be sent to the router manager
  1142. //
  1143. pMsg->wnMsg.ddeEvent = DDE_CONNECT_INTERFACE;
  1144. pMsg->wnMsg.dwUserIfIndex = pInterface->dwIfIndex;
  1145. pMsg->wnMsg.dwAdapterIndex = dwAdapterIndex;
  1146. pMsg->wnMsg.dwPacketSrcAddr = dwHdrSrc;
  1147. pMsg->wnMsg.dwPacketDestAddr = dwDest;
  1148. pMsg->wnMsg.ulPacketLength = uiLength;
  1149. pMsg->wnMsg.byPacketProtocol = byProtocol;
  1150. if(uiLength)
  1151. {
  1152. RtlCopyMemory(pMsg->wnMsg.rgbyPacket,
  1153. pbyBuffer,
  1154. MIN(MAX_PACKET_COPY_SIZE,uiLength));
  1155. }
  1156. //
  1157. // Complete any pending IRP or queue the notification
  1158. //
  1159. ExInitializeWorkItem(&pMsg->wqi,
  1160. WanpCompleteIrp,
  1161. pMsg);
  1162. ExQueueWorkItem(&pMsg->wqi,
  1163. DelayedWorkQueue);
  1164. // WanpCompleteIrp(pMsg);
  1165. //
  1166. // Ok so we are done with the adapter and the interface
  1167. //
  1168. RtReleaseSpinLockFromDpcLevel(&(pInterface->rlLock));
  1169. DereferenceInterface(pInterface);
  1170. if(pAdapter)
  1171. {
  1172. RtReleaseSpinLock(&(pAdapter->rlLock),
  1173. kiIrql);
  1174. }
  1175. else
  1176. {
  1177. KeLowerIrql(kiIrql);
  1178. }
  1179. //
  1180. // No need to deref the adapter, since we didnt call FindAdapter
  1181. //
  1182. Trace(CONN, INFO,
  1183. ("DemandDialRequest: Returning adapter %d\n",
  1184. dwAdapterIndex));
  1185. return dwAdapterIndex;
  1186. }
  1187. PCONN_ENTRY
  1188. WanpCreateConnEntry(
  1189. DIAL_USAGE duUsage
  1190. )
  1191. /*++
  1192. Routine Description:
  1193. Allocate a connection entry and find a free slot for it in the
  1194. connection table. Sets the slot into the conn entry
  1195. The connection entry returned is not refcounted.
  1196. Locks:
  1197. Must be called with the g_rlConnTableLock held.
  1198. Arguments:
  1199. duUsage Type of the connection.
  1200. Return Value:
  1201. Pointer to allocate conn entry (if successfull)
  1202. --*/
  1203. {
  1204. PCONN_ENTRY pConnEntry;
  1205. KIRQL kiIrql;
  1206. PULONG_PTR puipTable;
  1207. ULONG ulSize;
  1208. ULONG i, ulIndex;
  1209. TraceEnter(CONN, "CreateConnEntry");
  1210. pConnEntry = AllocateConnection();
  1211. if(pConnEntry is NULL)
  1212. {
  1213. return NULL;
  1214. }
  1215. RtlZeroMemory(pConnEntry,
  1216. sizeof(CONN_ENTRY));
  1217. //
  1218. // The refcount of a connection entry is set to 0 and not 1
  1219. //
  1220. InitConnEntryRefCount(pConnEntry);
  1221. pConnEntry->byState = CS_CONNECTING;
  1222. pConnEntry->duUsage = duUsage;
  1223. //
  1224. // Find a free slot. g_ulNextIndex is a hint
  1225. //
  1226. for(i = 0, ulIndex = g_ulNextConnIndex;
  1227. i < g_ulConnTableSize;
  1228. i++)
  1229. {
  1230. //
  1231. // Slot 0 is initialized to (ULONG_PTR)-1 so it cant match
  1232. //
  1233. if(g_puipConnTable[ulIndex] is (ULONG_PTR)0)
  1234. {
  1235. //
  1236. // Free Slot
  1237. //
  1238. g_puipConnTable[ulIndex] = (ULONG_PTR)pConnEntry;
  1239. g_rgulConns[duUsage]++;
  1240. pConnEntry->ulSlotIndex = ulIndex;
  1241. //
  1242. // We just assume that the next one will be free
  1243. // If not, the timer can fix it. If we get a connection before
  1244. // the timer gets a chance to fix it then we will take a
  1245. // perf hit
  1246. //
  1247. g_ulNextConnIndex++;
  1248. g_ulNextConnIndex = g_ulNextConnIndex % g_ulConnTableSize;
  1249. return pConnEntry;
  1250. }
  1251. ulIndex++;
  1252. //
  1253. // Wrap around
  1254. //
  1255. ulIndex = ulIndex % g_ulConnTableSize;
  1256. }
  1257. //
  1258. // Couldnt find a slot. Grow the table. We are still holding the
  1259. // lock. The way we do this is by growing the table in blocks of
  1260. // 64 entries. We then copy out what we have and update the next index
  1261. // etc
  1262. //
  1263. ulSize = (g_ulConnTableSize + WAN_CONN_TABLE_INCREMENT) * sizeof(ULONG_PTR);
  1264. puipTable = RtAllocate(NonPagedPool,
  1265. ulSize,
  1266. WAN_CONN_TAG);
  1267. if(puipTable is NULL)
  1268. {
  1269. Trace(CONN, ERROR,
  1270. ("AllocateConnEntry: couldnt realloc table of size %d\n",
  1271. ulSize));
  1272. FreeConnection(pConnEntry);
  1273. return NULL;
  1274. }
  1275. //
  1276. // Zero out the new memory
  1277. //
  1278. RtlZeroMemory(puipTable,
  1279. ulSize);
  1280. //
  1281. // Copy out the old table
  1282. //
  1283. RtlCopyMemory(puipTable,
  1284. g_puipConnTable,
  1285. g_ulConnTableSize * sizeof(ULONG_PTR));
  1286. //
  1287. // Free the old table
  1288. //
  1289. RtFree(g_puipConnTable);
  1290. //
  1291. // Set up pointers, indices etc
  1292. //
  1293. g_puipConnTable = puipTable;
  1294. //
  1295. // Since the table was totally full, the next index will be
  1296. // at the start of the new memory. Set the entry to that
  1297. //
  1298. g_puipConnTable[g_ulConnTableSize] = (ULONG_PTR)pConnEntry;
  1299. g_rgulConns[duUsage]++;
  1300. pConnEntry->ulSlotIndex = g_ulConnTableSize;
  1301. //
  1302. // Set the next index to one after the slot we just used
  1303. //
  1304. g_ulNextConnIndex = g_ulConnTableSize + 1;
  1305. //
  1306. // Increast the size to what is currently is
  1307. //
  1308. g_ulConnTableSize += WAN_CONN_TABLE_INCREMENT;
  1309. return pConnEntry;
  1310. }
  1311. VOID
  1312. WanIpCloseLink(
  1313. PVOID pvAdapterContext,
  1314. PVOID pvLinkContext
  1315. )
  1316. /*++
  1317. Routine Description:
  1318. This function is called by IP when its ref counts on the link fall
  1319. to 0.
  1320. Locks:
  1321. None needed
  1322. Arguments:
  1323. pvAdapterContext The context we passed for the P2MP interface
  1324. pvLinkContext The context we passed for a link in IpAddLink()
  1325. Return Value:
  1326. None
  1327. --*/
  1328. {
  1329. PCONN_ENTRY pConnEntry;
  1330. KIRQL kiIrql;
  1331. TraceEnter(CONN, "IpCloseLink");
  1332. RtAssert(pvAdapterContext is g_pServerAdapter);
  1333. pConnEntry = (PCONN_ENTRY)pvLinkContext;
  1334. #if DBG
  1335. RtAcquireSpinLock(pConnEntry->prlLock, &kiIrql);
  1336. pConnEntry->byState = CS_IP_DELETED_LINK;
  1337. RtReleaseSpinLock(pConnEntry->prlLock, kiIrql);
  1338. #endif
  1339. DereferenceConnEntry(pConnEntry);
  1340. }
  1341. VOID
  1342. WanpDeleteConnEntry(
  1343. PCONN_ENTRY pConnEntry
  1344. )
  1345. /*++
  1346. Routine Description:
  1347. This function is called when the refcount on a connection falls to zero
  1348. The connection entry is different from the other structures in wanarp
  1349. in that even when the refcount falls to zero, the pAdapter has a
  1350. pointer to the connection. However when we get here we know that
  1351. no new sends could be forthcoming on this connection because we
  1352. set the connection state to be disconnecting. We have already
  1353. gotten a LinkDown indication on this and all our pending SendComplete's
  1354. have been called
  1355. We also sets the next free index for the connection table
  1356. No shrinking is done here because we do that off a timer
  1357. Locks:
  1358. Acquires the g_rlConnTableLock. The connection entry itself should
  1359. not be locked
  1360. Arguments:
  1361. pConnEntry The connection entry to free
  1362. Return Value:
  1363. None
  1364. --*/
  1365. {
  1366. ULONG ulIndex;
  1367. KIRQL kiIrql;
  1368. PULONG_PTR puipTable;
  1369. SIZE_T stSize;
  1370. PADAPTER pAdapter;
  1371. //
  1372. // Get the slot number
  1373. //
  1374. ulIndex = pConnEntry->ulSlotIndex;
  1375. RtAcquireSpinLock(&g_rlConnTableLock,
  1376. &kiIrql);
  1377. g_puipConnTable[ulIndex] = (ULONG_PTR)0;
  1378. #if DBG
  1379. RtAssert((pConnEntry->duUsage is DU_CALLIN) or
  1380. (pConnEntry->duUsage is DU_CALLOUT) or
  1381. (pConnEntry->duUsage is DU_ROUTER));
  1382. #endif
  1383. g_rgulConns[pConnEntry->duUsage]--;
  1384. if(g_puipConnTable[g_ulNextConnIndex] isnot (ULONG_PTR)0)
  1385. {
  1386. g_ulNextConnIndex = ulIndex;
  1387. }
  1388. RtReleaseSpinLockFromDpcLevel(&g_rlConnTableLock);
  1389. //
  1390. // Get the adapter this connection is mapped to
  1391. //
  1392. pAdapter = pConnEntry->pAdapter;
  1393. #if DBG
  1394. pConnEntry->ulSlotIndex = 0;
  1395. pConnEntry->pAdapter = NULL;
  1396. #endif
  1397. //
  1398. // Done with the connection entry
  1399. //
  1400. FreeConnection(pConnEntry);
  1401. if(pAdapter is NULL)
  1402. {
  1403. KeLowerIrql(kiIrql);
  1404. //
  1405. // Wasnt mapped. Can happen when this function is called to
  1406. // merely free resources from an error case
  1407. //
  1408. return;
  1409. }
  1410. //
  1411. // Lock the adapter list
  1412. //
  1413. EnterWriterAtDpcLevel(&g_rwlAdapterLock);
  1414. if(pAdapter is g_pServerAdapter)
  1415. {
  1416. ExitWriter(&g_rwlAdapterLock,
  1417. kiIrql);
  1418. //
  1419. // Client connection, simply deref the adapter
  1420. //
  1421. DereferenceAdapter(pAdapter);
  1422. return;
  1423. }
  1424. ExitWriterFromDpcLevel(&g_rwlAdapterLock);
  1425. //
  1426. // Lock the adapter
  1427. //
  1428. RtAcquireSpinLockAtDpcLevel(&(pAdapter->rlLock));
  1429. //
  1430. // Remove the entry from the adapter
  1431. //
  1432. pAdapter->pConnEntry = NULL;
  1433. //
  1434. // Done with the adapter
  1435. //
  1436. RtReleaseSpinLock(&(pAdapter->rlLock),
  1437. kiIrql);
  1438. //
  1439. // Called with no locks held
  1440. //
  1441. WanpUnmapAdapter(pAdapter);
  1442. //
  1443. // Dereference the adapter because the conn entry had a pointer
  1444. // to it, which is now gone
  1445. //
  1446. DereferenceAdapter(pAdapter);
  1447. return;
  1448. }
  1449. VOID
  1450. WanpNotifyRouterManager(
  1451. PPENDING_NOTIFICATION pMsg,
  1452. PUMODE_INTERFACE pInterface,
  1453. PADAPTER pAdapter,
  1454. PCONN_ENTRY pConnEntry,
  1455. BOOLEAN bConnected
  1456. )
  1457. /*++
  1458. Routine Description:
  1459. Notifies the router manager when an interface is connected or
  1460. disconnected
  1461. Locks:
  1462. The interface must be locked
  1463. Arguments:
  1464. pMsg
  1465. pInterface The interface being connected or disconnected
  1466. pAdapter
  1467. bConnected Set to TRUE if the interface is being connected
  1468. Return Value:
  1469. --*/
  1470. {
  1471. KIRQL kiIrql;
  1472. TraceEnter(CONN, "WanpNotifyRouterManager");
  1473. if(bConnected)
  1474. {
  1475. pMsg->wnMsg.ddeEvent = DDE_INTERFACE_CONNECTED;
  1476. }
  1477. else
  1478. {
  1479. pMsg->wnMsg.ddeEvent = DDE_INTERFACE_DISCONNECTED;
  1480. }
  1481. pMsg->wnMsg.dwUserIfIndex = pInterface->dwIfIndex;
  1482. pMsg->wnMsg.dwAdapterIndex = pAdapter->dwAdapterIndex;
  1483. pMsg->wnMsg.dwLocalAddr = pConnEntry->dwLocalAddr;
  1484. pMsg->wnMsg.dwLocalMask = pConnEntry->dwLocalMask;
  1485. pMsg->wnMsg.dwRemoteAddr = pConnEntry->dwRemoteAddr;
  1486. //
  1487. // Complete any pending IRP or queue the notification
  1488. //
  1489. WanpCompleteIrp(pMsg);
  1490. }
  1491. PCONN_ENTRY
  1492. WanpGetConnEntryGivenAddress(
  1493. DWORD dwAddress
  1494. )
  1495. {
  1496. ULONG i;
  1497. KIRQL kiIrql;
  1498. PCONN_ENTRY pConnEntry;
  1499. BOOLEAN bFindFirst;
  1500. pConnEntry = NULL;
  1501. RtAcquireSpinLock(&g_rlConnTableLock,
  1502. &kiIrql);
  1503. if((dwAddress is 0xFFFFFFFF) and
  1504. (g_rgulConns[DU_CALLIN] is 1))
  1505. {
  1506. bFindFirst = TRUE;
  1507. }
  1508. else
  1509. {
  1510. bFindFirst = FALSE;
  1511. }
  1512. //
  1513. // Slot 0 is never used
  1514. //
  1515. for(i = 1; i < g_ulConnTableSize; i++)
  1516. {
  1517. //
  1518. // If there is a non-null connection and
  1519. // If either the dest matches, or we want to send a bcast to the
  1520. // first client (that is fully connected)
  1521. //
  1522. if(((PCONN_ENTRY)(g_puipConnTable[i]) isnot NULL) and
  1523. ((((PCONN_ENTRY)(g_puipConnTable[i]))->dwRemoteAddr is dwAddress) or
  1524. (bFindFirst and
  1525. (((PCONN_ENTRY)(g_puipConnTable[i]))->duUsage is DU_CALLIN) and
  1526. (((PCONN_ENTRY)(g_puipConnTable[i]))->byState is CS_CONNECTED))))
  1527. {
  1528. pConnEntry = (PCONN_ENTRY)(g_puipConnTable[i]);
  1529. ReferenceConnEntry(pConnEntry);
  1530. if(pConnEntry->lRefCount < 2)
  1531. {
  1532. #if DBG
  1533. REF_HIST_ENTRY __rheTemp;
  1534. InterlockedIncrement((PLONG)&((pConnEntry)->dwTotalRefOps));
  1535. KeQuerySystemTime(&(__rheTemp.liChangeTime));
  1536. __rheTemp.dwFileSig = __FILE_SIG__;
  1537. __rheTemp.dwLine = __LINE__;
  1538. pConnEntry->rheHistory[(pConnEntry->dwTotalRefOps) % MAX_REF_HISTORY] =
  1539. __rheTemp;
  1540. InterlockedIncrement((PLONG) &g_dwSendsOnDeletedLink);
  1541. #endif
  1542. InterlockedDecrement((PLONG)&(pConnEntry->lRefCount));
  1543. pConnEntry = NULL;
  1544. }
  1545. break;
  1546. }
  1547. }
  1548. RtReleaseSpinLock(&g_rlConnTableLock,
  1549. kiIrql);
  1550. return pConnEntry;
  1551. }
  1552. ULONG
  1553. WanpRemoveAllConnections(
  1554. VOID
  1555. )
  1556. {
  1557. KIRQL kiIrql;
  1558. ULONG ulCount, i;
  1559. RtAcquireSpinLock(&g_rlConnTableLock,
  1560. &kiIrql);
  1561. //
  1562. // Slot 0 is never used
  1563. //
  1564. for(ulCount = 0, i = 1; i < g_ulConnTableSize; i++)
  1565. {
  1566. PCONN_ENTRY pConnEntry;
  1567. pConnEntry = (PCONN_ENTRY)(g_puipConnTable[i]);
  1568. if(pConnEntry is NULL)
  1569. {
  1570. continue;
  1571. }
  1572. g_rgulConns[pConnEntry->duUsage]--;
  1573. FreeConnection(pConnEntry);
  1574. ulCount++;
  1575. g_puipConnTable[i] = 0;
  1576. }
  1577. #if DBG
  1578. RtAssert((g_rgulConns[DU_CALLIN] + g_rgulConns[DU_CALLOUT] + g_rgulConns[DU_ROUTER]) is 0);
  1579. #endif
  1580. RtReleaseSpinLock(&g_rlConnTableLock,
  1581. kiIrql);
  1582. return ulCount;
  1583. }
  1584. BOOLEAN
  1585. WanpIsConnectionTableEmpty(
  1586. VOID
  1587. )
  1588. {
  1589. ULONG i;
  1590. KIRQL kiIrql;
  1591. RtAcquireSpinLock(&g_rlConnTableLock,
  1592. &kiIrql);
  1593. for(i = 1; i < g_ulConnTableSize; i++)
  1594. {
  1595. PCONN_ENTRY pConnEntry;
  1596. pConnEntry = (PCONN_ENTRY)(g_puipConnTable[i]);
  1597. if(pConnEntry isnot NULL)
  1598. {
  1599. RtAssert((g_rgulConns[DU_CALLIN] + g_rgulConns[DU_CALLOUT] + g_rgulConns[DU_ROUTER]) isnot 0);
  1600. RtReleaseSpinLock(&g_rlConnTableLock,
  1601. kiIrql);
  1602. return FALSE;
  1603. }
  1604. }
  1605. RtAssert((g_rgulConns[DU_CALLIN] + g_rgulConns[DU_CALLOUT] + g_rgulConns[DU_ROUTER]) is 0);
  1606. RtReleaseSpinLock(&g_rlConnTableLock,
  1607. kiIrql);
  1608. return TRUE;
  1609. }