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.

489 lines
9.6 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. update.c
  5. Abstract:
  6. The auto-static update routines
  7. Author:
  8. Stefan Solomon 05/18/1995
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. VOID
  14. SaveUpdate(PVOID InterfaceIndex);
  15. VOID
  16. RestoreInterface (PVOID InterfaceIndex);
  17. /*++
  18. Function: RequestUpdate
  19. Descr: Called to initiate an auto static update of routes and
  20. services on the specified interface.
  21. --*/
  22. DWORD
  23. RequestUpdate(IN HANDLE InterfaceIndex,
  24. IN HANDLE hEvent)
  25. {
  26. PICB icbp;
  27. DWORD rc;
  28. BOOL RoutesUpdateStarted = FALSE;
  29. BOOL ServicesUpdateStarted = FALSE;
  30. Trace(UPDATE_TRACE, "RequestUpdate: Entered for if # %d\n", InterfaceIndex);
  31. ACQUIRE_DATABASE_LOCK;
  32. if(RouterOperState != OPER_STATE_UP) {
  33. RELEASE_DATABASE_LOCK;
  34. return ERROR_CAN_NOT_COMPLETE;
  35. }
  36. if((icbp = GetInterfaceByIndex(PtrToUlong(InterfaceIndex))) == NULL) {
  37. RELEASE_DATABASE_LOCK;
  38. Trace(UPDATE_TRACE, "RequestUpdate: Nonexistent interface with # %d\n", InterfaceIndex);
  39. return ERROR_INVALID_HANDLE;
  40. }
  41. SS_ASSERT(!memcmp(&icbp->Signature, InterfaceSignature, 4));
  42. // check if the interface is bound to a connected adapter
  43. if(icbp->OperState != OPER_STATE_UP) {
  44. RELEASE_DATABASE_LOCK;
  45. Trace(UPDATE_TRACE, "RequestUpdate: adapter not connected on if # %d\n", InterfaceIndex);
  46. return ERROR_NOT_CONNECTED;
  47. }
  48. // check if an update is already pending
  49. if(IsUpdateRequestPending(icbp)) {
  50. RELEASE_DATABASE_LOCK;
  51. Trace(UPDATE_TRACE, "RequestUpdate: update already pending on if # %d\n", InterfaceIndex);
  52. return ERROR_UPDATE_IN_PROGRESS;
  53. }
  54. //
  55. // *** Start a new update ***
  56. //
  57. icbp->DIMUpdateEvent = hEvent;
  58. if((rc = RtProtRequestRoutesUpdate(icbp->InterfaceIndex)) == NO_ERROR) {
  59. icbp->UpdateReq.RoutesReqStatus = UPDATE_PENDING;
  60. }
  61. else
  62. {
  63. Trace(UPDATE_TRACE, "RequestUpdate: Routing Update is Disabled\n");
  64. }
  65. if((rc = RtProtRequestServicesUpdate(icbp->InterfaceIndex)) == NO_ERROR) {
  66. icbp->UpdateReq.ServicesReqStatus = UPDATE_PENDING;
  67. }
  68. else
  69. {
  70. Trace(UPDATE_TRACE, "RequestUpdate: Services Update is Disabled\n");
  71. }
  72. // if at least one of the protocols initiated the update, we qualify
  73. // the request as successfull, else it failed.
  74. if(!IsUpdateRequestPending(icbp)) {
  75. RELEASE_DATABASE_LOCK;
  76. return ERROR_CAN_NOT_COMPLETE;
  77. }
  78. RELEASE_DATABASE_LOCK;
  79. return PENDING;
  80. }
  81. /*++
  82. Function: UpdateCompleted
  83. Descr: Invoked by the router manager worker when the routing protocol
  84. signals completion of the update request
  85. --*/
  86. VOID
  87. UpdateCompleted(PUPDATE_COMPLETE_MESSAGE ucmsgp)
  88. {
  89. PICB icbp;
  90. BOOL UpdateDone;
  91. ULONG InterfaceIndex;
  92. HANDLE hDIMInterface;
  93. #if DBG
  94. char *updttype;
  95. #endif
  96. Trace(UPDATE_TRACE, "UpdateCompleted: Entered\n");
  97. UpdateDone = FALSE;
  98. ACQUIRE_DATABASE_LOCK;
  99. if((icbp = GetInterfaceByIndex(ucmsgp->InterfaceIndex)) == NULL) {
  100. RELEASE_DATABASE_LOCK;
  101. Trace(UPDATE_TRACE, "UpdateCompleted: Nonexistent interface with # %d\n",
  102. ucmsgp->InterfaceIndex);
  103. return;
  104. }
  105. InterfaceIndex = icbp->InterfaceIndex;
  106. // check if we have requested one, if not just discard
  107. if(!IsUpdateRequestPending(icbp)) {
  108. RELEASE_DATABASE_LOCK;
  109. return;
  110. }
  111. // fill in the result and check if we're done
  112. if(ucmsgp->UpdateType == DEMAND_UPDATE_ROUTES) {
  113. // ROUTES UPDATE
  114. Trace(UPDATE_TRACE, "UpdateCompleted: Routes update req done for if # %d with status %d\n",
  115. ucmsgp->InterfaceIndex,
  116. ucmsgp->UpdateStatus);
  117. if(ucmsgp->UpdateStatus == NO_ERROR) {
  118. icbp->UpdateReq.RoutesReqStatus = UPDATE_SUCCESSFULL;
  119. // if the update was successfull we delete all the static routes
  120. // for this interface, and then CONVERT all the routes added by the
  121. // protocol which did the update on this interface to static routes.
  122. DeleteAllStaticRoutes(icbp->InterfaceIndex);
  123. ConvertAllProtocolRoutesToStatic(icbp->InterfaceIndex, UpdateRoutesProtId);
  124. }
  125. else
  126. {
  127. icbp->UpdateReq.RoutesReqStatus = UPDATE_FAILURE;
  128. }
  129. if(icbp->UpdateReq.ServicesReqStatus != UPDATE_PENDING) {
  130. // we are done
  131. UpdateDone = TRUE;
  132. }
  133. }
  134. else
  135. {
  136. // SERVICES UPDATE
  137. Trace(UPDATE_TRACE, "UpdateCompleted: Services update req done for if # %d with status %d\n",
  138. ucmsgp->InterfaceIndex,
  139. ucmsgp->UpdateStatus);
  140. if(ucmsgp->UpdateStatus == NO_ERROR) {
  141. icbp->UpdateReq.ServicesReqStatus = UPDATE_SUCCESSFULL;
  142. // we delete all the static services for this interface and then
  143. // CONVERT all the services added by the protocol which did the
  144. // update routes on this interface to static services
  145. DeleteAllStaticServices(InterfaceIndex);
  146. ConvertAllServicesToStatic(InterfaceIndex);
  147. }
  148. else
  149. {
  150. icbp->UpdateReq.ServicesReqStatus = UPDATE_FAILURE;
  151. }
  152. if(icbp->UpdateReq.RoutesReqStatus != UPDATE_PENDING) {
  153. // we are done
  154. UpdateDone = TRUE;
  155. }
  156. }
  157. if(UpdateDone) {
  158. if((icbp->UpdateReq.RoutesReqStatus == UPDATE_SUCCESSFULL) &&
  159. (icbp->UpdateReq.ServicesReqStatus == UPDATE_SUCCESSFULL)) {
  160. icbp->UpdateResult = NO_ERROR;
  161. }
  162. else
  163. {
  164. if((icbp->UpdateReq.RoutesReqStatus == UPDATE_FAILURE) ||
  165. (icbp->UpdateReq.ServicesReqStatus == UPDATE_FAILURE)) {
  166. icbp->UpdateResult = ERROR_CAN_NOT_COMPLETE;
  167. }
  168. else
  169. {
  170. // this is for the case when one or both protocols couldn't
  171. // do updates because they were not configured to update.
  172. icbp->UpdateResult = NO_ERROR;
  173. }
  174. }
  175. ResetUpdateRequest(icbp);
  176. if(icbp->MIBInterfaceType != IF_TYPE_ROUTER_WORKSTATION_DIALOUT) {
  177. SetEvent(icbp->DIMUpdateEvent);
  178. CloseHandle (icbp->DIMUpdateEvent);
  179. icbp->DIMUpdateEvent = NULL;
  180. }
  181. }
  182. // complete the update action by signaling DIM the final result
  183. // and saving the update result on disk
  184. if(UpdateDone &&
  185. (icbp->MIBInterfaceType != IF_TYPE_ROUTER_WORKSTATION_DIALOUT)) {
  186. InterfaceIndex = icbp->InterfaceIndex;
  187. if(RtlQueueWorkItem((icbp->UpdateResult == NO_ERROR) ? SaveUpdate : RestoreInterface,
  188. (PVOID)UlongToPtr(InterfaceIndex), 0) == STATUS_SUCCESS) {
  189. WorkItemsPendingCounter++;
  190. }
  191. }
  192. RELEASE_DATABASE_LOCK;
  193. }
  194. /*++
  195. Function: SaveUpdate
  196. Descr: Saves the new interface configuration on permanent storage
  197. --*/
  198. VOID
  199. SaveUpdate(PVOID InterfaceIndex)
  200. {
  201. LPVOID InterfaceInfop = NULL;
  202. ULONG InterfaceInfoSize = 0;
  203. DWORD rc;
  204. HANDLE hDIMInterface;
  205. PICB icbp;
  206. if(RouterOperState != OPER_STATE_UP) {
  207. goto Exit;
  208. }
  209. rc = GetInterfaceInfo((HANDLE)InterfaceIndex,
  210. InterfaceInfop,
  211. &InterfaceInfoSize);
  212. if(rc != ERROR_INSUFFICIENT_BUFFER) {
  213. // !!! log an error !!!
  214. goto Exit;
  215. }
  216. InterfaceInfop = GlobalAlloc(GPTR, InterfaceInfoSize);
  217. if(InterfaceInfop == NULL) {
  218. // !!! log error !!!
  219. goto Exit;
  220. }
  221. rc = GetInterfaceInfo((HANDLE)InterfaceIndex,
  222. InterfaceInfop,
  223. &InterfaceInfoSize);
  224. if(rc != NO_ERROR) {
  225. // !!! log error !!!
  226. GlobalFree(InterfaceInfop);
  227. goto Exit;
  228. }
  229. ACQUIRE_DATABASE_LOCK;
  230. if((icbp = GetInterfaceByIndex(PtrToUlong(InterfaceIndex))) == NULL) {
  231. RELEASE_DATABASE_LOCK;
  232. goto Exit;
  233. }
  234. hDIMInterface = icbp->hDIMInterface;
  235. RELEASE_DATABASE_LOCK;
  236. // save the info on disk
  237. rc = SaveInterfaceInfo(hDIMInterface,
  238. PID_IPX,
  239. InterfaceInfop,
  240. InterfaceInfoSize);
  241. SS_ASSERT(rc == NO_ERROR);
  242. GlobalFree(InterfaceInfop);
  243. Exit:
  244. ACQUIRE_DATABASE_LOCK;
  245. WorkItemsPendingCounter--;
  246. RELEASE_DATABASE_LOCK;
  247. }
  248. /*++
  249. Function: RestoreInterface
  250. Descr: Restore interface configuration from permanent storage
  251. --*/
  252. VOID
  253. RestoreInterface (PVOID InterfaceIndex)
  254. {
  255. LPVOID InterfaceInfop = NULL;
  256. ULONG InterfaceInfoSize = 0;
  257. DWORD rc;
  258. HANDLE hDIMInterface;
  259. PICB icbp;
  260. if(RouterOperState != OPER_STATE_UP) {
  261. goto Exit;
  262. }
  263. ACQUIRE_DATABASE_LOCK;
  264. if((icbp = GetInterfaceByIndex(PtrToUlong(InterfaceIndex))) == NULL) {
  265. RELEASE_DATABASE_LOCK;
  266. goto Exit;
  267. }
  268. hDIMInterface = icbp->hDIMInterface;
  269. RELEASE_DATABASE_LOCK;
  270. // get the info from disk
  271. InterfaceInfoSize = 0;
  272. InterfaceInfop = NULL;
  273. rc = RestoreInterfaceInfo (hDIMInterface,
  274. PID_IPX,
  275. InterfaceInfop,
  276. &InterfaceInfoSize);
  277. if (rc==ERROR_BUFFER_TOO_SMALL) {
  278. InterfaceInfop = GlobalAlloc (GMEM_FIXED, InterfaceInfoSize);
  279. if (InterfaceInfop!=NULL) {
  280. rc = RestoreInterfaceInfo(hDIMInterface,
  281. PID_IPX,
  282. InterfaceInfop,
  283. &InterfaceInfoSize);
  284. }
  285. else
  286. rc = GetLastError ();
  287. }
  288. if (rc == NO_ERROR)
  289. rc = SetInterfaceInfo (InterfaceIndex, InterfaceInfop);
  290. if (InterfaceInfop!=NULL)
  291. GlobalFree(InterfaceInfop);
  292. Exit:
  293. ACQUIRE_DATABASE_LOCK;
  294. WorkItemsPendingCounter--;
  295. RELEASE_DATABASE_LOCK;
  296. }
  297. /*++
  298. Function: GetDIMUpdateResult
  299. Descr: Called by DDM to retrieve a message posted for it
  300. --*/
  301. DWORD
  302. GetDIMUpdateResult(IN HANDLE InterfaceIndex,
  303. OUT LPDWORD UpdateResultp)
  304. {
  305. PLIST_ENTRY lep;
  306. PICB icbp;
  307. ACQUIRE_DATABASE_LOCK;
  308. if(RouterOperState != OPER_STATE_UP) {
  309. RELEASE_DATABASE_LOCK;
  310. return ERROR_CAN_NOT_COMPLETE;
  311. }
  312. if((icbp = GetInterfaceByIndex(PtrToUlong(InterfaceIndex))) == NULL) {
  313. RELEASE_DATABASE_LOCK;
  314. return ERROR_INVALID_PARAMETER;
  315. }
  316. // check that the update is not pending
  317. if(IsUpdateRequestPending(icbp)) {
  318. RELEASE_DATABASE_LOCK;
  319. return ERROR_CAN_NOT_COMPLETE;
  320. }
  321. *UpdateResultp = icbp->UpdateResult;
  322. RELEASE_DATABASE_LOCK;
  323. return NO_ERROR;
  324. }