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.

2762 lines
64 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. net\routing\ip\rtrmgr\demand.c
  5. Abstract:
  6. Handles demand dial/connection events from WANARP driver.
  7. Revision History:
  8. Gurdeep Singh Pall 6/8/95 Created
  9. --*/
  10. #include "allinc.h"
  11. DWORD
  12. InitializeWanArp(
  13. VOID
  14. )
  15. /*++
  16. Routine Description:
  17. Creates a handle to WANARP and posts an IRP for notification
  18. Since the IRP is completed asynchrnously and uses DemandDialEvent for
  19. notification, the event must have already been created
  20. Arguments:
  21. None
  22. Return Value:
  23. NO_ERROR or some error code
  24. --*/
  25. {
  26. DWORD dwResult;
  27. ULONG ulSize, ulCount, i;
  28. NTSTATUS Status;
  29. IO_STATUS_BLOCK IoStatusBlock;
  30. PWANARP_QUEUE_INFO pQueueInfo;
  31. TraceEnter("InitializeWanArp");
  32. g_hWanarpRead = CreateFile(WANARP_DOS_NAME_T,
  33. GENERIC_READ,
  34. FILE_SHARE_READ | FILE_SHARE_WRITE,
  35. NULL,
  36. OPEN_EXISTING,
  37. FILE_FLAG_OVERLAPPED,
  38. NULL);
  39. if(g_hWanarpRead is INVALID_HANDLE_VALUE)
  40. {
  41. g_hWanarpRead = NULL;
  42. dwResult = GetLastError();
  43. Trace1(ERR,
  44. "InitializeWanArp: Could not open WANARP for read - %d",
  45. dwResult);
  46. TraceLeave("InitializeWanArp");
  47. return dwResult;
  48. }
  49. g_hWanarpWrite = CreateFile(WANARP_DOS_NAME_T,
  50. GENERIC_READ | GENERIC_WRITE,
  51. FILE_SHARE_READ | FILE_SHARE_WRITE,
  52. NULL,
  53. OPEN_EXISTING,
  54. FILE_FLAG_OVERLAPPED,
  55. NULL);
  56. if(g_hWanarpWrite is INVALID_HANDLE_VALUE)
  57. {
  58. CloseHandle(g_hWanarpRead);
  59. g_hWanarpRead = NULL;
  60. g_hWanarpWrite = NULL;
  61. dwResult = GetLastError();
  62. Trace1(ERR,
  63. "InitializeWanArp: Could not open WANARP for write - %d",
  64. dwResult);
  65. TraceLeave("InitializeWanArp");
  66. return dwResult;
  67. }
  68. //
  69. // Get the number of call out interfaces and start queueing notifications
  70. //
  71. ulCount = 5;
  72. i = 0;
  73. while(i < 3)
  74. {
  75. ulSize = FIELD_OFFSET(WANARP_QUEUE_INFO, rgIfInfo) +
  76. (ulCount * sizeof(WANARP_IF_INFO));
  77. pQueueInfo = HeapAlloc(IPRouterHeap,
  78. 0,
  79. ulSize);
  80. if(pQueueInfo is NULL)
  81. {
  82. Status = ERROR_NOT_ENOUGH_MEMORY;
  83. break;
  84. }
  85. pQueueInfo->fQueue = 1;
  86. Status = NtDeviceIoControlFile(g_hWanarpWrite,
  87. NULL,
  88. NULL,
  89. NULL,
  90. &IoStatusBlock,
  91. IOCTL_WANARP_QUEUE,
  92. pQueueInfo,
  93. sizeof(WANARP_QUEUE_INFO),
  94. pQueueInfo,
  95. ulSize);
  96. if(Status isnot STATUS_SUCCESS)
  97. {
  98. if(Status is STATUS_MORE_ENTRIES)
  99. {
  100. IpRtAssert(ulCount > pQueueInfo->ulNumCallout);
  101. i++;
  102. ulCount = pQueueInfo->ulNumCallout + (i * 5);
  103. HeapFree(IPRouterHeap,
  104. 0,
  105. pQueueInfo);
  106. pQueueInfo = NULL;
  107. //
  108. // Go to the top of while()
  109. //
  110. continue;
  111. }
  112. else
  113. {
  114. HeapFree(IPRouterHeap,
  115. 0,
  116. pQueueInfo);
  117. pQueueInfo = NULL;
  118. break;
  119. }
  120. }
  121. else
  122. {
  123. break;
  124. }
  125. }
  126. if(Status isnot STATUS_SUCCESS)
  127. {
  128. //
  129. // Close the device and return failure
  130. //
  131. CloseHandle(g_hWanarpRead);
  132. CloseHandle(g_hWanarpWrite);
  133. g_hWanarpRead = NULL;
  134. g_hWanarpWrite = NULL;
  135. return Status;
  136. }
  137. //
  138. // Create any dial out interfaces
  139. //
  140. for(i = 0; i < pQueueInfo->ulNumCallout; i++)
  141. {
  142. UNICODE_STRING usTempName;
  143. PICB pIcb;
  144. dwResult = RtlStringFromGUID(&(pQueueInfo->rgIfInfo[i].InterfaceGuid),
  145. &usTempName);
  146. if(dwResult isnot STATUS_SUCCESS)
  147. {
  148. continue;
  149. }
  150. //
  151. // RtlString... returns a NULL terminated buffer
  152. //
  153. dwResult =
  154. CreateDialOutInterface(usTempName.Buffer,
  155. pQueueInfo->rgIfInfo[i].dwAdapterIndex,
  156. pQueueInfo->rgIfInfo[i].dwLocalAddr,
  157. pQueueInfo->rgIfInfo[i].dwLocalMask,
  158. pQueueInfo->rgIfInfo[i].dwRemoteAddr,
  159. &pIcb);
  160. }
  161. HeapFree(IPRouterHeap,
  162. 0,
  163. pQueueInfo);
  164. //
  165. // Post an irp for demand dial notifications.
  166. //
  167. PostIoctlForDemandDialNotification() ;
  168. TraceLeave("InitializeWanArp");
  169. return NO_ERROR ;
  170. }
  171. VOID
  172. CloseWanArp(
  173. VOID
  174. )
  175. {
  176. NTSTATUS Status;
  177. IO_STATUS_BLOCK IoStatusBlock;
  178. WANARP_QUEUE_INFO QueueInfo;
  179. TraceEnter("CloseWanArp");
  180. if(g_hWanarpRead)
  181. {
  182. CloseHandle(g_hWanarpRead);
  183. g_hWanarpRead = NULL;
  184. }
  185. if(g_hWanarpWrite)
  186. {
  187. QueueInfo.fQueue = 0;
  188. Status = NtDeviceIoControlFile(g_hWanarpWrite,
  189. NULL,
  190. NULL,
  191. NULL,
  192. &IoStatusBlock,
  193. IOCTL_WANARP_QUEUE,
  194. &QueueInfo,
  195. sizeof(WANARP_QUEUE_INFO),
  196. &QueueInfo,
  197. sizeof(WANARP_QUEUE_INFO));
  198. if(Status isnot STATUS_SUCCESS)
  199. {
  200. }
  201. CloseHandle(g_hWanarpWrite);
  202. g_hWanarpWrite = NULL;
  203. }
  204. TraceLeave("CloseWanArp");
  205. }
  206. DWORD
  207. HandleDemandDialEvent(
  208. VOID
  209. )
  210. /*++
  211. Routine Description:
  212. Called by the main thread whenever a demand dial event is received
  213. We mereley dispatch it to the right handler
  214. Locks:
  215. None
  216. Arguments:
  217. None
  218. Return Value:
  219. None
  220. --*/
  221. {
  222. PICB picb;
  223. DWORD dwResult;
  224. NTSTATUS Status;
  225. BOOL bPost;
  226. //
  227. // drain all demand dial events queued up in WANARP
  228. //
  229. TraceEnter("HandleDemandDialEvent");
  230. bPost = TRUE;
  231. //
  232. // Since, potentially, this can cause stuff to be written in the ICB,
  233. // we take lock as a WRITER
  234. //
  235. // *** Exclusion Begin ***
  236. ENTER_WRITER(ICB_LIST);
  237. EnterCriticalSection(&RouterStateLock);
  238. if(RouterState.IRS_State isnot RTR_STATE_RUNNING)
  239. {
  240. if(wnWanarpMsg.ddeEvent isnot DDE_INTERFACE_DISCONNECTED)
  241. {
  242. Trace1(IF,
  243. "ProcessDemandDialEvent: Shutting down. Ignoring event %d",
  244. wnWanarpMsg.ddeEvent);
  245. LeaveCriticalSection(&RouterStateLock);
  246. return NO_ERROR;
  247. }
  248. else
  249. {
  250. bPost = FALSE;
  251. }
  252. }
  253. LeaveCriticalSection(&RouterStateLock);
  254. picb = InterfaceLookupByICBSeqNumber( wnWanarpMsg.dwUserIfIndex );
  255. if ((wnWanarpMsg.ddeEvent is DDE_CONNECT_INTERFACE) or
  256. (wnWanarpMsg.ddeEvent is DDE_INTERFACE_CONNECTED) or
  257. (wnWanarpMsg.ddeEvent is DDE_INTERFACE_DISCONNECTED))
  258. {
  259. IpRtAssert(picb);
  260. if (picb isnot NULL)
  261. {
  262. switch(wnWanarpMsg.ddeEvent)
  263. {
  264. case DDE_CONNECT_INTERFACE:
  265. {
  266. HandleConnectionRequest(picb);
  267. break ;
  268. }
  269. case DDE_INTERFACE_CONNECTED:
  270. {
  271. HandleConnectionNotification(picb);
  272. break ;
  273. }
  274. case DDE_INTERFACE_DISCONNECTED:
  275. {
  276. HandleDisconnectionNotification(picb);
  277. break ;
  278. }
  279. default:
  280. {
  281. Trace1(ERR,
  282. "ProcessDemandDialEvent: Illegal event %d from WanArp",
  283. wnWanarpMsg.ddeEvent);
  284. break;
  285. }
  286. }
  287. }
  288. else
  289. {
  290. Trace2(
  291. ANY, "Event %d, could not find interface with ICB %d",
  292. wnWanarpMsg.ddeEvent, wnWanarpMsg.dwUserIfIndex
  293. );
  294. }
  295. }
  296. else
  297. {
  298. switch(wnWanarpMsg.ddeEvent)
  299. {
  300. case DDE_CALLOUT_LINKUP:
  301. {
  302. HandleDialOutLinkUp();
  303. break ;
  304. }
  305. case DDE_CALLOUT_LINKDOWN:
  306. {
  307. HandleDialOutLinkDown();
  308. break ;
  309. }
  310. default:
  311. {
  312. Trace1(ERR,
  313. "ProcessDemandDialEvent: Illegal event %d from WanArp",
  314. wnWanarpMsg.ddeEvent);
  315. break;
  316. }
  317. }
  318. }
  319. // *** Exclusion End ***
  320. EXIT_LOCK(ICB_LIST);
  321. if(bPost)
  322. {
  323. PostIoctlForDemandDialNotification();
  324. }
  325. TraceLeave("HandleDemandDialEvent");
  326. return NO_ERROR;
  327. }
  328. VOID
  329. HandleConnectionRequest(
  330. PICB picb
  331. )
  332. /*++
  333. Routine Description:
  334. Called when we get a connection request from WANARP.
  335. Locks:
  336. ICB_LIST lock held as WRITER
  337. Arguments:
  338. None
  339. Return Value:
  340. None
  341. --*/
  342. {
  343. BOOL bRet;
  344. HANDLE hDim;
  345. DWORD dwResult;
  346. NTSTATUS nStatus;
  347. Trace2(IF,
  348. "HandleConnectionRequest: Connection request for %S, %d",
  349. picb->pwszName, picb->dwSeqNumber);
  350. if(picb->dwOperationalState is CONNECTED)
  351. {
  352. //
  353. // Really weird. Connection attempt for an i/f that
  354. // WANARP knows is already connected
  355. //
  356. Trace2(IF,
  357. "HandleConnectionRequest: Connection request for %S but %S is already UP",
  358. picb->pwszName, picb->pwszName);
  359. return;
  360. }
  361. bRet = FALSE;
  362. do
  363. {
  364. dwResult = ProcessPacketFromWanArp(picb);
  365. if(dwResult isnot NO_ERROR)
  366. {
  367. //
  368. // Demand dial filter rules are to drop this packet
  369. //
  370. break;
  371. }
  372. if ((picb->dwAdminState is IF_ADMIN_STATUS_DOWN) or
  373. (picb->dwOperationalState is UNREACHABLE))
  374. {
  375. Trace3(IF,
  376. "HandleConnectionRequest: %S has admin state %d and operational state %d. Failing connection request",
  377. picb->pwszName,
  378. picb->dwAdminState,
  379. picb->dwOperationalState);
  380. break;
  381. }
  382. #if DBG
  383. if(picb->dwOperationalState is CONNECTING)
  384. {
  385. Trace2(IF,
  386. "HandleConnectionRequest: RACE CONDITION %S is connecting. Notifications %d",
  387. picb->pwszName,
  388. picb->fConnectionFlags);
  389. }
  390. #endif
  391. Trace1(DEMAND, "Calling DIM to connect %S",
  392. picb->pwszName);
  393. //
  394. // Call DIM to make the connection. Let go of the ICB lock
  395. //
  396. hDim = picb->hDIMHandle;
  397. EXIT_LOCK(ICB_LIST);
  398. dwResult = (ConnectInterface)(hDim,
  399. PID_IP);
  400. ENTER_WRITER(ICB_LIST);
  401. if(dwResult isnot NO_ERROR)
  402. {
  403. if(dwResult is PENDING)
  404. {
  405. //
  406. // We dont clear notification flags because there may be a
  407. // race condition and we may have already gotten
  408. // InterfaceConnected() from DIM
  409. //
  410. Trace1(DEMAND,
  411. "HandleConnectionRequest: Conn attempt for %S pending",
  412. picb->pwszName);
  413. }
  414. else
  415. {
  416. break;
  417. }
  418. }
  419. //
  420. // So bRet is TRUE if DIM returned NO_ERROR or PENDING
  421. //
  422. bRet = TRUE;
  423. }while(FALSE);
  424. if(!bRet)
  425. {
  426. nStatus = NotifyWanarpOfFailure(picb);
  427. if((nStatus isnot STATUS_PENDING) and
  428. (nStatus isnot STATUS_SUCCESS))
  429. {
  430. Trace2(ERR,
  431. "HandleConnectionRequest: %X for connection failed for %S",
  432. nStatus,
  433. picb->pwszName);
  434. }
  435. //
  436. // If it was connecting, then the stack has set the
  437. // interface context to something other than 0xffffffff.
  438. // Hence he wont dial out on that route We need to change
  439. // the context in the stack back to invalid so that new
  440. // packets cause the demand dial
  441. //
  442. ChangeAdapterIndexForDodRoutes(picb->dwIfIndex);
  443. }
  444. else
  445. {
  446. picb->dwOperationalState = CONNECTING;
  447. }
  448. }
  449. VOID
  450. HandleConnectionNotification(
  451. PICB picb
  452. )
  453. /*++
  454. Routine Description:
  455. Called when WANARP informs us that an interface is connected
  456. Locks:
  457. None
  458. Arguments:
  459. None
  460. Return Value:
  461. None
  462. --*/
  463. {
  464. PADAPTER_INFO pBindNode;
  465. //
  466. // Plug in the Adapter info we get from the LINE_UP indication.
  467. // There is only one address for a WAN interface
  468. //
  469. ENTER_WRITER(BINDING_LIST);
  470. picb->bBound = TRUE;
  471. picb->dwNumAddresses = wnWanarpMsg.dwLocalAddr?1:0;
  472. IpRtAssert(picb->dwIfIndex is wnWanarpMsg.dwAdapterIndex);
  473. if(picb->dwNumAddresses)
  474. {
  475. picb->pibBindings[0].dwAddress = wnWanarpMsg.dwLocalAddr;
  476. picb->pibBindings[0].dwMask = wnWanarpMsg.dwLocalMask;
  477. IpRtAssert(picb->pibBindings[0].dwMask is 0xFFFFFFFF);
  478. }
  479. else
  480. {
  481. picb->pibBindings[0].dwAddress = 0;
  482. picb->pibBindings[0].dwMask = 0;
  483. }
  484. if(picb->ritType is ROUTER_IF_TYPE_FULL_ROUTER)
  485. {
  486. picb->dwRemoteAddress = wnWanarpMsg.dwRemoteAddr;
  487. }
  488. else
  489. {
  490. picb->dwRemoteAddress = 0;
  491. }
  492. Trace4(IF,
  493. "HandleConnNotif: Connection notification for %S. Local %d.%d.%d.%d. Remote %d.%d.%d.%d",
  494. picb->pwszName,
  495. PRINT_IPADDR(picb->pibBindings[0].dwAddress),
  496. PRINT_IPADDR(picb->dwRemoteAddress),
  497. picb->dwSeqNumber);
  498. //
  499. // For wan interfaces we always have a binding struct in the hash
  500. // table. So retrieve that
  501. //
  502. pBindNode = GetInterfaceBinding(picb->dwIfIndex);
  503. if(!pBindNode)
  504. {
  505. Trace1(ERR,
  506. "HandleConnNotif: Binding not found for %S",
  507. picb->pwszName);
  508. IpRtAssert(FALSE);
  509. //
  510. // Something really bad happened and we didnt have a
  511. // bind block for the interface
  512. //
  513. AddBinding(picb);
  514. }
  515. else
  516. {
  517. //
  518. // Good a binding was found. Assert that it is ours
  519. // and then update it
  520. //
  521. IpRtAssert(pBindNode->dwIfIndex is picb->dwIfIndex);
  522. IpRtAssert(pBindNode->pInterfaceCB is picb);
  523. pBindNode->bBound = TRUE;
  524. pBindNode->dwNumAddresses = picb->dwNumAddresses;
  525. pBindNode->dwRemoteAddress = picb->dwRemoteAddress ;
  526. //
  527. // struct copy out the address and mask
  528. //
  529. pBindNode->rgibBinding[0] = picb->pibBindings[0];
  530. //
  531. // We dont take the IP_ADDR_TABLE lock here because we have the
  532. // ICB lock. During SNMP get we first take the addr lock then
  533. // the icb lock. So we cant do the opposite here else we will
  534. // deadlock. This may cause inconsistent information for one
  535. // request, but we can live with that
  536. //
  537. g_LastUpdateTable[IPADDRCACHE] = 0;
  538. }
  539. EXIT_LOCK(BINDING_LIST);
  540. if(picb->dwOperationalState is UNREACHABLE)
  541. {
  542. //
  543. // going from unreachable to connecting
  544. //
  545. WanInterfaceDownToInactive(picb);
  546. }
  547. if(picb->dwOperationalState isnot CONNECTING)
  548. {
  549. //
  550. // We can get a LinkUp without getting a ConnectionRequest
  551. // This is the case when a user explicitly brings up a
  552. // connection.
  553. //
  554. picb->dwOperationalState = CONNECTING;
  555. }
  556. SetNdiswanNotification(picb);
  557. if(HaveAllNotificationsBeenReceived(picb))
  558. {
  559. picb->dwOperationalState = CONNECTED ;
  560. WanInterfaceInactiveToUp(picb) ;
  561. }
  562. }
  563. VOID
  564. HandleDisconnectionNotification(
  565. PICB picb
  566. )
  567. /*++
  568. Routine Description:
  569. Handles a disconnection notification from WANARP
  570. If the interface was connected, we make it inactive
  571. We remove and bindings on the interface. This removal doesnt free the
  572. bindings, only set the state to unbound
  573. If the interface was marked for deletion, we go ahead and delete the
  574. interface
  575. Locks:
  576. None
  577. Arguments:
  578. None
  579. Return Value:
  580. None
  581. --*/
  582. {
  583. Trace2(IF,
  584. "HandleDisconnectionNotif: Disconnection notification for %S %d",
  585. picb->pwszName, picb->dwSeqNumber);
  586. if(picb->dwOperationalState is CONNECTED)
  587. {
  588. //
  589. // We would have called InactiveToUp
  590. //
  591. WanInterfaceUpToInactive(picb,
  592. FALSE);
  593. }
  594. else
  595. {
  596. //
  597. // We have only set the addresses, clear those out
  598. //
  599. DeAllocateBindings(picb);
  600. }
  601. picb->dwOperationalState = DISCONNECTED ;
  602. g_LastUpdateTable[IPADDRCACHE] = 0;
  603. if(IsInterfaceMarkedForDeletion(picb))
  604. {
  605. RemoveInterfaceFromLists(picb);
  606. DeleteSingleInterface(picb);
  607. HeapFree(IPRouterHeap, 0, picb);
  608. }
  609. else
  610. {
  611. ClearNotificationFlags(picb);
  612. }
  613. }
  614. DWORD
  615. HandleDialOutLinkUp(
  616. VOID
  617. )
  618. /*++
  619. Routine Description:
  620. Handles the notification from wanarp that we have a new dial out interface
  621. Locks:
  622. ICB list lock as writer
  623. Arguments:
  624. None
  625. Return Value:
  626. NO_ERROR
  627. --*/
  628. {
  629. DWORD dwResult;
  630. PICB pNewIcb;
  631. INTERFACE_ROUTE_INFO rifRoute;
  632. Trace4(IF,
  633. "DialOutLinkUp: Connection notification for 0x%x %d.%d.%d.%d/%d.%d.%d.%d %d.%d.%d.%d",
  634. wnWanarpMsg.dwAdapterIndex,
  635. PRINT_IPADDR(wnWanarpMsg.dwLocalAddr),
  636. PRINT_IPADDR(wnWanarpMsg.dwLocalMask),
  637. PRINT_IPADDR(wnWanarpMsg.dwRemoteAddr));
  638. dwResult = CreateDialOutInterface(wnWanarpMsg.rgwcName,
  639. wnWanarpMsg.dwAdapterIndex,
  640. wnWanarpMsg.dwLocalAddr,
  641. wnWanarpMsg.dwLocalMask,
  642. wnWanarpMsg.dwRemoteAddr,
  643. &pNewIcb);
  644. if(dwResult isnot NO_ERROR)
  645. {
  646. return dwResult;
  647. }
  648. AddAutomaticRoutes(pNewIcb,
  649. wnWanarpMsg.dwLocalAddr,
  650. wnWanarpMsg.dwLocalMask);
  651. #if 0
  652. //
  653. // Add the route to the server
  654. //
  655. if(pNewIcb->dwRemoteAddress isnot INVALID_IP_ADDRESS)
  656. {
  657. rifRoute.dwRtInfoMask = HOST_ROUTE_MASK;
  658. rifRoute.dwRtInfoNextHop = pNewIcb->dwRemoteAddress;
  659. rifRoute.dwRtInfoDest = pNewIcb->dwRemoteAddress;
  660. rifRoute.dwRtInfoIfIndex = pNewIcb->dwIfIndex;
  661. rifRoute.dwRtInfoMetric1 = 1;
  662. rifRoute.dwRtInfoMetric2 = 0;
  663. rifRoute.dwRtInfoMetric3 = 0;
  664. rifRoute.dwRtInfoPreference =
  665. ComputeRouteMetric(MIB_IPPROTO_NETMGMT);
  666. rifRoute.dwRtInfoViewSet = RTM_VIEW_MASK_UCAST |
  667. RTM_VIEW_MASK_MCAST; // XXX config
  668. rifRoute.dwRtInfoType = MIB_IPROUTE_TYPE_DIRECT;
  669. rifRoute.dwRtInfoProto = MIB_IPPROTO_NETMGMT;
  670. rifRoute.dwRtInfoAge = 0;
  671. rifRoute.dwRtInfoNextHopAS = 0;
  672. rifRoute.dwRtInfoPolicy = 0;
  673. dwResult = AddSingleRoute(pNewIcb->dwIfIndex,
  674. &rifRoute,
  675. pNewIcb->pibBindings[0].dwMask,
  676. 0, // RTM_ROUTE_INFO::Flags
  677. TRUE, // Valid route
  678. TRUE,
  679. TRUE,
  680. NULL);
  681. if(dwResult isnot NO_ERROR)
  682. {
  683. Trace1(ERR,
  684. "HandleDialOutLinkUp: Couldnt add server route for 0x%x",
  685. pNewIcb->dwIfIndex);
  686. }
  687. }
  688. if(wnWanarpMsg.fDefaultRoute)
  689. {
  690. INTERFACE_ROUTE_INFO rifRoute;
  691. ChangeDefaultRouteMetrics(TRUE);
  692. pNewIcb->bChangedMetrics = TRUE;
  693. //
  694. // Add route to def gateway
  695. //
  696. rifRoute.dwRtInfoDest = 0;
  697. rifRoute.dwRtInfoMask = 0;
  698. rifRoute.dwRtInfoNextHop = wnWanarpMsg.dwLocalAddr;
  699. rifRoute.dwRtInfoIfIndex = wnWanarpMsg.dwAdapterIndex;
  700. rifRoute.dwRtInfoMetric1 = 1;
  701. rifRoute.dwRtInfoMetric2 = 0;
  702. rifRoute.dwRtInfoMetric3 = 0;
  703. rifRoute.dwRtInfoPreference =
  704. ComputeRouteMetric(PROTO_IP_LOCAL);
  705. rifRoute.dwRtInfoViewSet = RTM_VIEW_MASK_UCAST |
  706. RTM_VIEW_MASK_MCAST; // XXX config
  707. rifRoute.dwRtInfoType = MIB_IPROUTE_TYPE_DIRECT;
  708. rifRoute.dwRtInfoProto = PROTO_IP_NETMGMT;
  709. rifRoute.dwRtInfoAge = INFINITE;
  710. rifRoute.dwRtInfoNextHopAS = 0;
  711. rifRoute.dwRtInfoPolicy = 0;
  712. dwResult = AddSingleRoute(wnWanarpMsg.dwAdapterIndex,
  713. &rifRoute,
  714. ALL_ONES_MASK,
  715. 0, // RTM_ROUTE_INFO::Flags
  716. TRUE,
  717. FALSE,
  718. FALSE,
  719. NULL);
  720. if(dwResult isnot NO_ERROR)
  721. {
  722. Trace1(ERR,
  723. "HandleDialOutLinkUp: Couldnt add default route for 0x%x",
  724. wnWanarpMsg.dwAdapterIndex);
  725. }
  726. }
  727. else
  728. {
  729. DWORD dwAddr, dwMask;
  730. dwMask = GetClassMask(wnWanarpMsg.dwLocalAddr);
  731. dwAddr = wnWanarpMsg.dwLocalAddr & dwMask;
  732. //
  733. // Add route to class subnet
  734. //
  735. rifRoute.dwRtInfoDest = dwAddr;
  736. rifRoute.dwRtInfoMask = dwMask;
  737. rifRoute.dwRtInfoNextHop = wnWanarpMsg.dwLocalAddr;
  738. rifRoute.dwRtInfoIfIndex = wnWanarpMsg.dwAdapterIndex;
  739. rifRoute.dwRtInfoMetric1 = 1;
  740. rifRoute.dwRtInfoMetric2 = 0;
  741. rifRoute.dwRtInfoMetric3 = 0;
  742. rifRoute.dwRtInfoPreference = ComputeRouteMetric(PROTO_IP_LOCAL);
  743. rifRoute.dwRtInfoViewSet = RTM_VIEW_MASK_UCAST |
  744. RTM_VIEW_MASK_MCAST; // XXX config
  745. rifRoute.dwRtInfoType = MIB_IPROUTE_TYPE_DIRECT;
  746. rifRoute.dwRtInfoProto = PROTO_IP_LOCAL;
  747. rifRoute.dwRtInfoAge = INFINITE;
  748. rifRoute.dwRtInfoNextHopAS = 0;
  749. rifRoute.dwRtInfoPolicy = 0;
  750. dwResult = AddSingleRoute(wnWanarpMsg.dwAdapterIndex,
  751. &rifRoute,
  752. ALL_ONES_MASK,
  753. 0, // RTM_ROUTE_INFO::Flags
  754. TRUE,
  755. FALSE,
  756. FALSE,
  757. NULL);
  758. if(dwResult isnot NO_ERROR)
  759. {
  760. Trace1(ERR,
  761. "HandleDialOutLinkUp: Couldnt add subnet route for 0x%x",
  762. wnWanarpMsg.dwAdapterIndex);
  763. }
  764. }
  765. #endif
  766. return NO_ERROR;
  767. }
  768. DWORD
  769. CreateDialOutInterface(
  770. IN PWCHAR pwszIfName,
  771. IN DWORD dwIfIndex,
  772. IN DWORD dwLocalAddr,
  773. IN DWORD dwLocalMask,
  774. IN DWORD dwRemoteAddr,
  775. OUT ICB **ppIcb
  776. )
  777. /*++
  778. Routine Description:
  779. Creates an ICB for a dial out interface
  780. We check to see that the interface doesnt already exist and if so, we
  781. add the interface to our list using the index and name supplied by
  782. wanarp.
  783. Locks:
  784. ICB list lock as writer
  785. Arguments:
  786. Return Value:
  787. NO_ERROR
  788. --*/
  789. {
  790. PICB pNewIcb;
  791. PADAPTER_INFO pBindNode;
  792. PICB_BINDING pBinding;
  793. #if DBG
  794. pNewIcb = InterfaceLookupByIfIndex(dwIfIndex);
  795. IpRtAssert(pNewIcb is NULL);
  796. #endif // DBG
  797. pNewIcb = CreateIcb(pwszIfName,
  798. NULL,
  799. ROUTER_IF_TYPE_DIALOUT,
  800. IF_ADMIN_STATUS_UP,
  801. dwIfIndex);
  802. if(pNewIcb is NULL)
  803. {
  804. *ppIcb = NULL;
  805. return ERROR_CAN_NOT_COMPLETE;
  806. }
  807. //
  808. // Set up the bindings
  809. //
  810. pNewIcb->bBound = TRUE;
  811. pNewIcb->dwNumAddresses = dwLocalAddr ? 1 : 0;
  812. pNewIcb->dwRemoteAddress = dwRemoteAddr;
  813. IpRtAssert(pNewIcb->dwIfIndex is dwIfIndex);
  814. if(pNewIcb->dwNumAddresses)
  815. {
  816. pNewIcb->pibBindings[0].dwAddress = dwLocalAddr;
  817. pNewIcb->pibBindings[0].dwMask = dwLocalMask;
  818. }
  819. else
  820. {
  821. pNewIcb->pibBindings[0].dwAddress = 0;
  822. pNewIcb->pibBindings[0].dwMask = 0;
  823. }
  824. ENTER_WRITER(BINDING_LIST);
  825. pBindNode = GetInterfaceBinding(pNewIcb->dwIfIndex);
  826. if(pBindNode is NULL)
  827. {
  828. IpRtAssert(FALSE);
  829. AddBinding(pNewIcb);
  830. }
  831. else
  832. {
  833. IpRtAssert(pBindNode->dwIfIndex is pNewIcb->dwIfIndex);
  834. IpRtAssert(pBindNode->pInterfaceCB is pNewIcb);
  835. pBindNode->bBound = TRUE;
  836. pBindNode->dwNumAddresses = pNewIcb->dwNumAddresses;
  837. pBindNode->dwRemoteAddress = pNewIcb->dwRemoteAddress;
  838. //
  839. // struct copy out the address and mask
  840. //
  841. pBindNode->rgibBinding[0] = pNewIcb->pibBindings[0];
  842. }
  843. EXIT_LOCK(BINDING_LIST);
  844. //
  845. // Insert pNewIcb in interface list and hash table
  846. // This increments the interface count and sets the seq number
  847. //
  848. InsertInterfaceInLists(pNewIcb);
  849. *ppIcb = pNewIcb;
  850. //
  851. // Update the address cache
  852. //
  853. g_LastUpdateTable[IPADDRCACHE] = 0;
  854. return NO_ERROR;
  855. }
  856. DWORD
  857. HandleDialOutLinkDown(
  858. VOID
  859. )
  860. /*++
  861. Routine Description:
  862. Handles the linkdown notification for a dial out interface.
  863. Locks:
  864. ICB list lock as writer
  865. Arguments:
  866. None
  867. Return Value:
  868. NO_ERROR
  869. --*/
  870. {
  871. PICB pIcb;
  872. Trace1(IF,
  873. "DialOutLinkDown: Disconnection notification for %d",
  874. wnWanarpMsg.dwAdapterIndex);
  875. pIcb = InterfaceLookupByIfIndex(wnWanarpMsg.dwAdapterIndex);
  876. if(pIcb is NULL)
  877. {
  878. IpRtAssert(FALSE);
  879. return NO_ERROR;
  880. }
  881. RemoveInterfaceFromLists(pIcb);
  882. //
  883. // This will delete the default route if there was one
  884. //
  885. DeleteSingleInterface(pIcb);
  886. if(pIcb->bChangedMetrics)
  887. {
  888. ChangeDefaultRouteMetrics(FALSE);
  889. }
  890. HeapFree(IPRouterHeap,
  891. 0,
  892. pIcb);
  893. return NO_ERROR;
  894. }
  895. NTSTATUS
  896. NotifyWanarpOfFailure(
  897. PICB picb
  898. )
  899. /*++
  900. Routine Description:
  901. Sends an IOCTL_WANARP_CONNECT_FAILED to WANARP
  902. Locks:
  903. None
  904. Arguments:
  905. picb ICB of the interface on whom the connection failed
  906. Return Value:
  907. None
  908. --*/
  909. {
  910. NTSTATUS Status;
  911. IO_STATUS_BLOCK IoStatusBlock;
  912. WANARP_CONNECT_FAILED_INFO ConnectInfo;
  913. ConnectInfo.dwUserIfIndex = picb->dwSeqNumber;
  914. Status = NtDeviceIoControlFile(g_hWanarpWrite,
  915. NULL,
  916. NULL,
  917. NULL,
  918. &IoStatusBlock,
  919. IOCTL_WANARP_CONNECT_FAILED,
  920. &ConnectInfo,
  921. sizeof(WANARP_CONNECT_FAILED_INFO),
  922. NULL,
  923. 0);
  924. IpRtAssert(Status isnot STATUS_PENDING);
  925. return Status;
  926. }
  927. DWORD
  928. ProcessPacketFromWanArp(
  929. PICB picb
  930. )
  931. /*++
  932. Routine Description:
  933. Filters the packet which is causing a demand dial connection. If the
  934. packet is valid, logs the packet
  935. Locks:
  936. ICB_LIST held as READER
  937. Arguments:
  938. picb ICB of interface to dial
  939. Return Value:
  940. NO_ERROR Dial out
  941. ERROR_INVALID_DATA Dont dial out
  942. --*/
  943. {
  944. CHAR pszSrc[20], pszDest[20], pszProto[5], pszLength[32];
  945. CHAR pszName[MAX_INTERFACE_NAME_LEN + 1];
  946. DWORD dwSize, dwResult;
  947. BYTE rgbyPacket[sizeof(IP_HEADER) + MAX_PACKET_COPY_SIZE];
  948. PBYTE pbyData;
  949. PFFORWARD_ACTION faAction;
  950. PIP_HEADER pHeader;
  951. TraceEnter("ProcessPacketFromWanArp");
  952. //
  953. // Now create a packet
  954. //
  955. dwSize = min(wnWanarpMsg.ulPacketLength,
  956. MAX_PACKET_COPY_SIZE);
  957. if(picb->ihDemandFilterInterface isnot INVALID_HANDLE_VALUE)
  958. {
  959. IpRtAssert(picb->pDemandFilter);
  960. //
  961. // TCP/IP seems to not give us a packet sometimes
  962. //
  963. if(!dwSize)
  964. {
  965. Trace3(ERR,
  966. "ProcPktFromWanarp: Packet from %d.%d.%d.%d to %d.%d.%d.%d protocol 0x%02x had 0 size!!",
  967. PRINT_IPADDR(wnWanarpMsg.dwPacketSrcAddr),
  968. PRINT_IPADDR(wnWanarpMsg.dwPacketDestAddr),
  969. wnWanarpMsg.byPacketProtocol);
  970. TraceLeave("ProcessPacketFromWanArp");
  971. return ERROR_INVALID_DATA;
  972. }
  973. pHeader = (PIP_HEADER)rgbyPacket;
  974. //
  975. // Zero out the header
  976. //
  977. ZeroMemory(rgbyPacket,
  978. sizeof(IP_HEADER));
  979. //
  980. // Set the header with the info we have
  981. //
  982. pHeader->byVerLen = 0x45;
  983. pHeader->byProtocol = wnWanarpMsg.byPacketProtocol;
  984. pHeader->dwSrc = wnWanarpMsg.dwPacketSrcAddr;
  985. pHeader->dwDest = wnWanarpMsg.dwPacketDestAddr;
  986. pHeader->wLength = htons((WORD)(dwSize + sizeof(IP_HEADER)));
  987. //
  988. // Copy out the data portion
  989. //
  990. pbyData = rgbyPacket + sizeof(IP_HEADER);
  991. CopyMemory(pbyData,
  992. wnWanarpMsg.rgbyPacket,
  993. dwSize);
  994. dwResult = PfTestPacket(picb->ihDemandFilterInterface,
  995. NULL,
  996. dwSize + sizeof(IP_HEADER),
  997. rgbyPacket,
  998. &faAction);
  999. //
  1000. // If the call succeeded and the action was drop, no need to process
  1001. // futher
  1002. //
  1003. if(dwResult is NO_ERROR)
  1004. {
  1005. if(faAction is PF_ACTION_DROP)
  1006. {
  1007. Trace5(DEMAND,
  1008. "ProcPktFromWanarp: Result %d action %s for packet from %d.%d.%d.%d to %d.%d.%d.%d protocol 0x%02x",
  1009. dwResult, faAction == PF_ACTION_DROP? "Drop": "RtInfo",
  1010. PRINT_IPADDR(wnWanarpMsg.dwPacketSrcAddr),
  1011. PRINT_IPADDR(wnWanarpMsg.dwPacketDestAddr),
  1012. wnWanarpMsg.byPacketProtocol);
  1013. TraceLeave("ProcessPacketFromWanarp");
  1014. return ERROR_INVALID_DATA;
  1015. }
  1016. }
  1017. else
  1018. {
  1019. //
  1020. // In case of error we fall through and bring the link up
  1021. //
  1022. Trace4(DEMAND,
  1023. "ProcPktFromWanarp: Result %d for packet from %d.%d.%d.%d to %d.%d.%d.%d protocol 0x%02x",
  1024. dwResult,
  1025. PRINT_IPADDR(wnWanarpMsg.dwPacketSrcAddr),
  1026. PRINT_IPADDR(wnWanarpMsg.dwPacketDestAddr),
  1027. wnWanarpMsg.byPacketProtocol);
  1028. }
  1029. }
  1030. strcpy(pszSrc,
  1031. inet_ntoa(*((PIN_ADDR)(&(wnWanarpMsg.dwPacketSrcAddr)))));
  1032. strcpy(pszDest,
  1033. inet_ntoa(*((PIN_ADDR)(&(wnWanarpMsg.dwPacketDestAddr)))));
  1034. sprintf(pszProto,"%02x",wnWanarpMsg.byPacketProtocol);
  1035. WideCharToMultiByte(CP_ACP,
  1036. 0,
  1037. picb->pwszName,
  1038. -1,
  1039. pszName,
  1040. MAX_INTERFACE_NAME_LEN,
  1041. NULL,
  1042. NULL);
  1043. pszName[MAX_INTERFACE_NAME_LEN] = '\0';
  1044. sprintf(pszLength,"%d",dwSize);
  1045. LogWarnData5(DEMAND_DIAL_PACKET,
  1046. pszSrc,
  1047. pszDest,
  1048. pszProto,
  1049. pszName,
  1050. pszLength,
  1051. dwSize,
  1052. wnWanarpMsg.rgbyPacket);
  1053. TraceLeave("ProcessPacketFromWanarp");
  1054. return NO_ERROR;
  1055. }
  1056. DWORD
  1057. PostIoctlForDemandDialNotification(
  1058. VOID
  1059. )
  1060. /*++
  1061. Routine Description:
  1062. Posts a notification irp with WANARP.
  1063. Arguments:
  1064. None
  1065. Return Value:
  1066. --*/
  1067. {
  1068. DWORD bytesrecvd ;
  1069. DWORD retcode = NO_ERROR;
  1070. TraceEnter("PostIoctlForDemandDialNotification");
  1071. ZeroMemory(&WANARPOverlapped,
  1072. sizeof (OVERLAPPED));
  1073. WANARPOverlapped.hEvent = g_hDemandDialEvent ;
  1074. if (!DeviceIoControl(g_hWanarpWrite,
  1075. (DWORD) IOCTL_WANARP_NOTIFICATION,
  1076. &wnWanarpMsg,
  1077. sizeof(wnWanarpMsg),
  1078. &wnWanarpMsg,
  1079. sizeof(wnWanarpMsg),
  1080. (LPDWORD) &bytesrecvd,
  1081. &WANARPOverlapped))
  1082. {
  1083. retcode = GetLastError();
  1084. if(retcode isnot ERROR_IO_PENDING)
  1085. {
  1086. Trace1(ERR,
  1087. "PostIoctlForDemandDialNotification: Couldnt post irp with WANARP: %d\n",
  1088. retcode) ;
  1089. }
  1090. else
  1091. {
  1092. Trace0(IF, "PostIoctlForDemandDialNotification: Notification pending in WANARP");
  1093. }
  1094. }
  1095. TraceLeave("PostIoctlForDemandDialNotification");
  1096. return retcode ;
  1097. }
  1098. DWORD
  1099. AddInterfaceToWanArp(
  1100. PICB picb
  1101. )
  1102. /*++
  1103. Routine Description:
  1104. Adds the given interface with WANARP
  1105. Has a side effect of getting an interface index
  1106. Arguments:
  1107. The ICB of the interface to add
  1108. Return Value:
  1109. --*/
  1110. {
  1111. DWORD out,dwResult;
  1112. IO_STATUS_BLOCK IoStatusBlock;
  1113. NTSTATUS nStatus;
  1114. PADAPTER_INFO pBindNode;
  1115. WANARP_ADD_INTERFACE_INFO info;
  1116. TraceEnter("AddInterfaceToWanArp");
  1117. Trace1(IF,
  1118. "AddInterfaceToWanArp: Adding %S to WanArp",
  1119. picb->pwszName);
  1120. info.dwUserIfIndex = picb->dwSeqNumber;
  1121. info.dwAdapterIndex = INVALID_IF_INDEX;
  1122. if(picb->ritType is ROUTER_IF_TYPE_INTERNAL)
  1123. {
  1124. info.bCallinInterface = TRUE;
  1125. }
  1126. else
  1127. {
  1128. info.bCallinInterface = FALSE;
  1129. }
  1130. nStatus = NtDeviceIoControlFile(g_hWanarpWrite,
  1131. NULL,
  1132. NULL,
  1133. NULL,
  1134. &IoStatusBlock,
  1135. IOCTL_WANARP_ADD_INTERFACE,
  1136. &info,
  1137. sizeof(WANARP_ADD_INTERFACE_INFO),
  1138. &info,
  1139. sizeof(WANARP_ADD_INTERFACE_INFO));
  1140. if(nStatus isnot STATUS_SUCCESS)
  1141. {
  1142. Trace2(ERR,
  1143. "AddInterfaceToWANARP: Status %x adding %S to WanArp",
  1144. nStatus,
  1145. picb->pwszName);
  1146. return RtlNtStatusToDosError(nStatus);
  1147. }
  1148. IpRtAssert(info.dwAdapterIndex isnot 0);
  1149. IpRtAssert(info.dwAdapterIndex isnot INVALID_IF_INDEX);
  1150. picb->dwIfIndex = info.dwAdapterIndex;
  1151. //
  1152. // If this was the internal interface allocate memory and copy out
  1153. // the name
  1154. //
  1155. if(picb->ritType is ROUTER_IF_TYPE_INTERNAL)
  1156. {
  1157. info.rgwcDeviceName[WANARP_MAX_DEVICE_NAME_LEN] = UNICODE_NULL;
  1158. picb->pwszDeviceName =
  1159. HeapAlloc(IPRouterHeap,
  1160. HEAP_ZERO_MEMORY,
  1161. (wcslen(info.rgwcDeviceName) + 1) * sizeof(WCHAR));
  1162. if(picb->pwszDeviceName is NULL)
  1163. {
  1164. Trace2(ERR,
  1165. "AddInterfaceToWANARP: Unable to allocate %d bytes when adding %S to wanarp",
  1166. (wcslen(info.rgwcDeviceName) + 1) * sizeof(WCHAR),
  1167. picb->pwszName);
  1168. return ERROR_NOT_ENOUGH_MEMORY;
  1169. }
  1170. wcscpy(picb->pwszDeviceName,
  1171. info.rgwcDeviceName);
  1172. Trace2(DEMAND,
  1173. "AddInterfaceToWANARP: %S device name %S\n",
  1174. picb->pwszName,
  1175. picb->pwszDeviceName);
  1176. g_pInternalInterfaceCb = picb;
  1177. }
  1178. TraceLeave("AddInterfaceToWANARP");
  1179. return NO_ERROR;
  1180. }
  1181. DWORD
  1182. DeleteInterfaceWithWanArp(
  1183. PICB picb
  1184. )
  1185. /*++
  1186. Routine Description:
  1187. Deletes the given interface with WANARP
  1188. Arguments:
  1189. The ICB of the interface to delete
  1190. Return Value:
  1191. --*/
  1192. {
  1193. DWORD out,dwResult;
  1194. OVERLAPPED overlapped ;
  1195. WANARP_DELETE_INTERFACE_INFO DeleteInfo;
  1196. TraceEnter("DeleteInterfaceWithWANARP");
  1197. DeleteInfo.dwUserIfIndex = picb->dwSeqNumber;
  1198. memset (&overlapped, 0, sizeof(OVERLAPPED)) ;
  1199. if (!DeviceIoControl (g_hWanarpWrite,
  1200. IOCTL_WANARP_DELETE_INTERFACE,
  1201. &DeleteInfo,
  1202. sizeof(WANARP_DELETE_INTERFACE_INFO),
  1203. NULL,
  1204. 0,
  1205. &out,
  1206. &overlapped))
  1207. {
  1208. dwResult = GetLastError();
  1209. Trace2(ERR,
  1210. "DeleteInterfaceWithWANARP: Error %d deleting %S",
  1211. dwResult,
  1212. picb->pwszName);
  1213. return dwResult;
  1214. }
  1215. TraceLeave("DeleteInterfaceWithWANARP");
  1216. return NO_ERROR;
  1217. }
  1218. #if 0
  1219. DWORD
  1220. CreateInternalInterfaceIcb(
  1221. PWCHAR pwszName,
  1222. ICB **ppicb
  1223. )
  1224. /*++
  1225. Routine Description:
  1226. This routine parses the TCPIP Parameters\Interfaces key to figure out
  1227. the name of the Internal Interface (ServerAdapter). The internal interface
  1228. has the substring "IPIN"
  1229. Arguments:
  1230. None
  1231. Return Value:
  1232. NO_ERROR
  1233. --*/
  1234. {
  1235. HKEY hIfKey;
  1236. DWORD i, dwResult, dwSize, dwNumEntries, dwMaxKeyLen;
  1237. BOOL bFoundAdapter;
  1238. CHAR *pbyKeyName, pszServerAdapter[256];
  1239. PICB pInterfaceCb;
  1240. TraceEnter("CreateInternalInterfaceIcb");
  1241. *ppicb = NULL;
  1242. dwResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  1243. REG_KEY_TCPIP_INTERFACES,
  1244. 0,
  1245. KEY_ALL_ACCESS,
  1246. &hIfKey);
  1247. if(dwResult isnot NO_ERROR)
  1248. {
  1249. Trace2(ERR,
  1250. "CreateInternalIcb: Error %d opening %s\n",
  1251. dwResult,
  1252. REG_KEY_TCPIP_INTERFACES);
  1253. return dwResult;
  1254. }
  1255. dwResult = RegQueryInfoKey(hIfKey,
  1256. NULL,
  1257. NULL,
  1258. NULL,
  1259. &dwNumEntries,
  1260. &dwMaxKeyLen,
  1261. NULL,
  1262. NULL,
  1263. NULL,
  1264. NULL,
  1265. NULL,
  1266. NULL);
  1267. if(dwResult isnot NO_ERROR)
  1268. {
  1269. Trace1(ERR,
  1270. "CreateIpIpInterface: Error %d querying key",
  1271. dwResult);
  1272. return dwResult;
  1273. }
  1274. //
  1275. // Have to have some interfaces
  1276. //
  1277. IpRtAssert(dwNumEntries isnot 0)
  1278. //
  1279. // Allocate enough memory for max key len
  1280. //
  1281. dwSize = (dwMaxKeyLen + 4) * sizeof(CHAR);
  1282. pbyKeyName = HeapAlloc(IPRouterHeap,
  1283. HEAP_ZERO_MEMORY,
  1284. dwSize);
  1285. if(pbyKeyName is NULL)
  1286. {
  1287. Trace1(ERR,
  1288. "CreateIpIpInterface: Error allocating %d bytes",
  1289. dwSize);
  1290. return ERROR_NOT_ENOUGH_MEMORY;
  1291. }
  1292. for(i = 0; ; i++)
  1293. {
  1294. DWORD dwKeyLen;
  1295. FILETIME ftLastTime;
  1296. dwKeyLen = dwMaxKeyLen;
  1297. dwResult = RegEnumKeyExA(hIfKey,
  1298. i,
  1299. pbyKeyName,
  1300. &dwKeyLen,
  1301. NULL,
  1302. NULL,
  1303. NULL,
  1304. &ftLastTime);
  1305. if(dwResult isnot NO_ERROR)
  1306. {
  1307. if(dwResult is ERROR_NO_MORE_ITEMS)
  1308. {
  1309. //
  1310. // Done
  1311. //
  1312. break;
  1313. }
  1314. continue;
  1315. }
  1316. //
  1317. // See if this is the server adapter. That is known by the fact that it contains
  1318. // IPIN as a substring
  1319. //
  1320. //
  1321. // Upcase the string
  1322. //
  1323. _strupr(pbyKeyName);
  1324. if(strstr(pbyKeyName,SERVER_ADAPTER_SUBSTRING) is NULL)
  1325. {
  1326. //
  1327. // This is not the server adapter
  1328. //
  1329. continue;
  1330. }
  1331. //
  1332. // Well we have a server adapter
  1333. //
  1334. ZeroMemory(pszServerAdapter,256);
  1335. strcpy(pszServerAdapter,"\\DEVICE\\");
  1336. strcat(pszServerAdapter,pbyKeyName);
  1337. Trace1(IF,
  1338. "InitInternalInterface: Using %s as the dial in adapter",
  1339. pszServerAdapter);
  1340. bFoundAdapter = TRUE;
  1341. break;
  1342. }
  1343. HeapFree(IPRouterHeap,
  1344. 0,
  1345. pbyKeyName);
  1346. RegCloseKey(hIfKey);
  1347. if(!bFoundAdapter)
  1348. {
  1349. return ERROR_NOT_FOUND;
  1350. }
  1351. else
  1352. {
  1353. WCHAR pwszTempName[256];
  1354. DWORD dwICBSize, dwNameLen;
  1355. UNICODE_STRING usTempString,usIcbName;
  1356. usTempString.MaximumLength = 256 * sizeof(WCHAR);
  1357. usTempString.Buffer = pwszTempName;
  1358. usIcbName.MaximumLength = 256 * sizeof(WCHAR);
  1359. //
  1360. // Only copy out the name and not the \Device\ part
  1361. //
  1362. MultiByteToWideChar(CP_ACP,
  1363. 0,
  1364. pszServerAdapter + strlen(ADAPTER_PREFIX_STRING),
  1365. -1,
  1366. pwszTempName,
  1367. 256);
  1368. //
  1369. // Add a WCHAR each for UNICODE_NULL for name and device name
  1370. // Add 2 bytes for alignment issues
  1371. //
  1372. dwNameLen =
  1373. (sizeof(WCHAR) * (wcslen(pwszName) + wcslen(pwszTempName) + 2)) + 2;
  1374. dwICBSize = sizeof(ICB) + dwNameLen;
  1375. pInterfaceCb = (PICB)HeapAlloc(IPRouterHeap,
  1376. HEAP_ZERO_MEMORY,
  1377. dwICBSize);
  1378. if(pInterfaceCb is NULL)
  1379. {
  1380. Trace1(ERR,
  1381. "InitInternalInterface: Error allocating %d bytes for ICB",
  1382. dwICBSize);
  1383. return ERROR_NOT_ENOUGH_MEMORY;
  1384. }
  1385. //
  1386. // Save the DIM name in the pwszName field
  1387. //
  1388. pInterfaceCb->pwszName = (PWCHAR) ((PBYTE)pInterfaceCb + sizeof(ICB));
  1389. //
  1390. // Word align the pointer
  1391. //
  1392. pInterfaceCb->pwszName =
  1393. (PWCHAR)(((UINT_PTR)pInterfaceCb->pwszName + 1) & ~0x1);
  1394. CopyMemory(pInterfaceCb->pwszName,
  1395. pwszName,
  1396. wcslen(pwszName) * sizeof(WCHAR));
  1397. //
  1398. // 1 WCHAR for UNICODE_NULL and 1 byte for alignment
  1399. //
  1400. pInterfaceCb->pwszDeviceName =
  1401. (PWCHAR)((PBYTE)pInterfaceCb->pwszName +
  1402. ((wcslen(pwszName) + 1) * sizeof(WCHAR)) + 1);
  1403. //
  1404. // And align this, too
  1405. //
  1406. pInterfaceCb->pwszDeviceName =
  1407. (PWCHAR)(((UINT_PTR)pInterfaceCb->pwszDeviceName + 1) & ~0x1);
  1408. usTempString.Length = sizeof(WCHAR) * wcslen(pwszTempName);
  1409. usIcbName.Buffer = pInterfaceCb->pwszDeviceName;
  1410. RtlUpcaseUnicodeString(&usIcbName,
  1411. &usTempString,
  1412. FALSE);
  1413. pInterfaceCb->pwszDeviceName[wcslen(pwszTempName)] = UNICODE_NULL;
  1414. *ppicb = pInterfaceCb;
  1415. }
  1416. TraceLeave("CreateInternalInterfaceIcb");
  1417. return NO_ERROR;
  1418. }
  1419. #endif
  1420. DWORD
  1421. AccessIfEntryWanArp(
  1422. IN DWORD dwAction,
  1423. IN PICB picb,
  1424. IN OUT PMIB_IFROW lpOutBuf
  1425. )
  1426. /*++
  1427. Routine Description:
  1428. Gets or sets the statistics from the wanarp
  1429. Arguments:
  1430. dwAction Can be SET_IF or GET_IF
  1431. picb the Interface Control Block
  1432. pOutBuf
  1433. Return Value:
  1434. NO_ERROR or some error code
  1435. --*/
  1436. {
  1437. NTSTATUS Status = STATUS_SUCCESS;
  1438. IO_STATUS_BLOCK IoStatusBlock;
  1439. WANARP_GET_IF_STATS_INFO GetStatsInfo;
  1440. TraceEnter("AccessIfEntryWanArp");
  1441. GetStatsInfo.dwUserIfIndex = picb->dwSeqNumber;
  1442. if(dwAction is ACCESS_GET)
  1443. {
  1444. Status = NtDeviceIoControlFile(g_hWanarpRead,
  1445. NULL,
  1446. NULL,
  1447. NULL,
  1448. &IoStatusBlock,
  1449. IOCTL_WANARP_GET_IF_STATS,
  1450. &GetStatsInfo,
  1451. sizeof(WANARP_GET_IF_STATS_INFO),
  1452. &GetStatsInfo,
  1453. sizeof(WANARP_GET_IF_STATS_INFO));
  1454. RtlCopyMemory(&(lpOutBuf->dwIndex),
  1455. &(GetStatsInfo.ifeInfo),
  1456. sizeof(IFEntry));
  1457. }
  1458. else
  1459. {
  1460. // To be implemented: return SUCCESS for now
  1461. }
  1462. if(Status isnot STATUS_SUCCESS)
  1463. {
  1464. IpRtAssert(Status isnot STATUS_PENDING);
  1465. Trace2(ERR,
  1466. "AccessIfEntryWanArp: NtStatus %x when getting information for %S",
  1467. Status,
  1468. picb->pwszName);
  1469. TraceLeave("AccessIfEntryWanArp");
  1470. return Status;
  1471. }
  1472. TraceLeave("AccessIfEntryWanArp");
  1473. return NO_ERROR;
  1474. }
  1475. DWORD
  1476. DeleteInternalInterface(
  1477. VOID
  1478. )
  1479. /*++
  1480. Routine Description:
  1481. Deletes the ServerAdapter (internal) interface
  1482. Locks:
  1483. Arguments:
  1484. Return Value:
  1485. NO_ERROR
  1486. --*/
  1487. {
  1488. if(g_pInternalInterfaceCb is NULL)
  1489. {
  1490. return NO_ERROR;
  1491. }
  1492. if(g_pInternalInterfaceCb->pwszDeviceName isnot NULL)
  1493. {
  1494. HeapFree(IPRouterHeap,
  1495. 0,
  1496. g_pInternalInterfaceCb->pwszDeviceName);
  1497. g_pInternalInterfaceCb->pwszDeviceName = NULL;
  1498. }
  1499. //
  1500. // Call DeleteSingleInterface to do the same thing as is done
  1501. // for LAN interfaces
  1502. //
  1503. DeleteSingleInterface(g_pInternalInterfaceCb);
  1504. RemoveInterfaceLookup(g_pInternalInterfaceCb);
  1505. HeapFree(IPRouterHeap,
  1506. 0,
  1507. g_pInternalInterfaceCb);
  1508. g_pInternalInterfaceCb = NULL;
  1509. return NO_ERROR;
  1510. }
  1511. DWORD
  1512. AddDemandFilterInterface(
  1513. PICB picb,
  1514. PRTR_INFO_BLOCK_HEADER pInterfaceInfo
  1515. )
  1516. /*++
  1517. Routine Description:
  1518. Adds an interface to the filter driver. This interface is never bound to
  1519. an IP interface, instead we add demand dial filters to it and when a
  1520. request is made to dial out, we match the packet causing the dialling
  1521. against the filters (using the TestPacket() function) and use the returned
  1522. action to determine whether we should dial out or not.
  1523. If there are no filters, the interface is not added to the driver.
  1524. Otherwise, a copy of the filters is kept with the picb, and a transformed
  1525. set of filters is added to the driver
  1526. The handle associated with the interface and the driver is kept in the
  1527. picb
  1528. Arguments:
  1529. picb
  1530. pInterfaceInfo
  1531. Return Value:
  1532. NO_ERROR
  1533. --*/
  1534. {
  1535. DWORD dwResult;
  1536. PPF_FILTER_DESCRIPTOR pfdFilters;
  1537. PFFORWARD_ACTION faAction;
  1538. PRTR_TOC_ENTRY pToc;
  1539. PFILTER_DESCRIPTOR pInfo;
  1540. ULONG i, j, ulSize, ulNumFilters;
  1541. TraceEnter("AddDemandFilterInterface");
  1542. IpRtAssert((picb->ritType is ROUTER_IF_TYPE_HOME_ROUTER) or
  1543. (picb->ritType is ROUTER_IF_TYPE_FULL_ROUTER));
  1544. IpRtAssert(picb->pDemandFilter is NULL);
  1545. picb->ihDemandFilterInterface = INVALID_HANDLE_VALUE;
  1546. pToc = GetPointerToTocEntry(IP_DEMAND_DIAL_FILTER_INFO,
  1547. pInterfaceInfo);
  1548. //
  1549. // We dont add if there is no INFO, or if the info size is 0 or
  1550. // if the number of filters is 0 AND the default action is DROP
  1551. //
  1552. if((pToc is NULL) or (pToc->InfoSize is 0))
  1553. {
  1554. //
  1555. // Either there is no filter info (TOC is NULL) or the user
  1556. // wanted the filters deleted (which they have been)
  1557. //
  1558. Trace1(IF,
  1559. "AddDemandFilterInterface: filter info NULL or info size 0 for %S, so leaving",
  1560. picb->pwszName);
  1561. TraceLeave("AddDemandFilterInterface");
  1562. return NO_ERROR;
  1563. }
  1564. pInfo = GetInfoFromTocEntry(pInterfaceInfo,
  1565. pToc);
  1566. if(pInfo is NULL)
  1567. {
  1568. Trace1(IF,
  1569. "AddDemandFilterInterface: filter info NULL for %S, so leaving",
  1570. picb->pwszName);
  1571. TraceLeave("AddDemandFilterInterface");
  1572. return NO_ERROR;
  1573. }
  1574. //
  1575. // See how many filters we have
  1576. //
  1577. pfdFilters = NULL;
  1578. ulNumFilters = pInfo->dwNumFilters;
  1579. if((ulNumFilters is 0) and
  1580. (pInfo->faDefaultAction is PF_ACTION_FORWARD))
  1581. {
  1582. Trace1(IF,
  1583. "AddDemandFilterInterface: 0 filters and default of FORWARD for %S, so leaving",
  1584. picb->pwszName);
  1585. TraceLeave("AddDemandFilterInterface");
  1586. return NO_ERROR;
  1587. }
  1588. //
  1589. // The size we need for these many filters
  1590. //
  1591. ulSize = FIELD_OFFSET(FILTER_DESCRIPTOR,fiFilter[0]) +
  1592. (ulNumFilters * sizeof(FILTER_INFO));
  1593. //
  1594. // The infosize must be atleast as large as the filters
  1595. //
  1596. IpRtAssert(ulSize <= pToc->InfoSize);
  1597. //
  1598. // Copy out the info for ourselves
  1599. //
  1600. picb->pDemandFilter = HeapAlloc(IPRouterHeap,
  1601. 0,
  1602. ulSize);
  1603. if(picb->pDemandFilter is NULL)
  1604. {
  1605. Trace1(ERR,
  1606. "AddDemandFilterInterface: Error allocating %d bytes for demand dial filters",
  1607. ulSize);
  1608. return ERROR_NOT_ENOUGH_MEMORY;
  1609. }
  1610. CopyMemory(picb->pDemandFilter,
  1611. pInfo,
  1612. ulSize);
  1613. faAction = pInfo->faDefaultAction;
  1614. if(ulNumFilters isnot 0)
  1615. {
  1616. PDWORD pdwAddr;
  1617. //
  1618. // We have filters, so copy them to the new format
  1619. // The address and mask will come at the end of all of the filters
  1620. // so we allocate 16 bytes extra for each filter. Then we add a
  1621. // 8 bytes so that we can align the block
  1622. //
  1623. ulSize = ulNumFilters * (sizeof(PF_FILTER_DESCRIPTOR) + 16) + 8;
  1624. pfdFilters = HeapAlloc(IPRouterHeap,
  1625. 0,
  1626. ulSize);
  1627. if(pfdFilters is NULL)
  1628. {
  1629. HeapFree(IPRouterHeap,
  1630. 0,
  1631. picb->pDemandFilter);
  1632. Trace1(ERR,
  1633. "AddDemandFilterInterface: Error allocating %d bytes",
  1634. ulSize);
  1635. return ERROR_NOT_ENOUGH_MEMORY;
  1636. }
  1637. //
  1638. // Pointer to the start of the address block
  1639. //
  1640. pdwAddr = (PDWORD)&(pfdFilters[ulNumFilters]);
  1641. //
  1642. // Now convert the filters
  1643. //
  1644. for(i = 0, j = 0; i < ulNumFilters; i++)
  1645. {
  1646. pfdFilters[i].dwFilterFlags = 0;
  1647. pfdFilters[i].dwRule = 0;
  1648. pfdFilters[i].pfatType = PF_IPV4;
  1649. //
  1650. // Set the pointers
  1651. //
  1652. pfdFilters[i].SrcAddr = (PBYTE)&(pdwAddr[j++]);
  1653. pfdFilters[i].SrcMask = (PBYTE)&(pdwAddr[j++]);
  1654. pfdFilters[i].DstAddr = (PBYTE)&(pdwAddr[j++]);
  1655. pfdFilters[i].DstMask = (PBYTE)&(pdwAddr[j++]);
  1656. //
  1657. // Copy in the src/dst addr/masks
  1658. //
  1659. *(PDWORD)pfdFilters[i].SrcAddr = pInfo->fiFilter[i].dwSrcAddr;
  1660. *(PDWORD)pfdFilters[i].SrcMask = pInfo->fiFilter[i].dwSrcMask;
  1661. *(PDWORD)pfdFilters[i].DstAddr = pInfo->fiFilter[i].dwDstAddr;
  1662. *(PDWORD)pfdFilters[i].DstMask = pInfo->fiFilter[i].dwDstMask;
  1663. //
  1664. // Copy the protocol
  1665. //
  1666. pfdFilters[i].dwProtocol = pInfo->fiFilter[i].dwProtocol;
  1667. //
  1668. // Late bound makes no sense for this
  1669. //
  1670. pfdFilters[i].fLateBound = 0;
  1671. //
  1672. // The ports
  1673. //
  1674. pfdFilters[i].wSrcPort = pInfo->fiFilter[i].wSrcPort;
  1675. pfdFilters[i].wDstPort = pInfo->fiFilter[i].wDstPort;
  1676. //
  1677. // Since we dont support ranges, set to 0
  1678. //
  1679. pfdFilters[i].wSrcPortHighRange = 0;
  1680. pfdFilters[i].wDstPortHighRange = 0;
  1681. }
  1682. }
  1683. //
  1684. // Now add create the interace and set the info
  1685. //
  1686. dwResult = PfCreateInterface(0,
  1687. faAction,
  1688. PF_ACTION_FORWARD,
  1689. FALSE,
  1690. FALSE,
  1691. &(picb->ihDemandFilterInterface));
  1692. if(dwResult isnot NO_ERROR)
  1693. {
  1694. Trace2(ERR,
  1695. "AddDemandFilterInterface: Err %d creating filter i/f for %S",
  1696. dwResult,
  1697. picb->pwszName);
  1698. }
  1699. else
  1700. {
  1701. //
  1702. // Set the filters
  1703. //
  1704. if(ulNumFilters isnot 0)
  1705. {
  1706. dwResult = PfAddFiltersToInterface(picb->ihDemandFilterInterface,
  1707. ulNumFilters,
  1708. pfdFilters,
  1709. 0,
  1710. NULL,
  1711. NULL);
  1712. if(dwResult isnot NO_ERROR)
  1713. {
  1714. Trace2(ERR,
  1715. "AddDemandFilterInterface: Err %d setting filters on %S",
  1716. dwResult,
  1717. picb->pwszName);
  1718. PfDeleteInterface(picb->ihDemandFilterInterface);
  1719. }
  1720. }
  1721. }
  1722. if(pfdFilters)
  1723. {
  1724. HeapFree(IPRouterHeap,
  1725. 0,
  1726. pfdFilters);
  1727. }
  1728. if(dwResult isnot NO_ERROR)
  1729. {
  1730. //
  1731. // Something bad happened. Set the handles to invalid so that
  1732. // we know we did not add the filters
  1733. //
  1734. picb->ihDemandFilterInterface = INVALID_HANDLE_VALUE;
  1735. if(picb->pDemandFilter)
  1736. {
  1737. HeapFree(IPRouterHeap,
  1738. 0,
  1739. picb->pDemandFilter);
  1740. picb->pDemandFilter = NULL;
  1741. }
  1742. }
  1743. TraceLeave("SetInterfaceFilterInfo");
  1744. return dwResult;
  1745. }
  1746. DWORD
  1747. DeleteDemandFilterInterface(
  1748. PICB picb
  1749. )
  1750. /*++
  1751. Routine Description:
  1752. This function deletes a filter interface (and all associated filters)
  1753. Also frees the memory holding the filters
  1754. Locks:
  1755. ICB_LIST held as WRITER
  1756. Arguments:
  1757. None
  1758. Return Value:
  1759. None
  1760. --*/
  1761. {
  1762. TraceEnter("DeleteDemandFilterInterface");
  1763. IpRtAssert((picb->ritType is ROUTER_IF_TYPE_HOME_ROUTER) or
  1764. (picb->ritType is ROUTER_IF_TYPE_FULL_ROUTER));
  1765. if(picb->pDemandFilter isnot NULL)
  1766. {
  1767. HeapFree(IPRouterHeap,
  1768. 0,
  1769. picb->pDemandFilter);
  1770. picb->pDemandFilter = NULL;
  1771. }
  1772. if(picb->ihDemandFilterInterface is INVALID_HANDLE_VALUE)
  1773. {
  1774. Trace1(IF,
  1775. "DeleteDemandFilterInterface: No context, assuming interface %S not added to filter driver",
  1776. picb->pwszName);
  1777. return NO_ERROR;
  1778. }
  1779. PfDeleteInterface(picb->ihDemandFilterInterface);
  1780. picb->ihDemandFilterInterface = INVALID_HANDLE_VALUE;
  1781. TraceLeave("DeleteDemandFilterInterface");
  1782. return NO_ERROR;
  1783. }
  1784. DWORD
  1785. SetDemandDialFilters(
  1786. PICB picb,
  1787. PRTR_INFO_BLOCK_HEADER pInterfaceInfo
  1788. )
  1789. {
  1790. DWORD dwResult;
  1791. PRTR_TOC_ENTRY pToc;
  1792. if((picb->ritType isnot ROUTER_IF_TYPE_HOME_ROUTER) and
  1793. (picb->ritType isnot ROUTER_IF_TYPE_FULL_ROUTER))
  1794. {
  1795. return NO_ERROR;
  1796. }
  1797. TraceEnter("SetDemandDialFilters");
  1798. pToc = GetPointerToTocEntry(IP_DEMAND_DIAL_FILTER_INFO,
  1799. pInterfaceInfo);
  1800. if(pToc is NULL)
  1801. {
  1802. //
  1803. // Both NULL, means we dont need to change anything
  1804. //
  1805. Trace1(DEMAND,
  1806. "SetDemandDialFilters: No filters for %S, so leaving",
  1807. picb->pwszName);
  1808. TraceLeave("SetDemandDialFilters");
  1809. return NO_ERROR;
  1810. }
  1811. if(picb->ihDemandFilterInterface isnot INVALID_HANDLE_VALUE)
  1812. {
  1813. //
  1814. // This interface was added to the filter driver,
  1815. // Delete it so that the filters are all deleted and then readd
  1816. // the filters
  1817. //
  1818. IpRtAssert(picb->pDemandFilter isnot NULL);
  1819. dwResult = DeleteDemandFilterInterface(picb);
  1820. //
  1821. // This better succeed, we dont have a failure path here
  1822. //
  1823. IpRtAssert(dwResult is NO_ERROR);
  1824. }
  1825. dwResult = AddDemandFilterInterface(picb,
  1826. pInterfaceInfo);
  1827. if(dwResult isnot NO_ERROR)
  1828. {
  1829. CHAR Name[MAX_INTERFACE_NAME_LEN + 1];
  1830. PCHAR pszName;
  1831. pszName = Name;
  1832. WideCharToMultiByte(CP_ACP,
  1833. 0,
  1834. picb->pwszName,
  1835. -1,
  1836. pszName,
  1837. MAX_INTERFACE_NAME_LEN,
  1838. NULL,
  1839. NULL);
  1840. LogErr1(CANT_ADD_DD_FILTERS,
  1841. pszName,
  1842. dwResult);
  1843. }
  1844. TraceLeave("SetDemandDialFilters");
  1845. return dwResult;
  1846. }
  1847. DWORD
  1848. GetDemandFilters(
  1849. PICB picb,
  1850. PRTR_TOC_ENTRY pToc,
  1851. PBYTE pbDataPtr,
  1852. PRTR_INFO_BLOCK_HEADER pInfoHdrAndBuffer,
  1853. PDWORD pdwSize
  1854. )
  1855. /*++
  1856. Routine Description:
  1857. This function copies out the demand dial filters and set the TOC
  1858. Locks:
  1859. ICB_LIST lock held as READER
  1860. Arguments:
  1861. None
  1862. Return Value:
  1863. None
  1864. --*/
  1865. {
  1866. DWORD dwInBufLen,i;
  1867. PFILTER_DESCRIPTOR pFilterDesc;
  1868. TraceEnter("GetDemandFilters");
  1869. IpRtAssert((picb->ritType is ROUTER_IF_TYPE_HOME_ROUTER) or
  1870. (picb->ritType is ROUTER_IF_TYPE_FULL_ROUTER));
  1871. //
  1872. // Set size returned to 0
  1873. //
  1874. *pdwSize = 0;
  1875. //
  1876. // Safe init of both the TOCs.
  1877. //
  1878. //pToc[0].InfoVersion = IP_DEMAND_DIAL_FILTER_INFO;
  1879. pToc[0].InfoType = IP_DEMAND_DIAL_FILTER_INFO;
  1880. pToc[0].Count = 0;
  1881. pToc[0].InfoSize = 0;
  1882. if((picb->ihDemandFilterInterface is INVALID_HANDLE_VALUE) or
  1883. (picb->pDemandFilter is NULL))
  1884. {
  1885. Trace1(IF,
  1886. "GetDemandFilters: No context or no filters for %S",
  1887. picb->pwszName);
  1888. return ERROR_NO_DATA;
  1889. }
  1890. //
  1891. // Set the offset in the TOC
  1892. //
  1893. pToc[0].Offset = (ULONG) (pbDataPtr - (PBYTE)pInfoHdrAndBuffer);
  1894. pToc[0].Count = 1;
  1895. pToc[0].InfoSize = FIELD_OFFSET(FILTER_DESCRIPTOR,fiFilter[0]) +
  1896. (picb->pDemandFilter->dwNumFilters * sizeof(FILTER_INFO));
  1897. //pToc[0].Version = IPRTR_INFO_VERSION_5;
  1898. //
  1899. // Just copy out the filters
  1900. //
  1901. CopyMemory(pbDataPtr,
  1902. picb->pDemandFilter,
  1903. pToc[0].InfoSize);
  1904. //
  1905. // The size copied in
  1906. //
  1907. *pdwSize = pToc[0].InfoSize;
  1908. TraceLeave("GetDemandFilters");
  1909. return NO_ERROR;
  1910. }
  1911. VOID
  1912. TryUpdateInternalInterface(
  1913. VOID
  1914. )
  1915. /*++
  1916. Routine Description:
  1917. This function is called when a client dials in and we have not
  1918. bound the internal interface
  1919. The way of doing this is as follows:
  1920. If the server adapter is not initialized, read the address from the
  1921. registry. If we read the address, all is good, break out and move on
  1922. If no address was found, wait on the DHCP event with a time out
  1923. If someone configures the server adapter in the meantime, we will get
  1924. the DHCP event, if we miss the event (since it is PULSED), we will
  1925. timeout and we loop back and retry the steps above.
  1926. Now we do this N times. If we fail, then we just wait for the next
  1927. client to dial in
  1928. Locks:
  1929. ICB_LIST held as WRITER
  1930. Arguments:
  1931. None
  1932. Return Value:
  1933. None
  1934. --*/
  1935. {
  1936. DWORD dwResult, dwInitCount;
  1937. TraceEnter("TryUpdateInternalInterface");
  1938. dwInitCount = 0;
  1939. //
  1940. // This is only called when the server is not initialized
  1941. //
  1942. IpRtAssert(g_bUninitServer);
  1943. while(g_bUninitServer)
  1944. {
  1945. Trace0(ERR,
  1946. "TryUpdateInternalInterface: Server adapter not init");
  1947. dwResult = UpdateBindingInformation(g_pInternalInterfaceCb);
  1948. if(dwResult isnot NO_ERROR)
  1949. {
  1950. if((dwResult is ERROR_ADDRESS_ALREADY_ASSOCIATED) and
  1951. (g_pInternalInterfaceCb->bBound is TRUE))
  1952. {
  1953. //
  1954. // This means that the worker thread found an address
  1955. //
  1956. IpRtAssert(g_pInternalInterfaceCb->dwNumAddresses is 1);
  1957. Trace1(IF,
  1958. "TryUpdateInternalInterface: Address already present for %S",
  1959. g_pInternalInterfaceCb->pwszName);
  1960. g_bUninitServer = FALSE;
  1961. break;
  1962. }
  1963. else
  1964. {
  1965. Trace2(ERR,
  1966. "TryUpdateInternalInterface: Err %d trying to update binding for %S",
  1967. dwResult,
  1968. g_pInternalInterfaceCb->pwszName);
  1969. }
  1970. dwInitCount++;
  1971. if(dwInitCount >= MAX_SERVER_INIT_TRIES)
  1972. {
  1973. //
  1974. // We try x times and then give up. Next client around
  1975. // things should work
  1976. //
  1977. break;
  1978. }
  1979. else
  1980. {
  1981. Sleep(SERVER_INIT_SLEEP_TIME);
  1982. }
  1983. }
  1984. else
  1985. {
  1986. g_bUninitServer = FALSE;
  1987. }
  1988. }
  1989. //
  1990. // If we broke out because the interface was initialized, bring it up
  1991. //
  1992. if(!g_bUninitServer)
  1993. {
  1994. dwResult = LanEtcInterfaceDownToUp(g_pInternalInterfaceCb,
  1995. FALSE);
  1996. if(dwResult isnot NO_ERROR)
  1997. {
  1998. Trace1(ERR,
  1999. "TryUpdateInternalInterface: Error %d bringing up server if",
  2000. dwResult);
  2001. }
  2002. }
  2003. TraceLeave("TryUpdateInternalInterface");
  2004. }