Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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