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

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