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.

1473 lines
41 KiB

  1. /********************************************************************/
  2. /** Copyright(c) 1995 Microsoft Corporation. **/
  3. /********************************************************************/
  4. //***
  5. //
  6. // Filename: ifobject.c
  7. //
  8. // Description: Routines to manipulate ROUTER_INTERFACE_OBJECTs
  9. //
  10. // History: May 11,1995 NarenG Created original version.
  11. //
  12. #include "ddm.h"
  13. #include "objects.h"
  14. #include "handlers.h"
  15. #include "timer.h"
  16. #include <util.h>
  17. #include <rasapiif.h>
  18. #include <ras.h>
  19. typedef struct _DDM_SUBENTRY_ENUMCONTEXT
  20. {
  21. ROUTER_INTERFACE_OBJECT *pIfObject;
  22. BOOL fAtLeastOneDeviceAvailable;
  23. } DDM_SUBENTRY_ENUMCONTEXT;
  24. //
  25. // This actually lives in rasapi.dll
  26. //
  27. DWORD
  28. DDMGetPhonebookInfo(
  29. LPWSTR lpwsPhonebookName,
  30. LPWSTR lpwsPhonebookEntry,
  31. LPDWORD lpdwNumSubEntries,
  32. LPDWORD lpdwNumRedialAttempts,
  33. LPDWORD lpdwNumSecondsBetweenAttempts,
  34. BOOL * lpfRedialOnLinkFailure,
  35. CHAR * szzParameters,
  36. LPDWORD lpdwDialMode,
  37. PVOID * ppvContext,
  38. PVOID pvSubEntryEnumHandler,
  39. PVOID pvSubEntryEnumHandlerContext
  40. );
  41. VOID
  42. DDMFreePhonebookContext(
  43. VOID *pvContext
  44. );
  45. VOID
  46. DDMEnumerateSubEntries(
  47. PVOID pvContext,
  48. LPWSTR pwsInterfaceName,
  49. FARPROC IfObjectSubEntryEnumHandler,
  50. VOID *pvEnumContext
  51. );
  52. RASEVENT *
  53. DDMGetRasEvent(HCONN hConnection)
  54. {
  55. CONNECTION_OBJECT *pConn = NULL;
  56. RASEVENT *pEvent;
  57. pEvent = (RASEVENT *) LOCAL_ALLOC(LPTR, sizeof(RASEVENT));
  58. if(pEvent != NULL)
  59. {
  60. pConn = ConnObjGetPointer(hConnection);
  61. if(pConn != NULL)
  62. {
  63. if( pConn->pDeviceList &&
  64. pConn->pDeviceList[0])
  65. {
  66. pEvent->rDeviceType =
  67. pConn->pDeviceList[0]->dwDeviceType;
  68. }
  69. CopyMemory(&pEvent->guidId, &pConn->guid,
  70. sizeof(GUID));
  71. pEvent->hConnection = hConnection;
  72. }
  73. }
  74. return pEvent;
  75. }
  76. //**
  77. //
  78. // Call: IfObjectAllocateAndInit
  79. //
  80. // Returns: ROUTER_INTERFACE_OBJECT * - Success
  81. // NULL - Failure
  82. //
  83. // Description: Allocates and initializes a ROUTER_INTERFACE_OBJECT structure
  84. //
  85. ROUTER_INTERFACE_OBJECT *
  86. IfObjectAllocateAndInit(
  87. IN LPWSTR lpwstrName,
  88. IN ROUTER_INTERFACE_STATE State,
  89. IN ROUTER_INTERFACE_TYPE IfType,
  90. IN HCONN hConnection,
  91. IN BOOL fEnabled,
  92. IN DWORD dwMinUnreachabilityInterval,
  93. IN DWORD dwMaxUnreachabilityInterval,
  94. IN LPWSTR lpwsDialoutHours,
  95. IN OUT PVOID * ppvContext
  96. )
  97. {
  98. return( ( (ROUTER_INTERFACE_OBJECT*(*)(
  99. LPWSTR,
  100. ROUTER_INTERFACE_STATE,
  101. ROUTER_INTERFACE_TYPE,
  102. HCONN,
  103. BOOL,
  104. DWORD,
  105. DWORD,
  106. LPWSTR,
  107. PVOID *))gblDDMConfigInfo.lpfnIfObjectAllocateAndInit)(
  108. lpwstrName,
  109. State,
  110. IfType,
  111. hConnection,
  112. fEnabled,
  113. dwMinUnreachabilityInterval,
  114. dwMaxUnreachabilityInterval,
  115. lpwsDialoutHours,
  116. NULL));
  117. }
  118. //**
  119. //
  120. // Call: IfObjectAreAllTransportsDisconnected
  121. //
  122. // Returns: TRUE
  123. // FALSE
  124. //
  125. // Description: Checks to see if all the transports for an interface are
  126. // disconnected.
  127. //
  128. BOOL
  129. IfObjectAreAllTransportsDisconnected(
  130. IN ROUTER_INTERFACE_OBJECT * pIfObject
  131. )
  132. {
  133. DWORD dwTransportIndex;
  134. for ( dwTransportIndex = 0;
  135. dwTransportIndex < gblDDMConfigInfo.dwNumRouterManagers;
  136. dwTransportIndex++ )
  137. {
  138. if ( pIfObject->Transport[dwTransportIndex].fState
  139. & RITRANSPORT_CONNECTED )
  140. {
  141. return( FALSE );
  142. }
  143. }
  144. return( TRUE );
  145. }
  146. //**
  147. //
  148. // Call: IfObjectGetPointerByName
  149. //
  150. // Returns: ROUTER_INTERFACE_OBJECT * - Pointer to the interface object
  151. // structure with the given name, if it exists.
  152. // NULL - if it doesn't exist.
  153. //
  154. // Description: Simply calls the DIM entry point to do the work.
  155. //
  156. ROUTER_INTERFACE_OBJECT *
  157. IfObjectGetPointerByName(
  158. IN LPWSTR lpwstrName,
  159. IN BOOL fIncludeClientInterfaces
  160. )
  161. {
  162. return(((ROUTER_INTERFACE_OBJECT*(*)( LPWSTR, BOOL ))
  163. gblDDMConfigInfo.lpfnIfObjectGetPointerByName)(
  164. lpwstrName,
  165. fIncludeClientInterfaces));
  166. }
  167. //**
  168. //
  169. // Call: IfObjectGetPointer
  170. //
  171. // Returns: ROUTER_INTERFACE_OBJECT * - Pointer to the interface object
  172. // structure with the given handle, if it exists.
  173. // NULL - if it doesn't exist.
  174. //
  175. // Description: Simply calls the DIM entry point to do the work.
  176. //
  177. ROUTER_INTERFACE_OBJECT *
  178. IfObjectGetPointer(
  179. IN HANDLE hDIMInterface
  180. )
  181. {
  182. return(((ROUTER_INTERFACE_OBJECT*(*)( HANDLE ))
  183. gblDDMConfigInfo.lpfnIfObjectGetPointer)( hDIMInterface ));
  184. }
  185. //**
  186. //
  187. // Call: IfObjectRemove
  188. //
  189. // Returns: None
  190. //
  191. // Description: Simply calls the DIM entrypoint to remove the interface object
  192. // from the table. The object is DeAllocated.
  193. //
  194. VOID
  195. IfObjectRemove(
  196. IN HANDLE hDIMInterface
  197. )
  198. {
  199. ((VOID(*)( HANDLE ))gblDDMConfigInfo.lpfnIfObjectRemove)( hDIMInterface );
  200. }
  201. //**
  202. //
  203. // Call: IfObjectDisconnected
  204. //
  205. // Returns: None
  206. //
  207. // Description: Sets this interface to the disconnected state
  208. //
  209. VOID
  210. IfObjectDisconnected(
  211. ROUTER_INTERFACE_OBJECT * pIfObject
  212. )
  213. {
  214. DWORD dwIndex;
  215. BOOL fReachable = TRUE;
  216. HANDLE hConnection;
  217. //
  218. // If already disconnected, then simply return
  219. //
  220. if ( pIfObject->State == RISTATE_DISCONNECTED )
  221. {
  222. return;
  223. }
  224. //
  225. // If this interface is persistent then we do not want to connect
  226. // again because the local admin or router managers initiated the
  227. // disconnect
  228. //
  229. if ( pIfObject->fFlags & IFFLAG_DISCONNECT_INITIATED )
  230. {
  231. pIfObject->dwNumOfReConnectAttemptsCounter = 0;
  232. TimerQRemove( pIfObject->hDIMInterface, ReConnectInterface );
  233. TimerQRemove( pIfObject->hDIMInterface, ReConnectPersistentInterface );
  234. }
  235. hConnection = pIfObject->hConnection;
  236. pIfObject->State = RISTATE_DISCONNECTED;
  237. pIfObject->hConnection = (HCONN)INVALID_HANDLE_VALUE;
  238. pIfObject->fFlags &= ~IFFLAG_LOCALLY_INITIATED;
  239. pIfObject->hRasConn = (HRASCONN)NULL;
  240. //
  241. // If we are not unreachable due to connection failure
  242. //
  243. if ( !( pIfObject->fFlags & IFFLAG_CONNECTION_FAILURE ) )
  244. {
  245. //
  246. // Check reachability state
  247. //
  248. DWORD dwUnreachabilityReason;
  249. if ( pIfObject->fFlags & IFFLAG_OUT_OF_RESOURCES )
  250. {
  251. dwUnreachabilityReason = INTERFACE_OUT_OF_RESOURCES;
  252. fReachable = FALSE;
  253. }
  254. else if ( gblDDMConfigInfo.pServiceStatus->dwCurrentState
  255. == SERVICE_PAUSED )
  256. {
  257. dwUnreachabilityReason = INTERFACE_SERVICE_IS_PAUSED;
  258. fReachable = FALSE;
  259. }
  260. else if ( !( pIfObject->fFlags & IFFLAG_ENABLED ) )
  261. {
  262. dwUnreachabilityReason = INTERFACE_DISABLED;
  263. fReachable = FALSE;
  264. }
  265. else if ( pIfObject->fFlags & IFFLAG_DIALOUT_HOURS_RESTRICTION )
  266. {
  267. dwUnreachabilityReason = INTERFACE_DIALOUT_HOURS_RESTRICTION;
  268. fReachable = FALSE;
  269. }
  270. //
  271. // Notify the router manager that this interface is disabled if the
  272. // admin has disabled it or the service is paused, now that the
  273. // interface is disconnected.
  274. //
  275. for ( dwIndex = 0;
  276. dwIndex < gblDDMConfigInfo.dwNumRouterManagers;
  277. dwIndex++ )
  278. {
  279. pIfObject->Transport[dwIndex].fState &= ~RITRANSPORT_CONNECTED;
  280. if ( !fReachable )
  281. {
  282. if (pIfObject->Transport[dwIndex].hInterface ==
  283. INVALID_HANDLE_VALUE)
  284. {
  285. continue;
  286. }
  287. gblRouterManagers[dwIndex].DdmRouterIf.InterfaceNotReachable(
  288. pIfObject->Transport[dwIndex].hInterface,
  289. dwUnreachabilityReason );
  290. }
  291. }
  292. if ( !fReachable )
  293. {
  294. if ( pIfObject->IfType == ROUTER_IF_TYPE_FULL_ROUTER )
  295. {
  296. LogUnreachabilityEvent( dwUnreachabilityReason,
  297. pIfObject->lpwsInterfaceName );
  298. }
  299. }
  300. //
  301. // If this interface is marked as persistent then try to reconnect
  302. // only if the admin did not disconnect the interface
  303. //
  304. if ( ( fReachable ) &&
  305. ( pIfObject->fFlags & IFFLAG_PERSISTENT ) &&
  306. ( !( pIfObject->fFlags & IFFLAG_DISCONNECT_INITIATED ) ) )
  307. {
  308. TimerQInsert( pIfObject->hDIMInterface,
  309. 1,
  310. ReConnectPersistentInterface );
  311. }
  312. //
  313. // Notify that this connection has been disconnected
  314. //
  315. IfObjectConnectionChangeNotification();
  316. {
  317. //
  318. // Notify netman that a connection went down.
  319. //
  320. DWORD retcode;
  321. RASEVENT *pRasEvent = NULL;
  322. CONNECTION_OBJECT *pConn = NULL;
  323. pRasEvent = DDMGetRasEvent(hConnection);
  324. if(pRasEvent != NULL)
  325. {
  326. pRasEvent->Type = INCOMING_DISCONNECTED;
  327. retcode = RasSendNotification(pRasEvent);
  328. DDM_PRINT(gblDDMConfigInfo.dwTraceId, TRACE_FSM,
  329. "RasSendNotification(INCOMING_DISCONNETED rc=0x%x",
  330. retcode);
  331. LOCAL_FREE(pRasEvent);
  332. }
  333. }
  334. }
  335. }
  336. //**
  337. //
  338. // Call: IfObjectConnected
  339. //
  340. // Returns: None
  341. //
  342. // Description: Sets this interface to the CONNECTED state and notifies the
  343. // router managers, if any, about unreachable transports.
  344. //
  345. DWORD
  346. IfObjectConnected(
  347. IN HANDLE hDDMInterface,
  348. IN HCONN hConnection,
  349. IN PPP_PROJECTION_RESULT *pProjectionResult
  350. )
  351. {
  352. DWORD dwIndex;
  353. ROUTER_INTERFACE_OBJECT * pIfObject;
  354. BOOL fXportConnected = FALSE;
  355. EnterCriticalSection( &(gblpInterfaceTable->CriticalSection) );
  356. pIfObject = IfObjectGetPointer( hDDMInterface );
  357. if ( pIfObject == (ROUTER_INTERFACE_OBJECT *)NULL )
  358. {
  359. LeaveCriticalSection( &(gblpInterfaceTable->CriticalSection) );
  360. return( ERROR_INVALID_HANDLE );
  361. }
  362. if ( pIfObject->State == RISTATE_CONNECTED )
  363. {
  364. //
  365. // Already connected
  366. //
  367. LeaveCriticalSection( &(gblpInterfaceTable->CriticalSection) );
  368. return( NO_ERROR );
  369. }
  370. pIfObject->hConnection = hConnection;
  371. pIfObject->State = RISTATE_CONNECTED;
  372. pIfObject->fFlags &= ~IFFLAG_CONNECTION_FAILURE;
  373. //
  374. // If we are connected and we initiated the connection then reset the
  375. // unreachability interval
  376. //
  377. if ( pIfObject->fFlags & IFFLAG_LOCALLY_INITIATED )
  378. {
  379. pIfObject->dwReachableAfterSeconds
  380. = pIfObject->dwReachableAfterSecondsMin;
  381. }
  382. //
  383. // Remove any reconnect calls that may be on the timer queue
  384. //
  385. TimerQRemove( pIfObject->hDIMInterface, ReConnectInterface );
  386. TimerQRemove( pIfObject->hDIMInterface, ReConnectPersistentInterface );
  387. for ( dwIndex = 0;
  388. dwIndex < gblDDMConfigInfo.dwNumRouterManagers;
  389. dwIndex++ )
  390. {
  391. fXportConnected = FALSE;
  392. switch( gblRouterManagers[dwIndex].DdmRouterIf.dwProtocolId )
  393. {
  394. case PID_IPX:
  395. if ( pProjectionResult->ipx.dwError == NO_ERROR )
  396. {
  397. fXportConnected = TRUE;
  398. }
  399. break;
  400. case PID_IP:
  401. if ( pProjectionResult->ip.dwError == NO_ERROR )
  402. {
  403. fXportConnected = TRUE;
  404. }
  405. break;
  406. default:
  407. break;
  408. }
  409. if ( pIfObject->Transport[dwIndex].hInterface == INVALID_HANDLE_VALUE )
  410. {
  411. continue;
  412. }
  413. if ( fXportConnected )
  414. {
  415. DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM,
  416. "Notifying Protocol = 0x%x,Interface=%ws is Connected",
  417. gblRouterManagers[dwIndex].DdmRouterIf.dwProtocolId,
  418. pIfObject->lpwsInterfaceName );
  419. pIfObject->Transport[dwIndex].fState |= RITRANSPORT_CONNECTED;
  420. gblRouterManagers[dwIndex].DdmRouterIf.InterfaceConnected(
  421. pIfObject->Transport[dwIndex].hInterface,
  422. NULL,
  423. pProjectionResult );
  424. }
  425. else
  426. {
  427. DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM,
  428. "Notifying Protocol = 0x%x,Interface=%ws is UnReachable=%d",
  429. gblRouterManagers[dwIndex].DdmRouterIf.dwProtocolId,
  430. pIfObject->lpwsInterfaceName,
  431. INTERFACE_CONNECTION_FAILURE );
  432. gblRouterManagers[dwIndex].DdmRouterIf.InterfaceNotReachable(
  433. pIfObject->Transport[dwIndex].hInterface,
  434. INTERFACE_CONNECTION_FAILURE );
  435. }
  436. }
  437. IfObjectConnectionChangeNotification();
  438. LeaveCriticalSection( &(gblpInterfaceTable->CriticalSection) );
  439. {
  440. DWORD retcode;
  441. RASEVENT *pRasEvent = NULL;
  442. CONNECTION_OBJECT *pConn = NULL;
  443. //
  444. // Get the device type
  445. //
  446. EnterCriticalSection(&(gblDeviceTable.CriticalSection));
  447. pRasEvent = DDMGetRasEvent(hConnection);
  448. LeaveCriticalSection(&(gblDeviceTable.CriticalSection));
  449. if(pRasEvent != NULL)
  450. {
  451. //
  452. // Notify netman of the connection
  453. //
  454. pRasEvent->Type = INCOMING_CONNECTED;
  455. retcode = RasSendNotification(pRasEvent);
  456. DDM_PRINT(gblDDMConfigInfo.dwTraceId, TRACE_FSM,
  457. "RasSendNotification(ENTRY_CONNECTED) rc=0x%x",
  458. retcode);
  459. LOCAL_FREE(pRasEvent);
  460. }
  461. }
  462. return( NO_ERROR );
  463. }
  464. //**
  465. //
  466. // Call: IfObjectComputeReachableDelay
  467. //
  468. // Returns: The delay
  469. //
  470. // Description: Computes the next reachability delay based on the
  471. // current one. Following is the sequenced used:
  472. //
  473. // min, 10, 20, 35, 50, 65, 90, 120, 120, 120, ...
  474. //
  475. // The reachability delay is used to govern when to
  476. // re-attempt to connect an interface that in the
  477. // past was unable to connect (presumably because of
  478. // an error on the other side).
  479. //
  480. // In Win2k, the sequence was x0=min, xi = (xi-1 * 2)
  481. // This sequence was found to be problematic because
  482. // the increase was so steep that it was common in
  483. // installations with many interfaces to find interfaces
  484. // that wouldn't be retried for days.
  485. //
  486. // The new sequence is designed to max out at two hours.
  487. // If an interface is expected to be unreachable for more
  488. // than two hours at a time, then a dialout hours restriction
  489. // should be used to achieve the desired effect.
  490. //
  491. DWORD
  492. IfObjectComputeReachableDelay(
  493. IN ROUTER_INTERFACE_OBJECT * pIfObject)
  494. {
  495. DWORD dwSeconds = 0;
  496. if (pIfObject->dwReachableAfterSeconds ==
  497. pIfObject->dwReachableAfterSecondsMin)
  498. {
  499. dwSeconds = 600;
  500. }
  501. switch (pIfObject->dwReachableAfterSeconds)
  502. {
  503. case 10*60:
  504. dwSeconds = 20*60;
  505. break;
  506. case 20*60:
  507. dwSeconds = 35*60;
  508. break;
  509. case 35*60:
  510. dwSeconds = 50*60;
  511. break;
  512. case 50*60:
  513. dwSeconds = 65*60;
  514. break;
  515. case 65*60:
  516. dwSeconds = 90*60;
  517. break;
  518. case 90*60:
  519. case 120*60:
  520. dwSeconds = 120*60;
  521. break;
  522. }
  523. return dwSeconds;
  524. }
  525. //**
  526. //
  527. // Call: IfObjectNotifyOfReachabilityChange
  528. //
  529. // Returns: None
  530. //
  531. // Description: Notifies the object of change in reachablity status.
  532. //
  533. //
  534. VOID
  535. IfObjectNotifyOfReachabilityChange(
  536. IN ROUTER_INTERFACE_OBJECT * pIfObject,
  537. IN BOOL fReachable,
  538. IN UNREACHABILITY_REASON dwReason
  539. )
  540. {
  541. DWORD dwIndex;
  542. if ( pIfObject->IfType != ROUTER_IF_TYPE_FULL_ROUTER )
  543. {
  544. return;
  545. }
  546. if ( pIfObject->State != RISTATE_DISCONNECTED )
  547. {
  548. return;
  549. }
  550. switch( dwReason )
  551. {
  552. case INTERFACE_SERVICE_IS_PAUSED:
  553. //
  554. // Check if we are unreachable due to other reasons as well, if we
  555. // are, then no need to notify this object of (un)reachability.
  556. //
  557. if ( pIfObject->fFlags & IFFLAG_OUT_OF_RESOURCES )
  558. {
  559. return;
  560. }
  561. if ( !( pIfObject->fFlags & IFFLAG_ENABLED ) )
  562. {
  563. return;
  564. }
  565. if ( pIfObject->fFlags & IFFLAG_CONNECTION_FAILURE )
  566. {
  567. return;
  568. }
  569. if ( pIfObject->fFlags & IFFLAG_DIALOUT_HOURS_RESTRICTION )
  570. {
  571. return;
  572. }
  573. break;
  574. case INTERFACE_CONNECTION_FAILURE:
  575. //
  576. // If we are marking this interface as not reachable due to connection
  577. // failure then we will mark as reachable after dwReachableAfterSeconds
  578. //
  579. if ( !fReachable )
  580. {
  581. //
  582. // Don't do this if the admin disconnected the interface
  583. //
  584. if ( !( pIfObject->fFlags & IFFLAG_DISCONNECT_INITIATED ) )
  585. {
  586. DWORD dwDelay, dwTime, dwDelta, dwCur;
  587. dwCur = pIfObject->dwReachableAfterSeconds;
  588. dwDelay = IfObjectComputeReachableDelay(pIfObject);
  589. dwDelta = (dwDelay > dwCur) ? dwDelay - dwCur : 0;
  590. if (dwDelta != 0)
  591. {
  592. dwTime = dwCur + (GetTickCount() % dwDelta);
  593. }
  594. else
  595. {
  596. dwTime = dwCur;
  597. }
  598. DDMTRACE2(
  599. "Will mark interface %ws as reachable after %d seconds",
  600. pIfObject->lpwsInterfaceName, dwTime );
  601. TimerQInsert(
  602. pIfObject->hDIMInterface,
  603. dwTime,
  604. MarkInterfaceAsReachable);
  605. if (dwDelay < pIfObject->dwReachableAfterSecondsMax)
  606. {
  607. pIfObject->dwReachableAfterSeconds = dwDelay;
  608. }
  609. }
  610. }
  611. else
  612. {
  613. //
  614. // Notify of reachability only if the interface is reachable
  615. //
  616. if ( pIfObject->fFlags & IFFLAG_OUT_OF_RESOURCES )
  617. {
  618. return;
  619. }
  620. if ( gblDDMConfigInfo.pServiceStatus->dwCurrentState
  621. == SERVICE_PAUSED )
  622. {
  623. return;
  624. }
  625. if ( !( pIfObject->fFlags & IFFLAG_ENABLED ) )
  626. {
  627. return;
  628. }
  629. if ( pIfObject->fFlags & IFFLAG_DIALOUT_HOURS_RESTRICTION )
  630. {
  631. return;
  632. }
  633. }
  634. break;
  635. case INTERFACE_DISABLED:
  636. if ( pIfObject->fFlags & IFFLAG_OUT_OF_RESOURCES )
  637. {
  638. return;
  639. }
  640. if ( gblDDMConfigInfo.pServiceStatus->dwCurrentState == SERVICE_PAUSED )
  641. {
  642. return;
  643. }
  644. if ( pIfObject->fFlags & IFFLAG_CONNECTION_FAILURE )
  645. {
  646. return;
  647. }
  648. if ( pIfObject->fFlags & IFFLAG_DIALOUT_HOURS_RESTRICTION )
  649. {
  650. return;
  651. }
  652. break;
  653. case INTERFACE_OUT_OF_RESOURCES:
  654. if ( gblDDMConfigInfo.pServiceStatus->dwCurrentState == SERVICE_PAUSED )
  655. {
  656. return;
  657. }
  658. if ( !( pIfObject->fFlags & IFFLAG_ENABLED ) )
  659. {
  660. return;
  661. }
  662. if ( pIfObject->fFlags & IFFLAG_CONNECTION_FAILURE )
  663. {
  664. return;
  665. }
  666. if ( pIfObject->fFlags & IFFLAG_DIALOUT_HOURS_RESTRICTION )
  667. {
  668. return;
  669. }
  670. break;
  671. case INTERFACE_DIALOUT_HOURS_RESTRICTION:
  672. if ( gblDDMConfigInfo.pServiceStatus->dwCurrentState == SERVICE_PAUSED )
  673. {
  674. return;
  675. }
  676. if ( !( pIfObject->fFlags & IFFLAG_ENABLED ) )
  677. {
  678. return;
  679. }
  680. if ( pIfObject->fFlags & IFFLAG_CONNECTION_FAILURE )
  681. {
  682. return;
  683. }
  684. if ( pIfObject->fFlags & IFFLAG_OUT_OF_RESOURCES )
  685. {
  686. return;
  687. }
  688. break;
  689. default:
  690. RTASSERT( FALSE );
  691. break;
  692. }
  693. for ( dwIndex = 0;
  694. dwIndex < gblDDMConfigInfo.dwNumRouterManagers;
  695. dwIndex++ )
  696. {
  697. if ( pIfObject->Transport[dwIndex].hInterface == INVALID_HANDLE_VALUE )
  698. {
  699. continue;
  700. }
  701. if ( fReachable )
  702. {
  703. DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM,
  704. "Notifying Protocol = 0x%x, Interface=%ws is Reachable",
  705. gblRouterManagers[dwIndex].DdmRouterIf.dwProtocolId,
  706. pIfObject->lpwsInterfaceName );
  707. gblRouterManagers[dwIndex].DdmRouterIf.InterfaceReachable(
  708. pIfObject->Transport[dwIndex].hInterface );
  709. }
  710. else
  711. {
  712. DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM,
  713. "Notifying Protocol = 0x%x,Interface=%ws is UnReachable=%d",
  714. gblRouterManagers[dwIndex].DdmRouterIf.dwProtocolId,
  715. pIfObject->lpwsInterfaceName,
  716. dwReason );
  717. gblRouterManagers[dwIndex].DdmRouterIf.InterfaceNotReachable(
  718. pIfObject->Transport[dwIndex].hInterface,
  719. dwReason );
  720. }
  721. }
  722. if ( pIfObject->IfType == ROUTER_IF_TYPE_FULL_ROUTER )
  723. {
  724. if ( fReachable )
  725. {
  726. DDMLogInformation(ROUTERLOG_IF_REACHABLE,1,&(pIfObject->lpwsInterfaceName));
  727. }
  728. else
  729. {
  730. LogUnreachabilityEvent( dwReason, pIfObject->lpwsInterfaceName );
  731. }
  732. }
  733. //
  734. // If this interface is reachable, and it is persistent and it has not
  735. // been disconnected by the administrator, then attempt to reconnect now
  736. //
  737. if ( ( pIfObject->fFlags & IFFLAG_PERSISTENT ) &&
  738. ( fReachable ) &&
  739. ( !( pIfObject->fFlags & IFFLAG_DISCONNECT_INITIATED ) ) )
  740. {
  741. TimerQInsert(pIfObject->hDIMInterface,1,ReConnectPersistentInterface);
  742. }
  743. }
  744. //**
  745. //
  746. // Call: IfObjectNotifyAllOfReachabilityChange
  747. //
  748. // Returns: None
  749. //
  750. // Description: Check to see if need to run through all the interfaces and
  751. // notify the ones that are not un\reachable now.
  752. //
  753. //
  754. VOID
  755. IfObjectNotifyAllOfReachabilityChange(
  756. IN BOOL fReachable,
  757. IN UNREACHABILITY_REASON dwReason
  758. )
  759. {
  760. DWORD dwBucketIndex;
  761. ROUTER_INTERFACE_OBJECT * pIfObject;
  762. DWORD fAvailableMedia;
  763. BOOL fNotify;
  764. if ( dwReason == INTERFACE_OUT_OF_RESOURCES )
  765. {
  766. //
  767. // No need to notify
  768. //
  769. if ( !gblMediaTable.fCheckInterfaces )
  770. {
  771. return;
  772. }
  773. gblMediaTable.fCheckInterfaces = FALSE;
  774. MediaObjGetAvailableMediaBits( &fAvailableMedia );
  775. }
  776. for ( dwBucketIndex = 0; dwBucketIndex < NUM_IF_BUCKETS; dwBucketIndex++ )
  777. {
  778. for( pIfObject = gblpInterfaceTable->IfBucket[dwBucketIndex];
  779. pIfObject != (ROUTER_INTERFACE_OBJECT *)NULL;
  780. pIfObject = pIfObject->pNext )
  781. {
  782. fNotify = TRUE;
  783. if ( dwReason == INTERFACE_OUT_OF_RESOURCES )
  784. {
  785. fNotify = FALSE;
  786. if ((pIfObject->fMediaUsed & fAvailableMedia) && fReachable )
  787. {
  788. //
  789. // If previously unreachable, mark as reachable
  790. //
  791. if ( pIfObject->fFlags & IFFLAG_OUT_OF_RESOURCES )
  792. {
  793. pIfObject->fFlags &= ~IFFLAG_OUT_OF_RESOURCES;
  794. fNotify = TRUE;
  795. }
  796. }
  797. if ((!(pIfObject->fMediaUsed & fAvailableMedia)) && !fReachable)
  798. {
  799. //
  800. // If previously reachable and currently disconnected,
  801. // mark as unreachable
  802. //
  803. if ( ( !( pIfObject->fFlags & IFFLAG_OUT_OF_RESOURCES ) )
  804. && ( pIfObject->State == RISTATE_DISCONNECTED ) )
  805. {
  806. pIfObject->fFlags |= IFFLAG_OUT_OF_RESOURCES;
  807. fNotify = TRUE;
  808. }
  809. }
  810. }
  811. if ( fNotify )
  812. {
  813. IfObjectNotifyOfReachabilityChange( pIfObject,
  814. fReachable,
  815. dwReason );
  816. }
  817. }
  818. }
  819. }
  820. //**
  821. //
  822. // Call: IfObjectAddClientInterface
  823. //
  824. // Returns: None
  825. //
  826. // Description: Add this client interface with all the router managers.
  827. //
  828. //
  829. DWORD
  830. IfObjectAddClientInterface(
  831. IN ROUTER_INTERFACE_OBJECT * pIfObject,
  832. IN PBYTE pClientStaticRoutes
  833. )
  834. {
  835. DWORD dwIndex;
  836. DIM_ROUTER_INTERFACE * pDdmRouterIf;
  837. DWORD dwRetCode = NO_ERROR;
  838. for ( dwIndex = 0;
  839. dwIndex < gblDDMConfigInfo.dwNumRouterManagers;
  840. dwIndex++ )
  841. {
  842. pDdmRouterIf=&(gblRouterManagers[dwIndex].DdmRouterIf);
  843. if ( ( pDdmRouterIf->dwProtocolId == PID_IP ) &&
  844. ( pClientStaticRoutes != NULL ) )
  845. {
  846. dwRetCode = pDdmRouterIf->AddInterface(
  847. pIfObject->lpwsInterfaceName,
  848. pClientStaticRoutes,
  849. pIfObject->IfType,
  850. pIfObject->hDIMInterface,
  851. &(pIfObject->Transport[dwIndex].hInterface));
  852. }
  853. else
  854. {
  855. dwRetCode = pDdmRouterIf->AddInterface(
  856. pIfObject->lpwsInterfaceName,
  857. gblRouterManagers[dwIndex].pDefaultClientInterface,
  858. pIfObject->IfType,
  859. pIfObject->hDIMInterface,
  860. &(pIfObject->Transport[dwIndex].hInterface));
  861. }
  862. if ( dwRetCode != NO_ERROR )
  863. {
  864. LPWSTR lpwsInsertStrings[2];
  865. lpwsInsertStrings[0] = pIfObject->lpwsInterfaceName;
  866. lpwsInsertStrings[1] = ( pDdmRouterIf->dwProtocolId == PID_IP )
  867. ? L"IP" : L"IPX";
  868. DDMLogErrorString( ROUTERLOG_COULDNT_ADD_INTERFACE, 2,
  869. lpwsInsertStrings, dwRetCode, 2 );
  870. pIfObject->Transport[dwIndex].hInterface = INVALID_HANDLE_VALUE;
  871. break;
  872. }
  873. }
  874. if ( dwRetCode != NO_ERROR )
  875. {
  876. //
  877. // Unload this interface for all the router managers that we loaded.
  878. //
  879. while ( dwIndex-- > 0 )
  880. {
  881. pDdmRouterIf=&(gblRouterManagers[dwIndex].DdmRouterIf);
  882. pDdmRouterIf->DeleteInterface(
  883. pIfObject->Transport[dwIndex].hInterface );
  884. pIfObject->Transport[dwIndex].hInterface = INVALID_HANDLE_VALUE;
  885. }
  886. }
  887. return( dwRetCode );
  888. }
  889. //**
  890. //
  891. // Call: IfObjectDeleteInterface
  892. //
  893. // Returns: None
  894. //
  895. // Description: Delete this interface with all the router managers.
  896. //
  897. //
  898. VOID
  899. IfObjectDeleteInterface(
  900. ROUTER_INTERFACE_OBJECT * pIfObject
  901. )
  902. {
  903. DWORD dwIndex;
  904. DIM_ROUTER_INTERFACE * pDdmRouterIf;
  905. DWORD dwRetCode;
  906. for ( dwIndex = 0;
  907. dwIndex < gblDDMConfigInfo.dwNumRouterManagers;
  908. dwIndex++ )
  909. {
  910. if ( pIfObject->Transport[dwIndex].hInterface == INVALID_HANDLE_VALUE )
  911. {
  912. continue;
  913. }
  914. pDdmRouterIf=&(gblRouterManagers[dwIndex].DdmRouterIf);
  915. dwRetCode = pDdmRouterIf->DeleteInterface(
  916. pIfObject->Transport[dwIndex].hInterface );
  917. if ( dwRetCode != NO_ERROR )
  918. {
  919. LPWSTR lpwsInsertStrings[2];
  920. lpwsInsertStrings[0] = pIfObject->lpwsInterfaceName;
  921. lpwsInsertStrings[1] = ( pDdmRouterIf->dwProtocolId == PID_IP )
  922. ? L"IP" : L"IPX";
  923. DDMLogErrorString( ROUTERLOG_COULDNT_REMOVE_INTERFACE, 2,
  924. lpwsInsertStrings, dwRetCode, 2 );
  925. }
  926. }
  927. }
  928. //**
  929. //
  930. // Call: IfObjectInsertInTable
  931. //
  932. // Returns: None
  933. //
  934. // Description: Simply calls the DIM entrypoint to insert an interface object
  935. // into the interfaec table.
  936. //
  937. DWORD
  938. IfObjectInsertInTable(
  939. IN ROUTER_INTERFACE_OBJECT * pIfObject
  940. )
  941. {
  942. return( ((DWORD(*)(ROUTER_INTERFACE_OBJECT *))
  943. gblDDMConfigInfo.lpfnIfObjectInsertInTable)( pIfObject ) );
  944. }
  945. VOID
  946. IfObjectSubEntryEnumHandler(PVOID pvContext, WCHAR *pszDeviceType)
  947. {
  948. DDM_SUBENTRY_ENUMCONTEXT *pContext =
  949. (DDM_SUBENTRY_ENUMCONTEXT *)pvContext;
  950. DWORD dwRetCode;
  951. if(NULL == pContext)
  952. {
  953. return;
  954. }
  955. dwRetCode = MediaObjSetMediaBit(pszDeviceType,
  956. &(pContext->pIfObject->fMediaUsed));
  957. if ( dwRetCode == NO_ERROR )
  958. {
  959. pContext->fAtLeastOneDeviceAvailable = TRUE;
  960. }
  961. }
  962. VOID
  963. IfObjectFreePhonebookContext(IN VOID *pvContext)
  964. {
  965. DDMFreePhonebookContext(pvContext);
  966. }
  967. //**
  968. //
  969. // Call: IfObjectLoadPhonebookInfo
  970. //
  971. // Returns: NO_ERROR - Success
  972. // Non-zero returns - Failure
  973. //
  974. // Description: Will read the phonebook entry for this interface and set
  975. // bits for a device type used and all other phonebook information
  976. // used.
  977. //
  978. DWORD
  979. IfObjectLoadPhonebookInfo(
  980. IN ROUTER_INTERFACE_OBJECT * pIfObject,
  981. IN OUT PVOID *ppvContext
  982. )
  983. {
  984. LPRASENTRY pRasEntry = NULL;
  985. LPRASSUBENTRY pRasSubEntry = NULL;
  986. DWORD dwRetCode = NO_ERROR;
  987. DWORD dwIndex;
  988. DWORD dwSize;
  989. DWORD dwDummy;
  990. BOOL fRedialOnLinkFailure;
  991. BOOL fAtLeastOneDeviceAvailable = FALSE;
  992. DWORD dwDialMode = RASEDM_DialAll;
  993. VOID * pvSubEntryHandlerContext = NULL;
  994. VOID * pvSubEntryHandler = NULL;
  995. DDM_SUBENTRY_ENUMCONTEXT EnumContext;
  996. EnumContext.pIfObject = pIfObject;
  997. EnumContext.fAtLeastOneDeviceAvailable = FALSE;
  998. pvSubEntryHandlerContext = &EnumContext;
  999. pvSubEntryHandler = (VOID *)IfObjectSubEntryEnumHandler;
  1000. dwRetCode = DDMGetPhonebookInfo(
  1001. gblpRouterPhoneBook,
  1002. pIfObject->lpwsInterfaceName,
  1003. &(pIfObject->dwNumSubEntries),
  1004. &(pIfObject->dwNumOfReConnectAttempts),
  1005. &(pIfObject->dwSecondsBetweenReConnectAttempts),
  1006. &fRedialOnLinkFailure,
  1007. pIfObject->PppInterfaceInfo.szzParameters,
  1008. &dwDialMode,
  1009. ppvContext,
  1010. pvSubEntryHandler,
  1011. pvSubEntryHandlerContext
  1012. );
  1013. if ( dwRetCode != NO_ERROR )
  1014. {
  1015. return( dwRetCode );
  1016. }
  1017. if ( fRedialOnLinkFailure )
  1018. {
  1019. pIfObject->fFlags |= IFFLAG_PERSISTENT;
  1020. }
  1021. else
  1022. {
  1023. pIfObject->fFlags &= ~IFFLAG_PERSISTENT;
  1024. }
  1025. if( RASEDM_DialAsNeeded == dwDialMode)
  1026. {
  1027. pIfObject->fFlags |= IFFLAG_DIALMODE_DIALASNEEDED;
  1028. }
  1029. else
  1030. {
  1031. pIfObject->fFlags &= ~(IFFLAG_DIALMODE_DIALASNEEDED);
  1032. }
  1033. if( RASEDM_DialAll == dwDialMode )
  1034. {
  1035. pIfObject->fFlags |= IFFLAG_DIALMODE_DIALALL;
  1036. }
  1037. else
  1038. {
  1039. pIfObject->fFlags &= ~(IFFLAG_DIALMODE_DIALALL);
  1040. }
  1041. fAtLeastOneDeviceAvailable =
  1042. EnumContext.fAtLeastOneDeviceAvailable;
  1043. #if 0
  1044. else
  1045. {
  1046. //
  1047. // Iterate through all the subentries - fall back to the
  1048. // slow algorithm - we don't have the context
  1049. //
  1050. for( dwIndex = 1; dwIndex <= pIfObject->dwNumSubEntries; dwIndex++ )
  1051. {
  1052. //
  1053. // Get the device type
  1054. //
  1055. dwSize = 0;
  1056. dwRetCode = RasGetSubEntryProperties(
  1057. gblpRouterPhoneBook,
  1058. pIfObject->lpwsInterfaceName,
  1059. dwIndex,
  1060. NULL,
  1061. &dwSize,
  1062. (LPBYTE)&dwDummy,
  1063. &dwDummy );
  1064. if ( dwRetCode != ERROR_BUFFER_TOO_SMALL )
  1065. {
  1066. return ( dwRetCode );
  1067. }
  1068. pRasSubEntry = LOCAL_ALLOC( LPTR, dwSize );
  1069. if ( pRasSubEntry == NULL )
  1070. {
  1071. return ( GetLastError() );
  1072. }
  1073. ZeroMemory( pRasSubEntry, dwSize );
  1074. pRasSubEntry->dwSize = sizeof( RASSUBENTRY );
  1075. dwRetCode = RasGetSubEntryProperties(
  1076. gblpRouterPhoneBook,
  1077. pIfObject->lpwsInterfaceName,
  1078. dwIndex,
  1079. pRasSubEntry,
  1080. &dwSize,
  1081. (LPBYTE)&dwDummy,
  1082. &dwDummy );
  1083. if ( dwRetCode != NO_ERROR )
  1084. {
  1085. LOCAL_FREE( pRasSubEntry );
  1086. return( dwRetCode );
  1087. }
  1088. //
  1089. // Set the bit for this media
  1090. //
  1091. dwRetCode = MediaObjSetMediaBit( pRasSubEntry->szDeviceType,
  1092. &(pIfObject->fMediaUsed) );
  1093. LOCAL_FREE( pRasSubEntry );
  1094. if ( dwRetCode == NO_ERROR )
  1095. {
  1096. fAtLeastOneDeviceAvailable = TRUE;
  1097. }
  1098. }
  1099. }
  1100. #endif
  1101. if ( !fAtLeastOneDeviceAvailable )
  1102. {
  1103. return( ERROR_INTERFACE_HAS_NO_DEVICES );
  1104. }
  1105. return( NO_ERROR );
  1106. }
  1107. //**
  1108. //
  1109. // Call: IfObjectInitiatePersistentConnections
  1110. //
  1111. // Returns: None
  1112. //
  1113. // Description: Will initiate connections for all demand dial interfaces that
  1114. // are marked as persistent
  1115. //
  1116. VOID
  1117. IfObjectInitiatePersistentConnections(
  1118. VOID
  1119. )
  1120. {
  1121. DWORD dwBucketIndex;
  1122. ROUTER_INTERFACE_OBJECT * pIfObject;
  1123. DWORD dwRetCode;
  1124. EnterCriticalSection( &(gblpInterfaceTable->CriticalSection) );
  1125. for ( dwBucketIndex = 0; dwBucketIndex < NUM_IF_BUCKETS; dwBucketIndex++ )
  1126. {
  1127. for( pIfObject = gblpInterfaceTable->IfBucket[dwBucketIndex];
  1128. pIfObject != (ROUTER_INTERFACE_OBJECT *)NULL;
  1129. pIfObject = pIfObject->pNext )
  1130. {
  1131. if ( pIfObject->IfType == ROUTER_IF_TYPE_FULL_ROUTER )
  1132. {
  1133. if ( pIfObject->fFlags & IFFLAG_PERSISTENT )
  1134. {
  1135. dwRetCode = RasConnectionInitiate( pIfObject, FALSE );
  1136. DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM,
  1137. "Initiated persistent connection to %ws,dwRetCode=%d\n",
  1138. pIfObject->lpwsInterfaceName, dwRetCode );
  1139. if ( dwRetCode != NO_ERROR )
  1140. {
  1141. LPWSTR lpwsAudit[1];
  1142. lpwsAudit[0] = pIfObject->lpwsInterfaceName;
  1143. DDMLogErrorString(
  1144. ROUTERLOG_PERSISTENT_CONNECTION_FAILURE,
  1145. 1, lpwsAudit, dwRetCode, 1 );
  1146. }
  1147. }
  1148. else
  1149. {
  1150. //
  1151. // Otherwise set dialout hours restrictions, if any
  1152. //
  1153. IfObjectSetDialoutHoursRestriction( pIfObject );
  1154. }
  1155. }
  1156. }
  1157. }
  1158. LeaveCriticalSection( &(gblpInterfaceTable->CriticalSection) );
  1159. }
  1160. //**
  1161. //
  1162. // Call: IfObjectDisconnectInterfaces
  1163. //
  1164. // Returns: None
  1165. //
  1166. // Description: Will disconnect all interfaces that are connected or in the
  1167. // process of connecting.
  1168. //
  1169. VOID
  1170. IfObjectDisconnectInterfaces(
  1171. VOID
  1172. )
  1173. {
  1174. ROUTER_INTERFACE_OBJECT * pIfObject;
  1175. DWORD dwBucketIndex;
  1176. EnterCriticalSection( &(gblpInterfaceTable->CriticalSection) );
  1177. for ( dwBucketIndex = 0; dwBucketIndex < NUM_IF_BUCKETS; dwBucketIndex++ )
  1178. {
  1179. for( pIfObject = gblpInterfaceTable->IfBucket[dwBucketIndex];
  1180. pIfObject != (ROUTER_INTERFACE_OBJECT *)NULL;
  1181. pIfObject = pIfObject->pNext )
  1182. {
  1183. if ( ( pIfObject->State != RISTATE_DISCONNECTED ) &&
  1184. ( pIfObject->fFlags & IFFLAG_LOCALLY_INITIATED ) )
  1185. {
  1186. DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM,
  1187. "IfObjectDisconnectInterfaces: hanging up 0x%x",
  1188. pIfObject->hRasConn);
  1189. RasHangUp( pIfObject->hRasConn );
  1190. }
  1191. }
  1192. }
  1193. LeaveCriticalSection( &(gblpInterfaceTable->CriticalSection) );
  1194. }
  1195. //**
  1196. //
  1197. // Call: IfObjectConnectionChangeNotification
  1198. //
  1199. // Returns: NO_ERROR - Success
  1200. // Non-zero returns - Failure
  1201. //
  1202. // Description:
  1203. //
  1204. VOID
  1205. IfObjectConnectionChangeNotification(
  1206. VOID
  1207. )
  1208. {
  1209. NOTIFICATION_EVENT * pNotificationEvent;
  1210. for( pNotificationEvent = (NOTIFICATION_EVENT *)
  1211. (gblDDMConfigInfo.NotificationEventListHead.Flink);
  1212. pNotificationEvent != (NOTIFICATION_EVENT *)
  1213. &(gblDDMConfigInfo.NotificationEventListHead);
  1214. pNotificationEvent = (NOTIFICATION_EVENT *)
  1215. (pNotificationEvent->ListEntry.Flink) )
  1216. {
  1217. SetEvent( pNotificationEvent->hEventRouter );
  1218. }
  1219. }
  1220. //**
  1221. //
  1222. // Call: IfObjectSetDialoutHoursRestriction
  1223. //
  1224. // Returns: NONE
  1225. //
  1226. // Description: Called from ifapi.c from DIM to initiate dialout hours
  1227. // restriction for this interface.
  1228. //
  1229. VOID
  1230. IfObjectSetDialoutHoursRestriction(
  1231. IN ROUTER_INTERFACE_OBJECT * pIfObject
  1232. )
  1233. {
  1234. TimerQRemove( pIfObject->hDIMInterface, SetDialoutHoursRestriction );
  1235. SetDialoutHoursRestriction( pIfObject->hDIMInterface );
  1236. }