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.

2268 lines
52 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. routing\ip\wanarp\ioctl.c
  5. Abstract:
  6. IOCTL handlers for wanarp
  7. Revision History:
  8. AmritanR
  9. --*/
  10. #define __FILE_SIG__ IOCTL_SIG
  11. #include "inc.h"
  12. NTSTATUS
  13. WanProcessNotification(
  14. PIRP pIrp,
  15. ULONG ulInLength,
  16. ULONG ulOutLength
  17. )
  18. /*++
  19. Routine Description:
  20. The handler for IOCTL_WANARP_NOTIFICATION. We see if we have some info
  21. we wish to return to the caller and if we do, we return it. Otherwise,
  22. we pend the IRP and use it later when we need to report an event to
  23. the user mode
  24. Locks:
  25. Acquires the IoCancelSpinLock
  26. Arguments:
  27. Return Value:
  28. STATUS_PENDING
  29. STATUS_SUCCESS
  30. STATUS_BUFFER_TOO_SMALL
  31. --*/
  32. {
  33. KIRQL kiIrql;
  34. PLIST_ENTRY pleNode;
  35. PVOID pvIoBuffer;
  36. PPENDING_NOTIFICATION pNotification;
  37. TraceEnter(CONN, "ProcessNotification");
  38. pvIoBuffer = pIrp->AssociatedIrp.SystemBuffer;
  39. pIrp->IoStatus.Information = 0;
  40. if((ulInLength < sizeof(WANARP_NOTIFICATION)) or
  41. (ulOutLength < sizeof(WANARP_NOTIFICATION)))
  42. {
  43. return STATUS_BUFFER_TOO_SMALL;
  44. }
  45. //
  46. // use cancel spin lock to prevent irp being cancelled during this call.
  47. //
  48. IoAcquireCancelSpinLock(&kiIrql);
  49. //
  50. // If we have a pending notification then complete it - else
  51. // queue the notification IRP
  52. //
  53. if(!IsListEmpty(&g_lePendingNotificationList))
  54. {
  55. //
  56. // We have some old info
  57. //
  58. Trace(GLOBAL, TRACE,
  59. ("ProcNotification: Pending notification being completed\n"));
  60. //
  61. // Remove it off the pending list
  62. //
  63. pleNode = RemoveHeadList(&g_lePendingNotificationList);
  64. //
  65. // Get a pointer to the structure
  66. //
  67. pNotification = CONTAINING_RECORD(pleNode,
  68. PENDING_NOTIFICATION,
  69. leNotificationLink);
  70. //
  71. // Copy out the event to the user mode buffer
  72. //
  73. RtlCopyMemory(pIrp->AssociatedIrp.SystemBuffer,
  74. &pNotification->wnMsg,
  75. sizeof(WANARP_NOTIFICATION));
  76. //
  77. // Mark the IRP as non pending (and hence non cancelable)
  78. //
  79. IoSetCancelRoutine(pIrp,
  80. NULL);
  81. //
  82. // Fill the irp info
  83. //
  84. pIrp->IoStatus.Information = sizeof(WANARP_NOTIFICATION);
  85. IoReleaseCancelSpinLock(kiIrql);
  86. //
  87. // Free the allocated notification
  88. //
  89. FreeNotification(pNotification);
  90. return STATUS_SUCCESS;
  91. }
  92. Trace(GLOBAL, TRACE,
  93. ("ProcNotification: Notification being queued\n"));
  94. //
  95. // Queue this IRP to use for later
  96. //
  97. //
  98. // Mark the irp as pending
  99. //
  100. IoMarkIrpPending(pIrp);
  101. //
  102. // Queue up the irp at the end
  103. //
  104. InsertTailList(&g_lePendingIrpList,
  105. &(pIrp->Tail.Overlay.ListEntry));
  106. //
  107. // Set the cancel routine
  108. //
  109. IoSetCancelRoutine(pIrp,
  110. WanCancelNotificationIrp);
  111. IoReleaseCancelSpinLock(kiIrql);
  112. return STATUS_PENDING;
  113. }
  114. NTSTATUS
  115. WanAddUserModeInterface(
  116. PIRP pIrp,
  117. ULONG ulInLength,
  118. ULONG ulOutLength
  119. )
  120. /*++
  121. Routine Description:
  122. The handler for IOCTL_WANARP_ADD_INTERFACE.
  123. We walk our list of interface and make sure we dont have an interface
  124. with the same user mode index as the one we are being asked to create.
  125. If this is a new interface, we create a UMODE_INTERFACE structure
  126. and string it to the list. If it is the server interface then we also
  127. keep a special pointer to it
  128. Locks:
  129. Acquires the g_rwlIfLock as WRITER
  130. Arguments:
  131. Return Value:
  132. STATUS_SUCCESS
  133. STATUS_BUFFER_TOO_SMALL
  134. STATUS_OBJECT_NAME_EXISTS
  135. STATUS_OBJECT_NAME_NOT_FOUND
  136. STATUS_INSUFFICIENT_RESOURCES
  137. --*/
  138. {
  139. PVOID pvIoBuffer;
  140. PUMODE_INTERFACE pInterface;
  141. KIRQL kiIrql;
  142. NTSTATUS nStatus;
  143. PWANARP_ADD_INTERFACE_INFO pAddIfInfo;
  144. TraceEnter(ADPT, "AddUserModeInterface");
  145. pvIoBuffer = pIrp->AssociatedIrp.SystemBuffer;
  146. pIrp->IoStatus.Information = 0;
  147. if(ulInLength < sizeof(WANARP_ADD_INTERFACE_INFO))
  148. {
  149. return STATUS_BUFFER_TOO_SMALL;
  150. }
  151. pAddIfInfo = (PWANARP_ADD_INTERFACE_INFO)pvIoBuffer;
  152. if(pAddIfInfo->bCallinInterface)
  153. {
  154. if(ulOutLength < sizeof(WANARP_ADD_INTERFACE_INFO))
  155. {
  156. return STATUS_BUFFER_TOO_SMALL;
  157. }
  158. RtlZeroMemory(pAddIfInfo->rgwcDeviceName,
  159. (WANARP_MAX_DEVICE_NAME_LEN + 2) * sizeof(WCHAR));
  160. EnterReader(&g_rwlAdapterLock,
  161. &kiIrql);
  162. if(g_pServerAdapter is NULL)
  163. {
  164. ExitReader(&g_rwlAdapterLock,
  165. kiIrql);
  166. Trace(ADPT, ERROR,
  167. ("AddUserModeInterface: No Server adapter\n"));
  168. return STATUS_OBJECT_NAME_NOT_FOUND;
  169. }
  170. //
  171. // Lock out the server adapter
  172. //
  173. RtAcquireSpinLockAtDpcLevel(&(g_pServerAdapter->rlLock));
  174. RtAssert(g_pServerInterface);
  175. RtAcquireSpinLockAtDpcLevel(&(g_pServerInterface->rlLock));
  176. ExitReaderFromDpcLevel(&g_rwlAdapterLock);
  177. if(pAddIfInfo->dwUserIfIndex isnot WANARP_INVALID_IFINDEX)
  178. {
  179. //
  180. // In this case all we need to do is set the interface index
  181. // for the server adapter. It is OK for this index to be INVALID
  182. // in that case, the user is merely asking for the server
  183. // adapter name
  184. //
  185. g_pServerInterface->dwIfIndex = pAddIfInfo->dwUserIfIndex;
  186. }
  187. //
  188. // We also need to return the name to the user
  189. //
  190. RtAssert(g_pServerAdapter->usDeviceNameW.Length <= WANARP_MAX_DEVICE_NAME_LEN * sizeof(WCHAR));
  191. RtlCopyMemory(pAddIfInfo->rgwcDeviceName,
  192. &(g_pServerAdapter->usDeviceNameW.Buffer[wcslen(TCPIP_IF_PREFIX) + 1]),
  193. g_pServerAdapter->usDeviceNameW.Length - ((wcslen(TCPIP_IF_PREFIX) + 1) * sizeof(WCHAR)));
  194. //
  195. // Also copy out the index
  196. //
  197. pAddIfInfo->dwAdapterIndex = g_pServerInterface->dwRsvdAdapterIndex;
  198. RtReleaseSpinLockFromDpcLevel(&(g_pServerInterface->rlLock));
  199. RtReleaseSpinLock(&(g_pServerAdapter->rlLock),
  200. kiIrql);
  201. //
  202. // We need to copy out info in this case
  203. //
  204. pIrp->IoStatus.Information = sizeof(WANARP_ADD_INTERFACE_INFO);
  205. return STATUS_SUCCESS;
  206. }
  207. EnterWriter(&g_rwlIfLock,
  208. &kiIrql);
  209. pInterface = WanpFindInterfaceGivenIndex(pAddIfInfo->dwUserIfIndex);
  210. if(pInterface isnot NULL)
  211. {
  212. //
  213. // Found an interface with the matching index. Not good
  214. //
  215. DereferenceInterface(pInterface);
  216. RtReleaseSpinLockFromDpcLevel(&(pInterface->rlLock));
  217. ExitWriter(&g_rwlIfLock,
  218. kiIrql);
  219. Trace(ADPT, ERROR,
  220. ("AddUserModeInterface: %d already exists\n",
  221. pAddIfInfo->dwUserIfIndex));
  222. return STATUS_OBJECT_NAME_EXISTS;
  223. }
  224. ExitWriter(&g_rwlIfLock,
  225. kiIrql);
  226. pInterface = RtAllocate(NonPagedPool,
  227. sizeof(UMODE_INTERFACE),
  228. WAN_INTERFACE_TAG);
  229. if(pInterface is NULL)
  230. {
  231. return STATUS_INSUFFICIENT_RESOURCES;
  232. }
  233. RtlZeroMemory(pInterface,
  234. sizeof(UMODE_INTERFACE));
  235. //
  236. // Reserve an Index with IP
  237. // This sets the value to invalid if it cant find an index
  238. //
  239. nStatus = WanpGetNewIndex(&(pInterface->dwRsvdAdapterIndex));
  240. if(nStatus isnot STATUS_SUCCESS)
  241. {
  242. RtFree(pInterface);
  243. return STATUS_INSUFFICIENT_RESOURCES;
  244. }
  245. Trace(ADPT, TRACE,
  246. ("AddUserModeInterface: for 0x%x - will use 0x%x\n",
  247. pAddIfInfo->dwUserIfIndex,
  248. pInterface->dwRsvdAdapterIndex));
  249. RtInitializeSpinLock(&(pInterface->rlLock));
  250. //
  251. // Initialize the interface
  252. //
  253. pInterface->dwIfIndex = pAddIfInfo->dwUserIfIndex;
  254. pInterface->dwAdminState = IF_ADMIN_STATUS_UP;
  255. pInterface->dwOperState = IF_OPER_STATUS_DISCONNECTED;
  256. pInterface->dwLastChange = GetTimeTicks();
  257. pAddIfInfo->dwAdapterIndex = pInterface->dwRsvdAdapterIndex;
  258. //
  259. // Now set the refcount to 1 to account for the fact that the interface
  260. // will be put on the g_leIfList.
  261. //
  262. InitInterfaceRefCount(pInterface);
  263. pInterface->duUsage = DU_ROUTER;
  264. EnterWriter(&g_rwlIfLock,
  265. &kiIrql);
  266. InsertHeadList(&g_leIfList,
  267. &(pInterface->leIfLink));
  268. ExitWriter(&g_rwlIfLock,
  269. kiIrql);
  270. pIrp->IoStatus.Information = sizeof(WANARP_ADD_INTERFACE_INFO);
  271. return STATUS_SUCCESS;
  272. }
  273. NTSTATUS
  274. WanDeleteUserModeInterface(
  275. PIRP pIrp,
  276. ULONG ulInLength,
  277. ULONG ulOutLength
  278. )
  279. /*++
  280. Routine Description:
  281. Handler for IOCTL_WANARP_DELETE_INTERFACE.
  282. We lookup our list to see if we have the interface. If we do, then
  283. we remove the interface from the g_leIfList and dereference it.
  284. If the interface was not mapped, then this should be the last
  285. reference on the interface, otherwise when the refcount goes to 0, it
  286. will get deleted.
  287. Locks:
  288. Acquires the g_rwlIfLock as WRITER and then calls FindInterface
  289. which locks the interface in question
  290. Arguments:
  291. Return Value:
  292. STATUS_BUFFER_TOO_SMALL
  293. STATUS_OBJECT_NAME_NOT_FOUND
  294. STATUS_SUCCESS
  295. --*/
  296. {
  297. KIRQL kiIrql;
  298. PUMODE_INTERFACE pInterface;
  299. PVOID pvIoBuffer;
  300. PWANARP_DELETE_INTERFACE_INFO pDeleteInfo;
  301. TraceEnter(ADPT, "DeleteUserModeInterface");
  302. pvIoBuffer = pIrp->AssociatedIrp.SystemBuffer;
  303. pIrp->IoStatus.Information = 0;
  304. if(ulInLength < sizeof(WANARP_DELETE_INTERFACE_INFO))
  305. {
  306. return STATUS_BUFFER_TOO_SMALL;
  307. }
  308. pDeleteInfo = (PWANARP_DELETE_INTERFACE_INFO)pvIoBuffer;
  309. //
  310. // Cant service binds or unbinds here
  311. //
  312. WanpAcquireResource(&g_wrBindMutex);
  313. EnterWriter(&g_rwlIfLock,
  314. &kiIrql);
  315. //
  316. // Find the interface for the index
  317. //
  318. pInterface = WanpFindInterfaceGivenIndex(pDeleteInfo->dwUserIfIndex);
  319. //
  320. // If the interface is not found, bug out
  321. //
  322. Trace(ADPT, TRACE,
  323. ("DeleteUserModeInterface: Deleting i/f 0x%x\n",
  324. pDeleteInfo->dwUserIfIndex));
  325. if(pInterface is NULL)
  326. {
  327. ExitWriter(&g_rwlIfLock,
  328. kiIrql);
  329. WanpReleaseResource(&g_wrBindMutex);
  330. Trace(ADPT, ERROR,
  331. ("DeleteUserModeInterface: Couldnt find i/f 0x%x\n",
  332. pDeleteInfo->dwUserIfIndex));
  333. return STATUS_OBJECT_NAME_NOT_FOUND;
  334. }
  335. RemoveEntryList(&(pInterface->leIfLink));
  336. ExitWriterFromDpcLevel(&g_rwlIfLock);
  337. //
  338. // If found, the interface is locked
  339. // So dereference it and remove it from the list. The interface may
  340. // not get deleted here because it is already mapped and has a connection
  341. // active on it.
  342. //
  343. if(pInterface->dwOperState >= IF_OPER_STATUS_CONNECTING)
  344. {
  345. Trace(ADPT, ERROR,
  346. ("DeleteUserModeInterface: I/f %d is in state %d\n",
  347. pInterface->dwIfIndex,
  348. pInterface->dwOperState));
  349. }
  350. RtReleaseSpinLock(&(pInterface->rlLock),
  351. kiIrql);
  352. //
  353. // Dereference the interface twice. Once because we put a ref on it
  354. // when we called FindInterface... and once because we removed it
  355. // from the if list
  356. //
  357. DereferenceInterface(pInterface);
  358. DereferenceInterface(pInterface);
  359. WanpReleaseResource(&g_wrBindMutex);
  360. return STATUS_SUCCESS;
  361. }
  362. VOID
  363. WanpCleanOutInterfaces(
  364. VOID
  365. )
  366. /*++
  367. Routine Description:
  368. Called to delete all the interface from the system.
  369. We remove the interface from the g_leIfList and dereference it.
  370. For the server interface we simply mark it as disconnected
  371. Locks:
  372. Acquires the g_rwlIfLock as WRITER
  373. Arguments:
  374. Return Value:
  375. None
  376. --*/
  377. {
  378. KIRQL kiIrql;
  379. PUMODE_INTERFACE pInterface;
  380. TraceEnter(ADPT, "CleanOutInterfaces");
  381. //
  382. // Cant service binds or unbinds here
  383. //
  384. WanpAcquireResource(&g_wrBindMutex);
  385. EnterWriter(&g_rwlAdapterLock,
  386. &kiIrql);
  387. EnterWriterAtDpcLevel(&g_rwlIfLock);
  388. while(!IsListEmpty(&g_leIfList))
  389. {
  390. PLIST_ENTRY pleNode;
  391. pleNode = RemoveHeadList(&g_leIfList);
  392. pInterface = CONTAINING_RECORD(pleNode,
  393. UMODE_INTERFACE,
  394. leIfLink);
  395. if(pInterface->dwOperState >= IF_OPER_STATUS_CONNECTING)
  396. {
  397. Trace(ADPT, ERROR,
  398. ("CleanOutInterfaces: I/f %d is in state %d\n",
  399. pInterface->dwIfIndex,
  400. pInterface->dwOperState));
  401. }
  402. DereferenceInterface(pInterface);
  403. }
  404. //
  405. // What should we do with the server interface?
  406. //
  407. ExitWriterFromDpcLevel(&g_rwlIfLock);
  408. ExitWriter(&g_rwlAdapterLock,
  409. kiIrql);
  410. WanpReleaseResource(&g_wrBindMutex);
  411. return;
  412. }
  413. VOID
  414. WanpDeleteInterface(
  415. PUMODE_INTERFACE pInterface
  416. )
  417. /*++
  418. Routine Description
  419. Called by DereferenceInterface() when the refcount on an interface
  420. falls to 0
  421. Locks
  422. The interface is neither locked nor refcounted. Since there are no
  423. stored pointers to the interface, this structure can not be accessed
  424. by anyone but this function
  425. Arguments
  426. pInterface The interface to delete
  427. Return Value
  428. None
  429. --*/
  430. {
  431. PADAPTER pAdapter;
  432. if(pInterface is g_pServerInterface)
  433. {
  434. //
  435. // If this is the server interface, make sure that all
  436. // connection entries are gone
  437. //
  438. }
  439. //
  440. // There should be no interface mapped to it because otherwise we wouldnt
  441. // be down to a refcount of 0
  442. //
  443. RtAssert(pInterface->dwRsvdAdapterIndex isnot INVALID_IF_INDEX);
  444. RtAssert(pInterface->dwRsvdAdapterIndex isnot 0);
  445. WanpFreeIndex(pInterface->dwRsvdAdapterIndex);
  446. RtAssert(pInterface->pAdapter is NULL);
  447. RtFree(pInterface);
  448. }
  449. NTSTATUS
  450. WanProcessConnectionFailure(
  451. PIRP pIrp,
  452. ULONG ulInLength,
  453. ULONG ulOutLength
  454. )
  455. /*++
  456. Routine Description:
  457. Handler for IOCTL_WANARP_CONNECT_FAILED
  458. We find the interface that failed to connect. If we do find one, we
  459. mark its state as disconnected and then see if it was mapped to an
  460. adapter (as it should be). If we find an adapter, we do funky stuff
  461. with lock orders, clean out the packets queued to the adapter and
  462. unmap the adapter.
  463. Locks:
  464. One of the more complex functions.
  465. We take the g_rwlIfLock to get to the interface and lock it.
  466. Then we get a pointer to the adapter, and ref it. We release the
  467. interface lock and lock the adapter.
  468. Arguments:
  469. Return Value:
  470. STATUS_BUFFER_TOO_SMALL
  471. STATUS_OBJECT_NAME_NOT_FOUND
  472. STATUS_INVALID_PARAMETER
  473. STATUS_INVALID_DEVICE_STATE
  474. STATUS_SUCCESS
  475. --*/
  476. {
  477. PNDIS_PACKET packet;
  478. PADAPTER pAdapter;
  479. PUMODE_INTERFACE pInterface;
  480. DWORD dwIfIndex;
  481. PVOID pvIoBuffer;
  482. KIRQL kiIrql;
  483. TraceEnter(CONN, "ProcessConnectionFailure");
  484. pvIoBuffer = pIrp->AssociatedIrp.SystemBuffer;
  485. pIrp->IoStatus.Information = 0;
  486. if(ulInLength < sizeof(WANARP_CONNECT_FAILED_INFO))
  487. {
  488. return STATUS_BUFFER_TOO_SMALL;
  489. }
  490. dwIfIndex = ((PWANARP_CONNECT_FAILED_INFO)pvIoBuffer)->dwUserIfIndex;
  491. pIrp->IoStatus.Information = 0;
  492. //
  493. // Find the interface
  494. //
  495. EnterReader(&g_rwlIfLock,
  496. &kiIrql);
  497. pInterface = WanpFindInterfaceGivenIndex(dwIfIndex);
  498. if(pInterface is NULL)
  499. {
  500. ExitReader(&g_rwlIfLock,
  501. kiIrql);
  502. Trace(CONN, ERROR,
  503. ("ProcessConnectionFailure: Couldnt find i/f for index %d\n",
  504. dwIfIndex));
  505. return STATUS_OBJECT_NAME_NOT_FOUND;
  506. }
  507. if(pInterface is g_pServerInterface)
  508. {
  509. //
  510. // Cant get a disconnect on this
  511. //
  512. RtReleaseSpinLockFromDpcLevel(&(pInterface->rlLock));
  513. DereferenceInterface(pInterface);
  514. ExitReader(&g_rwlIfLock,
  515. kiIrql);
  516. Trace(CONN, ERROR,
  517. ("ProcessConnectionFailure: disconnect on server i/f (%d)n",
  518. dwIfIndex));
  519. return STATUS_INVALID_PARAMETER;
  520. }
  521. ExitReaderFromDpcLevel(&g_rwlIfLock);
  522. RtAssert(pInterface->dwIfIndex is dwIfIndex);
  523. //
  524. // So now the interface is locked.
  525. //
  526. Trace(CONN, TRACE,
  527. ("ProcessConnectionFailure for %d %p\n", pInterface->dwIfIndex, pInterface));
  528. if(pInterface->dwOperState isnot IF_OPER_STATUS_CONNECTING)
  529. {
  530. Trace(CONN, ERROR,
  531. ("ProcessConnectionFailure: %p is in state %d\n",
  532. pInterface,
  533. pInterface->dwOperState));
  534. RtReleaseSpinLock(&(pInterface->rlLock),
  535. kiIrql);
  536. DereferenceInterface(pInterface);
  537. return STATUS_INVALID_DEVICE_STATE;
  538. }
  539. pAdapter = pInterface->pAdapter;
  540. if(pAdapter is NULL)
  541. {
  542. //
  543. // This is the case where we couldnt find an adapter added to IP
  544. // to make a DOD connection
  545. // We dont need to do too much here, just release the interface
  546. // lock and remove ref that was put by FindInterface()
  547. //
  548. RtAssert(pInterface->dwOperState is IF_OPER_STATUS_CONNECTING);
  549. pInterface->dwOperState = IF_OPER_STATUS_DISCONNECTED;
  550. pInterface->dwLastChange= GetTimeTicks();
  551. RtAssert(pInterface->ulPacketsPending is 0);
  552. RtReleaseSpinLock(&(pInterface->rlLock),
  553. kiIrql);
  554. DereferenceInterface(pInterface);
  555. return STATUS_SUCCESS;
  556. }
  557. //
  558. // We should never get a connection failure if have gotten a LinkUp
  559. //
  560. RtAssert(pAdapter->pConnEntry is NULL);
  561. //
  562. // If we do have an adapter then it can not go away because the
  563. // interface has a refcount on it (i.e when we set the pAdapter field
  564. // in the interface, we refcounted the adapter because we had a stored
  565. // pointer to it)
  566. //
  567. RtAssert(pInterface->dwOperState is IF_OPER_STATUS_CONNECTING);
  568. //
  569. // If the interface is still mapped, unmap it and drain any packets we
  570. // may have queued
  571. //
  572. pInterface->ulPacketsPending = 0;
  573. pInterface->dwOperState = IF_OPER_STATUS_DISCONNECTED;
  574. pInterface->dwLastChange= GetTimeTicks();
  575. //
  576. // The adapter can not go away because the interface has a refcount on
  577. // it (i.e when we set the pAdapter field in the interface, we
  578. // refcounted the adapter because we had a stored pointer to it)
  579. //
  580. pAdapter = pInterface->pAdapter;
  581. RtAssert(pAdapter);
  582. //
  583. // Clear out the adapter field, BUT DONT DEREF the adapter
  584. //
  585. pInterface->pAdapter = NULL;
  586. //
  587. // So we are done with the interface. We now go and clean out the
  588. // adapter. To do that we need to acquire the adapter lock. However we
  589. // can not do that since we have the interface lock. So we first
  590. // reference the adapter (so that it will be around). Then we
  591. // let go of the interface lock. (The interface can not go away since
  592. // we put a refcount on the it when we called FindInterface). After
  593. // which we can acquire the adapter lock
  594. //
  595. ReferenceAdapter(pAdapter);
  596. RtReleaseSpinLockFromDpcLevel(&(pInterface->rlLock));
  597. //
  598. // The adapter has to be around, because of the refcount
  599. //
  600. RtAcquireSpinLockAtDpcLevel(&(pAdapter->rlLock));
  601. //
  602. // Make sure that the adapter still thinks that it is mapped to the
  603. // interface in question
  604. //
  605. if(pAdapter->pInterface is pInterface)
  606. {
  607. RtAssert(pAdapter->byState is AS_MAPPED);
  608. //
  609. // Drain all the packets
  610. //
  611. Trace(CONN, TRACE,
  612. ("ProcsConnFailure: Draining and freeing any queued packets\n"));
  613. while(!IsListEmpty(&(pAdapter->lePendingPktList)))
  614. {
  615. PLIST_ENTRY pleNode;
  616. PNDIS_PACKET pnpPacket;
  617. pleNode = RemoveHeadList(&(pAdapter->lePendingPktList));
  618. //
  619. // get to the packet structure in which LIST_ENTRY is embedded
  620. //
  621. pnpPacket = CONTAINING_RECORD(pleNode,
  622. NDIS_PACKET,
  623. MacReserved);
  624. WanpFreePacketAndBuffers(pnpPacket);
  625. }
  626. if(!IsListEmpty(&(pAdapter->lePendingHdrList)))
  627. {
  628. LIST_ENTRY leTempList;
  629. leTempList = pAdapter->lePendingHdrList;
  630. pAdapter->lePendingHdrList.Flink->Blink = &leTempList;
  631. pAdapter->lePendingHdrList.Blink->Flink = &leTempList;
  632. InitializeListHead(&(pAdapter->lePendingHdrList));
  633. FreeBufferListToPool(&g_bpHeaderBufferPool,
  634. &leTempList);
  635. }
  636. pAdapter->pInterface = NULL;
  637. //
  638. // Deref the interface because we are clearing out a stored pointer
  639. //
  640. DereferenceInterface(pInterface);
  641. //
  642. // Deref the adapter now (due to the fact that we cleared out
  643. // the pAdapter field in pInterface
  644. //
  645. DereferenceAdapter(pAdapter);
  646. }
  647. //
  648. // Done with the adapter
  649. //
  650. RtReleaseSpinLockFromDpcLevel(&(pAdapter->rlLock));
  651. WanpUnmapAdapter(pAdapter);
  652. KeLowerIrql(kiIrql);
  653. //
  654. // Remove ref that was put by FindInterface()
  655. //
  656. DereferenceInterface(pInterface);
  657. //
  658. // Remove the ref that was put when we let go of the interface lock
  659. //
  660. DereferenceAdapter(pAdapter);
  661. return STATUS_SUCCESS;
  662. }
  663. NTSTATUS
  664. WanGetIfStats(
  665. PIRP pIrp,
  666. ULONG ulInLength,
  667. ULONG ulOutLength
  668. )
  669. /*++
  670. Routine Description:
  671. Locks:
  672. Arguments:
  673. Return Value:
  674. NO_ERROR
  675. --*/
  676. {
  677. PVOID pvIoBuffer;
  678. PWANARP_GET_IF_STATS_INFO pInfo;
  679. KIRQL kiIrql;
  680. PUMODE_INTERFACE pInterface;
  681. pvIoBuffer = pIrp->AssociatedIrp.SystemBuffer;
  682. pIrp->IoStatus.Information = 0;
  683. if((ulOutLength < (FIELD_OFFSET(WANARP_GET_IF_STATS_INFO, ifeInfo)
  684. + IFE_FIXED_SIZE))or
  685. (ulInLength < (FIELD_OFFSET(WANARP_GET_IF_STATS_INFO, ifeInfo)
  686. + IFE_FIXED_SIZE)))
  687. {
  688. return STATUS_BUFFER_TOO_SMALL;
  689. }
  690. EnterReader(&g_rwlIfLock,
  691. &kiIrql);
  692. pInfo = (PWANARP_GET_IF_STATS_INFO)pvIoBuffer;
  693. pInterface = WanpFindInterfaceGivenIndex(pInfo->dwUserIfIndex);
  694. if(pInterface is NULL)
  695. {
  696. ExitReader(&g_rwlIfLock,
  697. kiIrql);
  698. return STATUS_OBJECT_NAME_NOT_FOUND;
  699. }
  700. ExitReaderFromDpcLevel(&g_rwlIfLock);
  701. //
  702. // We dont take the adapter lock, because the adapter can not
  703. // go away while the interface is mapped to it.
  704. // Sure the qlen can be inconsistent, but hey
  705. //
  706. if((pInterface->pAdapter) and
  707. (pInterface->pAdapter->pConnEntry))
  708. {
  709. pInfo->ifeInfo.if_index = pInterface->pAdapter->dwAdapterIndex;
  710. pInfo->ifeInfo.if_outqlen = pInterface->pAdapter->ulQueueLen;
  711. pInfo->ifeInfo.if_mtu = pInterface->pAdapter->pConnEntry->ulMtu;
  712. pInfo->ifeInfo.if_speed = pInterface->pAdapter->pConnEntry->ulSpeed;
  713. }
  714. else
  715. {
  716. pInfo->ifeInfo.if_index = (uint)-1;
  717. pInfo->ifeInfo.if_outqlen = 0;
  718. pInfo->ifeInfo.if_mtu = WANARP_DEFAULT_MTU;
  719. pInfo->ifeInfo.if_speed = WANARP_DEFAULT_SPEED;
  720. }
  721. pInfo->ifeInfo.if_adminstatus = pInterface->dwAdminState;
  722. pInfo->ifeInfo.if_operstatus = pInterface->dwOperState;
  723. pInfo->ifeInfo.if_lastchange = pInterface->dwLastChange;
  724. pInfo->ifeInfo.if_inoctets = pInterface->ulInOctets;
  725. pInfo->ifeInfo.if_inucastpkts = pInterface->ulInUniPkts;
  726. pInfo->ifeInfo.if_innucastpkts = pInterface->ulInNonUniPkts;
  727. pInfo->ifeInfo.if_indiscards = pInterface->ulInDiscards;
  728. pInfo->ifeInfo.if_inerrors = pInterface->ulInErrors;
  729. pInfo->ifeInfo.if_inunknownprotos = pInterface->ulInUnknownProto;
  730. pInfo->ifeInfo.if_outoctets = pInterface->ulOutOctets;
  731. pInfo->ifeInfo.if_outucastpkts = pInterface->ulOutUniPkts;
  732. pInfo->ifeInfo.if_outnucastpkts = pInterface->ulOutNonUniPkts;
  733. pInfo->ifeInfo.if_outdiscards = pInterface->ulOutDiscards;
  734. pInfo->ifeInfo.if_outerrors = pInterface->ulOutErrors;
  735. RtReleaseSpinLock(&(pInterface->rlLock),
  736. kiIrql);
  737. DereferenceInterface(pInterface);
  738. pInfo->ifeInfo.if_type = IF_TYPE_PPP;
  739. pInfo->ifeInfo.if_physaddrlen = ARP_802_ADDR_LENGTH;
  740. pInfo->ifeInfo.if_descrlen = 0;
  741. RtlZeroMemory(pInfo->ifeInfo.if_physaddr,
  742. MAX_PHYSADDR_SIZE);
  743. pIrp->IoStatus.Information =
  744. FIELD_OFFSET(WANARP_GET_IF_STATS_INFO, ifeInfo) + IFE_FIXED_SIZE;
  745. return STATUS_SUCCESS;
  746. }
  747. NTSTATUS
  748. WanDeleteAdapters(
  749. PIRP pIrp,
  750. ULONG ulInLength,
  751. ULONG ulOutLength
  752. )
  753. /*++
  754. Routine Description:
  755. Handler for IOCTL_WANARP_DELETE_ADAPTERS.
  756. The caller indicates to us the number of adapters that she wants
  757. removed. If we have that many free adapters, we remove them and
  758. return the names of the devices, removed.
  759. Locks:
  760. Acquires the g_rwlAdaptersLock as WRITER
  761. Arguments:
  762. Return Value:
  763. STATUS_BUFFER_TOO_SMALL
  764. STATUS_SUCCESS
  765. --*/
  766. {
  767. KIRQL kiIrql;
  768. PADAPTER pAdapter;
  769. PVOID pvIoBuffer;
  770. ULONG i;
  771. PLIST_ENTRY pleNode;
  772. LIST_ENTRY leTempHead;
  773. PVOID pvNameBuffer;
  774. NTSTATUS nStatus;
  775. KEVENT keChangeEvent;
  776. PWANARP_DELETE_ADAPTERS_INFO pDeleteInfo;
  777. TraceEnter(ADPT, "DeleteAdapters");
  778. pvIoBuffer = pIrp->AssociatedIrp.SystemBuffer;
  779. pIrp->IoStatus.Information = 0;
  780. if(ulInLength < sizeof(WANARP_DELETE_ADAPTERS_INFO))
  781. {
  782. return STATUS_BUFFER_TOO_SMALL;
  783. }
  784. pDeleteInfo = (PWANARP_DELETE_ADAPTERS_INFO)pvIoBuffer;
  785. //
  786. // Dont service binds or unbinds here
  787. //
  788. WanpAcquireResource(&g_wrBindMutex);
  789. EnterWriter(&g_rwlAdapterLock,
  790. &kiIrql);
  791. if(pDeleteInfo->ulNumAdapters > g_ulNumFreeAdapters + g_ulNumAddedAdapters)
  792. {
  793. //
  794. // Asking to delete more adapters than are present
  795. //
  796. pIrp->IoStatus.Information = g_ulNumFreeAdapters + g_ulNumAddedAdapters;
  797. ExitWriter(&g_rwlAdapterLock,
  798. kiIrql);
  799. WanpReleaseResource(&g_wrBindMutex);
  800. return STATUS_INSUFFICIENT_RESOURCES;
  801. }
  802. //
  803. // So there are enough unmapped adapters. See if we have enough space to
  804. // return the names of the adapters
  805. //
  806. if(ulOutLength <
  807. FIELD_OFFSET(WANARP_DELETE_ADAPTERS_INFO, rgAdapterGuid[0]) +
  808. (pDeleteInfo->ulNumAdapters * sizeof(GUID)))
  809. {
  810. //
  811. // Not enough space to hold the names
  812. //
  813. ExitWriter(&g_rwlAdapterLock,
  814. kiIrql);
  815. WanpReleaseResource(&g_wrBindMutex);
  816. pIrp->IoStatus.Information =
  817. FIELD_OFFSET(WANARP_DELETE_ADAPTERS_INFO, rgAdapterGuid[0]) +
  818. (pDeleteInfo->ulNumAdapters * sizeof(GUID));
  819. return STATUS_BUFFER_TOO_SMALL;
  820. }
  821. pIrp->IoStatus.Information =
  822. FIELD_OFFSET(WANARP_DELETE_ADAPTERS_INFO, rgAdapterGuid[0]) +
  823. (pDeleteInfo->ulNumAdapters * sizeof(GUID));
  824. //
  825. // Everything's good. First see if we can remove the ones we want
  826. // removed from the free list
  827. //
  828. i = 0;
  829. while((i < pDeleteInfo->ulNumAdapters) and
  830. (!IsListEmpty(&g_leFreeAdapterList)))
  831. {
  832. pleNode = RemoveHeadList(&g_leFreeAdapterList);
  833. g_ulNumFreeAdapters--;
  834. pAdapter = CONTAINING_RECORD(pleNode,
  835. ADAPTER,
  836. leAdapterLink);
  837. RtAcquireSpinLockAtDpcLevel(&(pAdapter->rlLock));
  838. RtAssert(pAdapter->byState is AS_FREE);
  839. RtAssert(pAdapter->pInterface is NULL);
  840. //
  841. // Copy out the name
  842. // TCPIP_IF_PREFIX is \Device and we need to remove \Device\
  843. //
  844. ConvertStringToGuid(
  845. &(pAdapter->usDeviceNameW.Buffer[wcslen(TCPIP_IF_PREFIX) + 1]),
  846. pAdapter->usDeviceNameW.Length - ((wcslen(TCPIP_IF_PREFIX) + 1) * sizeof(WCHAR)),
  847. &(pDeleteInfo->rgAdapterGuid[i])
  848. );
  849. i++;
  850. //
  851. // Deref it for removing it from the list. This should delete
  852. // it
  853. //
  854. RtReleaseSpinLockFromDpcLevel(&(pAdapter->rlLock));
  855. DereferenceAdapter(pAdapter);
  856. }
  857. if(i is pDeleteInfo->ulNumAdapters)
  858. {
  859. //
  860. // We are done
  861. //
  862. ExitWriter(&g_rwlAdapterLock,
  863. kiIrql);
  864. WanpReleaseResource(&g_wrBindMutex);
  865. return STATUS_SUCCESS;
  866. }
  867. //
  868. // Need to get some added adapters deleted, too
  869. //
  870. InitializeListHead(&leTempHead);
  871. while((i < pDeleteInfo->ulNumAdapters) and
  872. (!IsListEmpty(&g_leAddedAdapterList)))
  873. {
  874. pleNode = RemoveHeadList(&g_leAddedAdapterList);
  875. g_ulNumAddedAdapters--;
  876. pAdapter = CONTAINING_RECORD(pleNode,
  877. ADAPTER,
  878. leAdapterLink);
  879. RtAcquireSpinLockAtDpcLevel(&(pAdapter->rlLock));
  880. pAdapter->byState = AS_REMOVING;
  881. InsertHeadList(&leTempHead,
  882. &(pAdapter->leAdapterLink));
  883. //
  884. // Copy out the name
  885. //
  886. ConvertStringToGuid(
  887. &(pAdapter->usDeviceNameW.Buffer[wcslen(TCPIP_IF_PREFIX) + 1]),
  888. pAdapter->usDeviceNameW.Length - ((wcslen(TCPIP_IF_PREFIX) + 1) * sizeof(WCHAR)),
  889. &(pDeleteInfo->rgAdapterGuid[i])
  890. );
  891. RtReleaseSpinLockFromDpcLevel(&(pAdapter->rlLock));
  892. i++;
  893. }
  894. //
  895. // We better have enough adapters
  896. //
  897. RtAssert(i is pDeleteInfo->ulNumAdapters);
  898. //
  899. // Now we can let go of the lock
  900. //
  901. ExitWriter(&g_rwlAdapterLock,
  902. kiIrql);
  903. KeInitializeEvent(&keChangeEvent,
  904. SynchronizationEvent,
  905. FALSE);
  906. //
  907. // Loop through and delete the adapters
  908. //
  909. while(!IsListEmpty(&leTempHead))
  910. {
  911. pleNode = RemoveHeadList(&leTempHead);
  912. pAdapter = CONTAINING_RECORD(pleNode,
  913. ADAPTER,
  914. leAdapterLink);
  915. EnterWriter(&g_rwlAdapterLock,
  916. &kiIrql);
  917. RtAcquireSpinLockAtDpcLevel(&(pAdapter->rlLock));
  918. //
  919. // Insert it into the change list
  920. //
  921. InsertHeadList(&g_leChangeAdapterList,
  922. &(pAdapter->leAdapterLink));
  923. //
  924. // Set the event to block on
  925. //
  926. RtAssert(pAdapter->pkeChangeEvent is NULL);
  927. pAdapter->pkeChangeEvent = &keChangeEvent;
  928. RtReleaseSpinLockFromDpcLevel(&(pAdapter->rlLock));
  929. ExitWriter(&g_rwlAdapterLock,
  930. kiIrql);
  931. g_pfnIpDeleteInterface(pAdapter->pvIpContext,
  932. FALSE);
  933. //
  934. // Wait till the CloseAdapter completes
  935. //
  936. nStatus = KeWaitForSingleObject(&keChangeEvent,
  937. Executive,
  938. KernelMode,
  939. FALSE,
  940. NULL);
  941. //
  942. // Remove from the change list
  943. //
  944. EnterWriter(&g_rwlAdapterLock,
  945. &kiIrql);
  946. #if DBG
  947. RtAssert(IsEntryOnList(&g_leChangeAdapterList,
  948. &(pAdapter->leAdapterLink)));
  949. #endif
  950. RtAcquireSpinLockAtDpcLevel(&(pAdapter->rlLock));
  951. RemoveEntryList(&(pAdapter->leAdapterLink));
  952. pAdapter->byState = 0xFF;
  953. pAdapter->pkeChangeEvent = NULL;
  954. RtReleaseSpinLockFromDpcLevel(&(pAdapter->rlLock));
  955. ExitWriter(&g_rwlAdapterLock,
  956. kiIrql);
  957. //
  958. // Dereference the adapter for removing from the list
  959. // (CloseAdapter will deref it for removing from IP)
  960. //
  961. DereferenceAdapter(pAdapter);
  962. }
  963. WanpReleaseResource(&g_wrBindMutex);
  964. return STATUS_SUCCESS;
  965. }
  966. NTSTATUS
  967. WanMapServerAdapter(
  968. PIRP pIrp,
  969. ULONG ulInLength,
  970. ULONG ulOutLength
  971. )
  972. /*++
  973. Routine Description:
  974. Called by RAS to add the server adapter and map it to an interface.
  975. It has to be done before the first client dials in.
  976. Locks:
  977. Acquires the g_wrBindMutex. Also acquires the adapter list lock and the
  978. adapter lock
  979. Arguments:
  980. Return Value:
  981. STATUS_SUCCESS
  982. STATUS_BUFFER_TOO_SMALL
  983. STATUS_NO_SUCH_DEVICE
  984. STATUS_DIRECTORY_NOT_EMPTY
  985. --*/
  986. {
  987. NTSTATUS nStatus;
  988. PVOID pvIoBuffer;
  989. KIRQL kiIrql;
  990. WCHAR rgwcGuid[GUID_STR_LEN + 1];
  991. KEVENT keTempEvent;
  992. PLIST_ENTRY pleNode;
  993. PADAPTER pTempAdapter;
  994. UNICODE_STRING usTempName;
  995. PUMODE_INTERFACE pInterface;
  996. PWANARP_MAP_SERVER_ADAPTER_INFO pInfo;
  997. TraceEnter(ADPT, "MapServerAdapter");
  998. pvIoBuffer = pIrp->AssociatedIrp.SystemBuffer;
  999. pInfo = (PWANARP_MAP_SERVER_ADAPTER_INFO)pvIoBuffer;
  1000. pIrp->IoStatus.Information = 0;
  1001. if((ulOutLength < sizeof(WANARP_MAP_SERVER_ADAPTER_INFO)) or
  1002. (ulInLength < sizeof(WANARP_MAP_SERVER_ADAPTER_INFO)))
  1003. {
  1004. return STATUS_BUFFER_TOO_SMALL;
  1005. }
  1006. WanpAcquireResource(&g_wrBindMutex);
  1007. EnterWriter(&g_rwlAdapterLock,
  1008. &kiIrql);
  1009. if(g_pServerAdapter is NULL)
  1010. {
  1011. Trace(ADPT, ERROR,
  1012. ("MapServerAdapter: No server adapter\n"));
  1013. ExitWriter(&g_rwlAdapterLock,
  1014. kiIrql);
  1015. WanpReleaseResource(&g_wrBindMutex);
  1016. return STATUS_NO_SUCH_DEVICE;
  1017. }
  1018. RtAssert(g_pServerInterface);
  1019. //
  1020. // Lock the adapter and change the state to let people know we are
  1021. // trying to add or remove the adapter, hence they should wait on the
  1022. // global event
  1023. //
  1024. RtAcquireSpinLockAtDpcLevel(&(g_pServerAdapter->rlLock));
  1025. if(pInfo->fMap is 0)
  1026. {
  1027. KEVENT keTempEvent;
  1028. //
  1029. // Trying to unmap
  1030. //
  1031. pIrp->IoStatus.Information = 0;
  1032. if(g_pServerAdapter->byState is AS_FREE)
  1033. {
  1034. //
  1035. // Nothing to do
  1036. //
  1037. RtReleaseSpinLockFromDpcLevel(&(g_pServerAdapter->rlLock));
  1038. ExitWriter(&g_rwlAdapterLock,
  1039. kiIrql);
  1040. WanpReleaseResource(&g_wrBindMutex);
  1041. return STATUS_SUCCESS;
  1042. }
  1043. //
  1044. // Since add is serialized, the only other state is AS_MAPPED
  1045. //
  1046. RtAssert(g_pServerAdapter->byState is AS_MAPPED);
  1047. //
  1048. // Make sure there are no new connections
  1049. //
  1050. if(!WanpIsConnectionTableEmpty())
  1051. {
  1052. Trace(ADPT, ERROR,
  1053. ("MapServerAdapter: Connection Table not empty\n"));
  1054. // RtAssert(FALSE);
  1055. RtReleaseSpinLockFromDpcLevel(&(g_pServerAdapter->rlLock));
  1056. ExitWriter(&g_rwlAdapterLock,
  1057. kiIrql);
  1058. WanpReleaseResource(&g_wrBindMutex);
  1059. return STATUS_DIRECTORY_NOT_EMPTY;
  1060. }
  1061. //
  1062. // Remove the adapter from ip, remove the cross ref
  1063. //
  1064. //
  1065. // Since we are changing the state, no one else should be also
  1066. // changing the state
  1067. //
  1068. RtAssert(g_pServerAdapter->pkeChangeEvent is NULL);
  1069. KeInitializeEvent(&keTempEvent,
  1070. SynchronizationEvent,
  1071. FALSE);
  1072. g_pServerAdapter->pkeChangeEvent = &keTempEvent;
  1073. ReferenceAdapter(g_pServerAdapter);
  1074. g_pServerAdapter->byState = AS_REMOVING;
  1075. RtReleaseSpinLockFromDpcLevel(&(g_pServerAdapter->rlLock));
  1076. ExitWriter(&g_rwlAdapterLock,
  1077. kiIrql);
  1078. //
  1079. // Delete from IP, but dont clear the index
  1080. //
  1081. g_pfnIpDeleteInterface(g_pServerAdapter->pvIpContext,
  1082. FALSE);
  1083. nStatus = KeWaitForSingleObject(&keTempEvent,
  1084. Executive,
  1085. KernelMode,
  1086. FALSE,
  1087. NULL);
  1088. RtAssert(nStatus is STATUS_SUCCESS);
  1089. EnterWriter(&g_rwlAdapterLock,
  1090. &kiIrql);
  1091. RtAcquireSpinLockAtDpcLevel(&(g_pServerAdapter->rlLock));
  1092. #if DBG
  1093. Trace(ADPT, INFO,
  1094. ("MapServerAdapter: Removed %s (server adapter) from Ip\n",
  1095. g_pServerAdapter->asDeviceNameA.Buffer));
  1096. #endif
  1097. g_pServerAdapter->pkeChangeEvent = NULL;
  1098. g_pServerAdapter->byState = AS_FREE;
  1099. g_pServerInterface->pAdapter = NULL;
  1100. g_pServerAdapter->pInterface = NULL;
  1101. //
  1102. // deref because of the cross ref
  1103. //
  1104. DereferenceAdapter(g_pServerAdapter);
  1105. DereferenceInterface(g_pServerInterface);
  1106. g_pServerAdapter->dwAdapterIndex = 0;
  1107. //
  1108. // If anyone is waiting on a state change, notify them
  1109. //
  1110. for(pleNode = g_pServerAdapter->leEventList.Flink;
  1111. pleNode isnot &(g_pServerAdapter->leEventList);
  1112. pleNode = pleNode->Flink)
  1113. {
  1114. PWAN_EVENT_NODE pTempEvent;
  1115. pTempEvent = CONTAINING_RECORD(pleNode,
  1116. WAN_EVENT_NODE,
  1117. leEventLink);
  1118. KeSetEvent(&(pTempEvent->keEvent),
  1119. 0,
  1120. FALSE);
  1121. }
  1122. pTempAdapter = g_pServerAdapter;
  1123. RtReleaseSpinLockFromDpcLevel(&(g_pServerAdapter->rlLock));
  1124. ExitWriter(&g_rwlAdapterLock,
  1125. kiIrql);
  1126. WanpReleaseResource(&g_wrBindMutex);
  1127. DereferenceAdapter(pTempAdapter);
  1128. return STATUS_SUCCESS;
  1129. }
  1130. if(g_pServerAdapter->byState isnot AS_FREE)
  1131. {
  1132. //
  1133. // Valid states are AS_FREE, AS_ADDING, AS_MAPPED.
  1134. // It can not be in the process of being added since the resource
  1135. // is acquired
  1136. //
  1137. RtAssert(g_pServerAdapter->byState is AS_MAPPED);
  1138. RtAssert(g_pServerAdapter->pInterface is g_pServerInterface);
  1139. RtAssert(g_pServerInterface->pAdapter is g_pServerAdapter);
  1140. pInfo->dwAdapterIndex = g_pServerAdapter->dwAdapterIndex;
  1141. RtReleaseSpinLockFromDpcLevel(&(g_pServerAdapter->rlLock));
  1142. ExitWriter(&g_rwlAdapterLock,
  1143. kiIrql);
  1144. WanpReleaseResource(&g_wrBindMutex);
  1145. pIrp->IoStatus.Information = sizeof(WANARP_MAP_SERVER_ADAPTER_INFO);
  1146. return STATUS_SUCCESS;
  1147. }
  1148. RtAssert(g_pServerInterface->pAdapter is NULL);
  1149. RtAssert(g_pServerAdapter->pInterface is NULL);
  1150. ReferenceAdapter(g_pServerAdapter);
  1151. g_pServerAdapter->byState = AS_ADDING;
  1152. //
  1153. // Since we are changing the state, no one else should be also
  1154. // changing the state
  1155. //
  1156. RtAssert(g_pServerAdapter->pkeChangeEvent is NULL)
  1157. KeInitializeEvent(&keTempEvent,
  1158. SynchronizationEvent,
  1159. FALSE);
  1160. g_pServerAdapter->pkeChangeEvent = &keTempEvent;
  1161. RtReleaseSpinLockFromDpcLevel(&(g_pServerAdapter->rlLock));
  1162. ExitWriter(&g_rwlAdapterLock,
  1163. kiIrql);
  1164. usTempName.MaximumLength = (GUID_STR_LEN + 1) * sizeof(WCHAR);
  1165. usTempName.Length = GUID_STR_LEN * sizeof(WCHAR);
  1166. usTempName.Buffer = rgwcGuid;
  1167. ConvertGuidToString(&(g_pServerInterface->Guid),
  1168. rgwcGuid);
  1169. nStatus = WanpAddAdapterToIp(g_pServerAdapter,
  1170. TRUE,
  1171. g_pServerInterface->dwRsvdAdapterIndex,
  1172. &usTempName,
  1173. IF_TYPE_PPP,
  1174. IF_ACCESS_POINTTOMULTIPOINT,
  1175. IF_CONNECTION_PASSIVE);
  1176. if(nStatus isnot STATUS_SUCCESS)
  1177. {
  1178. Trace(ADPT, ERROR,
  1179. ("MapServerAdapter: %x adding %x to IP\n",
  1180. nStatus, g_pServerAdapter));
  1181. EnterWriter(&g_rwlAdapterLock,
  1182. &kiIrql);
  1183. RtAcquireSpinLockAtDpcLevel(&(g_pServerAdapter->rlLock));
  1184. g_pServerAdapter->byState = AS_FREE;
  1185. g_pServerAdapter->pkeChangeEvent = NULL;
  1186. //
  1187. // If anyone is waiting on a state change, notify them
  1188. //
  1189. for(pleNode = g_pServerAdapter->leEventList.Flink;
  1190. pleNode isnot &(g_pServerAdapter->leEventList);
  1191. pleNode = pleNode->Flink)
  1192. {
  1193. PWAN_EVENT_NODE pTempEvent;
  1194. pTempEvent = CONTAINING_RECORD(pleNode,
  1195. WAN_EVENT_NODE,
  1196. leEventLink);
  1197. KeSetEvent(&(pTempEvent->keEvent),
  1198. 0,
  1199. FALSE);
  1200. }
  1201. pTempAdapter = g_pServerAdapter;
  1202. RtReleaseSpinLockFromDpcLevel(&(g_pServerAdapter->rlLock));
  1203. ExitWriter(&g_rwlAdapterLock,
  1204. kiIrql);
  1205. #if DBG
  1206. Trace(ADPT, ERROR,
  1207. ("MapServerAdapter: Couldnt add %s to Ip as server adapter\n",
  1208. pTempAdapter->asDeviceNameA.Buffer));
  1209. #endif
  1210. DereferenceAdapter(pTempAdapter);
  1211. WanpReleaseResource(&g_wrBindMutex);
  1212. return nStatus;
  1213. }
  1214. //
  1215. // Wait till the OpenAdapter is called
  1216. //
  1217. nStatus = KeWaitForSingleObject(&keTempEvent,
  1218. Executive,
  1219. KernelMode,
  1220. FALSE,
  1221. NULL);
  1222. RtAssert(nStatus is STATUS_SUCCESS);
  1223. Trace(ADPT, TRACE,
  1224. ("MapServerAdapter: IPAddInterface succeeded for adapter %w\n",
  1225. g_pServerAdapter->usDeviceNameW.Buffer));
  1226. EnterWriter(&g_rwlAdapterLock,
  1227. &kiIrql);
  1228. RtAcquireSpinLockAtDpcLevel(&(g_pServerAdapter->rlLock));
  1229. //
  1230. // Cross ref the structures
  1231. //
  1232. g_pServerAdapter->pInterface = g_pServerInterface;
  1233. g_pServerInterface->pAdapter = g_pServerAdapter;
  1234. g_pServerAdapter->byState = AS_MAPPED;
  1235. g_pServerInterface->dwOperState = IF_OPER_STATUS_CONNECTED;
  1236. g_pServerInterface->dwLastChange= GetTimeTicks();
  1237. //
  1238. // bump the refcount because of the cross ref
  1239. //
  1240. ReferenceAdapter(g_pServerAdapter);
  1241. ReferenceInterface(g_pServerInterface);
  1242. pInfo->dwAdapterIndex = g_pServerAdapter->dwAdapterIndex;
  1243. g_pServerAdapter->pkeChangeEvent = NULL;
  1244. //
  1245. // If anyone is waiting on a state change, notify them
  1246. //
  1247. for(pleNode = g_pServerAdapter->leEventList.Flink;
  1248. pleNode isnot &(g_pServerAdapter->leEventList);
  1249. pleNode = pleNode->Flink)
  1250. {
  1251. PWAN_EVENT_NODE pTempEvent;
  1252. pTempEvent = CONTAINING_RECORD(pleNode,
  1253. WAN_EVENT_NODE,
  1254. leEventLink);
  1255. KeSetEvent(&(pTempEvent->keEvent),
  1256. 0,
  1257. FALSE);
  1258. }
  1259. pTempAdapter = g_pServerAdapter;
  1260. RtReleaseSpinLockFromDpcLevel(&(g_pServerAdapter->rlLock));
  1261. ExitWriter(&g_rwlAdapterLock,
  1262. kiIrql);
  1263. DereferenceAdapter(pTempAdapter);
  1264. WanpReleaseResource(&g_wrBindMutex);
  1265. pIrp->IoStatus.Information = sizeof(WANARP_MAP_SERVER_ADAPTER_INFO);
  1266. return STATUS_SUCCESS;
  1267. }
  1268. NTSTATUS
  1269. WanStartStopQueuing(
  1270. PIRP pIrp,
  1271. ULONG ulInLength,
  1272. ULONG ulOutLength
  1273. )
  1274. /*++
  1275. Routine Description:
  1276. The handler for IOCTL_WANARP_QUEUE.
  1277. It is used to start or stop queuing notifications to the router manager.
  1278. On start, we return the dial out interfaces that we currently have.
  1279. Locks:
  1280. Acquires the IoCancelSpinLock
  1281. Arguments:
  1282. Return Value:
  1283. STATUS_PENDING
  1284. STATUS_SUCCESS
  1285. STATUS_BUFFER_TOO_SMALL
  1286. --*/
  1287. {
  1288. KIRQL kiIrql;
  1289. PLIST_ENTRY pleNode;
  1290. PVOID pvIoBuffer;
  1291. ULONG i, ulMaxInterfaces, ulSizeReq;
  1292. PWANARP_QUEUE_INFO pQueueInfo;
  1293. PPENDING_NOTIFICATION pNotification;
  1294. TraceEnter(GLOBAL, "StartStopQueuing");
  1295. pvIoBuffer = pIrp->AssociatedIrp.SystemBuffer;
  1296. pIrp->IoStatus.Information = 0;
  1297. if(ulInLength < FIELD_OFFSET(WANARP_QUEUE_INFO, rgIfInfo))
  1298. {
  1299. return STATUS_BUFFER_TOO_SMALL;
  1300. }
  1301. //
  1302. // use cancel spin lock to prevent irp being cancelled during this call.
  1303. //
  1304. IoAcquireCancelSpinLock(&kiIrql);
  1305. //
  1306. // If the user is stopping queueing, delete all the pending notifications
  1307. //
  1308. pQueueInfo = (PWANARP_QUEUE_INFO)pvIoBuffer;
  1309. if(!pQueueInfo->fQueue)
  1310. {
  1311. g_bQueueNotifications = FALSE;
  1312. while(!IsListEmpty(&g_lePendingNotificationList))
  1313. {
  1314. //
  1315. // We have some old info
  1316. // Remove it off the pending list
  1317. //
  1318. pleNode = RemoveHeadList(&g_lePendingNotificationList);
  1319. //
  1320. // Get a pointer to the structure
  1321. //
  1322. pNotification = CONTAINING_RECORD(pleNode,
  1323. PENDING_NOTIFICATION,
  1324. leNotificationLink);
  1325. //
  1326. // Free the allocated notification
  1327. //
  1328. FreeNotification(pNotification);
  1329. }
  1330. //
  1331. // Done
  1332. //
  1333. IoReleaseCancelSpinLock(kiIrql);
  1334. WanpClearPendingIrps();
  1335. return STATUS_SUCCESS;
  1336. }
  1337. //
  1338. // The user wants to start queueing
  1339. // See if she has given us enough space to copy out
  1340. // the current dial outs
  1341. //
  1342. if(ulOutLength < FIELD_OFFSET(WANARP_QUEUE_INFO, rgIfInfo))
  1343. {
  1344. IoReleaseCancelSpinLock(kiIrql);
  1345. return STATUS_BUFFER_TOO_SMALL;
  1346. }
  1347. EnterReaderAtDpcLevel(&g_rwlAdapterLock);
  1348. ulSizeReq = FIELD_OFFSET(WANARP_QUEUE_INFO, rgIfInfo) +
  1349. (g_ulNumDialOutInterfaces * sizeof(WANARP_IF_INFO));
  1350. pQueueInfo->ulNumCallout = g_ulNumDialOutInterfaces;
  1351. if(ulOutLength < ulSizeReq)
  1352. {
  1353. pIrp->IoStatus.Information = FIELD_OFFSET(WANARP_QUEUE_INFO, rgIfInfo);
  1354. ExitReaderFromDpcLevel(&g_rwlAdapterLock);
  1355. IoReleaseCancelSpinLock(kiIrql);
  1356. return STATUS_MORE_ENTRIES;
  1357. }
  1358. ulMaxInterfaces =
  1359. (ulOutLength - FIELD_OFFSET(WANARP_QUEUE_INFO, rgIfInfo)) / sizeof(WANARP_IF_INFO);
  1360. //
  1361. // Have enough space
  1362. // Walk the list of mapped adapters looking for CALLOUTs
  1363. //
  1364. for(i = 0, pleNode = g_leMappedAdapterList.Flink;
  1365. pleNode isnot &g_leMappedAdapterList;
  1366. pleNode = pleNode->Flink)
  1367. {
  1368. PUMODE_INTERFACE pIf;
  1369. PADAPTER pAdapter;
  1370. PCONN_ENTRY pConnEntry;
  1371. pAdapter = CONTAINING_RECORD(pleNode,
  1372. ADAPTER,
  1373. leAdapterLink);
  1374. //
  1375. // Lock the adapter and check its connection entry
  1376. //
  1377. RtAcquireSpinLockAtDpcLevel(&(pAdapter->rlLock));
  1378. pConnEntry = pAdapter->pConnEntry;
  1379. if(pConnEntry and
  1380. (pConnEntry->duUsage is DU_CALLOUT))
  1381. {
  1382. RtAssert(i < ulMaxInterfaces);
  1383. pIf = pAdapter->pInterface;
  1384. RtAssert(pIf);
  1385. RtAssert(pIf->dwRsvdAdapterIndex);
  1386. pQueueInfo->rgIfInfo[i].InterfaceGuid = pIf->Guid;
  1387. pQueueInfo->rgIfInfo[i].dwAdapterIndex = pIf->dwRsvdAdapterIndex;
  1388. pQueueInfo->rgIfInfo[i].dwLocalAddr = pConnEntry->dwLocalAddr;
  1389. pQueueInfo->rgIfInfo[i].dwLocalMask = pConnEntry->dwLocalMask;
  1390. pQueueInfo->rgIfInfo[i].dwRemoteAddr = pConnEntry->dwRemoteAddr;
  1391. i++;
  1392. }
  1393. RtReleaseSpinLockFromDpcLevel(&(pAdapter->rlLock));
  1394. }
  1395. g_bQueueNotifications = TRUE;
  1396. ExitReaderFromDpcLevel(&g_rwlAdapterLock);
  1397. IoReleaseCancelSpinLock(kiIrql);
  1398. pIrp->IoStatus.Information = ulSizeReq;
  1399. return STATUS_SUCCESS;
  1400. }
  1401. VOID
  1402. WanCancelNotificationIrp(
  1403. PDEVICE_OBJECT pDeviceObject,
  1404. PIRP pIrp
  1405. )
  1406. /*++
  1407. Routine Description:
  1408. Called to cancel a queued irp
  1409. Locks:
  1410. Arguments:
  1411. Return Value:
  1412. --*/
  1413. {
  1414. Trace(GLOBAL, TRACE,
  1415. ("CancelNotificationIrp\n"));
  1416. //
  1417. // Mark this Irp as cancelled
  1418. //
  1419. pIrp->IoStatus.Status = STATUS_CANCELLED;
  1420. pIrp->IoStatus.Information = 0;
  1421. //
  1422. // Take off our own list
  1423. //
  1424. RemoveEntryList(&pIrp->Tail.Overlay.ListEntry);
  1425. //
  1426. // Release cancel spin lock which the IO system acquired
  1427. //
  1428. IoReleaseCancelSpinLock(pIrp->CancelIrql);
  1429. IoCompleteRequest(pIrp,
  1430. IO_NETWORK_INCREMENT);
  1431. }
  1432. VOID
  1433. WanpCompleteIrp(
  1434. PPENDING_NOTIFICATION pEvent
  1435. )
  1436. /*++
  1437. Routine Description:
  1438. Completes a notification irp.
  1439. Locks:
  1440. Arguments:
  1441. Return Value:
  1442. --*/
  1443. {
  1444. KIRQL kiIrql;
  1445. Trace(GLOBAL, TRACE,
  1446. ("Completing Notification Irp\n"));
  1447. //
  1448. // grab cancel spin lock
  1449. //
  1450. IoAcquireCancelSpinLock(&kiIrql);
  1451. if(!g_bQueueNotifications)
  1452. {
  1453. IoReleaseCancelSpinLock(kiIrql);
  1454. FreeNotification(pEvent);
  1455. return;
  1456. }
  1457. if(!IsListEmpty(&g_lePendingIrpList))
  1458. {
  1459. PLIST_ENTRY pleNode;
  1460. PIRP pIrp;
  1461. //
  1462. // We have a pending IRP. Use it to return info to router manager
  1463. //
  1464. pleNode = RemoveHeadList(&g_lePendingIrpList) ;
  1465. pIrp = CONTAINING_RECORD(pleNode,
  1466. IRP,
  1467. Tail.Overlay.ListEntry);
  1468. RtlCopyMemory(pIrp->AssociatedIrp.SystemBuffer,
  1469. &(pEvent->wnMsg),
  1470. sizeof(WANARP_NOTIFICATION));
  1471. Trace(GLOBAL, TRACE,
  1472. ("Returning Irp with event code of %d\n",
  1473. ((PWANARP_NOTIFICATION)pIrp->AssociatedIrp.SystemBuffer)->ddeEvent));
  1474. IoSetCancelRoutine(pIrp,
  1475. NULL);
  1476. pIrp->IoStatus.Status = STATUS_SUCCESS;
  1477. pIrp->IoStatus.Information = sizeof(WANARP_NOTIFICATION);
  1478. //
  1479. // release lock
  1480. //
  1481. IoReleaseCancelSpinLock(kiIrql);
  1482. IoCompleteRequest(pIrp,
  1483. IO_NETWORK_INCREMENT);
  1484. //
  1485. // Free the allocated notification
  1486. //
  1487. FreeNotification(pEvent);
  1488. }
  1489. else
  1490. {
  1491. Trace(GLOBAL, TRACE,
  1492. ("Found no pending Irp so queuing the notification\n"));
  1493. InsertTailList(&g_lePendingNotificationList,
  1494. &(pEvent->leNotificationLink));
  1495. //
  1496. // release lock
  1497. //
  1498. IoReleaseCancelSpinLock(kiIrql);
  1499. }
  1500. }
  1501. NTSTATUS
  1502. WanpGetNewIndex(
  1503. OUT PULONG pulIndex
  1504. )
  1505. /*++
  1506. Routine Description:
  1507. Gets a new interface index from IP
  1508. Locks:
  1509. None
  1510. Arguments:
  1511. pulIndex OUT interface index
  1512. Return Value:
  1513. --*/
  1514. {
  1515. ULONG ulMax;
  1516. *pulIndex = INVALID_IF_INDEX;
  1517. return g_pfnIpReserveIndex(1, pulIndex, &ulMax);
  1518. }
  1519. VOID
  1520. WanpFreeIndex(
  1521. IN ULONG ulIndex
  1522. )
  1523. /*++
  1524. Routine Description:
  1525. Frees an index back to IP
  1526. Locks:
  1527. None
  1528. Arguments:
  1529. ulIndex
  1530. Return Value:
  1531. --*/
  1532. {
  1533. ULONG ulMax;
  1534. g_pfnIpDereserveIndex(1,
  1535. ulIndex);
  1536. }