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.

191 lines
4.5 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. update.c
  5. Abstract:
  6. RIP Auto-Static Update
  7. Author:
  8. Stefan Solomon 07/06/1995
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. // Max update retries
  14. #define MAX_UPDATE_RETRIES 3
  15. VOID
  16. PostUpdateCompleteMessage(ULONG InterfaceIndex,
  17. DWORD Status);
  18. DWORD
  19. WINAPI
  20. DoUpdateRoutes(ULONG InterfaceIndex)
  21. {
  22. DWORD rc;
  23. PICB icbp;
  24. PWORK_ITEM wip;
  25. ACQUIRE_DATABASE_LOCK;
  26. if((rc = ValidStateAndIfIndex(InterfaceIndex, &icbp)) != NO_ERROR) {
  27. RELEASE_DATABASE_LOCK;
  28. return rc;
  29. }
  30. ACQUIRE_IF_LOCK(icbp);
  31. // check if there are any parameters which disable doing update on this if
  32. if((icbp->IfConfigInfo.AdminState != ADMIN_STATE_ENABLED) ||
  33. (icbp->IfConfigInfo.UpdateMode != IPX_AUTO_STATIC_UPDATE) ||
  34. (icbp->IfStats.RipIfOperState != OPER_STATE_UP)) {
  35. rc = ERROR_CAN_NOT_COMPLETE;
  36. goto Exit;
  37. }
  38. // send a general request packet
  39. if(SendRipGenRequest(icbp) != NO_ERROR) {
  40. rc = ERROR_CAN_NOT_COMPLETE;
  41. goto Exit;
  42. }
  43. // allocate an update status check wi and queue it in timer queue for 10 sec
  44. if((wip = AllocateWorkItem(UPDATE_STATUS_CHECK_TYPE)) == NULL) {
  45. goto Exit;
  46. }
  47. wip->icbp = icbp;
  48. wip->AdapterIndex = INVALID_ADAPTER_INDEX;
  49. wip->IoCompletionStatus = NO_ERROR;
  50. wip->WorkItemSpecific.WIS_Update.UpdatedRoutesCount = 0;
  51. wip->WorkItemSpecific.WIS_Update.UpdateRetriesCount = 1;
  52. // save Listen state and enable it so we can execute the update command
  53. wip->WorkItemSpecific.WIS_Update.OldRipListen = icbp->IfConfigInfo.Listen;
  54. wip->WorkItemSpecific.WIS_Update.OldRipInterval = icbp->IfConfigInfo.PeriodicUpdateInterval;
  55. icbp->IfConfigInfo.Listen = ADMIN_STATE_ENABLED;
  56. icbp->IfConfigInfo.PeriodicUpdateInterval = MAXULONG;
  57. // delete all previous routes we kept for this if
  58. DeleteAllRipRoutes(icbp->InterfaceIndex);
  59. // Enqueue the update status check work item in the timer queue and increment
  60. // ref count
  61. IfRefStartWiTimer(wip, CHECK_UPDATE_TIME_MILISECS);
  62. rc = NO_ERROR;
  63. Exit:
  64. RELEASE_IF_LOCK(icbp);
  65. RELEASE_DATABASE_LOCK;
  66. return rc;
  67. }
  68. /*++
  69. Function: CheckUpdateStatus
  70. Descr: Entered with the update status check wi processing every 10 sec.
  71. Compares the wi number of routes with the RTM held number of
  72. rip routes. If same -> update done, else go in timer queue again
  73. Remark: Called with the Interface Lock held
  74. --*/
  75. VOID
  76. IfCheckUpdateStatus(PWORK_ITEM wip)
  77. {
  78. ULONG RipRoutesCount;
  79. PICB icbp;
  80. icbp = wip->icbp;
  81. // check if the interface is up and running
  82. if(icbp->IfStats.RipIfOperState != OPER_STATE_UP) {
  83. // restore Rip Listen
  84. icbp->IfConfigInfo.Listen = wip->WorkItemSpecific.WIS_Update.OldRipListen;
  85. icbp->IfConfigInfo.PeriodicUpdateInterval
  86. = wip->WorkItemSpecific.WIS_Update.OldRipInterval;
  87. // discard the CheckUpdateStatus work item and signal update failure
  88. PostUpdateCompleteMessage(icbp->InterfaceIndex, ERROR_CAN_NOT_COMPLETE);
  89. FreeWorkItem(wip);
  90. return;
  91. }
  92. RipRoutesCount = GetRipRoutesCount(icbp->InterfaceIndex);
  93. //if we have not received anything yet, send a new request up to the max
  94. if(RipRoutesCount == 0) {
  95. // if we can retry send a new request
  96. if(++wip->WorkItemSpecific.WIS_Update.UpdateRetriesCount <= MAX_UPDATE_RETRIES) {
  97. SendRipGenRequest(icbp);
  98. IfRefStartWiTimer(wip, CHECK_UPDATE_TIME_MILISECS);
  99. return;
  100. }
  101. }
  102. if(wip->WorkItemSpecific.WIS_Update.UpdatedRoutesCount == RipRoutesCount) {
  103. // the number of routes didn't change in the last 10 seconds OR
  104. // restore Rip Listen & update interval
  105. icbp->IfConfigInfo.Listen = wip->WorkItemSpecific.WIS_Update.OldRipListen;
  106. icbp->IfConfigInfo.PeriodicUpdateInterval
  107. = wip->WorkItemSpecific.WIS_Update.OldRipInterval;
  108. PostUpdateCompleteMessage(icbp->InterfaceIndex, NO_ERROR);
  109. FreeWorkItem(wip);
  110. }
  111. else
  112. {
  113. // still getting new routes -> update with the latest count
  114. wip->WorkItemSpecific.WIS_Update.UpdatedRoutesCount = RipRoutesCount;
  115. // Enqueue the update status check work item in the timer queue and increment
  116. // ref count
  117. IfRefStartWiTimer(wip, CHECK_UPDATE_TIME_MILISECS);
  118. }
  119. }
  120. VOID
  121. PostUpdateCompleteMessage(ULONG InterfaceIndex,
  122. DWORD Status)
  123. {
  124. MESSAGE Result;
  125. Result.UpdateCompleteMessage.InterfaceIndex = InterfaceIndex;
  126. Result.UpdateCompleteMessage.UpdateType = DEMAND_UPDATE_ROUTES;
  127. Result.UpdateCompleteMessage.UpdateStatus = Status;
  128. PostEventMessage(UPDATE_COMPLETE, &Result);
  129. }