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.

1014 lines
22 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. ifmgr.c
  5. Abstract:
  6. RIP Interface Manager
  7. Author:
  8. Stefan Solomon 07/06/1995
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. #define IsInterfaceBound(icbp)\
  14. ((icbp)->AdapterBindingInfo.AdapterIndex != INVALID_ADAPTER_INDEX)
  15. #define IsInterfaceEnabled(icbp)\
  16. (((icbp)->IfConfigInfo.AdminState == ADMIN_STATE_ENABLED) &&\
  17. ((icbp)->IpxIfAdminState == ADMIN_STATE_ENABLED))
  18. VOID
  19. StartInterface(PICB icbp);
  20. VOID
  21. StopInterface(PICB icbp);
  22. PICB
  23. CreateInterfaceCB(LPWSTR InterfaceName,
  24. ULONG InterfaceIndex,
  25. PRIP_IF_INFO IfConfigInfop,
  26. NET_INTERFACE_TYPE NetInterfaceType,
  27. PRIP_IF_STATS IfStatsp OPTIONAL);
  28. VOID
  29. DiscardInterfaceCB(PICB icbp);
  30. DWORD
  31. CreateNewFiltersBlock(PRIP_IF_FILTERS_I *fcbpp,
  32. PRIP_IF_FILTERS RipIfFiltersp);
  33. DWORD
  34. CreateOldFiltersBlockCopy(PRIP_IF_FILTERS_I *fcbpp,
  35. PRIP_IF_FILTERS_I RipIfFiltersp);
  36. DWORD WINAPI
  37. AddInterface(
  38. IN LPWSTR InterfaceName,
  39. IN ULONG InterfaceIndex,
  40. IN NET_INTERFACE_TYPE NetInterfaceType,
  41. IN PVOID InterfaceInfo)
  42. {
  43. PICB icbp;
  44. PRIP_IF_FILTERS_I fcbp;
  45. Trace(IFMGR_TRACE, "AddInterface: Entered for if # %d\n", InterfaceIndex);
  46. ACQUIRE_DATABASE_LOCK;
  47. if(RipOperState != OPER_STATE_UP) {
  48. RELEASE_DATABASE_LOCK;
  49. return ERROR_CAN_NOT_COMPLETE;
  50. }
  51. if(GetInterfaceByIndex(InterfaceIndex) != NULL) {
  52. RELEASE_DATABASE_LOCK;
  53. return ERROR_INVALID_PARAMETER;
  54. }
  55. // create the filters block for this interface
  56. if(CreateNewFiltersBlock(&fcbp, &((PRIP_IF_CONFIG)InterfaceInfo)->RipIfFilters) != NO_ERROR) {
  57. RELEASE_DATABASE_LOCK;
  58. return ERROR_CAN_NOT_COMPLETE;
  59. }
  60. if((icbp = CreateInterfaceCB(
  61. InterfaceName,
  62. InterfaceIndex,
  63. (PRIP_IF_INFO)InterfaceInfo,
  64. NetInterfaceType,
  65. NULL)) == NULL) {
  66. if(fcbp) {
  67. GlobalFree(fcbp);
  68. }
  69. RELEASE_DATABASE_LOCK;
  70. return ERROR_CAN_NOT_COMPLETE;
  71. }
  72. // bind the filters block with the interface control block
  73. icbp->RipIfFiltersIp = fcbp;
  74. RELEASE_DATABASE_LOCK;
  75. return NO_ERROR;
  76. }
  77. DWORD WINAPI
  78. DeleteInterface(
  79. IN ULONG InterfaceIndex)
  80. {
  81. PICB icbp;
  82. DWORD rc;
  83. Trace(IFMGR_TRACE,"DeleteInterface: Entered for if # %d\n", InterfaceIndex);
  84. ACQUIRE_DATABASE_LOCK;
  85. if((rc = ValidStateAndIfIndex(InterfaceIndex, &icbp)) != NO_ERROR) {
  86. RELEASE_DATABASE_LOCK;
  87. return rc;
  88. }
  89. ACQUIRE_IF_LOCK(icbp);
  90. if(!DeleteRipInterface(icbp)) {
  91. // interface CB still exists but has been discarded
  92. RELEASE_IF_LOCK(icbp);
  93. }
  94. RELEASE_DATABASE_LOCK;
  95. return NO_ERROR;
  96. }
  97. DWORD WINAPI
  98. GetInterfaceConfigInfo(
  99. IN ULONG InterfaceIndex,
  100. IN PVOID InterfaceInfo,
  101. IN OUT PULONG InterfaceInfoSize)
  102. {
  103. PICB icbp;
  104. DWORD rc, i;
  105. ULONG ifconfigsize;
  106. PRIP_IF_FILTERS_I fcbp;
  107. PRIP_IF_FILTERS RipIfFiltersp;
  108. PRIP_ROUTE_FILTER_INFO rfp;
  109. PRIP_ROUTE_FILTER_INFO_I rfip;
  110. ACQUIRE_DATABASE_LOCK;
  111. if((rc = ValidStateAndIfIndex(InterfaceIndex, &icbp)) != NO_ERROR) {
  112. RELEASE_DATABASE_LOCK;
  113. return rc;
  114. }
  115. ACQUIRE_IF_LOCK(icbp);
  116. ifconfigsize = sizeof(RIP_IF_CONFIG);
  117. if((fcbp = icbp->RipIfFiltersIp) != NULL) {
  118. ifconfigsize += (fcbp->SupplyFilterCount +
  119. fcbp->ListenFilterCount - 1) * sizeof(RIP_ROUTE_FILTER_INFO);
  120. }
  121. if((InterfaceInfo == NULL) || (*InterfaceInfoSize < ifconfigsize)) {
  122. *InterfaceInfoSize = ifconfigsize;
  123. RELEASE_IF_LOCK(icbp);
  124. RELEASE_DATABASE_LOCK;
  125. return ERROR_INSUFFICIENT_BUFFER;
  126. }
  127. ((PRIP_IF_CONFIG)InterfaceInfo)->RipIfInfo = icbp->IfConfigInfo;
  128. RipIfFiltersp = &(((PRIP_IF_CONFIG)InterfaceInfo)->RipIfFilters);
  129. if(fcbp == NULL) {
  130. // no filters
  131. memset(RipIfFiltersp, 0, sizeof(RIP_IF_FILTERS));
  132. }
  133. else
  134. {
  135. // convert all filters from internal to external format
  136. if(fcbp->SupplyFilterAction) {
  137. RipIfFiltersp->SupplyFilterAction = IPX_ROUTE_FILTER_PERMIT;
  138. }
  139. else
  140. {
  141. RipIfFiltersp->SupplyFilterAction = IPX_ROUTE_FILTER_DENY;
  142. }
  143. RipIfFiltersp->SupplyFilterCount = fcbp->SupplyFilterCount;
  144. if(fcbp->ListenFilterAction) {
  145. RipIfFiltersp->ListenFilterAction = IPX_ROUTE_FILTER_PERMIT;
  146. }
  147. else
  148. {
  149. RipIfFiltersp->ListenFilterAction = IPX_ROUTE_FILTER_DENY;
  150. }
  151. RipIfFiltersp->ListenFilterCount = fcbp->ListenFilterCount;
  152. rfp = RipIfFiltersp->RouteFilter;
  153. rfip = fcbp->RouteFilterI;
  154. for(i=0;
  155. i<fcbp->SupplyFilterCount + fcbp->ListenFilterCount;
  156. i++, rfp++, rfip++)
  157. {
  158. PUTULONG2LONG(rfp->Network, rfip->Network);
  159. PUTULONG2LONG(rfp->Mask, rfip->Mask);
  160. }
  161. }
  162. *InterfaceInfoSize = ifconfigsize;
  163. RELEASE_IF_LOCK(icbp);
  164. RELEASE_DATABASE_LOCK;
  165. return NO_ERROR;
  166. }
  167. DWORD WINAPI
  168. SetInterfaceConfigInfo(
  169. IN ULONG InterfaceIndex,
  170. IN PVOID InterfaceInfo)
  171. {
  172. DWORD rc;
  173. PICB icbp;
  174. PRIP_IF_FILTERS_I fcbp;
  175. ACQUIRE_DATABASE_LOCK;
  176. if((rc = ValidStateAndIfIndex(InterfaceIndex, &icbp)) != NO_ERROR) {
  177. RELEASE_DATABASE_LOCK;
  178. return rc;
  179. }
  180. // create the filters block for this interface
  181. if(CreateNewFiltersBlock(&fcbp, &((PRIP_IF_CONFIG)InterfaceInfo)->RipIfFilters) != NO_ERROR) {
  182. RELEASE_DATABASE_LOCK;
  183. return ERROR_CAN_NOT_COMPLETE;
  184. }
  185. rc = SetRipInterface(InterfaceIndex,
  186. (PRIP_IF_INFO)InterfaceInfo,
  187. fcbp,
  188. 0);
  189. RELEASE_DATABASE_LOCK;
  190. return rc;
  191. }
  192. DWORD WINAPI
  193. BindInterface(
  194. IN ULONG InterfaceIndex,
  195. IN PVOID BindingInfo)
  196. {
  197. PICB icbp, newicbp;
  198. DWORD rc;
  199. PWORK_ITEM wip;
  200. PRIP_IF_FILTERS_I fcbp = NULL;
  201. Trace(IFMGR_TRACE, "BindInterface: Entered for if # %d\n", InterfaceIndex);
  202. ACQUIRE_DATABASE_LOCK;
  203. if((rc = ValidStateAndIfIndex(InterfaceIndex, &icbp)) != NO_ERROR) {
  204. RELEASE_DATABASE_LOCK;
  205. return rc;
  206. }
  207. ACQUIRE_IF_LOCK(icbp);
  208. if(IsInterfaceBound(icbp)) {
  209. SS_ASSERT(FALSE);
  210. RELEASE_IF_LOCK(icbp);
  211. RELEASE_DATABASE_LOCK;
  212. return ERROR_INVALID_PARAMETER;
  213. }
  214. SS_ASSERT(icbp->IfStats.RipIfOperState != OPER_STATE_UP);
  215. if(icbp->RefCount) {
  216. // The interface is UNBOUND but is still referenced.
  217. // make a copy of the old if filters if any
  218. if(icbp->RipIfFiltersIp != NULL) {
  219. if(CreateOldFiltersBlockCopy(&fcbp, icbp->RipIfFiltersIp) != NO_ERROR) {
  220. // cannot allocate memory for the copy of the filters block
  221. RELEASE_IF_LOCK(icbp);
  222. RELEASE_DATABASE_LOCK;
  223. return ERROR_CAN_NOT_COMPLETE;
  224. }
  225. }
  226. // remove the old if Cb from the if list and hash
  227. RemoveIfFromDb(icbp);
  228. if((newicbp = CreateInterfaceCB(
  229. icbp->InterfaceName,
  230. InterfaceIndex,
  231. &icbp->IfConfigInfo,
  232. icbp->InterfaceType,
  233. &icbp->IfStats)) == NULL) {
  234. // restore the old if and get out
  235. AddIfToDb(icbp);
  236. if(fcbp != NULL) {
  237. GlobalFree(fcbp);
  238. }
  239. RELEASE_IF_LOCK(icbp);
  240. RELEASE_DATABASE_LOCK;
  241. return ERROR_CAN_NOT_COMPLETE;
  242. }
  243. // bind the old filters copy to the new interface
  244. if(icbp->RipIfFiltersIp != NULL) {
  245. newicbp->RipIfFiltersIp = fcbp;
  246. }
  247. newicbp->IfConfigInfo = icbp->IfConfigInfo;
  248. newicbp->IpxIfAdminState = icbp->IpxIfAdminState;
  249. DiscardInterfaceCB(icbp);
  250. RELEASE_IF_LOCK(icbp);
  251. ACQUIRE_IF_LOCK(newicbp);
  252. icbp = newicbp;
  253. }
  254. // bind the if to adapter and add it to adapter hash table
  255. BindIf(icbp, (PIPX_ADAPTER_BINDING_INFO)BindingInfo);
  256. // start work on this interface if the admin state is enabled
  257. if(IsInterfaceEnabled(icbp) && (InterfaceIndex!=0)) {
  258. StartInterface(icbp);
  259. }
  260. RELEASE_IF_LOCK(icbp);
  261. RELEASE_DATABASE_LOCK;
  262. return NO_ERROR;
  263. }
  264. DWORD WINAPI
  265. UnbindInterface(
  266. IN ULONG InterfaceIndex)
  267. {
  268. PICB icbp;
  269. DWORD rc;
  270. Trace(IFMGR_TRACE, "UnbindInterface: Entered for if # %d\n", InterfaceIndex);
  271. ACQUIRE_DATABASE_LOCK;
  272. if((rc = ValidStateAndIfIndex(InterfaceIndex, &icbp)) != NO_ERROR) {
  273. RELEASE_DATABASE_LOCK;
  274. return rc;
  275. }
  276. ACQUIRE_IF_LOCK(icbp);
  277. if(!IsInterfaceBound(icbp)) {
  278. // already unbound
  279. RELEASE_IF_LOCK(icbp);
  280. RELEASE_DATABASE_LOCK;
  281. return ERROR_INVALID_PARAMETER;
  282. }
  283. UnbindIf(icbp);
  284. if(icbp->IfStats.RipIfOperState == OPER_STATE_UP) {
  285. // remove RIP routes added by this interface and discard the send queue
  286. StopInterface(icbp);
  287. }
  288. RELEASE_IF_LOCK(icbp);
  289. RELEASE_DATABASE_LOCK;
  290. return NO_ERROR;
  291. }
  292. DWORD WINAPI
  293. EnableInterface(IN ULONG InterfaceIndex)
  294. {
  295. DWORD rc;
  296. PICB icbp;
  297. ACQUIRE_DATABASE_LOCK;
  298. if((rc = ValidStateAndIfIndex(InterfaceIndex, &icbp)) != NO_ERROR) {
  299. RELEASE_DATABASE_LOCK;
  300. return rc;
  301. }
  302. rc = SetRipInterface(InterfaceIndex, NULL, NULL, ADMIN_STATE_ENABLED);
  303. RELEASE_DATABASE_LOCK;
  304. return rc;
  305. }
  306. DWORD WINAPI
  307. DisableInterface(IN ULONG InterfaceIndex)
  308. {
  309. DWORD rc;
  310. PICB icbp;
  311. ACQUIRE_DATABASE_LOCK;
  312. if((rc = ValidStateAndIfIndex(InterfaceIndex, &icbp)) != NO_ERROR) {
  313. RELEASE_DATABASE_LOCK;
  314. return rc;
  315. }
  316. rc = SetRipInterface(InterfaceIndex, NULL, NULL, ADMIN_STATE_DISABLED);
  317. RELEASE_DATABASE_LOCK;
  318. return rc;
  319. }
  320. /*++
  321. Function: SetRipInterface
  322. Descr: set the new interface parameters.
  323. If the interface was actively doing something, all operations
  324. are implicitly aborted on this interface.
  325. Remark: Called with the database lock held
  326. --*/
  327. DWORD
  328. SetRipInterface(ULONG InterfaceIndex,
  329. PRIP_IF_INFO RipIfInfop, // if this parameter NULL -> Enable/Disable if
  330. PRIP_IF_FILTERS_I RipIfFiltersIp,
  331. ULONG IpxIfAdminState)
  332. {
  333. PICB icbp, newicbp;
  334. IPX_ADAPTER_BINDING_INFO AdapterBindingInfo;
  335. PWORK_ITEM wip;
  336. PRIP_IF_FILTERS_I fcbp = NULL;
  337. if((icbp = GetInterfaceByIndex(InterfaceIndex)) == NULL) {
  338. return ERROR_INVALID_PARAMETER;
  339. }
  340. ACQUIRE_IF_LOCK(icbp);
  341. if(icbp->RefCount) {
  342. // The interface is still referenced.
  343. // if this is an enable/disable interface call, we need to make a copy of the old
  344. // interface filter block
  345. if((RipIfInfop == NULL) &&
  346. (icbp->RipIfFiltersIp != NULL)) {
  347. if(CreateOldFiltersBlockCopy(&fcbp, icbp->RipIfFiltersIp) != NO_ERROR) {
  348. // cannot allocate memory for the copy of the filters block
  349. RELEASE_IF_LOCK(icbp);
  350. return ERROR_CAN_NOT_COMPLETE;
  351. }
  352. }
  353. // remove the old if CB from the if list and hash
  354. RemoveIfFromDb(icbp);
  355. // Create a new if CB and add it to the list
  356. if((newicbp = CreateInterfaceCB(
  357. icbp->InterfaceName,
  358. InterfaceIndex,
  359. &icbp->IfConfigInfo,
  360. icbp->InterfaceType,
  361. &icbp->IfStats)) == NULL) {
  362. // restore the old if and get out
  363. AddIfToDb(icbp);
  364. if(fcbp != NULL) {
  365. GlobalFree(fcbp);
  366. }
  367. RELEASE_IF_LOCK(icbp);
  368. return ERROR_CAN_NOT_COMPLETE;
  369. }
  370. // bind the new interface cb with a copy of the old filter block if this is just an
  371. // enable/disable
  372. if((RipIfInfop == NULL) &&
  373. (icbp->RipIfFiltersIp != NULL)) {
  374. newicbp->RipIfFiltersIp = fcbp;
  375. }
  376. if(IsInterfaceBound(icbp)) {
  377. // copy the binding info and insert the new one in adapters hash table
  378. // if bound.
  379. AdapterBindingInfo = icbp->AdapterBindingInfo;
  380. // remove the old if from the adapters hash and insert the new one
  381. UnbindIf(icbp);
  382. BindIf(newicbp, &AdapterBindingInfo);
  383. }
  384. // copy the old config info and the old binding info
  385. newicbp->IfConfigInfo = icbp->IfConfigInfo;
  386. newicbp->IpxIfAdminState = icbp->IpxIfAdminState;
  387. DiscardInterfaceCB(icbp);
  388. ACQUIRE_IF_LOCK(newicbp);
  389. RELEASE_IF_LOCK(icbp);
  390. icbp = newicbp;
  391. }
  392. //
  393. // *** Set the new config info OR Set the new Ipx If Admin State ***
  394. //
  395. // if this is a SetInterface call, modify the configuration
  396. if(RipIfInfop != NULL) {
  397. // config info has changed
  398. icbp->IfConfigInfo = *RipIfInfop;
  399. // dispose of the old filters block if any and bind to the new one
  400. if((icbp->RipIfFiltersIp != NULL) && (icbp->RipIfFiltersIp!=RipIfFiltersIp)) {
  401. GlobalFree(icbp->RipIfFiltersIp);
  402. }
  403. icbp->RipIfFiltersIp = RipIfFiltersIp;
  404. }
  405. else
  406. {
  407. // Ipx interface admin state has changed
  408. icbp->IpxIfAdminState = IpxIfAdminState;
  409. }
  410. if (InterfaceIndex!=0) {
  411. if(IsInterfaceBound(icbp)) {
  412. if(IsInterfaceEnabled(icbp)) {
  413. StartInterface(icbp);
  414. }
  415. else
  416. {
  417. // interface has been disabled
  418. if(icbp->IfStats.RipIfOperState == OPER_STATE_UP) {
  419. // remove the routes and discard the changes bcast queue
  420. StopInterface(icbp);
  421. }
  422. else
  423. icbp->IfStats.RipIfOperState = OPER_STATE_DOWN;
  424. }
  425. }
  426. else {
  427. if (IsInterfaceEnabled(icbp)
  428. && (icbp->InterfaceType!=PERMANENT))
  429. icbp->IfStats.RipIfOperState = OPER_STATE_SLEEPING;
  430. else
  431. icbp->IfStats.RipIfOperState = OPER_STATE_DOWN;
  432. }
  433. }
  434. RELEASE_IF_LOCK(icbp);
  435. return NO_ERROR;
  436. }
  437. /*++
  438. Function: StartInterface
  439. Descr: Start work on this interface
  440. Remark: Called with interface lock held
  441. --*/
  442. VOID
  443. StartInterface(PICB icbp)
  444. {
  445. PWORK_ITEM bcwip, grwip;
  446. Trace(IFMGR_TRACE, "StartInterface: Entered for if index %d\n", icbp->InterfaceIndex);
  447. icbp->IfStats.RipIfOperState = OPER_STATE_UP;
  448. // check that this is not the internal interface and
  449. // check the update type and make a periodic update work item if necessary
  450. if(((icbp->IfConfigInfo.UpdateMode == IPX_STANDARD_UPDATE) &&
  451. (icbp->IfConfigInfo.Supply == ADMIN_STATE_ENABLED)) ||
  452. (icbp->InterfaceType == LOCAL_WORKSTATION_DIAL)) {
  453. if((bcwip = AllocateWorkItem(PERIODIC_BCAST_PACKET_TYPE)) == NULL) {
  454. goto ErrorExit;
  455. }
  456. // init the periodic bcast work item
  457. bcwip->icbp = icbp;
  458. bcwip->AdapterIndex = icbp->AdapterBindingInfo.AdapterIndex;
  459. // mark the work item state as "start of bcast"
  460. bcwip->WorkItemSpecific.WIS_EnumRoutes.RtmEnumerationHandle = NULL;
  461. // start bcast on this interface
  462. IfPeriodicBcast(bcwip);
  463. // send a general request packet on this interface
  464. SendRipGenRequest(icbp);
  465. }
  466. if(((icbp->InterfaceType == REMOTE_WORKSTATION_DIAL) ||
  467. (icbp->InterfaceType == LOCAL_WORKSTATION_DIAL)) &&
  468. SendGenReqOnWkstaDialLinks) {
  469. if((grwip = AllocateWorkItem(PERIODIC_GEN_REQUEST_TYPE)) == NULL) {
  470. goto ErrorExit;
  471. }
  472. grwip->icbp = icbp;
  473. grwip->AdapterIndex = icbp->AdapterBindingInfo.AdapterIndex;
  474. IfPeriodicGenRequest(grwip);
  475. }
  476. return;
  477. ErrorExit:
  478. icbp->IfStats.RipIfOperState = OPER_STATE_DOWN;
  479. return;
  480. }
  481. /*++
  482. Function: StopInterface
  483. Descr: Stop work on this interface:
  484. remove rip routes added by this interface
  485. set oper state to sleeping
  486. Remark: Called with database AND interface locks held
  487. --*/
  488. VOID
  489. StopInterface(PICB icbp)
  490. {
  491. PLIST_ENTRY lep;
  492. PWORK_ITEM wip;
  493. Trace(IFMGR_TRACE, "StopInterface: Entered for if index %d\n", icbp->InterfaceIndex);
  494. DeleteAllRipRoutes(icbp->InterfaceIndex);
  495. if (IsInterfaceEnabled (icbp))
  496. icbp->IfStats.RipIfOperState = OPER_STATE_SLEEPING;
  497. else
  498. icbp->IfStats.RipIfOperState = OPER_STATE_DOWN;
  499. }
  500. /*++
  501. Function: CreateInterfaceCB
  502. Descr: allocate interface CB
  503. init if lock
  504. init if index
  505. init if config info
  506. init if stats
  507. add if to db
  508. mark it unbound
  509. --*/
  510. PICB
  511. CreateInterfaceCB(
  512. LPWSTR InterfaceName,
  513. ULONG InterfaceIndex,
  514. PRIP_IF_INFO IfConfigInfop,
  515. NET_INTERFACE_TYPE InterfaceType,
  516. PRIP_IF_STATS IfStatsp OPTIONAL)
  517. {
  518. PICB icbp;
  519. if((icbp = GlobalAlloc(GPTR,
  520. FIELD_OFFSET(ICB,InterfaceName[wcslen(InterfaceName)+1]))) == NULL) {
  521. return NULL;
  522. }
  523. // create the interface lock
  524. try {
  525. InitializeCriticalSection(&icbp->InterfaceLock);
  526. }
  527. except(EXCEPTION_EXECUTE_HANDLER) {
  528. GlobalFree(icbp);
  529. return NULL;
  530. }
  531. // initialize the ICB
  532. wcscpy (icbp->InterfaceName, InterfaceName);
  533. icbp->InterfaceIndex = InterfaceIndex;
  534. icbp->IfConfigInfo = *IfConfigInfop;
  535. icbp->InterfaceType = InterfaceType;
  536. if(IfStatsp != NULL) {
  537. icbp->IfStats = *IfStatsp;
  538. }
  539. else
  540. {
  541. icbp->IfStats.RipIfOperState = OPER_STATE_DOWN;
  542. icbp->IfStats.RipIfInputPackets = 0;
  543. icbp->IfStats.RipIfOutputPackets = 0;
  544. }
  545. icbp->RefCount = 0;
  546. // link the ICB in the ordered if list and the if hash table
  547. AddIfToDb(icbp);
  548. icbp->Discarded = FALSE;
  549. // init the changes bcast queue
  550. InitializeListHead(&icbp->ChangesBcastQueue);
  551. // mark the interface as unbound to any adapter
  552. icbp->AdapterBindingInfo.AdapterIndex = INVALID_ADAPTER_INDEX;
  553. // set the ipx if admin state to disabled until we find out what it is
  554. icbp->IpxIfAdminState = ADMIN_STATE_DISABLED;
  555. // set the filters block ptr to null initially
  556. icbp->RipIfFiltersIp = NULL;
  557. return icbp;
  558. }
  559. /*++
  560. Function: DiscardInterfaceCB
  561. Descr: insert the if in the discarded list
  562. mark it discarded
  563. set its oper state to down so the referencing work items will
  564. know to
  565. --*/
  566. VOID
  567. DiscardInterfaceCB(PICB icbp)
  568. {
  569. icbp->IfStats.RipIfOperState = OPER_STATE_DOWN;
  570. InsertTailList(&DiscardedIfList, &icbp->IfListLinkage);
  571. icbp->Discarded = TRUE;
  572. Trace(IFMGR_TRACE, "DiscardInterface: interface CB for if # %d moved on DISCARDED list\n",
  573. icbp->InterfaceIndex);
  574. }
  575. /*++
  576. Function: DeleteRipInterface
  577. Descr: remove the if from the database
  578. unbinds and stops the if if active
  579. if not referenced frees the if CB and destroys the lock,
  580. else discards it
  581. Returns: TRUE - interface CB has been freed and if lock deleted
  582. FALSE - interface CB has been discarded and if lock is valid
  583. Remark: called with if lock held AND database lock held
  584. --*/
  585. BOOL
  586. DeleteRipInterface(PICB icbp)
  587. {
  588. // remove the interface from the database
  589. RemoveIfFromDb(icbp);
  590. // check if the interface is still bound to an adapter.
  591. if(IsInterfaceBound(icbp)) {
  592. UnbindIf(icbp);
  593. }
  594. // set if state to sleeping and remove changes bcast queued at the if cb
  595. if(icbp->IfStats.RipIfOperState == OPER_STATE_UP) {
  596. StopInterface(icbp);
  597. }
  598. // check if the interface is still referenced
  599. if(icbp->RefCount == 0) {
  600. Trace(IFMGR_TRACE, "DeleteRipInterface: free interface CB for if # %d\n",
  601. icbp->InterfaceIndex);
  602. // no more references to this interface CB, free it
  603. //
  604. DestroyInterfaceCB(icbp);
  605. return TRUE;
  606. }
  607. else
  608. {
  609. // the interface CB is still referenced. It will be freed by the
  610. // worker when the RefCount becomes 0.
  611. DiscardInterfaceCB(icbp);
  612. return FALSE;
  613. }
  614. }
  615. DWORD
  616. ValidStateAndIfIndex(ULONG InterfaceIndex,
  617. PICB *icbpp)
  618. {
  619. if(RipOperState != OPER_STATE_UP) {
  620. return ERROR_CAN_NOT_COMPLETE;
  621. }
  622. if((*icbpp = GetInterfaceByIndex(InterfaceIndex)) == NULL) {
  623. return ERROR_INVALID_PARAMETER;
  624. }
  625. return NO_ERROR;
  626. }
  627. /*++
  628. Function: CreateFiltersBlock
  629. Descr: Allocates and initializes a filters block from the
  630. Add/Set Interface Config filter parameter
  631. --*/
  632. DWORD
  633. CreateNewFiltersBlock(PRIP_IF_FILTERS_I *fcbpp,
  634. PRIP_IF_FILTERS RipIfFiltersp)
  635. {
  636. ULONG FcbSize, i;
  637. PRIP_ROUTE_FILTER_INFO rfp;
  638. PRIP_ROUTE_FILTER_INFO_I rfip;
  639. if((RipIfFiltersp->SupplyFilterCount == 0) &&
  640. (RipIfFiltersp->ListenFilterCount == 0)) {
  641. *fcbpp = NULL;
  642. return NO_ERROR;
  643. }
  644. FcbSize = sizeof(RIP_IF_FILTERS_I) +
  645. (RipIfFiltersp->SupplyFilterCount +
  646. RipIfFiltersp->ListenFilterCount - 1) * sizeof(RIP_ROUTE_FILTER_INFO_I);
  647. if((*fcbpp = GlobalAlloc(GPTR, FcbSize)) == NULL) {
  648. return ERROR_CAN_NOT_COMPLETE;
  649. }
  650. if(RipIfFiltersp->SupplyFilterAction == IPX_ROUTE_FILTER_PERMIT) {
  651. (*fcbpp)->SupplyFilterAction = TRUE;
  652. }
  653. else
  654. {
  655. (*fcbpp)->SupplyFilterAction = FALSE;
  656. }
  657. if(RipIfFiltersp->ListenFilterAction == IPX_ROUTE_FILTER_PERMIT) {
  658. (*fcbpp)->ListenFilterAction = TRUE;
  659. }
  660. else
  661. {
  662. (*fcbpp)->ListenFilterAction = FALSE;
  663. }
  664. (*fcbpp)->SupplyFilterCount = RipIfFiltersp->SupplyFilterCount;
  665. (*fcbpp)->ListenFilterCount = RipIfFiltersp->ListenFilterCount;
  666. // convert route_filters into route_filters_i
  667. rfp = RipIfFiltersp->RouteFilter;
  668. rfip = (*fcbpp)->RouteFilterI;
  669. for(i=0;
  670. i<RipIfFiltersp->SupplyFilterCount + RipIfFiltersp->ListenFilterCount;
  671. i++, rfp++, rfip++)
  672. {
  673. GETLONG2ULONG(&rfip->Network, rfp->Network);
  674. GETLONG2ULONG(&rfip->Mask, rfp->Mask);
  675. }
  676. return NO_ERROR;
  677. }
  678. /*++
  679. Function: CreateOldFiltersBlockCopy
  680. Descr: Allocates and initializes a filters block from an existing filters block
  681. --*/
  682. DWORD
  683. CreateOldFiltersBlockCopy(PRIP_IF_FILTERS_I *fcbpp,
  684. PRIP_IF_FILTERS_I RipIfFiltersp)
  685. {
  686. ULONG FcbSize;
  687. FcbSize = sizeof(RIP_IF_FILTERS_I) +
  688. (RipIfFiltersp->SupplyFilterCount +
  689. RipIfFiltersp->ListenFilterCount - 1) * sizeof(RIP_ROUTE_FILTER_INFO_I);
  690. if((*fcbpp = GlobalAlloc(GPTR, FcbSize)) == NULL) {
  691. return ERROR_CAN_NOT_COMPLETE;
  692. }
  693. memcpy(*fcbpp, RipIfFiltersp, FcbSize);
  694. return NO_ERROR;
  695. }
  696. VOID
  697. DestroyInterfaceCB(PICB icbp)
  698. {
  699. DeleteCriticalSection(&icbp->InterfaceLock);
  700. if(icbp->RipIfFiltersIp) {
  701. GlobalFree(icbp->RipIfFiltersIp);
  702. }
  703. GlobalFree(icbp);
  704. }