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

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