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.

3714 lines
105 KiB

  1. //=============================================================================
  2. // Copyright (c) 1997 Microsoft Corporation
  3. // Module Name: If.c
  4. //
  5. // Abstract:
  6. // This module implements some of the Igmp API's related with interfaces.
  7. // _AddInterface, _DeleteInterface, _EnableInterface, _DisableInterface,
  8. // _BindInterface, _UnbindInterface, _ConnectRasClient, _DisconectRasClient,
  9. // _SetInterfaceConfigInfo, _GetInterfaceConfigInfo.
  10. //
  11. // Author: K.S.Lokesh (lokeshs@) 11-1-97
  12. //=============================================================================
  13. #include "pchigmp.h"
  14. #pragma hdrstop
  15. //------------------------------------------------------------------------------
  16. // _AddInterface
  17. //
  18. // This api is called to add an interface to Igmp. The interface can be a Proxy
  19. // or an Igmp router(v1/v2). Further, the interface can be a RAS or DemandDial
  20. // or a Permanent interface. This routine creates the interface entry and
  21. // associated structures including timers.
  22. //
  23. // Locks: Runs completely in ListLock and ExclusiveIfLock.
  24. // Calls: _AddIfEntry()
  25. // Return Values: ERROR_CAN_NOT_COMPLETE, Error, NO_ERROR.
  26. //------------------------------------------------------------------------------
  27. DWORD
  28. WINAPI
  29. AddInterface(
  30. IN PWCHAR pwszInterfaceName,//not used
  31. IN ULONG IfIndex,
  32. IN NET_INTERFACE_TYPE dwIfType,
  33. IN DWORD dwMediaType,
  34. IN WORD wAccessType,
  35. IN WORD wConnectionType,
  36. IN PVOID pvConfig,
  37. IN ULONG ulStructureVersion,
  38. IN ULONG ulStructureSize,
  39. IN ULONG ulStructureCount
  40. )
  41. {
  42. DWORD Error=NO_ERROR;
  43. CHAR str[60];
  44. if (!EnterIgmpApi()) { return ERROR_CAN_NOT_COMPLETE; }
  45. // make sure it is not an unsupported igmp version structure
  46. if (ulStructureVersion>=IGMP_CONFIG_VERSION_600) {
  47. Trace1(ERR, "Unsupported IGMP version structure: %0x",
  48. ulStructureVersion);
  49. IgmpAssertOnError(FALSE);
  50. LeaveIgmpApi();
  51. return ERROR_CAN_NOT_COMPLETE;
  52. }
  53. switch (dwIfType) {
  54. case PERMANENT: //lan
  55. lstrcpy(str, "PERMANENT(IGMP_IF_NOT_RAS)"); break;
  56. case DEMAND_DIAL:
  57. lstrcpy(str, "DEMAND_DIAL(IGMP_IF_RAS_ROUTER)");break;
  58. case LOCAL_WORKSTATION_DIAL:
  59. lstrcpy(str, "LOCAL_WORKSTATION_DIAL(IGMP_IF_RAS_SERVER)"); break;
  60. }
  61. Trace2(ENTER, "entering AddInterface(): IfIndex:%0x IfType:%s",
  62. IfIndex, str);
  63. // entire procedure runs in IfListLock and exclusive IfLock.
  64. ACQUIRE_IF_LIST_LOCK("_AddInterface");
  65. ACQUIRE_IF_LOCK_EXCLUSIVE(IfIndex, "_AddInterface");
  66. //
  67. // create the interface entry
  68. //
  69. Error = AddIfEntry(IfIndex, dwIfType, (PIGMP_MIB_IF_CONFIG)pvConfig,
  70. ulStructureVersion, ulStructureSize
  71. );
  72. RELEASE_IF_LIST_LOCK("_AddInterface");
  73. RELEASE_IF_LOCK_EXCLUSIVE(IfIndex, "_AddInterface");
  74. Trace2(LEAVE1, "leaving AddInterface(%0x): %d\n", IfIndex, Error);
  75. if (Error!=NO_ERROR) {
  76. Trace1(ERR, "Error adding interface:%0x to IGMP\n", IfIndex);
  77. IgmpAssertOnError(FALSE);
  78. }
  79. LeaveIgmpApi();
  80. return Error;
  81. }
  82. //------------------------------------------------------------------------------
  83. // _AddIfEntry
  84. //
  85. // Creates and initializes a new interface entry and associated data structures.
  86. //
  87. // Called by: _AddInterface().
  88. // Locks: Assumes IfListLock and exclusive IfLock throughout.
  89. //------------------------------------------------------------------------------
  90. DWORD
  91. AddIfEntry(
  92. DWORD IfIndex,
  93. NET_INTERFACE_TYPE dwExternalIfType,
  94. PIGMP_MIB_IF_CONFIG pConfigExt,
  95. ULONG ulStructureVersion,
  96. ULONG ulStructureSize
  97. )
  98. {
  99. DWORD Error = NO_ERROR, IfType;
  100. PIF_TABLE_ENTRY pite = NULL;
  101. PLIST_ENTRY ple, phead;
  102. PIGMP_IF_TABLE pIfTable = g_pIfTable;
  103. BOOL bProxy;
  104. BEGIN_BREAKOUT_BLOCK1 {
  105. //
  106. // fail if the interface exists.
  107. //
  108. pite = GetIfByIndex(IfIndex);
  109. if (pite != NULL) {
  110. Trace1(ERR, "interface %0x already exists", IfIndex);
  111. IgmpAssertOnError(FALSE);
  112. Error = ERROR_INVALID_PARAMETER;
  113. GOTO_END_BLOCK1;
  114. }
  115. // convert iftype to igmp iftype
  116. switch (dwExternalIfType) {
  117. case PERMANENT :
  118. IfType = IGMP_IF_NOT_RAS;
  119. break;
  120. case DEMAND_DIAL:
  121. IfType = IGMP_IF_RAS_ROUTER;
  122. break;
  123. case LOCAL_WORKSTATION_DIAL:
  124. {
  125. IfType = IGMP_IF_RAS_SERVER;
  126. // currently there can be at most one ras table entry
  127. if (g_RasIfIndex!=0) {
  128. Trace2(ERR,
  129. "Error. Cannot have more than one ras server IF(%0x:%0x)",
  130. g_RasIfIndex, IfIndex
  131. );
  132. IgmpAssertOnError(FALSE);
  133. Error = ERROR_CAN_NOT_COMPLETE;
  134. Logerr0(RAS_IF_EXISTS, Error);
  135. GOTO_END_BLOCK1;
  136. }
  137. break;
  138. }
  139. case REMOTE_WORKSTATION_DIAL :
  140. Error = ERROR_INVALID_PARAMETER;
  141. break;
  142. default :
  143. Error = ERROR_INVALID_PARAMETER;
  144. break;
  145. } //end switch (IfType)
  146. // Validate the interface config
  147. Error = ValidateIfConfig(pConfigExt, IfIndex, IfType,
  148. ulStructureVersion, ulStructureSize
  149. );
  150. if (Error!=NO_ERROR)
  151. GOTO_END_BLOCK1;
  152. //
  153. // allocate memory for the new interface and Zero it.
  154. // Fields that are to be initialized to 0 or NULL are commented out.
  155. //
  156. pite = IGMP_ALLOC(sizeof(IF_TABLE_ENTRY), 0x2, IfIndex);
  157. PROCESS_ALLOC_FAILURE3(pite,
  158. "error %d allocating %d bytes for interface %0x", Error,
  159. sizeof(IF_TABLE_ENTRY), IfIndex,
  160. GOTO_END_BLOCK1);
  161. Trace2(CONFIG, "IfEntry %0x for IfIndex:%0x", (ULONG_PTR)pite, IfIndex);
  162. ZeroMemory(pite, sizeof(IF_TABLE_ENTRY));
  163. //
  164. // set the interface type
  165. //
  166. pite->IfType = (UCHAR)IfType;
  167. //
  168. // if proxy, make sure that a proxy interface does not already exist
  169. //
  170. if ( IS_CONFIG_IGMPPROXY(pConfigExt) ){
  171. bProxy = TRUE;
  172. //
  173. // multiple proxy interfaces cannot exist
  174. //
  175. if (g_ProxyIfIndex!=0) {
  176. Error = ERROR_CAN_NOT_COMPLETE;
  177. Trace1(IF, "Cannot create multiple proxy interfaces. "
  178. "If %d is Proxy", g_ProxyIfIndex);
  179. Logerr0(PROXY_IF_EXISTS, Error);
  180. GOTO_END_BLOCK1;
  181. }
  182. }
  183. else {
  184. bProxy = FALSE;
  185. }
  186. } END_BREAKOUT_BLOCK1;
  187. if (Error != NO_ERROR) {
  188. IGMP_FREE_NOT_NULL(pite);
  189. return Error;
  190. }
  191. //
  192. // initialize fields for the interface
  193. //
  194. InitializeListHead(&pite->LinkByAddr);
  195. InitializeListHead(&pite->LinkByIndex);
  196. InitializeListHead(&pite->HTLinkByIndex);
  197. InitializeListHead(&pite->ListOfSameIfGroups);
  198. InitializeListHead(&pite->ListOfSameIfGroupsNew);
  199. InitializeListHead(&pite->Config.ListOfStaticGroups);
  200. //pite->NumGIEntriesInNewList = 0;
  201. // IfType already set before
  202. pite->IfIndex = IfIndex;
  203. // Ip addr set when interface is bound
  204. //pite->IpAddr = 0;
  205. // set interface status (neither bound, enabled or activated)
  206. pite->Status = IF_CREATED_FLAG;
  207. // copy the interface config
  208. CopyinIfConfig(&pite->Config, pConfigExt, IfIndex);
  209. // initialize the Info struct, and If bindings to 0/NULL
  210. //pite->pBinding = NULL;
  211. //ZeroMemory(&pite->Info, sizeof(IF_INFO));
  212. //
  213. // Create RAS table if it is a RAS server interface
  214. //
  215. if ( IS_RAS_SERVER_IF(pite->IfType)) {
  216. InitializeRasTable(IfIndex, pite);
  217. }
  218. else {
  219. //pite->pRasTable = NULL;
  220. }
  221. //
  222. // initialize the sockets to invalid_socket
  223. //
  224. pite->SocketEntry.Socket = INVALID_SOCKET;
  225. pite->SocketEntry.pSocketEventsEntry = NULL;
  226. InitializeListHead(&pite->SocketEntry.LinkByInterfaces);
  227. // set (non)query timer to not created.
  228. //Other fields set in activate interface.
  229. //pite->QueryTimer.Status = 0;
  230. //pite->NonQueryTimer.Status = 0;
  231. //pite->pPrevIfGroupEnumPtr = NULL;
  232. //pite->PrevIfGroupEnumSignature = 0;
  233. pite->StaticGroupSocket = INVALID_SOCKET;
  234. // insert the interface in the hash table at the end.
  235. InsertTailList(&pIfTable->HashTableByIndex[IF_HASH_VALUE(IfIndex)],
  236. &pite->HTLinkByIndex);
  237. //
  238. // insert the interface into the list ordered by index
  239. //
  240. {
  241. PIF_TABLE_ENTRY piteTmp;
  242. phead = &pIfTable->ListByIndex;
  243. for (ple=phead->Flink; ple!=phead; ple=ple->Flink) {
  244. piteTmp = CONTAINING_RECORD(ple, IF_TABLE_ENTRY, LinkByIndex);
  245. if (pite->IfIndex < piteTmp->IfIndex)
  246. break;
  247. }
  248. }
  249. InsertTailList(ple, &pite->LinkByIndex);
  250. // changes to the interface table fields.
  251. pIfTable->NumInterfaces++;
  252. // the interface will be inserted into list ordered by IpAddr
  253. // when it is activated.
  254. //
  255. // create proxy HT, and set proxy info in global structure.
  256. //
  257. if (bProxy) {
  258. DWORD dwSize = PROXY_HASH_TABLE_SZ * sizeof(LIST_ENTRY);
  259. DWORD i;
  260. PLIST_ENTRY pProxyHashTable;
  261. BEGIN_BREAKOUT_BLOCK2 {
  262. pProxyHashTable = pite->pProxyHashTable = IGMP_ALLOC(dwSize, 0x4,
  263. IfIndex);
  264. PROCESS_ALLOC_FAILURE2(pProxyHashTable,
  265. "error %d allocating %d bytes for interface table",
  266. Error, dwSize, GOTO_END_BLOCK2);
  267. for (i=0; i<PROXY_HASH_TABLE_SZ; i++) {
  268. InitializeListHead(pProxyHashTable+i);
  269. }
  270. InterlockedExchangePointer(&g_pProxyIfEntry, pite);
  271. InterlockedExchange(&g_ProxyIfIndex, IfIndex);
  272. pite->CreationFlags |= CREATED_PROXY_HASH_TABLE;
  273. } END_BREAKOUT_BLOCK2;
  274. }
  275. //
  276. // set ras info in global structure. Ras table already created before.
  277. //
  278. if (IS_RAS_SERVER_IF(pite->IfType)) {
  279. InterlockedExchangePointer(&g_pRasIfEntry, pite);
  280. InterlockedExchange(&g_RasIfIndex, IfIndex);
  281. }
  282. if ( (Error!=NO_ERROR)&&(pite!=NULL) )
  283. DeleteIfEntry(pite);
  284. return Error;
  285. } //end _AddIfEntry
  286. //------------------------------------------------------------------------------
  287. // _DeleteInterface
  288. //
  289. // Deletes the interface, deactivating if it is activated.
  290. //
  291. // Calls: _DeleteIfEntry()
  292. // Locks: Exclusive SocketsLock, IfListLock, Exclusive IfLock
  293. //------------------------------------------------------------------------------
  294. DWORD
  295. DeleteInterface(
  296. IN DWORD IfIndex
  297. )
  298. {
  299. DWORD Error = NO_ERROR;
  300. PIF_TABLE_ENTRY pite = NULL;
  301. if (!EnterIgmpApi()) { return ERROR_CAN_NOT_COMPLETE; }
  302. Trace1(ENTER, "entering DeleteInterface: %0x", IfIndex);
  303. //
  304. // acquire exclusive SocketsLock, IfListLock, Exclusive IfLock
  305. //
  306. ACQUIRE_SOCKETS_LOCK_EXCLUSIVE("_DeleteInterface");
  307. ACQUIRE_IF_LIST_LOCK("_DeleteInterface");
  308. ACQUIRE_IF_LOCK_EXCLUSIVE(IfIndex, "_DeleteInterface");
  309. // retrieve the interface specified
  310. pite = GetIfByIndex(IfIndex);
  311. if (pite == NULL) {
  312. Trace1(ERR,
  313. "_DeleteInterface() called for non existing interface(%0x)", IfIndex);
  314. IgmpAssertOnError(FALSE);
  315. Error = ERROR_INVALID_PARAMETER;
  316. }
  317. // delete the interface if found.
  318. else {
  319. Error = DeleteIfEntry(pite);
  320. //DebugCheck deldel remove #if dbg
  321. #if DBG
  322. DebugScanMemoryInterface(IfIndex);
  323. #endif
  324. }
  325. RELEASE_SOCKETS_LOCK_EXCLUSIVE("_DeleteInterface");
  326. RELEASE_IF_LIST_LOCK("_DeleteInterface");
  327. RELEASE_IF_LOCK_EXCLUSIVE(IfIndex, "_DeleteInterface");
  328. Trace2(LEAVE, "Leaving DeleteInterface(%0x): %d\n", IfIndex, Error);
  329. LeaveIgmpApi();
  330. return NO_ERROR;
  331. }
  332. //------------------------------------------------------------------------------
  333. // _DeleteIfEntry
  334. //
  335. // Assumes exclusive IF lock. Marks the interface as deleted, and removes it
  336. // from all global lists. Then queues a work item to do a lazy delete of
  337. // the Interface structures without having to take the exclusive IF lock.
  338. // If Ras interface, the work item will delete the Ras clients also.
  339. //
  340. // Called by: _DeleteInterface() or _AddIfEntry()
  341. // Calls:
  342. // _WF_CompleteIfDeactivateDelete (this calls _DeActivateInterfaceComplete())
  343. // Lock:
  344. // runs in exclusive SocketLock, IfListLock, exclusive IfLock
  345. //------------------------------------------------------------------------------
  346. DWORD
  347. DeleteIfEntry (
  348. PIF_TABLE_ENTRY pite
  349. )
  350. {
  351. DWORD dwRetval, Error = NO_ERROR;
  352. BOOL bProxy = IS_PROTOCOL_TYPE_PROXY(pite);
  353. //
  354. // Set deleted flag for the interface
  355. //
  356. pite->Status |= DELETED_FLAG;
  357. //
  358. // remove the interface from the InterfaceHashTable and IfIndex lists.
  359. //
  360. RemoveEntryList(&pite->LinkByIndex);
  361. RemoveEntryList(&pite->HTLinkByIndex);
  362. //
  363. // if activated, remove the interface from the list of activated interfaces
  364. // and if proxy or ras server, remove from global table.
  365. //
  366. // do not replace the below with IS_IF_ACTIVATED, as deleted flag is set
  367. if (pite->Status&IF_ACTIVATED_FLAG)
  368. RemoveEntryList(&pite->LinkByAddr);
  369. if (bProxy) {
  370. InterlockedExchangePointer(&g_pProxyIfEntry, NULL);
  371. InterlockedExchange(&g_ProxyIfIndex, 0);
  372. }
  373. if (g_pRasIfEntry == pite) {
  374. InterlockedExchangePointer(&g_pRasIfEntry, NULL);
  375. InterlockedExchange(&g_RasIfIndex, 0);
  376. }
  377. //
  378. // From now on, the interface cannot be accessed from any global list
  379. // and is as good as deleted. The only way it can be accessed is
  380. // through group list enumeration and timers getting fired, or input on
  381. // socket.
  382. //
  383. //
  384. // if Interface activated, deactivate it
  385. // Note: deleted flag is already set.
  386. //
  387. if (pite->Status&IF_ACTIVATED_FLAG) {
  388. //
  389. // I have already removed the interface from the list of activated
  390. // interfaces
  391. //
  392. //
  393. // Call MGM to release the interface ownership. If proxy then
  394. // deregister proxy protocol from Mgm. If RAS, deregister all clients
  395. //
  396. DeActivationDeregisterFromMgm(pite);
  397. //
  398. // queue work item to deactivate and delete the interface.
  399. //
  400. // _WF_CompleteIfDeactivateDelete will delete the Ras clients,
  401. // GI entries, and deinitialize pite structure. It will call
  402. // _CompleteIfDeletion() in the end.
  403. //
  404. CompleteIfDeactivateDelete(pite);
  405. }
  406. //
  407. // if it is not activated, then go ahead and delete it completely.
  408. //
  409. else {
  410. CompleteIfDeletion(pite);
  411. }
  412. // decrement the total number of interfaces
  413. g_pIfTable->NumInterfaces--;
  414. return NO_ERROR;
  415. } //end _DeleteIfEntry
  416. //------------------------------------------------------------------------------
  417. // _CompleteIfDeletion
  418. //
  419. // Frees memory with the static groups, frees
  420. // rasTable, proxyHashTable, binding and pite.
  421. //
  422. // Called by:
  423. // _DeleteIfEntry() if interface is not activated.
  424. // _DeActivateInterfaceComplete() if the pite deleted flag is set.
  425. //------------------------------------------------------------------------------
  426. VOID
  427. CompleteIfDeletion (
  428. PIF_TABLE_ENTRY pite
  429. )
  430. {
  431. if (pite==NULL)
  432. return;
  433. //
  434. // delete all static groups.
  435. //
  436. {
  437. PIF_STATIC_GROUP pStaticGroup;
  438. PLIST_ENTRY pHead, ple;
  439. pHead = &pite->Config.ListOfStaticGroups;
  440. for (ple=pHead->Flink; ple!=pHead; ) {
  441. pStaticGroup = CONTAINING_RECORD(ple, IF_STATIC_GROUP, Link);
  442. ple = ple->Flink;
  443. IGMP_FREE(pStaticGroup);
  444. }
  445. }
  446. // if ras server, then delete ras table.
  447. if ( IS_RAS_SERVER_IF(pite->IfType) ) {
  448. IGMP_FREE(pite->pRasTable);
  449. }
  450. //
  451. // if proxy interface, then delete the proxy Hash Table
  452. //
  453. if (IS_PROTOCOL_TYPE_PROXY(pite)) {
  454. if ( (pite->CreationFlags&CREATED_PROXY_HASH_TABLE)
  455. && pite->pProxyHashTable
  456. ) {
  457. // clean the hash table entries
  458. {
  459. DWORD i;
  460. PPROXY_GROUP_ENTRY ppge;
  461. PLIST_ENTRY pHead, ple,
  462. pProxyHashTable = pite->pProxyHashTable;
  463. for (i=0; i<PROXY_HASH_TABLE_SZ; i++) {
  464. pHead = &pProxyHashTable[i];
  465. for (ple=pHead->Flink; ple!=pHead; ) {
  466. ppge = CONTAINING_RECORD(ple, PROXY_GROUP_ENTRY, HT_Link);
  467. ple=ple->Flink;
  468. // delete all sources
  469. {
  470. PLIST_ENTRY pHeadSrc, pleSrc;
  471. PPROXY_SOURCE_ENTRY pSourceEntry;
  472. pHeadSrc = &ppge->ListSources;
  473. for (pleSrc=pHeadSrc->Flink; pleSrc!=pHeadSrc; ) {
  474. pSourceEntry = CONTAINING_RECORD(pleSrc,
  475. PROXY_SOURCE_ENTRY, LinkSources);
  476. pleSrc = pleSrc->Flink;
  477. IGMP_FREE(pSourceEntry);
  478. }
  479. }
  480. IGMP_FREE(ppge);
  481. }
  482. InitializeListHead(pHead);
  483. }
  484. }
  485. IGMP_FREE_NOT_NULL(pite->pProxyHashTable);
  486. }
  487. }
  488. // delete the bindings
  489. IGMP_FREE_NOT_NULL(pite->pBinding);
  490. // delete the interface table entry
  491. IGMP_FREE(pite);
  492. return;
  493. }
  494. //------------------------------------------------------------------------------
  495. // _ActivateInterface
  496. //
  497. // an interface is activated: when it is bound, enabled by routerMgr & in config
  498. // When activated,
  499. // (1) call is made to MGM to take interface ownership,
  500. // (2) static groups are appropriately joined, and socket for it created if req.
  501. // (3) Igmprtr: query timer and input socket is activated.
  502. // Note: it is already put in the list of activated IFs(ordered by IpAddr)
  503. //
  504. // Locks: assumes socketLock, IfListLock, exclusive IfLock
  505. // Called by: _BindIfEntry, _EnableIfEntry,
  506. //------------------------------------------------------------------------------
  507. DWORD
  508. ActivateInterface (
  509. PIF_TABLE_ENTRY pite
  510. )
  511. {
  512. DWORD IfIndex = pite->IfIndex;
  513. PIGMP_IF_CONFIG pConfig = &pite->Config;
  514. PIF_INFO pInfo = &pite->Info;
  515. PIGMP_TIMER_ENTRY pQueryTimer = &pite->QueryTimer,
  516. pNonQueryTimer = &pite->NonQueryTimer;
  517. LONGLONG llCurTime = GetCurrentIgmpTime();
  518. BOOL bProxy = IS_PROTOCOL_TYPE_PROXY(pite);
  519. DWORD Error = NO_ERROR;
  520. PLIST_ENTRY pHead, ple;
  521. PIF_STATIC_GROUP pStaticGroup;
  522. Trace2(ENTER, "entering ActivateInterface(%0x:%d.%d.%d.%d)",
  523. IfIndex, PRINT_IPADDR(pite->IpAddr));
  524. BEGIN_BREAKOUT_BLOCK1 {
  525. //
  526. // set time when it is activated
  527. //
  528. pite->Info.TimeWhenActivated = llCurTime;
  529. //
  530. // create sockets for interface
  531. //
  532. Error = CreateIfSockets(pite);
  533. if (Error != NO_ERROR) {
  534. Trace2(IF, "error %d initializing sockets for interface %0x", Error,
  535. pite->IfIndex);
  536. GOTO_END_BLOCK1;
  537. }
  538. pite->CreationFlags |= SOCKETS_CREATED;
  539. //------------------------------------------
  540. // PROXY INTERFACE PROCESSING (break at end)
  541. //------------------------------------------
  542. if (bProxy) {
  543. //
  544. // set status to activated here so that the MGM (*,*) join callbacks will
  545. // be successful.
  546. //
  547. pite->Status |= IF_ACTIVATED_FLAG;
  548. //
  549. // register the protocol with mgm
  550. //
  551. Error = RegisterProtocolWithMgm(PROTO_IP_IGMP_PROXY);
  552. if (Error!=NO_ERROR)
  553. GOTO_END_BLOCK1;
  554. pite->CreationFlags |= REGISTERED_PROTOCOL_WITH_MGM;
  555. //
  556. // enumerate all existing groups from MGM
  557. //
  558. {
  559. DWORD dwBufferSize, dwNumEntries, dwRetval, i;
  560. MGM_ENUM_TYPES MgmEnumType = 0;
  561. SOURCE_GROUP_ENTRY BufferSGEntries[20];
  562. HANDLE hMgmEnum;
  563. // start enumeration
  564. dwBufferSize = sizeof(SOURCE_GROUP_ENTRY)*20;
  565. Error = MgmGroupEnumerationStart(g_MgmProxyHandle, MgmEnumType,
  566. &hMgmEnum);
  567. if (Error!=NO_ERROR) {
  568. Trace1(ERR, "MgmGroupEnumerationStart() returned error:%d",
  569. Error);
  570. IgmpAssertOnError(FALSE);
  571. GOTO_END_BLOCK1;
  572. }
  573. // get group entries from mgm
  574. // and insert group into Proxy's group list / increment refcount
  575. do {
  576. dwRetval = MgmGroupEnumerationGetNext(hMgmEnum, &dwBufferSize,
  577. (PBYTE)BufferSGEntries,
  578. &dwNumEntries);
  579. for (i=0; i<dwNumEntries; i++) {
  580. ProcessProxyGroupChange(BufferSGEntries[i].dwSourceAddr,
  581. BufferSGEntries[i].dwGroupAddr,
  582. ADD_FLAG, NOT_STATIC_GROUP);
  583. }
  584. } while (dwRetval==ERROR_MORE_DATA);
  585. // end enumeration
  586. dwRetval = MgmGroupEnumerationEnd(hMgmEnum);
  587. if (dwRetval!=NO_ERROR) {
  588. Trace1(ERR, "MgmGroupEnumerationEnd() returned error:%d",
  589. dwRetval);
  590. IgmpAssertOnError(FALSE);
  591. }
  592. } //end block:enumerate existing groups
  593. //
  594. // take interface ownership
  595. //
  596. Error = MgmTakeInterfaceOwnership(g_MgmProxyHandle, IfIndex, 0);
  597. if (Error!=NO_ERROR) {
  598. Trace1(MGM, "MgmTakeInterfaceOwnership rejected for interface %0x",
  599. IfIndex);
  600. Logerr0(MGM_TAKE_IF_OWNERSHIP_FAILED, Error);
  601. GOTO_END_BLOCK1;
  602. }
  603. else {
  604. Trace1(MGM, "MgmTakeInterfaceOwnership successful for interface %0x",
  605. IfIndex);
  606. }
  607. pite->CreationFlags |= TAKEN_INTERFACE_OWNERSHIP_WITH_MGM;
  608. //
  609. // proxy does a (*,*) join
  610. //
  611. Error = MgmAddGroupMembershipEntry(g_MgmProxyHandle, 0, 0, 0, 0,
  612. IfIndex, 0, MGM_JOIN_STATE_FLAG);
  613. if (Error!=NO_ERROR) {
  614. Trace1(ERR,
  615. "Proxy failed to add *,* entry to MGM on interface %0x",
  616. IfIndex);
  617. IgmpAssertOnError(FALSE);
  618. GOTO_END_BLOCK1;
  619. }
  620. Trace0(MGM, "proxy added *,* entry to MGM");
  621. pite->CreationFlags|= DONE_STAR_STAR_JOIN;
  622. //
  623. // do static joins
  624. //
  625. pHead = &pite->Config.ListOfStaticGroups;
  626. for (ple=pHead->Flink; ple!=pHead; ple=ple->Flink) {
  627. DWORD i;
  628. pStaticGroup = CONTAINING_RECORD(ple, IF_STATIC_GROUP, Link);
  629. for (i=0; i<pStaticGroup->NumSources; i++) {
  630. ProcessProxyGroupChange(pStaticGroup->Sources[i], pStaticGroup->GroupAddr,
  631. ADD_FLAG, STATIC_GROUP);
  632. }
  633. if (pStaticGroup->NumSources==0)
  634. ProcessProxyGroupChange(0, pStaticGroup->GroupAddr,
  635. ADD_FLAG, STATIC_GROUP);
  636. }
  637. GOTO_END_BLOCK1;
  638. } // done processing for a proxy interface
  639. //-----------------------------------------
  640. // IGMP ROUTER INTERFACE
  641. //-----------------------------------------
  642. //
  643. // take interface ownership
  644. //
  645. Error = MgmTakeInterfaceOwnership(g_MgmIgmprtrHandle, IfIndex, 0);
  646. if (Error!=NO_ERROR) {
  647. Trace1(MGM, "TakeInterfaceOwnership rejected for interface %0x",
  648. IfIndex);
  649. Logerr0(MGM_TAKE_IF_OWNERSHIP_FAILED, Error);
  650. GOTO_END_BLOCK1;
  651. }
  652. pite->CreationFlags |= TAKEN_INTERFACE_OWNERSHIP_WITH_MGM;
  653. //
  654. // see if any other MCast protocol is owning that interface
  655. // this affects whether a non-querier registers group with Mgm or not
  656. //
  657. {
  658. DWORD dwProtoId, dwComponentId;
  659. MgmGetProtocolOnInterface(IfIndex, 0, &dwProtoId, &dwComponentId);
  660. if (dwProtoId==PROTO_IP_IGMP) {
  661. SET_MPROTOCOL_ABSENT_ON_IGMPRTR(pite);
  662. }
  663. else {
  664. SET_MPROTOCOL_PRESENT_ON_IGMPRTR(pite);
  665. }
  666. }
  667. //
  668. // when interface is activated, it is by default enabled by mgm.
  669. //
  670. MGM_ENABLE_IGMPRTR(pite);
  671. //
  672. // if ras server interface, then register all the ras clients as they
  673. // would not have been registered
  674. //
  675. if (IS_RAS_SERVER_IF(pite->IfType)) {
  676. PRAS_TABLE_ENTRY prte;
  677. // join all ras clients
  678. pHead = &pite->pRasTable->ListByAddr;
  679. for (ple=pHead->Flink; ple!=pHead; ple=ple->Flink) {
  680. prte = CONTAINING_RECORD(ple, RAS_TABLE_ENTRY, LinkByAddr);
  681. Error = MgmTakeInterfaceOwnership(g_MgmIgmprtrHandle, IfIndex,
  682. prte->NHAddr);
  683. if (Error!=NO_ERROR) {
  684. Trace2(MGM,
  685. "TakeInterfaceOwnership rejected for interface %0x "
  686. "NHAddr(%d.%d.%d.%d)",
  687. IfIndex, PRINT_IPADDR(prte->NHAddr));
  688. Logerr0(MGM_TAKE_IF_OWNERSHIP_FAILED, Error);
  689. }
  690. else {
  691. prte->CreationFlags |= TAKEN_INTERFACE_OWNERSHIP_WITH_MGM;
  692. }
  693. }
  694. }
  695. //
  696. // INITIALIZE THE INFO STRUCTURE AND SET THE TIMERS
  697. //
  698. //
  699. // start as querier with version specified in the config
  700. //
  701. pInfo->QuerierState = RTR_QUERIER;
  702. pInfo->QuerierIpAddr = pite->IpAddr;
  703. pInfo->LastQuerierChangeTime = llCurTime;
  704. //
  705. // how many startup queries left to be sent
  706. //
  707. pInfo->StartupQueryCountCurrent = pConfig->StartupQueryCount;
  708. {
  709. MIB_IFROW TmpIfEntry;
  710. TmpIfEntry.dwIndex = IfIndex;
  711. if (GetIfEntry(&TmpIfEntry ) == NO_ERROR)
  712. pInfo->PacketSize = TmpIfEntry.dwMtu;
  713. else
  714. pInfo->PacketSize = INPUT_PACKET_SZ;
  715. }
  716. //
  717. // initialize the query timer
  718. //
  719. pQueryTimer->Function = T_QueryTimer;
  720. pQueryTimer->Context = &pQueryTimer->Context;
  721. pQueryTimer->Timeout = pConfig->StartupQueryInterval;
  722. pQueryTimer->Status = TIMER_STATUS_CREATED;
  723. //
  724. // initialize non query timer
  725. //
  726. pNonQueryTimer->Function = T_NonQueryTimer;
  727. pNonQueryTimer->Context = &pNonQueryTimer->Context;
  728. pNonQueryTimer->Timeout = pConfig->OtherQuerierPresentInterval;
  729. pNonQueryTimer->Status = TIMER_STATUS_CREATED;
  730. //
  731. // take timer lock and insert timers into the list
  732. //
  733. ACQUIRE_TIMER_LOCK("_ActivateInterface");
  734. //
  735. // insert querier timer in the list
  736. //
  737. #if DEBUG_TIMER_TIMERID
  738. SET_TIMER_ID(pQueryTimer, 110, IfIndex, 0, 0);
  739. #endif;
  740. InsertTimer(pQueryTimer, pQueryTimer->Timeout, TRUE, DBG_Y);
  741. RELEASE_TIMER_LOCK("_ActivateInterface");
  742. //
  743. // activate Input socket
  744. //
  745. Error = WSAEventSelect(pite->SocketEntry.Socket,
  746. pite->SocketEntry.pSocketEventsEntry->InputEvent,
  747. FD_READ
  748. );
  749. if (Error != NO_ERROR) {
  750. Trace3(IF, "WSAEventSelect returned %d for interface %0x (%d.%d.%d.%d)",
  751. Error, IfIndex, PRINT_IPADDR(pite->IpAddr));
  752. Logerr1(EVENTSELECT_FAILED, "%I", pite->IpAddr, 0);
  753. GOTO_END_BLOCK1;
  754. }
  755. //
  756. // set the activated flag here so that the joins will work
  757. //
  758. pite->Status |= IF_ACTIVATED_FLAG;
  759. if (pInfo->StartupQueryCountCurrent) {
  760. //
  761. // send the initial general query
  762. //
  763. SEND_GEN_QUERY(pite);
  764. // decrement the number of startupQueryCount left to be sent
  765. pInfo->StartupQueryCountCurrent--;
  766. }
  767. //
  768. // do static joins (no static joins for ras server interface)
  769. //
  770. if (!IS_RAS_SERVER_IF(pite->IfType))
  771. {
  772. PGROUP_TABLE_ENTRY pge;
  773. PGI_ENTRY pgie;
  774. DWORD GroupAddr;
  775. SOCKADDR_IN saLocalIf;
  776. //
  777. // socket for static groups already created in _CreateIfSockets
  778. // irrespective of whether there are any static groups
  779. //
  780. pHead = &pite->Config.ListOfStaticGroups;
  781. for (ple=pHead->Flink; ple!=pHead; ple=ple->Flink) {
  782. pStaticGroup = CONTAINING_RECORD(ple, IF_STATIC_GROUP, Link);
  783. // IGMP_HOST_JOIN
  784. if (pStaticGroup->Mode==IGMP_HOST_JOIN) {
  785. DWORD i;
  786. if (pStaticGroup->NumSources==0
  787. || pStaticGroup->FilterType==EXCLUSION)
  788. {
  789. JoinMulticastGroup(pite->StaticGroupSocket,
  790. pStaticGroup->GroupAddr,
  791. pite->IfIndex,
  792. pite->IpAddr,
  793. 0
  794. );
  795. }
  796. for (i=0; i<pStaticGroup->NumSources; i++) {
  797. if (pStaticGroup->FilterType==INCLUSION) {
  798. JoinMulticastGroup(pite->StaticGroupSocket,
  799. pStaticGroup->GroupAddr,
  800. pite->IfIndex,
  801. pite->IpAddr,
  802. pStaticGroup->Sources[i]
  803. );
  804. }
  805. else {
  806. BlockSource(pite->StaticGroupSocket,
  807. pStaticGroup->GroupAddr,
  808. pite->IfIndex,
  809. pite->IpAddr,
  810. pStaticGroup->Sources[i]
  811. );
  812. }
  813. }
  814. }
  815. // IGMPRTR_MGM_ONLY
  816. else {
  817. BOOL bCreate = TRUE;
  818. DWORD i;
  819. GroupAddr = pStaticGroup->GroupAddr;
  820. ACQUIRE_GROUP_LOCK(GroupAddr, "_ActivateInterface");
  821. pge = GetGroupFromGroupTable(GroupAddr, &bCreate, 0);
  822. pgie = GetGIFromGIList(pge, pite, 0,
  823. pStaticGroup->NumSources==0?STATIC_GROUP:NOT_STATIC_GROUP,
  824. &bCreate, 0);
  825. for (i=0; i<pStaticGroup->NumSources; i++) {
  826. GetSourceEntry(pgie, pStaticGroup->Sources[i],
  827. pStaticGroup->FilterType,
  828. &bCreate, STATIC, MGM_YES);
  829. }
  830. RELEASE_GROUP_LOCK(GroupAddr, "_ActivateInterface");
  831. }
  832. }
  833. }
  834. } END_BREAKOUT_BLOCK1;
  835. if (Error!=NO_ERROR) {
  836. DeActivationDeregisterFromMgm(pite);
  837. DeActivateInterfaceComplete(pite);
  838. pite->Status &= ~IF_ACTIVATED_FLAG;
  839. if (bProxy) {
  840. Logerr1(ACTIVATION_FAILURE_PROXY, "%d",IfIndex, Error);
  841. }
  842. else {
  843. Logerr2(ACTIVATION_FAILURE_RTR, "%d%d",
  844. GET_IF_VERSION(pite), IfIndex, Error);
  845. }
  846. }
  847. else {
  848. if (bProxy) {
  849. Loginfo1(INTERFACE_PROXY_ACTIVATED, "%d",
  850. IfIndex, NO_ERROR);
  851. }
  852. else {
  853. Loginfo2(INTERFACE_RTR_ACTIVATED, "%d%d",
  854. GET_IF_VERSION(pite), IfIndex, NO_ERROR);
  855. }
  856. Trace1(START, "IGMP activated on interface:%0x", IfIndex);
  857. }
  858. Trace1(LEAVE, "leaving ActivateInterface():%d\n", Error);
  859. return Error;
  860. } //end _ActivateInterface
  861. //------------------------------------------------------------------------------
  862. // _DeActivateDeregisterFromMgm
  863. //------------------------------------------------------------------------------
  864. DWORD
  865. DeActivationDeregisterFromMgm(
  866. PIF_TABLE_ENTRY pite
  867. )
  868. {
  869. HANDLE hMgmHandle = IS_PROTOCOL_TYPE_PROXY(pite)
  870. ? g_MgmProxyHandle: g_MgmIgmprtrHandle;
  871. DWORD Error=NO_ERROR, IfIndex=pite->IfIndex;
  872. PLIST_ENTRY pHead, ple;
  873. //
  874. // Call MGM to release the interface ownership
  875. //
  876. if (pite->CreationFlags&TAKEN_INTERFACE_OWNERSHIP_WITH_MGM) {
  877. Error = MgmReleaseInterfaceOwnership(hMgmHandle, IfIndex,0);
  878. if (Error!=NO_ERROR) {
  879. Trace2(ERR, "MgmReleaseInterfaceOwnership returned error(%d) for If(%0x)",
  880. Error, IfIndex);
  881. IgmpAssertOnError(FALSE);
  882. }
  883. else
  884. pite->CreationFlags &= ~TAKEN_INTERFACE_OWNERSHIP_WITH_MGM;
  885. }
  886. //
  887. // if releasing proxy interface, then deregister proxy from mgm
  888. //
  889. if (IS_PROTOCOL_TYPE_PROXY(pite)
  890. && (pite->CreationFlags&REGISTERED_PROTOCOL_WITH_MGM))
  891. {
  892. Error = MgmDeRegisterMProtocol(g_MgmProxyHandle);
  893. if (Error!=NO_ERROR) {
  894. Trace1(ERR, "MgmDeRegisterMProtocol(proxy) returned error(%d)",
  895. Error);
  896. IgmpAssertOnError(FALSE);
  897. }
  898. else
  899. pite->CreationFlags &= ~REGISTERED_PROTOCOL_WITH_MGM;
  900. }
  901. //
  902. // delete all proxy alert entries
  903. //
  904. if (IS_PROTOCOL_TYPE_PROXY(pite)) {
  905. ACQUIRE_PROXY_ALERT_LOCK("_DeActivationDeregisterMgm");
  906. {
  907. for (ple=g_ProxyAlertsList.Flink; ple!=&g_ProxyAlertsList; ) {
  908. PPROXY_ALERT_ENTRY pProxyAlertEntry
  909. = CONTAINING_RECORD(ple, PROXY_ALERT_ENTRY, Link);
  910. ple = ple->Flink;
  911. IGMP_FREE(pProxyAlertEntry);
  912. }
  913. }
  914. InitializeListHead(&g_ProxyAlertsList);
  915. RELEASE_PROXY_ALERT_LOCK("_DeActivationDeregisterMgm");
  916. }
  917. //
  918. // if ras interface, then call mgm to release ownership of all ras clients
  919. //
  920. if (IS_RAS_SERVER_IF(pite->IfType)) {
  921. PRAS_TABLE_ENTRY prte;
  922. pHead = &pite->pRasTable->ListByAddr;
  923. for (ple=pHead->Flink; ple!=pHead; ple=ple->Flink) {
  924. prte = CONTAINING_RECORD(ple, RAS_TABLE_ENTRY, LinkByAddr);
  925. if (prte->CreationFlags & TAKEN_INTERFACE_OWNERSHIP_WITH_MGM) {
  926. Error = MgmReleaseInterfaceOwnership(g_MgmIgmprtrHandle, IfIndex,
  927. prte->NHAddr);
  928. if (Error!=NO_ERROR) {
  929. Trace3(ERR,
  930. "error:%d _MgmReleaseInterfaceOwnership() for If:%0x, "
  931. "NHAddr:%d.%d.%d.%d",
  932. Error, IfIndex, PRINT_IPADDR(prte->NHAddr));
  933. IgmpAssertOnError(FALSE);
  934. }
  935. prte->CreationFlags &= ~TAKEN_INTERFACE_OWNERSHIP_WITH_MGM;
  936. }
  937. }
  938. }
  939. return Error;
  940. }
  941. //------------------------------------------------------------------------------
  942. // DeActivateInterfaceInitial
  943. //
  944. // deregister from MGM. Then create a new interface entry structure which
  945. // replaces the old one in all the lists. Now the old interface entry and
  946. // all its associated structures can be lazily deleted.
  947. // Also update the global Proxy and Ras table pointers.
  948. //
  949. // Called by _UnBindIfEntry(), _DisableIfEntry()
  950. //------------------------------------------------------------------------------
  951. PIF_TABLE_ENTRY
  952. DeActivateInterfaceInitial (
  953. PIF_TABLE_ENTRY piteOld
  954. )
  955. {
  956. DWORD IfIndex = piteOld->IfIndex;
  957. PIF_TABLE_ENTRY piteNew;
  958. DWORD dwRetval, Error=NO_ERROR;
  959. PLIST_ENTRY pHead, ple, pleNext;
  960. Trace0(ENTER1, "Entering _DeActivateInterfaceInitial()");
  961. //
  962. // deregister from Mgm
  963. //
  964. DeActivationDeregisterFromMgm(piteOld);
  965. //
  966. // allocate memory for the new interface
  967. //
  968. piteNew = IGMP_ALLOC(sizeof(IF_TABLE_ENTRY), 0x8, IfIndex);
  969. PROCESS_ALLOC_FAILURE3(piteNew,
  970. "error %d allocating %d bytes for interface %0x",
  971. Error, sizeof(IF_TABLE_ENTRY), IfIndex,
  972. return NULL);
  973. // copy the old pite fields to the new pite
  974. CopyMemory(piteNew, piteOld, sizeof(IF_TABLE_ENTRY));
  975. // copy the old static groups to the new pite
  976. InitializeListHead(&piteNew->Config.ListOfStaticGroups);
  977. pHead = &piteOld->Config.ListOfStaticGroups;
  978. for (ple=pHead->Flink; ple!=pHead; ple=pleNext) {
  979. pleNext = ple->Flink;
  980. RemoveEntryList(ple);
  981. InsertTailList(&piteNew->Config.ListOfStaticGroups,
  982. ple);
  983. }
  984. // set the status
  985. MGM_DISABLE_IGMPRTR(piteNew);
  986. // LinkByAddr (not inserted in this list as the IF is deactivated)
  987. InitializeListHead(&piteNew->LinkByAddr);
  988. //
  989. // insert the new entry before the old entry, and remove the old
  990. // entry from the list of IFs ordered by index and from hash table
  991. //
  992. InsertTailList(&piteOld->LinkByIndex, &piteNew->LinkByIndex);
  993. RemoveEntryList(&piteOld->LinkByIndex);
  994. InsertTailList(&piteOld->HTLinkByIndex, &piteNew->HTLinkByIndex);
  995. RemoveEntryList(&piteOld->HTLinkByIndex);
  996. // initialize GI list to empty
  997. InitializeListHead(&piteNew->ListOfSameIfGroups);
  998. InitializeListHead(&piteNew->ListOfSameIfGroupsNew);
  999. piteNew->NumGIEntriesInNewList = 0;
  1000. // set binding of piteOld to NULL so that it doesnt get deleted
  1001. piteOld->pBinding = NULL;
  1002. // reset the Info fields
  1003. ZeroMemory(&piteNew->Info, sizeof(IF_INFO));
  1004. //
  1005. // create a new RAS table if it is a RAS server interface, and set ras
  1006. // pointer in global table. I could have reused the ras table, but dont
  1007. // so that resetting the fields is cleaner.
  1008. //
  1009. if ( IS_RAS_SERVER_IF(piteNew->IfType)) {
  1010. PRAS_TABLE_ENTRY prte;
  1011. InitializeRasTable(IfIndex, piteNew);
  1012. //
  1013. // recreate all ras client entries
  1014. //
  1015. pHead = &piteOld->pRasTable->ListByAddr;
  1016. for (ple=pHead->Flink; ple!=pHead; ple=ple->Flink) {
  1017. prte = CONTAINING_RECORD(ple, RAS_TABLE_ENTRY, LinkByAddr);
  1018. CreateRasClient(piteNew, &prte, prte->NHAddr);
  1019. }
  1020. InterlockedExchangePointer(&g_pRasIfEntry, piteNew);
  1021. }
  1022. //
  1023. // if proxy, then update the entry in the global table
  1024. // I reuse the proxy hash table. set it to null in piteOld so that it is not
  1025. // delete there.
  1026. //
  1027. if (g_pProxyIfEntry == piteOld) {
  1028. InterlockedExchangePointer(&g_pProxyIfEntry, piteNew);
  1029. // clean the hash table entries
  1030. {
  1031. DWORD i;
  1032. PPROXY_GROUP_ENTRY ppge;
  1033. PLIST_ENTRY pProxyHashTable = piteOld->pProxyHashTable;
  1034. if (piteOld->CreationFlags&CREATED_PROXY_HASH_TABLE) {
  1035. for (i=0; i<PROXY_HASH_TABLE_SZ; i++) {
  1036. pHead = &pProxyHashTable[i];
  1037. for (ple=pHead->Flink; ple!=pHead; ) {
  1038. ppge = CONTAINING_RECORD(ple, PROXY_GROUP_ENTRY, HT_Link);
  1039. ple=ple->Flink;
  1040. // delete all sources
  1041. {
  1042. PLIST_ENTRY pHeadSrc, pleSrc;
  1043. PPROXY_SOURCE_ENTRY pSourceEntry;
  1044. pHeadSrc = &ppge->ListSources;
  1045. for (pleSrc=pHeadSrc->Flink; pleSrc!=pHeadSrc; ) {
  1046. pSourceEntry = CONTAINING_RECORD(pleSrc,
  1047. PROXY_SOURCE_ENTRY, LinkSources);
  1048. pleSrc = pleSrc->Flink;
  1049. IGMP_FREE(pSourceEntry);
  1050. }
  1051. }
  1052. IGMP_FREE(ppge);
  1053. }
  1054. InitializeListHead(pHead);
  1055. }
  1056. }
  1057. }
  1058. piteOld->pProxyHashTable = NULL;
  1059. }
  1060. //
  1061. // socket is created when the interface is activated
  1062. //
  1063. piteNew->SocketEntry.Socket = INVALID_SOCKET;
  1064. //piteNew->SocketEntry.pSocketEventsEntry = NULL;
  1065. //InitializeListHead(&piteNew->SocketEntry.LinkByInterfaces);
  1066. // initialize the new timers
  1067. piteNew->QueryTimer.Status = 0;
  1068. piteNew->NonQueryTimer.Status = 0;
  1069. piteNew->pPrevIfGroupEnumPtr = NULL;
  1070. piteNew->PrevIfGroupEnumSignature = 0;
  1071. piteNew->StaticGroupSocket = INVALID_SOCKET;
  1072. // creationFlags already copied.
  1073. piteNew->CreationFlags &= ~CREATION_FLAGS_DEACTIVATION_CLEAR;
  1074. Trace0(LEAVE1, "Leaving _DeActivateInterfaceInitial()");
  1075. return piteNew;
  1076. }//end _DeActivateInterfaceInitial
  1077. //------------------------------------------------------------------------------
  1078. // _DeActivateInterfaceComplete
  1079. //
  1080. // If ras server, then for each ras client queues a work item to delete it.
  1081. // the last ras client will delete the pite entry.
  1082. // Deletes the GI entries, and calls _CompleteIfDeletion() if deleted flag
  1083. // or DeactivateDelete flag set on the IF entry.
  1084. // This routine assumes that the interface has been removed from any global
  1085. // lists that it needs to be removed from, and that the appropriate flags have
  1086. // been set. The only way they can still be used is by timers getting fired or
  1087. // by input on socket.
  1088. //
  1089. // Called by:
  1090. // _ActivateInterface:(if it fails), only in this case pite is not deleted.
  1091. // _DeleteIfEntry -->
  1092. // _DeActivationDeregisterFromMgm & _WF_CompleteIfDeactivateDelete
  1093. // _UnbindIfEntry & _DisableIfEntry -->
  1094. // _DeActivateInterfaceInitial & _WF_CompleteIfDeactivateDelete
  1095. // Lock:
  1096. // If called when interface is being deleted, then no interface locks required.
  1097. // else assumes exclusive interface lock.
  1098. // requires exclusive sockets list lock in either case.
  1099. //------------------------------------------------------------------------------
  1100. VOID
  1101. DeActivateInterfaceComplete (
  1102. PIF_TABLE_ENTRY pite
  1103. )
  1104. {
  1105. DWORD IfIndex = pite->IfIndex;
  1106. DWORD Error = NO_ERROR, dwRetval;
  1107. PLIST_ENTRY pHead, ple;
  1108. PGI_ENTRY pgie;
  1109. BOOL bProxy = IS_PROTOCOL_TYPE_PROXY(pite);;
  1110. Trace1(ENTER1, "Entering _DeActivateInterfaceComplete(%d)", IfIndex);
  1111. //
  1112. // do all deactivation here which is common for all interfaces
  1113. // whether ras server or not.
  1114. //
  1115. //
  1116. // unbind sockets from Input event and then close the sockets
  1117. //
  1118. if (pite->SocketEntry.Socket!=INVALID_SOCKET) {
  1119. //
  1120. // proxy does not bind its socket to input event as it
  1121. // does not want to receive any packets
  1122. //
  1123. if (!bProxy)
  1124. WSAEventSelect(pite->SocketEntry.Socket,
  1125. pite->SocketEntry.pSocketEventsEntry->InputEvent, 0);
  1126. }
  1127. if (pite->CreationFlags&SOCKETS_CREATED)
  1128. DeleteIfSockets(pite);
  1129. /////////////////////////////////////////////////////////
  1130. // IS_RAS_SERVER_IF
  1131. /////////////////////////////////////////////////////////
  1132. //
  1133. // go through the list of Ras clients. Mark them as deleted, remove them
  1134. // from all global lists, and set work item to delete them.
  1135. //
  1136. if (IS_RAS_SERVER_IF(pite->IfType)) {
  1137. PRAS_TABLE prt = pite->pRasTable;
  1138. PRAS_TABLE_ENTRY prte;
  1139. // go through the list of all Ras clients and set them to be deleted
  1140. pHead = &prt->ListByAddr;
  1141. for (ple=pHead->Flink; ple!=pHead; ) {
  1142. prte = CONTAINING_RECORD(ple, RAS_TABLE_ENTRY, LinkByAddr);
  1143. ple=ple->Flink;
  1144. //
  1145. // if ras client has deleted flag already set, then ignore it.
  1146. //
  1147. if (!(prte->Status&IF_DELETED_FLAG)) {
  1148. //
  1149. // set deleted flag for the ras client, so that no one else will
  1150. // try to access it
  1151. prte->Status |= IF_DELETED_FLAG;
  1152. //
  1153. // remove the RAS client from the Ras table lists so that no one
  1154. // will access it.
  1155. //
  1156. RemoveEntryList(&prte->HTLinkByAddr);
  1157. RemoveEntryList(&prte->LinkByAddr);
  1158. //
  1159. // clean up the ras client
  1160. //
  1161. DeleteRasClient(prte);
  1162. }
  1163. }
  1164. //
  1165. // delete the timers from pite entry
  1166. //
  1167. ACQUIRE_TIMER_LOCK("_DeActivateInterfaceComplete");
  1168. if (IS_TIMER_ACTIVE(pite->QueryTimer))
  1169. RemoveTimer(&pite->QueryTimer, DBG_Y);
  1170. if (IS_TIMER_ACTIVE(pite->NonQueryTimer))
  1171. RemoveTimer(&pite->NonQueryTimer, DBG_Y);
  1172. RELEASE_TIMER_LOCK("_DeActivateInterfaceComplete");
  1173. pite->CreationFlags = 0;
  1174. prt->RefCount--;
  1175. //
  1176. // deleting the pite entry(if deleted flag is set), and ras table will
  1177. // be done by the work item which deletes the last Ras client
  1178. // (when refcount==0) however if there are no ras clients, then I will
  1179. // have to do the cleanup here
  1180. //
  1181. if ( ((pite->Status&IF_DELETED_FLAG)
  1182. ||(pite->Status&IF_DEACTIVATE_DELETE_FLAG))
  1183. &&(prt->RefCount==0) )
  1184. {
  1185. CompleteIfDeletion(pite);
  1186. }
  1187. }
  1188. //------------------------------------------------------------
  1189. // NOT IS_RAS_SERVER_IF: PROXY IF
  1190. //------------------------------------------------------------
  1191. // PROXY INTERFACE. Just clean the hash table, and delete interface if req
  1192. else if ( (!IS_RAS_SERVER_IF(pite->IfType)) && bProxy) {
  1193. // the proxy hashTable will be deleted if
  1194. // necessary in _CompleteIfDeletion().
  1195. //
  1196. // delete the interface if either IF_DELETED_FLAG or
  1197. // IF_DEACTIVATE_DELETE_FLAG set. (interface not deleted when cleaning
  1198. // up because activate interface failed
  1199. //
  1200. if ( (pite->Status&IF_DELETED_FLAG)
  1201. ||(pite->Status&IF_DEACTIVATE_DELETE_FLAG) )
  1202. {
  1203. CompleteIfDeletion(pite);
  1204. }
  1205. }
  1206. //----------------------
  1207. // NOT PROXY interface
  1208. //----------------------
  1209. else if ( !IS_RAS_SERVER_IF(pite->IfType) ) {
  1210. //
  1211. // take exclusive lock on the If_Group List and remove all timers.
  1212. // From now on no one can enter from outside and no one is inside
  1213. // as all timers have been removed.
  1214. // have to take the if_group_list lock to make sure that no
  1215. // one is changing it.
  1216. ACQUIRE_IF_GROUP_LIST_LOCK(pite->IfIndex, "_DeActivateInterfaceComplete");
  1217. //
  1218. // Remove all timers
  1219. //
  1220. ACQUIRE_TIMER_LOCK("_DeActivateInterfaceComplete");
  1221. // delete all timers contained in GI entries and the sources
  1222. pHead = &pite->ListOfSameIfGroups;
  1223. DeleteAllTimers(pHead, NOT_RAS_CLIENT);
  1224. pHead = &pite->ListOfSameIfGroupsNew;
  1225. DeleteAllTimers(pHead, NOT_RAS_CLIENT);
  1226. pite->NumGIEntriesInNewList = 0;
  1227. // delete query timer
  1228. if (IS_TIMER_ACTIVE(pite->QueryTimer))
  1229. RemoveTimer(&pite->QueryTimer, DBG_Y);
  1230. if (IS_TIMER_ACTIVE(pite->NonQueryTimer))
  1231. RemoveTimer(&pite->NonQueryTimer, DBG_Y);
  1232. RELEASE_TIMER_LOCK("_DeActivateInterfaceComplete");
  1233. RELEASE_IF_GROUP_LIST_LOCK(pite->IfIndex, "_DeActivateInterfaceComplete");
  1234. //
  1235. // revisit the list and delete all GI entries. Need to take
  1236. // exclusive lock on the group bucket before deleting the GI entry
  1237. // No need to lock the If-Group list as deleted flag already set and
  1238. // no one can visit the list from outside or inside(all timers removed).
  1239. //
  1240. DeleteAllGIEntries(pite);
  1241. //
  1242. // if deleted flag set, then also delete the interface
  1243. //
  1244. if ( (pite->Status&IF_DELETED_FLAG)
  1245. ||(pite->Status&IF_DEACTIVATE_DELETE_FLAG) )
  1246. {
  1247. CompleteIfDeletion(pite);
  1248. }
  1249. } //deactivated if: Not(ras server if)
  1250. // do not use pite, or prt from here as they are deleted.
  1251. if (bProxy)
  1252. Loginfo1(PROXY_DEACTIVATED, "%d",IfIndex, NO_ERROR);
  1253. else
  1254. Loginfo1(RTR_DEACTIVATED, "%d",IfIndex, NO_ERROR);
  1255. Trace1(LEAVE, "leaving _DeActivateInterfaceComplete(%d)", IfIndex);
  1256. } //end _DeActivateInterfaceComplete
  1257. //------------------------------------------------------------------------------
  1258. // EnableInterface
  1259. //
  1260. // sets the status to enabled. If interface is also bound and enabled in
  1261. // config, then activate the interface.
  1262. //
  1263. // Locks: SocketsLock, IfListLock, Exclusive IfLock
  1264. //------------------------------------------------------------------------------
  1265. DWORD
  1266. EnableInterface(
  1267. IN DWORD IfIndex
  1268. )
  1269. {
  1270. DWORD Error = NO_ERROR;
  1271. if (!EnterIgmpApi()) { return ERROR_CAN_NOT_COMPLETE; }
  1272. Trace1(ENTER1, "entering _EnableInterface(%0x):", IfIndex);
  1273. Trace1(IF, "enabling interface %0x", IfIndex);
  1274. //
  1275. // enable the interface
  1276. //
  1277. ACQUIRE_SOCKETS_LOCK_EXCLUSIVE("_EnableInterface");
  1278. ACQUIRE_IF_LIST_LOCK("_EnableInterface");
  1279. ACQUIRE_IF_LOCK_EXCLUSIVE(IfIndex, "_EnableInterface");
  1280. Error = EnableIfEntry(IfIndex, TRUE);
  1281. RELEASE_SOCKETS_LOCK_EXCLUSIVE("_EnableInterface");
  1282. RELEASE_IF_LIST_LOCK("_EnableInterface");
  1283. RELEASE_IF_LOCK_EXCLUSIVE(IfIndex, "_EnableInterface");
  1284. Trace2(LEAVE1, "leaving _EnableInterface(%0x): %d\n", IfIndex, Error);
  1285. if (Error!=NO_ERROR) {
  1286. Trace1(ERR, "Error enabling interface:%0x\n", IfIndex);
  1287. IgmpAssertOnError(FALSE);
  1288. }
  1289. LeaveIgmpApi();
  1290. return Error;
  1291. }
  1292. //------------------------------------------------------------------------------
  1293. // _EnableInterface_ConfigChanged
  1294. //
  1295. // Set the status to enabled. If it is also bound, activate the interface.
  1296. //
  1297. // Locks: Runs entirely in Exclusive interface lock.
  1298. // Calls: EnableIfEntry() with mode config
  1299. //------------------------------------------------------------------------------
  1300. DWORD
  1301. EnableInterface_ConfigChanged(
  1302. DWORD IfIndex
  1303. )
  1304. {
  1305. DWORD Error=NO_ERROR;
  1306. Trace1(ENTER, "entering _EnableInterface_ConfigChanged(%d):", IfIndex);
  1307. Trace1(IF,
  1308. "Enabling Interface(%0x) due to change made by _SetInterfaceConfigInfo",
  1309. IfIndex);
  1310. //
  1311. // enable the interface
  1312. //
  1313. Error = EnableIfEntry(IfIndex, FALSE); // FALSE->change made by config
  1314. Trace2(LEAVE, "leaving _EnableInterface_ConfigChanged(%d): %d\n",
  1315. IfIndex, Error);
  1316. return Error;
  1317. } //end _DeActivateInterfaceInitial
  1318. //------------------------------------------------------------------------------
  1319. // BindInterface //
  1320. //------------------------------------------------------------------------------
  1321. DWORD
  1322. BindInterface(
  1323. IN DWORD IfIndex,
  1324. IN PVOID pBinding
  1325. )
  1326. /*++
  1327. Routine Description:
  1328. Sets the binding for the interface and activates it if it is also enabled.
  1329. Return Value
  1330. ERROR_INVALID_PARAMETER
  1331. NO_ERROR
  1332. Lock:
  1333. runs entirely in Interface Exclusive lock
  1334. Calls:
  1335. BindIfEntry()
  1336. --*/
  1337. {
  1338. DWORD Error=NO_ERROR;
  1339. if (!EnterIgmpApi()) { return ERROR_CAN_NOT_COMPLETE; }
  1340. Trace1(ENTER1, "entering BindInterface: %0x", IfIndex);
  1341. Trace1(IF, "binding interface %0x", IfIndex);
  1342. // pBinding should not be NULL
  1343. if (pBinding == NULL) {
  1344. Trace0(IF, "error: binding struct pointer is NULL");
  1345. Trace1(LEAVE, "leaving BindInterface: %0x", ERROR_INVALID_PARAMETER);
  1346. LeaveIgmpApi();
  1347. return ERROR_INVALID_PARAMETER;
  1348. }
  1349. //
  1350. // now bind the interface in the interface table
  1351. //
  1352. //
  1353. // take sockets lock, as activate interface might be called, and
  1354. // sockets lock should be taken before interface lock
  1355. //
  1356. ACQUIRE_SOCKETS_LOCK_EXCLUSIVE("_BindInterface");
  1357. ACQUIRE_IF_LIST_LOCK("_BindInterface");
  1358. ACQUIRE_IF_LOCK_EXCLUSIVE(IfIndex, "_BindInterface");
  1359. Error = BindIfEntry(IfIndex, pBinding);
  1360. RELEASE_SOCKETS_LOCK_EXCLUSIVE("_BindInterface");
  1361. RELEASE_IF_LIST_LOCK("_BindInterface");
  1362. RELEASE_IF_LOCK_EXCLUSIVE(IfIndex, "_BindInterface");
  1363. Trace2(LEAVE1, "leaving _BindInterface(%x): %d\n", IfIndex, Error);
  1364. if (Error!=NO_ERROR){
  1365. Trace1(ERR, "Error binding interface(%0x)\n", IfIndex);
  1366. IgmpAssertOnError(FALSE);
  1367. }
  1368. LeaveIgmpApi();
  1369. return Error;
  1370. }
  1371. //------------------------------------------------------------------------------
  1372. // _BindIfEntry
  1373. //
  1374. // Binds the ip addresses to the interface. The lowest of the ip addresses is
  1375. // picked up as the de-facto address for that interface. If the interface is
  1376. // already bound, it makes sure that the bindings are consistent. Currently
  1377. // you cannot change the bindings of an interface.
  1378. // If the interface is already enabled, then it is also activated.
  1379. //
  1380. // Locks:
  1381. // assumes exclusive interface lock.
  1382. // Called by: _BindInterface().
  1383. //------------------------------------------------------------------------------
  1384. DWORD
  1385. BindIfEntry(
  1386. DWORD IfIndex,
  1387. PIP_ADAPTER_BINDING_INFO pBinding
  1388. )
  1389. {
  1390. PIF_TABLE_ENTRY pite = NULL;
  1391. DWORD i, j, dwSize;
  1392. IPADDR MinAddr;
  1393. PIGMP_IF_BINDING pib;
  1394. PIGMP_IP_ADDRESS paddr;
  1395. BOOL bFound;
  1396. DWORD Error = NO_ERROR;
  1397. INT cmp;
  1398. pib = NULL;
  1399. //
  1400. // retrieve the interface entry
  1401. //
  1402. pite = GetIfByIndex(IfIndex);
  1403. if (pite == NULL) {
  1404. return ERROR_INVALID_PARAMETER;
  1405. }
  1406. //
  1407. // If the interface is already bound, check to see if he is giving
  1408. // us a different binding. If he is, then it is an error.
  1409. //
  1410. // return from this case. dont break.
  1411. if (IS_IF_BOUND(pite)) {
  1412. Trace1(IF, "interface %0x is already bound", IfIndex);
  1413. pib = pite->pBinding;
  1414. Error = NO_ERROR;
  1415. // number of address bindings before and now should be same
  1416. if(pib->AddrCount != pBinding->AddressCount){
  1417. Trace1(IF, "interface %0x is bound and has different binding",
  1418. IfIndex);
  1419. return ERROR_INVALID_PARAMETER;
  1420. }
  1421. //
  1422. // make sure that all address bindings are consistent
  1423. //
  1424. paddr = (PIGMP_IP_ADDRESS)((pib) + 1);
  1425. for(i = 0; i < pBinding->AddressCount; i++) {
  1426. bFound = FALSE;
  1427. for(j = 0; j < pBinding->AddressCount; j++) {
  1428. if((paddr[j].IpAddr == pBinding->Address[i].Address) &&
  1429. (paddr[j].SubnetMask == pBinding->Address[i].Mask))
  1430. {
  1431. bFound = TRUE;
  1432. break;
  1433. }
  1434. }
  1435. if(!bFound) {
  1436. Trace1(IF,
  1437. "interface %0x is bound and has different binding",
  1438. IfIndex);
  1439. return ERROR_INVALID_PARAMETER;
  1440. }
  1441. }
  1442. return NO_ERROR;
  1443. }
  1444. //
  1445. // make sure there is at least one address. However, unnumbered
  1446. // RAS server interfaces might have no IP addresses.
  1447. //
  1448. if ( (pBinding->AddressCount==0)&&(!IS_RAS_ROUTER_IF(pite->IfType)) ) {
  1449. return ERROR_CAN_NOT_COMPLETE;
  1450. }
  1451. BEGIN_BREAKOUT_BLOCK1 {
  1452. if (pBinding->AddressCount!=0) {
  1453. //
  1454. // allocate memory to store the binding
  1455. //
  1456. dwSize = sizeof(IGMP_IF_BINDING) +
  1457. pBinding->AddressCount * sizeof(IGMP_IP_ADDRESS);
  1458. pib = IGMP_ALLOC(dwSize, 0x10, IfIndex);
  1459. PROCESS_ALLOC_FAILURE3(pib,
  1460. "error %d allocating %d bytes for binding on interface %0x",
  1461. Error, dwSize, IfIndex, GOTO_END_BLOCK1);
  1462. //
  1463. // copy the bindings
  1464. //
  1465. pib->AddrCount = pBinding->AddressCount;
  1466. paddr = IGMP_BINDING_FIRST_ADDR(pib);
  1467. MinAddr = ~0;
  1468. for (i=0; i<pib->AddrCount; i++,paddr++) {
  1469. paddr->IpAddr = pBinding->Address[i].Address;
  1470. paddr->SubnetMask = pBinding->Address[i].Mask;
  1471. if (INET_CMP(MinAddr, paddr->IpAddr, cmp)>0)
  1472. MinAddr = paddr->IpAddr;
  1473. }
  1474. //
  1475. // set the Interface effective address to the smallest bound address
  1476. //
  1477. pite->IpAddr = MinAddr;
  1478. pite->Config.IpAddr = MinAddr;
  1479. //
  1480. // save the binding in the interface entry
  1481. //
  1482. pite->pBinding = pib;
  1483. }
  1484. // dont have to do the below as they are already set to those values
  1485. else {
  1486. pite->IpAddr = pite->Config.IpAddr = 0;
  1487. pite->pBinding = NULL;
  1488. }
  1489. //
  1490. // mark the interface as being bound
  1491. //
  1492. pite->Status |= IF_BOUND_FLAG;
  1493. //
  1494. // if interface is also enabled, it is now active
  1495. // so activate it
  1496. //
  1497. if (IS_IF_ENABLED_BOUND(pite)) {
  1498. //
  1499. // place interface on the list of active interfaces
  1500. //
  1501. Error = InsertIfByAddr(pite);
  1502. //
  1503. // error if another numbered interface with same IpAddr already exists
  1504. //
  1505. if (Error != NO_ERROR) {
  1506. Trace2(IF, "error %d inserting interface %0x in active list",
  1507. Error, IfIndex);
  1508. GOTO_END_BLOCK1;
  1509. }
  1510. //
  1511. // Activate the Interface
  1512. //
  1513. Error = ActivateInterface(pite);
  1514. //
  1515. // if could not activate the interface then undo the binding
  1516. //
  1517. if (Error != NO_ERROR) {
  1518. Trace1(ERR,
  1519. "Unbinding interface(%0x) because it could not be activated",
  1520. IfIndex);
  1521. IgmpAssertOnError(FALSE);
  1522. RemoveEntryList(&pite->LinkByAddr);
  1523. Error = ERROR_CAN_NOT_COMPLETE;
  1524. GOTO_END_BLOCK1;
  1525. }
  1526. }
  1527. } END_BREAKOUT_BLOCK1;
  1528. //
  1529. // if there was any error, then set the status to unbound (pite is null
  1530. // if interface was not found)
  1531. //
  1532. if (Error!=NO_ERROR) {
  1533. if (pite!=NULL)
  1534. {
  1535. pite->Status &= ~IF_BOUND_FLAG;
  1536. pite->pBinding = NULL;
  1537. pite->IpAddr = pite->Config.IpAddr = 0;
  1538. }
  1539. IGMP_FREE_NOT_NULL(pib);
  1540. }
  1541. return Error;
  1542. } //end BindIfEntry
  1543. //------------------------------------------------------------------------------
  1544. // UnBindInterface //
  1545. //------------------------------------------------------------------------------
  1546. DWORD
  1547. UnBindInterface(
  1548. IN DWORD IfIndex
  1549. )
  1550. /*++
  1551. Routine Description:
  1552. Calls UnBindIfEntry to unbind the interface.
  1553. Calls:
  1554. UnBindIfEntry();
  1555. Locks:
  1556. Runs completely in exclusive interface lock
  1557. --*/
  1558. {
  1559. DWORD Error=NO_ERROR;
  1560. if (!EnterIgmpApi()) { return ERROR_CAN_NOT_COMPLETE; }
  1561. Trace1(ENTER, "entering UnBindInterface(%0x):", IfIndex);
  1562. //
  1563. // unbind the interface
  1564. //
  1565. //
  1566. // take sockets lock, as activate interface might be called, and
  1567. // sockets lock should be taken before interface lock
  1568. //
  1569. ACQUIRE_SOCKETS_LOCK_EXCLUSIVE("_UnBindInterface");
  1570. ACQUIRE_IF_LIST_LOCK("_UnBindInterface");
  1571. ACQUIRE_IF_LOCK_EXCLUSIVE(IfIndex, "_UnBindInterface");
  1572. Error = UnBindIfEntry(IfIndex);
  1573. RELEASE_SOCKETS_LOCK_EXCLUSIVE("_UnBindInterface");
  1574. RELEASE_IF_LIST_LOCK("_UnBindInterface");
  1575. RELEASE_IF_LOCK_EXCLUSIVE(IfIndex, "_UnBindInterface");
  1576. Trace2(LEAVE, "leaving UnBindInterface(%0x): %d\n", IfIndex, Error);
  1577. LeaveIgmpApi();
  1578. return Error;
  1579. }
  1580. //------------------------------------------------------------------------------
  1581. // _UnBindIfEntry
  1582. //
  1583. // If the interface is activated, deactivates it. Removes the binding.
  1584. //
  1585. // MayCall: _DeActivateInterfaceComplete().
  1586. // Locks: assumes exclusive interface lock.
  1587. //------------------------------------------------------------------------------
  1588. DWORD
  1589. UnBindIfEntry(
  1590. DWORD IfIndex
  1591. )
  1592. {
  1593. DWORD Error = NO_ERROR, dwRetval;
  1594. PIF_TABLE_ENTRY pite, piteNew;
  1595. DWORD bProxy;
  1596. BEGIN_BREAKOUT_BLOCK1 {
  1597. //
  1598. // retrieve the interface specified
  1599. //
  1600. pite = GetIfByIndex(IfIndex);
  1601. if (pite == NULL) {
  1602. Trace1(ERR, "_UnbindInterface called for non existing interface(%0x)",
  1603. IfIndex);
  1604. IgmpAssertOnError(FALSE);
  1605. Error = ERROR_INVALID_PARAMETER;
  1606. GOTO_END_BLOCK1;
  1607. }
  1608. //
  1609. // quit if the interface is already unbound
  1610. //
  1611. if (!IS_IF_BOUND(pite)) {
  1612. Error = ERROR_INVALID_PARAMETER;
  1613. Trace1(ERR, "interface %0x is already unbound", IfIndex);
  1614. IgmpAssertOnError(FALSE);
  1615. GOTO_END_BLOCK1;
  1616. }
  1617. //
  1618. // clear the "bound" flag
  1619. //
  1620. pite->Status &= ~IF_BOUND_FLAG;
  1621. //
  1622. // unbind IF
  1623. //
  1624. IGMP_FREE(pite->pBinding);
  1625. pite->pBinding = NULL;
  1626. //
  1627. // if IF activated (ie also enabled), deactivate it
  1628. // note: check for activated flag, and not for enabled flag
  1629. //
  1630. if (IS_IF_ACTIVATED(pite)) {
  1631. // unset activated flag
  1632. pite->Status &= ~IF_ACTIVATED_FLAG;
  1633. // remove the interface from the list of activated interfaces
  1634. RemoveEntryList(&pite->LinkByAddr);
  1635. piteNew = DeActivateInterfaceInitial(pite);
  1636. //
  1637. // queue work item to deactivate and delete the interface.
  1638. //
  1639. // CompleteIfDeactivateDelete will delete the Ras clients, GI entries,
  1640. // and deinitialize pite structure
  1641. //
  1642. //
  1643. // set flag to indicate that the interface is being deleted following
  1644. // partial deactivation
  1645. //
  1646. pite->Status |= IF_DEACTIVATE_DELETE_FLAG;
  1647. CompleteIfDeactivateDelete(pite);
  1648. #ifdef WORKER_DBG
  1649. Trace2(WORKER, "Queuing IgmpWorker function: %s in %s",
  1650. "_WF_CompleteIfDeactivateDelete:", "_UnBindIfEntry");
  1651. #endif
  1652. }
  1653. else {
  1654. pite->IpAddr = pite->Config.IpAddr = 0;
  1655. }
  1656. } END_BREAKOUT_BLOCK1;
  1657. return Error;
  1658. } //end _UnBindIfEntry
  1659. //------------------------------------------------------------------------------
  1660. // Function: _EnableIfEntry
  1661. //------------------------------------------------------------------------------
  1662. DWORD
  1663. EnableIfEntry(
  1664. DWORD IfIndex,
  1665. BOOL bChangedByRtrmgr // changed by rtrmg or SetInterfaceConfigInfo
  1666. )
  1667. /*++
  1668. Routine Description:
  1669. Sets the status to enabled. If the interface is also bound, then activates
  1670. the interface.
  1671. Called by:
  1672. EnableInterface().
  1673. MayCall:
  1674. ActivateIfEntry()
  1675. Locks:
  1676. Assumes exclusive interface lock.
  1677. --*/
  1678. {
  1679. DWORD Error = NO_ERROR;
  1680. PLIST_ENTRY ple, phead;
  1681. PIF_TABLE_ENTRY pite = NULL;
  1682. BEGIN_BREAKOUT_BLOCK1 {
  1683. //
  1684. // retrieve the interface
  1685. //
  1686. pite = GetIfByIndex(IfIndex);
  1687. if (pite == NULL) {
  1688. Trace1(IF, "could not find interface %0x",IfIndex);
  1689. Error = ERROR_INVALID_PARAMETER;
  1690. GOTO_END_BLOCK1;
  1691. }
  1692. if (bChangedByRtrmgr) {
  1693. //
  1694. // quit if the interface is already enabled by the router manager
  1695. //
  1696. if (IS_IF_ENABLED_BY_RTRMGR(pite)) {
  1697. Trace1(IF, "interface %0x is already enabled by the router manager",
  1698. IfIndex);
  1699. Error = NO_ERROR;
  1700. GOTO_END_BLOCK1;
  1701. }
  1702. // set the flag to enabled by router manager
  1703. pite->Status |= IF_ENABLED_FLAG;
  1704. // print trace if enabled flag not set in the Config.
  1705. if (!IS_IF_ENABLED_IN_CONFIG(pite)) {
  1706. Trace1(IF,
  1707. "Interface(%0x) enabled by router manager but not enabled"
  1708. "in the Config", pite->IfIndex);
  1709. }
  1710. }
  1711. else {
  1712. //
  1713. // quit if the interface is already enabled in config
  1714. //
  1715. if (IS_IF_ENABLED_IN_CONFIG(pite)) {
  1716. Trace1(IF, "interface %0x is already enabled in Config",
  1717. IfIndex);
  1718. Error = NO_ERROR;
  1719. GOTO_END_BLOCK1;
  1720. }
  1721. // set the config flag to enabled
  1722. pite->Config.Flags |= IGMP_INTERFACE_ENABLED_IN_CONFIG;
  1723. // print trace if interface not enabled by router manager
  1724. if (!IS_IF_ENABLED_BY_RTRMGR(pite)) {
  1725. Trace1(IF,
  1726. "Interface(%0x) enabled in config but not enabled by router manager",
  1727. IfIndex);
  1728. Error = NO_ERROR;
  1729. GOTO_END_BLOCK1;
  1730. }
  1731. }
  1732. //
  1733. // if interface is already bound, it should be activated
  1734. // if the bInterfaceEnabled flag is also set in config (by the UI)
  1735. //
  1736. if (IS_IF_ENABLED_BOUND(pite)) {
  1737. //
  1738. // place interface on the list of active interfaces
  1739. //
  1740. Error = InsertIfByAddr(pite);
  1741. //
  1742. // error if another interface with same ip address already exists
  1743. //
  1744. if (Error != NO_ERROR) {
  1745. Trace2(IF, "error %d inserting interface %0x in active list",
  1746. Error, IfIndex);
  1747. GOTO_END_BLOCK1;
  1748. }
  1749. //
  1750. // Activate the Interface
  1751. //
  1752. Error = ActivateInterface(pite);
  1753. //
  1754. // if could not activate the interface then disable it again
  1755. //
  1756. if (Error != NO_ERROR) {
  1757. Trace1(ERR,
  1758. "Disabling interface(%0x) because it could not be activated",
  1759. IfIndex);
  1760. IgmpAssertOnError(FALSE);
  1761. RemoveEntryList(&pite->LinkByAddr);
  1762. Error = ERROR_CAN_NOT_COMPLETE;
  1763. GOTO_END_BLOCK1;
  1764. }
  1765. }
  1766. } END_BREAKOUT_BLOCK1;
  1767. //
  1768. // if an error occured somewhere, set the interface back to the previous
  1769. // disabled state.(pite may be null if interface was not found).
  1770. //
  1771. if ((Error!=NO_ERROR)&&(pite!=NULL)) {
  1772. if (bChangedByRtrmgr)
  1773. pite->Status &= ~IF_ENABLED_FLAG;
  1774. else
  1775. pite->Config.Flags &= ~IGMP_INTERFACE_ENABLED_IN_CONFIG;
  1776. }
  1777. return Error;
  1778. }//end EnableIfEntry
  1779. //------------------------------------------------------------------------------
  1780. // _DisableInterface
  1781. //
  1782. // If interface is activated, then deactivates it. Finally sets the disabled flag
  1783. // Locks: Runs completely in exclusive interface lock.
  1784. // Calls: _DisableIfEntry()
  1785. //------------------------------------------------------------------------------
  1786. DWORD
  1787. DisableInterface(
  1788. IN DWORD IfIndex
  1789. )
  1790. {
  1791. DWORD Error=NO_ERROR;
  1792. if (!EnterIgmpApi()) { return ERROR_CAN_NOT_COMPLETE; }
  1793. Trace1(ENTER, "entering DisableInterface(%0x):", IfIndex);
  1794. //
  1795. // disable the interface
  1796. //
  1797. ACQUIRE_SOCKETS_LOCK_EXCLUSIVE("_DisableInterface");
  1798. ACQUIRE_IF_LIST_LOCK("_DisableInterface");
  1799. ACQUIRE_IF_LOCK_EXCLUSIVE(IfIndex, "_DisableInterface");
  1800. Error = DisableIfEntry(IfIndex, TRUE);
  1801. RELEASE_SOCKETS_LOCK_EXCLUSIVE("_DisableInterface");
  1802. RELEASE_IF_LIST_LOCK("_DisableInterface");
  1803. RELEASE_IF_LOCK_EXCLUSIVE(IfIndex, "_DisableInterface");
  1804. Trace2(LEAVE, "leaving DisableInterface(%0x): %d\n", IfIndex, Error);
  1805. LeaveIgmpApi();
  1806. return Error;
  1807. }
  1808. //------------------------------------------------------------------------------
  1809. // _DisableInterface_ConfigChanged
  1810. //
  1811. //If interface is activated, then deactivates it. Finally sets the disabled flag
  1812. //
  1813. // Locks: assumes IfLists lock and exclusive If lock.
  1814. // Calls: _DisableIfEntry() with mode config
  1815. // Called by: _SetInterfaceConfigInfo()
  1816. //------------------------------------------------------------------------------
  1817. DWORD
  1818. DisableInterface_ConfigChanged(
  1819. DWORD IfIndex
  1820. )
  1821. {
  1822. DWORD Error=NO_ERROR;
  1823. Trace1(ENTER1, "entering _DisableInterface_ConfigChanged(%d):", IfIndex);
  1824. Trace1(IF,
  1825. "disabling interface(%0x) due to change made by _SetInterfaceConfigInfo",
  1826. IfIndex);
  1827. Error = DisableIfEntry(IfIndex, FALSE); // false->disabling from config
  1828. Trace2(LEAVE, "leaving _DisableInterface_ConfigChanged(%d): %d\n",
  1829. IfIndex, Error);
  1830. return Error;
  1831. }
  1832. //------------------------------------------------------------------------------
  1833. // _DisableIfEntry
  1834. //
  1835. // if interface is activated, then calls DeActivateInterfaceComplete(). Removes
  1836. // the enabled flag.
  1837. // Locks: Assumes exclusive interface lock.
  1838. // Called by: _DisableInterface()
  1839. //------------------------------------------------------------------------------
  1840. DWORD
  1841. DisableIfEntry(
  1842. DWORD IfIndex,
  1843. BOOL bChangedByRtrmgr
  1844. )
  1845. {
  1846. DWORD Error = NO_ERROR;
  1847. PIF_TABLE_ENTRY pite, piteNew;
  1848. BOOL bProxy;
  1849. BEGIN_BREAKOUT_BLOCK1 {
  1850. //
  1851. // retrieve the interface to be disabled
  1852. //
  1853. pite = GetIfByIndex(IfIndex);
  1854. if (pite == NULL) {
  1855. Trace1(IF, "could not find interface %0x", IfIndex);
  1856. Error = ERROR_INVALID_PARAMETER;
  1857. GOTO_END_BLOCK1;
  1858. }
  1859. if (bChangedByRtrmgr) {
  1860. //
  1861. // quit if already disabled by router manager
  1862. //
  1863. if (!IS_IF_ENABLED_BY_RTRMGR(pite)) {
  1864. Trace1(IF, "interface %0x already disabled by router manager",
  1865. IfIndex);
  1866. Error = ERROR_INVALID_PARAMETER;
  1867. GOTO_END_BLOCK1;
  1868. }
  1869. }
  1870. else {
  1871. //
  1872. // quit if already disabled in Config
  1873. //
  1874. if (!IS_IF_ENABLED_IN_CONFIG(pite)) {
  1875. Trace1(IF, "interface %0x already disabled in config",
  1876. IfIndex);
  1877. Error = ERROR_INVALID_PARAMETER;
  1878. GOTO_END_BLOCK1;
  1879. }
  1880. }
  1881. //
  1882. // clear the enabled flag
  1883. //
  1884. if (bChangedByRtrmgr)
  1885. pite->Status &= ~IF_ENABLED_FLAG;
  1886. else
  1887. pite->Config.Flags &= ~IGMP_INTERFACE_ENABLED_IN_CONFIG;
  1888. //
  1889. // if IF activated (ie also enabled), deactivate it
  1890. // note: check for activated flag, and not for enabled flag
  1891. //
  1892. if (IS_IF_ACTIVATED(pite)) {
  1893. // unset activated flag
  1894. pite->Status &= ~IF_ACTIVATED_FLAG;
  1895. // remove the interface from the list of activated interfaces
  1896. RemoveEntryList(&pite->LinkByAddr);
  1897. piteNew = DeActivateInterfaceInitial(pite);
  1898. //
  1899. // queue work item to deactivate and delete the interface.
  1900. //
  1901. // CompleteIfDeactivateDelete will delete the Ras clients, GI entries,
  1902. // and deinitialize pite structure
  1903. //
  1904. //
  1905. // set flag to indicate that the interface is being deleted following
  1906. // partial deactivation
  1907. //
  1908. pite->Status |= IF_DEACTIVATE_DELETE_FLAG;
  1909. CompleteIfDeactivateDelete(pite);
  1910. #ifdef WORKER_DBG
  1911. Trace2(WORKER, "Queuing IgmpWorker function: %s in %s",
  1912. "_WF_CompleteIfDeactivateDelete:", "_DisableIfEntry");
  1913. #endif
  1914. }
  1915. } END_BREAKOUT_BLOCK1;
  1916. return Error;
  1917. } //end _DisableIfEntry
  1918. //------------------------------------------------------------------------------
  1919. // _CreateRasClient
  1920. //------------------------------------------------------------------------------
  1921. DWORD
  1922. CreateRasClient (
  1923. PIF_TABLE_ENTRY pite,
  1924. PRAS_TABLE_ENTRY *pprteNew,
  1925. DWORD NHAddr
  1926. )
  1927. {
  1928. DWORD Error=NO_ERROR;
  1929. PLIST_ENTRY pHead, ple;
  1930. PRAS_TABLE prt = pite->pRasTable;
  1931. PRAS_TABLE_ENTRY prteCur, prte;
  1932. BEGIN_BREAKOUT_BLOCK1 {
  1933. //
  1934. // Create new Ras client entry and initialize the fields
  1935. //
  1936. prte = IGMP_ALLOC(sizeof(RAS_TABLE_ENTRY), 0x20, pite->IfIndex);
  1937. PROCESS_ALLOC_FAILURE2(prte,
  1938. "error %d allocating %d bytes in CreateRasClient()",
  1939. Error, sizeof(RAS_TABLE_ENTRY),
  1940. GOTO_END_BLOCK1);
  1941. *pprteNew = prte;
  1942. prte->NHAddr = NHAddr;
  1943. prte->IfTableEntry = pite;
  1944. InitializeListHead(&prte->ListOfSameClientGroups);
  1945. // increment refcount for the ras table
  1946. prt->RefCount++;
  1947. //
  1948. // insert into HashTable
  1949. //
  1950. InsertTailList(&prt->HashTableByAddr[RAS_HASH_VALUE(NHAddr)],
  1951. &prte->HTLinkByAddr);
  1952. //
  1953. // insert the client into list of clients ordered by IpAddr
  1954. //
  1955. pHead = &prt->ListByAddr;
  1956. for (ple=pHead->Flink; ple!=pHead; ple=ple->Flink) {
  1957. prteCur = CONTAINING_RECORD(ple, RAS_TABLE_ENTRY, LinkByAddr);
  1958. if (NHAddr>prteCur->NHAddr)
  1959. break;
  1960. }
  1961. InsertTailList(&prt->ListByAddr, &prte->LinkByAddr);
  1962. //
  1963. // Set Interface stats to 0
  1964. //
  1965. ZeroMemory(&prte->Info, sizeof(RAS_CLIENT_INFO));
  1966. prte->Status = IF_CREATED_FLAG;
  1967. prte->CreationFlags = 0;
  1968. } END_BREAKOUT_BLOCK1;
  1969. return Error;
  1970. }
  1971. //------------------------------------------------------------------------------
  1972. // _ConnectRasClient
  1973. //
  1974. // Called when a new RAS client dials up to the RAS server.
  1975. // A new entry is created in the RAS table.
  1976. // Locks: shared interface lock
  1977. // exclusive RAS table lock.
  1978. // Note:
  1979. // Ras client entry is created even if the interface is not activated
  1980. //------------------------------------------------------------------------------
  1981. DWORD
  1982. APIENTRY
  1983. ConnectRasClient (
  1984. ULONG IfIndex,
  1985. PVOID pvNHAddr
  1986. )
  1987. {
  1988. PIF_TABLE_ENTRY pite = NULL;
  1989. PRAS_TABLE prt;
  1990. PRAS_TABLE_ENTRY prte, prteCur;
  1991. PLIST_ENTRY pHead, ple;
  1992. DWORD Error = NO_ERROR;
  1993. PIP_LOCAL_BINDING pNHAddrBinding = (PIP_LOCAL_BINDING)pvNHAddr;
  1994. DWORD NHAddr = pNHAddrBinding->Address;
  1995. // mightdo
  1996. // currently rtrmgr passes 0 for IfIndex. so I set it to the value required
  1997. IfIndex = g_RasIfIndex;
  1998. Trace2(ENTER, "Entering ConnectRasClient(%d.%d.%d.%d):IfIndex(%0x)\n",
  1999. PRINT_IPADDR(NHAddr), IfIndex);
  2000. if (!EnterIgmpApi()) return ERROR_CAN_NOT_COMPLETE;
  2001. //
  2002. // take a shared lock on the interface
  2003. //
  2004. ACQUIRE_IF_LOCK_EXCLUSIVE(IfIndex, "_ConnectRasClient");
  2005. BEGIN_BREAKOUT_BLOCK1 {
  2006. //
  2007. // retrieve the RAS interface entry
  2008. //
  2009. pite = g_pRasIfEntry;
  2010. if ( (pite==NULL)||(g_RasIfIndex!=IfIndex) ) {
  2011. Error = ERROR_INVALID_PARAMETER;
  2012. GOTO_END_BLOCK1;
  2013. }
  2014. //
  2015. // check that it is a RAS server Interface
  2016. //
  2017. if (!IS_RAS_SERVER_IF(pite->IfType)) {
  2018. Error = ERROR_CAN_NOT_COMPLETE;
  2019. Trace2(ERR,
  2020. "Illegal attempt to connect Ras client(%d.%d.%d.%d) to non-Ras"
  2021. "interface(%0x)", PRINT_IPADDR(NHAddr), IfIndex
  2022. );
  2023. IgmpAssertOnError(FALSE);
  2024. Logerr2(CONNECT_FAILED, "%I%d", NHAddr,
  2025. pite->IfIndex, Error);
  2026. GOTO_END_BLOCK1;
  2027. }
  2028. } END_BREAKOUT_BLOCK1;
  2029. //
  2030. // if error, return from here
  2031. //
  2032. if (Error!=NO_ERROR) {
  2033. RELEASE_IF_LOCK_EXCLUSIVE(IfIndex, "_ConnectRasClient");
  2034. LeaveIgmpApi();
  2035. return Error;
  2036. }
  2037. //
  2038. // get pointer to RasTable, write lock RasTable and release interface lock
  2039. //
  2040. prt = pite->pRasTable;
  2041. BEGIN_BREAKOUT_BLOCK2 {
  2042. //
  2043. // check if a RAS client with similar address already exists
  2044. //
  2045. prte = GetRasClientByAddr(NHAddr, prt);
  2046. if (prte!=NULL) {
  2047. Trace1(ERR,
  2048. "Ras client(%d.%d.%d.%d) already exists. _ConnectRasClient failed",
  2049. PRINT_IPADDR(NHAddr)
  2050. );
  2051. IgmpAssertOnError(FALSE);
  2052. Error = ERROR_INVALID_PARAMETER;
  2053. GOTO_END_BLOCK2;
  2054. }
  2055. //
  2056. // Create new Ras client entry and initialize the fields
  2057. //
  2058. prte = IGMP_ALLOC(sizeof(RAS_TABLE_ENTRY), 0x40, IfIndex);
  2059. PROCESS_ALLOC_FAILURE2(prte,
  2060. "error %d allocating %d bytes in _ConnectRasClient()",
  2061. Error, sizeof(RAS_TABLE_ENTRY),
  2062. GOTO_END_BLOCK2);
  2063. prte->NHAddr = NHAddr;
  2064. prte->IfTableEntry = pite;
  2065. InitializeListHead(&prte->ListOfSameClientGroups);
  2066. // increment refcount for the ras table
  2067. prt->RefCount++;
  2068. //
  2069. // insert into HashTable
  2070. //
  2071. InsertTailList(&prt->HashTableByAddr[RAS_HASH_VALUE(NHAddr)],
  2072. &prte->HTLinkByAddr);
  2073. //
  2074. // insert the client into list of clients ordered by IpAddr
  2075. //
  2076. pHead = &prt->ListByAddr;
  2077. for (ple=pHead->Flink; ple!=pHead; ple=ple->Flink) {
  2078. prteCur = CONTAINING_RECORD(ple, RAS_TABLE_ENTRY, LinkByAddr);
  2079. if (NHAddr>prteCur->NHAddr)
  2080. break;
  2081. }
  2082. InsertTailList(&prt->ListByAddr, &prte->LinkByAddr);
  2083. //
  2084. // Set Interface stats to 0
  2085. //
  2086. ZeroMemory(&prte->Info, sizeof(RAS_CLIENT_INFO));
  2087. prte->Status = IF_CREATED_FLAG;
  2088. prte->CreationFlags = 0;
  2089. //
  2090. // call MGM to take ownership of this (interface, NHAddr)
  2091. // This call is not made if the interface is not activated.
  2092. //
  2093. if (IS_IF_ACTIVATED(pite)) {
  2094. Error = MgmTakeInterfaceOwnership(g_MgmIgmprtrHandle, IfIndex, NHAddr);
  2095. if (Error!=NO_ERROR) {
  2096. Trace2(MGM,
  2097. "_TakeInterfaceOwnership rejected for interface %0x NHAddr(%d.%d.%d.%d)",
  2098. IfIndex, PRINT_IPADDR(NHAddr));
  2099. Logerr0(MGM_TAKE_IF_OWNERSHIP_FAILED, Error);
  2100. }
  2101. else {
  2102. prte->CreationFlags |= TAKEN_INTERFACE_OWNERSHIP_WITH_MGM;
  2103. }
  2104. }
  2105. // register ras client with MGM when the interface is activated.
  2106. else {
  2107. Trace3(ERR,
  2108. "ras client(%d.%d.%d.%d) connected to an inactive ras server(%0x:%d)",
  2109. PRINT_IPADDR(NHAddr), IfIndex, pite->Status);
  2110. }
  2111. } END_BREAKOUT_BLOCK2;
  2112. RELEASE_IF_LOCK_EXCLUSIVE(IfIndex, "_ConnectRasClient");
  2113. LeaveIgmpApi();
  2114. Trace2(LEAVE, "Leaving _ConnectRasClient(%d.%d.%d.%d):%d\n",
  2115. PRINT_IPADDR(NHAddr), Error);
  2116. return Error;
  2117. } //end _ConnectRasClient
  2118. //------------------------------------------------------------------------------
  2119. // _DisconnectRasClient
  2120. //
  2121. // Takes shared interface lock. retrieves the Ras interface, takes write
  2122. // lock on the ras table, and then releases the shared interface lock.
  2123. //
  2124. // Removes the RasClient Entry from the Ras table so that no one can access
  2125. // it through a RAS table. Then queues a work item that will delete all
  2126. // GI entries.
  2127. //
  2128. // Calls: _DeleteRasClient()
  2129. //------------------------------------------------------------------------------
  2130. DWORD
  2131. APIENTRY
  2132. DisconnectRasClient (
  2133. DWORD IfIndex,
  2134. PVOID pvNHAddr
  2135. )
  2136. {
  2137. PIF_TABLE_ENTRY pite = NULL;
  2138. PRAS_TABLE prt;
  2139. PRAS_TABLE_ENTRY prte, prteCur;
  2140. DWORD Error = NO_ERROR;
  2141. PLIST_ENTRY pHead, ple;
  2142. PGI_ENTRY pgie;
  2143. PIP_LOCAL_BINDING pNHAddrBinding = (PIP_LOCAL_BINDING)pvNHAddr;
  2144. DWORD NHAddr = pNHAddrBinding->Address;
  2145. // mightdo
  2146. // currently rtrmgr passes 0 for IfIndex. so I set it to the value required
  2147. IfIndex = g_RasIfIndex;
  2148. Trace2(ENTER, "Entering DisconnectRasClient for IfIndex(%0x), NextHop(%d.%d.%d.%d)",
  2149. IfIndex, PRINT_IPADDR(NHAddr));
  2150. if (!EnterIgmpApi()) return ERROR_CAN_NOT_COMPLETE;
  2151. //
  2152. // take an exclusive lock on the interface
  2153. //
  2154. ACQUIRE_IF_LOCK_EXCLUSIVE(IfIndex, "_DisconnectRasClient");
  2155. BEGIN_BREAKOUT_BLOCK1 {
  2156. //
  2157. // retrieve the RAS interface entry from the global structure.
  2158. //
  2159. if ( (g_RasIfIndex!=IfIndex) || (g_pRasIfEntry==NULL) ) {
  2160. Error = ERROR_INVALID_PARAMETER;
  2161. Trace2(ERR,
  2162. "attempt to disconnect Ras client(%d.%d.%d.%d) from non-Ras "
  2163. "interface(%0x)", PRINT_IPADDR(NHAddr), IfIndex
  2164. );
  2165. IgmpAssertOnError(FALSE);
  2166. Logerr2(DISCONNECT_FAILED, "%I%d", NHAddr,
  2167. IfIndex, Error);
  2168. GOTO_END_BLOCK1;
  2169. }
  2170. pite = g_pRasIfEntry;
  2171. } END_BREAKOUT_BLOCK1;
  2172. //
  2173. // if error, return from here.
  2174. //
  2175. if (Error!=NO_ERROR) {
  2176. RELEASE_IF_LOCK_EXCLUSIVE(IfIndex, "_DisconnectRasClient");
  2177. LeaveIgmpApi();
  2178. return Error;
  2179. }
  2180. //
  2181. // get pointer to RasTable
  2182. //
  2183. prt = pite->pRasTable;
  2184. BEGIN_BREAKOUT_BLOCK2 {
  2185. //
  2186. // retrieve ras client
  2187. //
  2188. prte = GetRasClientByAddr(NHAddr, prt);
  2189. if (prte==NULL) {
  2190. Error = ERROR_INVALID_PARAMETER;
  2191. Trace2(ERR,
  2192. "Illegal attempt to disconnect non-existing Ras client(%d.%d.%d.%d) "
  2193. "from Ras interface(%0x)", PRINT_IPADDR(NHAddr), IfIndex);
  2194. IgmpAssertOnError(FALSE);
  2195. Logerr2(DISCONNECT_FAILED, "%I%d", NHAddr,
  2196. pite->IfIndex, Error);
  2197. GOTO_END_BLOCK2;
  2198. }
  2199. //
  2200. // break if ras client has deleted flag set
  2201. //
  2202. if ( (prte->Status&IF_DELETED_FLAG) ) {
  2203. Error = ERROR_CAN_NOT_COMPLETE;
  2204. GOTO_END_BLOCK2;
  2205. }
  2206. //
  2207. // set deleted flag for the ras client, so that no one else will
  2208. // try to access it
  2209. prte->Status |= IF_DELETED_FLAG;
  2210. //
  2211. // remove the RAS client from the Ras table lists so that no one will
  2212. // access it.
  2213. //
  2214. RemoveEntryList(&prte->HTLinkByAddr);
  2215. RemoveEntryList(&prte->LinkByAddr);
  2216. //
  2217. // release RasClient virtual interface
  2218. //
  2219. if (prte->CreationFlags & TAKEN_INTERFACE_OWNERSHIP_WITH_MGM)
  2220. {
  2221. Error = MgmReleaseInterfaceOwnership(g_MgmIgmprtrHandle, pite->IfIndex,
  2222. prte->NHAddr);
  2223. if (Error!=NO_ERROR) {
  2224. Trace2(ERR,
  2225. "Error: _MgmReleaseInterfaceOwnership for If:%0x, NHAddr:%d.%d.%d.%d",
  2226. pite->IfIndex, PRINT_IPADDR(prte->NHAddr));
  2227. IgmpAssertOnError(FALSE);
  2228. }
  2229. prte->CreationFlags &= ~TAKEN_INTERFACE_OWNERSHIP_WITH_MGM;
  2230. }
  2231. //
  2232. // remove the ras client's GI entries from the ras server interface
  2233. // list
  2234. //
  2235. ACQUIRE_IF_GROUP_LIST_LOCK(IfIndex, "_DisconectRasClient");
  2236. pHead = &prte->ListOfSameClientGroups;
  2237. for (ple=pHead->Flink; ple!=pHead; ple=ple->Flink) {
  2238. pgie = CONTAINING_RECORD(ple, GI_ENTRY, LinkBySameClientGroups);
  2239. RemoveEntryList(&pgie->LinkBySameIfGroups);
  2240. InitializeListHead(&pgie->LinkBySameIfGroups);
  2241. }
  2242. RELEASE_IF_GROUP_LIST_LOCK(IfIndex, "_DisconnectRasClient");
  2243. //
  2244. // Delete ras client. The refcount is not changed
  2245. // so the prte, prt, pite fields will be valid.
  2246. //
  2247. DeleteRasClient(prte);
  2248. } END_BREAKOUT_BLOCK2;
  2249. // release the interface lock
  2250. RELEASE_IF_LOCK_EXCLUSIVE(IfIndex, "_DisconnectRasClient");
  2251. Trace3(LEAVE,
  2252. "Leaving _DisconnectRasClient(%d) for IfIndex(%0x), NextHop(%d.%d.%d.%d)\n",
  2253. Error, IfIndex, PRINT_IPADDR(NHAddr)
  2254. );
  2255. LeaveIgmpApi();
  2256. return Error;
  2257. } //end _DisconnectRasClient
  2258. //------------------------------------------------------------------------------
  2259. // _SetInterfaceConfigInfo
  2260. //
  2261. // Resets the interface config. The router parameters might have changed.
  2262. // Also proxy<-->router transition might have taken place.
  2263. //
  2264. // Locks: takes IfLists lock initiallly itself just in case the interface had to
  2265. // be disabled. Runs completely in exclusive interface lock.
  2266. //------------------------------------------------------------------------------
  2267. DWORD
  2268. WINAPI
  2269. SetInterfaceConfigInfo(
  2270. IN DWORD IfIndex,
  2271. IN PVOID pvConfig,
  2272. IN ULONG ulStructureVersion,
  2273. IN ULONG ulStructureSize,
  2274. IN ULONG ulStructureCount
  2275. )
  2276. {
  2277. DWORD Error=NO_ERROR;
  2278. PIGMP_IF_CONFIG pConfigDst;
  2279. PIGMP_MIB_IF_CONFIG pConfigSrc;
  2280. PIF_TABLE_ENTRY pite = NULL;
  2281. DWORD OldState, OldProtoType, NewProtoType;
  2282. BOOL bIgmpProtocolChanged=FALSE, bEnabledStateChanged=FALSE;
  2283. BOOL bOldStateEnabled=FALSE;
  2284. if (!EnterIgmpApi()) { return ERROR_CAN_NOT_COMPLETE; }
  2285. Trace1(ENTER, "entering SetInterfaceConfigInfo(%d)", IfIndex);
  2286. // make sure it is not an unsupported igmp version structure
  2287. if (ulStructureVersion>=IGMP_CONFIG_VERSION_600) {
  2288. Trace1(ERR, "Unsupported IGMP version structure: %0x",
  2289. ulStructureVersion);
  2290. IgmpAssertOnError(FALSE);
  2291. LeaveIgmpApi();
  2292. return ERROR_CAN_NOT_COMPLETE;
  2293. }
  2294. ACQUIRE_SOCKETS_LOCK_EXCLUSIVE("_SetInterfaceConfigInfo");
  2295. ACQUIRE_IF_LIST_LOCK("_SetInterfaceConfigInfo");
  2296. ACQUIRE_IF_LOCK_EXCLUSIVE(IfIndex, "_SetInterfaceConfigInfo");
  2297. BEGIN_BREAKOUT_BLOCK1 {
  2298. if (pvConfig==NULL) {
  2299. Error = ERROR_CAN_NOT_COMPLETE;
  2300. GOTO_END_BLOCK1;
  2301. }
  2302. pConfigSrc = (PIGMP_MIB_IF_CONFIG)pvConfig;
  2303. //
  2304. // find the interface specified
  2305. //
  2306. pite = GetIfByIndex(IfIndex);
  2307. if (pite == NULL) {
  2308. Error = ERROR_INVALID_PARAMETER;
  2309. GOTO_END_BLOCK1;
  2310. }
  2311. //
  2312. // validate the new config values
  2313. //
  2314. Error = ValidateIfConfig(pConfigSrc, IfIndex, pite->IfType,
  2315. ulStructureVersion, ulStructureSize
  2316. );
  2317. if (Error!=NO_ERROR)
  2318. GOTO_END_BLOCK1;
  2319. pConfigDst = &pite->Config;
  2320. //
  2321. // make sure you are not setting multiple proxy interfaces
  2322. //
  2323. if (IS_CONFIG_IGMPPROXY(pConfigSrc)
  2324. &&!IS_CONFIG_IGMPPROXY(pConfigDst)
  2325. && (g_ProxyIfIndex!=0) )
  2326. {
  2327. Error = ERROR_INVALID_PARAMETER;
  2328. Trace1(ERR, "Cannot set multiple Proxy interfaces. Proxy exists on %d",
  2329. g_ProxyIfIndex);
  2330. IgmpAssertOnError(FALSE);
  2331. Logerr0(PROXY_IF_EXISTS, Error);
  2332. GOTO_END_BLOCK1;
  2333. }
  2334. //
  2335. // Process change in IgmpProtocolType (between proxy and router)
  2336. // (no special processing for changes between ver-1 and ver-2)
  2337. //
  2338. if (pConfigSrc->IgmpProtocolType != pConfigDst->IgmpProtocolType)
  2339. {
  2340. bIgmpProtocolChanged = TRUE;
  2341. GOTO_END_BLOCK1;
  2342. }
  2343. else
  2344. bIgmpProtocolChanged = FALSE;
  2345. OldProtoType = pConfigDst->IgmpProtocolType;
  2346. //
  2347. // if interface enabled state has changed, then process that change
  2348. // I dont have to look for version changes, etc
  2349. //
  2350. if (IGMP_ENABLED_FLAG_SET(pConfigSrc->Flags)
  2351. != IGMP_ENABLED_FLAG_SET(pConfigDst->Flags))
  2352. {
  2353. bEnabledStateChanged = TRUE;
  2354. pite->Info.OtherVerPresentTimeWarn = 0;
  2355. bOldStateEnabled = IGMP_ENABLED_FLAG_SET(pConfigDst->Flags);
  2356. GOTO_END_BLOCK1;
  2357. }
  2358. else
  2359. bEnabledStateChanged = FALSE;
  2360. // copy the new config
  2361. if (IS_IF_ACTIVATED(pite))
  2362. CopyinIfConfigAndUpdate(pite, pConfigSrc, IfIndex);
  2363. else
  2364. CopyinIfConfig(&pite->Config, pConfigSrc, IfIndex);
  2365. NewProtoType = pConfigDst->IgmpProtocolType;
  2366. /*
  2367. //
  2368. // if changing from V1 <-> V2
  2369. //
  2370. if ( ((OldProtoType==IGMP_ROUTER_V1) && (NewProtoType==IGMP_ROUTER_V2))
  2371. || ((OldProtoType==IGMP_ROUTER_V2) && (NewProtoType==IGMP_ROUTER_V1)) )
  2372. {
  2373. pite->Info.OtherVerPresentTimeWarn = 0;
  2374. }
  2375. */
  2376. } END_BREAKOUT_BLOCK1;
  2377. //
  2378. // change the protocol and check for state changes.
  2379. // This function will effectively delete the interface with the old
  2380. // protocol and create a new interface with the new protocol.
  2381. //
  2382. if ( (bIgmpProtocolChanged)&&(Error==NO_ERROR) )
  2383. ProcessIfProtocolChange(IfIndex, pConfigSrc);
  2384. //
  2385. // Process State Change: enable or disable interface
  2386. //
  2387. else if ( (bEnabledStateChanged)&&(Error==NO_ERROR) ) {
  2388. //
  2389. // disable the interface and then copy in the new config
  2390. //
  2391. if (bOldStateEnabled) {
  2392. // old state enabled, new state disabled
  2393. DisableInterface_ConfigChanged(IfIndex);
  2394. //
  2395. // copy the config
  2396. //
  2397. // get the pite entry again, as disable creates a new one
  2398. //
  2399. pite = GetIfByIndex(IfIndex);
  2400. CopyinIfConfig(&pite->Config, pConfigSrc, IfIndex);
  2401. }
  2402. //
  2403. // copy the new config before enabling it
  2404. //
  2405. else {
  2406. CopyinIfConfig(&pite->Config, pConfigSrc, IfIndex);
  2407. //
  2408. // set the enable state to false, so that the below call can
  2409. // enable the interface.
  2410. //
  2411. pite->Config.Flags &= ~IGMP_INTERFACE_ENABLED_IN_CONFIG;
  2412. // old state disabled, new state enabled
  2413. EnableInterface_ConfigChanged(IfIndex);
  2414. }
  2415. }
  2416. RELEASE_SOCKETS_LOCK_EXCLUSIVE("_SetInterfaceConfigInfo");
  2417. RELEASE_IF_LIST_LOCK("_SetInterfaceConfigInfo");
  2418. RELEASE_IF_LOCK_EXCLUSIVE(IfIndex, "_SetInterfaceConfigInfo");
  2419. Trace2(LEAVE, "leaving SetInterfaceConfigInfo(%d):%d\n", IfIndex, Error);
  2420. LeaveIgmpApi();
  2421. return Error;
  2422. } //end _SetInterfaceConfigInfo
  2423. //------------------------------------------------------------------------------
  2424. // _ProcessProtocolChange
  2425. //
  2426. // Called when the interface protocol has changed (proxy<->router).
  2427. // First disables the old interface so that all old protocol data is cleaned up.
  2428. // then sets the new config, and enables the interface again (if it was
  2429. // enabled before). This process takes care of creation/deletion of sockets, etc
  2430. //
  2431. // Locks: no locks when called. Except for _Disable(_Enable)Interface, all work
  2432. // is done inside an exclusive IfLock.
  2433. // Calls: _DisableInterface(), _EnableInterface() if required.
  2434. //------------------------------------------------------------------------------
  2435. DWORD
  2436. ProcessIfProtocolChange(
  2437. DWORD IfIndex,
  2438. PIGMP_MIB_IF_CONFIG pConfigSrc
  2439. )
  2440. {
  2441. DWORD Error=NO_ERROR, dwDisabled;
  2442. PIGMP_IF_CONFIG pConfigDst;
  2443. PIF_TABLE_ENTRY pite = NULL;
  2444. Trace1(ENTER, "Entered _ProcessIfProtocolChange(%d)", IfIndex);
  2445. //
  2446. // disable the interface so that all protocol specific data is lost
  2447. //
  2448. dwDisabled = DisableIfEntry(IfIndex, TRUE);
  2449. //
  2450. // find the interface specified and copy the config info. The config
  2451. // has already been validated.
  2452. //
  2453. ACQUIRE_IF_LOCK_EXCLUSIVE(IfIndex, "_ProcessIfProtocolChange");
  2454. BEGIN_BREAKOUT_BLOCK1 {
  2455. // get interface again
  2456. pite = GetIfByIndex(IfIndex);
  2457. if (pite == NULL) {
  2458. Error = ERROR_INVALID_PARAMETER;
  2459. GOTO_END_BLOCK1;
  2460. }
  2461. pConfigDst = &pite->Config;
  2462. //
  2463. // if old interface was Proxy, then remove it from the Global Struct
  2464. // and delete the Proxy_HT related structures
  2465. //
  2466. if (IS_PROTOCOL_TYPE_PROXY(pite)) {
  2467. // _DisableIfEntry would have deleted all the entries in the proxy
  2468. // Hash table
  2469. IGMP_FREE(pite->pProxyHashTable);
  2470. InterlockedExchange(&g_ProxyIfIndex, 0);
  2471. InterlockedExchangePointer(&g_pProxyIfEntry, NULL);
  2472. }
  2473. //
  2474. // copy the new config values
  2475. //
  2476. CopyinIfConfig(&pite->Config, pConfigSrc, IfIndex);
  2477. //
  2478. // if new interface is Proxy, then add it to the Global Struct
  2479. // and create the Proxy_HT structures
  2480. //
  2481. if (IS_PROTOCOL_TYPE_PROXY(pite)) {
  2482. DWORD dwSize = PROXY_HASH_TABLE_SZ * sizeof(LIST_ENTRY);
  2483. DWORD i;
  2484. PLIST_ENTRY pProxyHashTable;
  2485. pProxyHashTable = pite->pProxyHashTable = IGMP_ALLOC(dwSize, 0x80,IfIndex);
  2486. PROCESS_ALLOC_FAILURE2(pProxyHashTable,
  2487. "error %d allocating %d bytes for interface table",
  2488. Error, dwSize,
  2489. GOTO_END_BLOCK1);
  2490. for (i=0; i<PROXY_HASH_TABLE_SZ; i++) {
  2491. InitializeListHead(pProxyHashTable+i);
  2492. }
  2493. InterlockedExchangePointer(&g_pProxyIfEntry, pite);
  2494. InterlockedExchange(&g_ProxyIfIndex, IfIndex);
  2495. pite->CreationFlags |= CREATED_PROXY_HASH_TABLE;
  2496. }
  2497. } END_BREAKOUT_BLOCK1;
  2498. RELEASE_IF_LOCK_EXCLUSIVE(IfIndex, "_ProcessIfProtocolChange");
  2499. //
  2500. // enable the interface if the new state requires
  2501. // it to be enabled.
  2502. //
  2503. if ( (Error==NO_ERROR) && (dwDisabled==NO_ERROR) )
  2504. Error = EnableIfEntry(IfIndex, TRUE);
  2505. Trace2(LEAVE, "Leaving _ProcessIfProtocolChange(%d): %d\n",
  2506. IfIndex, Error);
  2507. return Error;
  2508. } //end _ProcessIfProtocolChange
  2509. //------------------------------------------------------------------------------
  2510. // _GetInterfaceConfigInfo
  2511. //
  2512. // The Router Manager calls us with a NULL config and ZERO size. We return
  2513. // the required size to it. It then allocates the needed memory and calls
  2514. // us a second time with a valid buffer. We validate parameters each time
  2515. // and copy out our config if we can
  2516. //
  2517. // Return Value
  2518. // ERROR_INSUFFICIENT_BUFFER If the size of the buffer is too small
  2519. // ERROR_INVALID_PARAMETER ERROR_INVALID_DATA NO_ERROR
  2520. //------------------------------------------------------------------------------
  2521. DWORD
  2522. WINAPI
  2523. GetInterfaceConfigInfo(
  2524. IN DWORD IfIndex,
  2525. IN OUT PVOID pvConfig,
  2526. IN OUT PDWORD pdwSize,
  2527. IN OUT PULONG pulStructureVersion,
  2528. IN OUT PULONG pulStructureSize,
  2529. IN OUT PULONG pulStructureCount
  2530. )
  2531. {
  2532. DWORD Error = NO_ERROR;
  2533. PIF_TABLE_ENTRY pite = NULL;
  2534. PIGMP_MIB_IF_CONFIG pConfigDst;
  2535. PIGMP_IF_CONFIG pConfigSrc;
  2536. if (!EnterIgmpApi()) { return ERROR_CAN_NOT_COMPLETE; }
  2537. Trace3(ENTER1,
  2538. "entering _GetInterfaceConfigInfo(%d): ConfigPrt(%08x) SizePrt(%08x)",
  2539. IfIndex, pvConfig, pdwSize
  2540. );
  2541. ACQUIRE_IF_LOCK_SHARED(IfIndex, "_GetInterfaceConfigInfo");
  2542. BEGIN_BREAKOUT_BLOCK1 {
  2543. //
  2544. // check the arguments
  2545. //
  2546. if (pdwSize == NULL) {
  2547. Error = ERROR_INVALID_PARAMETER;
  2548. GOTO_END_BLOCK1;
  2549. }
  2550. //
  2551. // find the interface specified
  2552. //
  2553. pite = GetIfByIndex(IfIndex);
  2554. if (pite == NULL) {
  2555. Error = ERROR_INVALID_PARAMETER;
  2556. GOTO_END_BLOCK1;
  2557. }
  2558. pConfigSrc = &pite->Config;
  2559. // get the size of the interface config
  2560. //
  2561. // check the buffer size
  2562. //
  2563. if (*pdwSize < pConfigSrc->ExtSize) {
  2564. Error = ERROR_INSUFFICIENT_BUFFER;
  2565. }
  2566. else {
  2567. pConfigDst = (PIGMP_MIB_IF_CONFIG)pvConfig;
  2568. //
  2569. // copy the interface config, and set the IP address
  2570. //
  2571. CopyoutIfConfig(pConfigDst, pite);
  2572. }
  2573. *pdwSize = pConfigSrc->ExtSize;
  2574. } END_BREAKOUT_BLOCK1;
  2575. RELEASE_IF_LOCK_SHARED(IfIndex, "_GetInterfaceConfigInfo");
  2576. if (pulStructureCount)
  2577. *pulStructureCount = 1;
  2578. if (pulStructureSize && pdwSize)
  2579. *pulStructureSize = *pdwSize;
  2580. if (pulStructureVersion)
  2581. *pulStructureVersion = IGMP_CONFIG_VERSION_500;
  2582. Trace2(LEAVE1, "leaving _GetInterfaceConfigInfo(%d): %d\n", IfIndex, Error);
  2583. LeaveIgmpApi();
  2584. return Error;
  2585. }
  2586. DWORD
  2587. WINAPI
  2588. InterfaceStatus(
  2589. ULONG IfIndex,
  2590. BOOL bIfActive,
  2591. DWORD dwStatusType,
  2592. PVOID pvStatusInfo
  2593. )
  2594. {
  2595. DWORD Error = NO_ERROR;
  2596. switch(dwStatusType)
  2597. {
  2598. case RIS_INTERFACE_ADDRESS_CHANGE:
  2599. {
  2600. PIP_ADAPTER_BINDING_INFO pBindInfo
  2601. = (PIP_ADAPTER_BINDING_INFO)pvStatusInfo;
  2602. if(pBindInfo->AddressCount)
  2603. {
  2604. Error = BindInterface(IfIndex, pvStatusInfo);
  2605. }
  2606. else
  2607. {
  2608. Error = UnBindInterface(IfIndex);
  2609. }
  2610. break;
  2611. }
  2612. case RIS_INTERFACE_ENABLED:
  2613. {
  2614. Error = EnableInterface(IfIndex);
  2615. break;
  2616. }
  2617. case RIS_INTERFACE_DISABLED:
  2618. {
  2619. Error = DisableInterface(IfIndex);
  2620. break;
  2621. }
  2622. }
  2623. return Error;
  2624. }
  2625. DWORD
  2626. WINAPI
  2627. IgmpMibIfConfigSize(
  2628. PIGMP_MIB_IF_CONFIG pConfig
  2629. )
  2630. {
  2631. DWORD Size = sizeof(IGMP_MIB_IF_CONFIG);
  2632. if (pConfig->NumStaticGroups && !IS_CONFIG_IGMP_V3(pConfig)) {
  2633. Size += pConfig->NumStaticGroups*sizeof(IGMP_STATIC_GROUP);
  2634. }
  2635. else if (pConfig->NumStaticGroups && IS_CONFIG_IGMP_V3(pConfig)) {
  2636. DWORD i;
  2637. PSTATIC_GROUP_V3 pStaticGroupV3 = GET_FIRST_STATIC_GROUP_V3(pConfig);
  2638. for (i=0; i<pConfig->NumStaticGroups; i++) {
  2639. DWORD EntrySize = sizeof(STATIC_GROUP_V3)
  2640. + pStaticGroupV3->NumSources*sizeof(IPADDR);
  2641. Size += EntrySize;
  2642. pStaticGroupV3 = (PSTATIC_GROUP_V3)
  2643. ((PCHAR)(pStaticGroupV3) + EntrySize);
  2644. }
  2645. }
  2646. return Size;
  2647. }