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.

1750 lines
50 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. net\routing\ipx\sap\intfdb.c
  5. Abstract:
  6. This module maintains IPX interface configuration
  7. and provides interface configuration API
  8. for external modules (Router Manager)
  9. Author:
  10. Vadim Eydelman 05-15-1995
  11. Revision History:
  12. --*/
  13. #include "sapp.h"
  14. #define IDB_NUM_OF_INTF_HASH_BUCKETS 256
  15. #define IDB_NUM_OF_ADPT_HASH_BUCKETS 32
  16. // Number of additional recv requests to post when binding the interface
  17. // that has listen enabled
  18. ULONG NewRequestsPerInterface=SAP_REQUESTS_PER_INTF_DEF;
  19. // Default filtering mode (for standalone service only)
  20. UCHAR FilterOutMode=SAP_DONT_FILTER;
  21. #define IntfHashFunction(intf) ((intf)&(IDB_NUM_OF_INTF_HASH_BUCKETS-1))
  22. #define AdptHashFunction(adpt) ((adpt)&(IDB_NUM_OF_ADPT_HASH_BUCKETS-1))
  23. UCHAR INTERNAL_IF_NODE[6] = {0};
  24. UCHAR INTERNAL_IF_NET[4] = {0};
  25. // Interface control block
  26. typedef struct _INTERFACE_NODE {
  27. INTERFACE_DATA IN_Data; // Externally visible data
  28. NET_INTERFACE_TYPE IN_Type; // Interface type
  29. PSAP_IF_FILTERS IN_Filters; // Filter description array
  30. PFILTER_NODE IN_FilterNodes; // Filter node array hashed in
  31. // the filter table
  32. LIST_ENTRY IN_IntfLink; // Link in interface table
  33. // Used to test if interface block is
  34. // is the table (it is not if Flink==Blink)
  35. LIST_ENTRY IN_AdptLink; // Link in adapter table
  36. LIST_ENTRY IN_ListLink; // Link in interface list
  37. LONG IN_RefCount; // Number of times interface data
  38. // was referenced, if above 0, interface block
  39. // can't be deleted (last client that refers
  40. // it will do this).
  41. BOOL IN_InUse; // Flag that is set when interface
  42. // is bound. It is reset by the last client
  43. // that refers to interface after it frees
  44. // all resources (if any) that were allocated
  45. // at bind time. If reference count is zero
  46. // but this flag is set, the last client that
  47. // refered to this interface is in process
  48. // of releasing resources (waiting on critical
  49. // section to lock interface block) and should
  50. // be allowed to finish this operation
  51. } INTERFACE_NODE, *PINTERFACE_NODE;
  52. // Usefull field access macros
  53. #define IN_Name IN_Data.name
  54. #define IN_IntfIdx IN_Data.index
  55. #define IN_Info IN_Data.info
  56. #define IN_Adpt IN_Data.adapter
  57. #define IN_AdptIdx IN_Data.adapter.AdapterIndex
  58. #define IN_Stats IN_Data.stats
  59. #define IN_Enabled IN_Data.enabled
  60. #define IN_FilterIn IN_Data.filterIn
  61. #define IN_FilterOut IN_Data.filterOut
  62. // This macro is used to screen interface blocks that were deleted
  63. // from the table or replaced and must be disposed of by the last
  64. // user that refers to it
  65. #define IsInterfaceValid(node) IsListEntry(&node->IN_IntfLink)
  66. // This macro must be used to identify interface blocks that
  67. // were deleted from the table and must be disposed of by the
  68. // last user that refers to it
  69. #define InvalidateInterface(node) InitializeListEntry(&node->IN_IntfLink)
  70. // Table of interface control blocks
  71. typedef struct _INTERFACE_TABLE {
  72. LONG IT_NumOfActiveInterfaces;
  73. // Number of active (enabled and bound)
  74. // interfaces (we close Adapter port when
  75. // this number drops to 0)
  76. #if DBG
  77. LIST_ENTRY IT_DetachedIntf; // List of interfaces that were
  78. // removed from the table and await to be
  79. // disposed of when the last client releases
  80. // reference to them
  81. #endif
  82. LIST_ENTRY IT_IntfHash[IDB_NUM_OF_INTF_HASH_BUCKETS];
  83. // Interface control blocks hashed by interface
  84. // index
  85. LIST_ENTRY IT_AdptHash[IDB_NUM_OF_ADPT_HASH_BUCKETS];
  86. // Interface control blocks hashed by adapter
  87. // index to which corresponding interface is
  88. // bound
  89. CRITICAL_SECTION IT_Lock; // Interface table data protection
  90. } INTERFACE_TABLE, *PINTERFACE_TABLE;
  91. // List of interface blocks in InterfaceIndex order
  92. typedef struct _INTERFACE_LIST {
  93. CRITICAL_SECTION IL_Lock; // List data protection
  94. LIST_ENTRY IL_Head; // List head
  95. } INTERFACE_LIST, *PINTERFACE_LIST;
  96. INTERFACE_TABLE InterfaceTable;
  97. INTERFACE_LIST InterfaceList;
  98. HANDLE ShutdownDoneEvent=NULL;
  99. // Find if interface control block exists for interface index and
  100. // return pointer to it (node), otherwise return place where
  101. // new interface block should be inserted (cur)
  102. #define if_IsInterfaceNode(InterfaceIndex,node,cur) { \
  103. PLIST_ENTRY HashList=&InterfaceTable.IT_IntfHash[ \
  104. IntfHashFunction(InterfaceIndex)]; \
  105. EnterCriticalSection (&InterfaceTable.IT_Lock); \
  106. cur = HashList->Flink; \
  107. while (cur != HashList) { \
  108. node = CONTAINING_RECORD (cur, INTERFACE_NODE, IN_IntfLink);\
  109. if (InterfaceIndex <= node->IN_IntfIdx) \
  110. break; \
  111. cur = cur->Flink; \
  112. } \
  113. } \
  114. if ((cur==&node->IN_IntfLink) \
  115. && (InterfaceIndex==node->IN_IntfIdx))
  116. // Local prototypes
  117. DWORD
  118. StartInterface (
  119. PINTERFACE_NODE node
  120. );
  121. VOID
  122. FreeBindingResources (
  123. PINTERFACE_NODE node
  124. );
  125. DWORD
  126. StopInterface (
  127. PINTERFACE_NODE node
  128. );
  129. #if DBG
  130. VOID
  131. DumpPacket (
  132. PSAP_BUFFER packet,
  133. DWORD count
  134. );
  135. #else
  136. #define DumpPacket(packet,count)
  137. #endif
  138. PWCHAR SapDuplicateString (IN PWCHAR pszString) {
  139. PWCHAR pszRet;
  140. DWORD dwLen;
  141. if (!pszString)
  142. return NULL;
  143. dwLen = wcslen (pszString);
  144. pszRet = GlobalAlloc (GMEM_FIXED, (dwLen * sizeof(WCHAR)) + sizeof(WCHAR));
  145. if (pszRet) {
  146. wcscpy (pszRet, pszString);
  147. }
  148. return pszRet;
  149. }
  150. VOID SapFreeDuplicatedString (IN PWCHAR pszString) {
  151. if (pszString)
  152. GlobalFree (pszString);
  153. }
  154. /*++
  155. *******************************************************************
  156. C r e a t e I n t e r f a c e T a b l e
  157. Routine Description:
  158. Allocates resources for interface table
  159. Arguments:
  160. None
  161. Return Value:
  162. NO_ERROR - resources were allocated successfully
  163. other - reason of failure (windows error code)
  164. *******************************************************************
  165. --*/
  166. DWORD
  167. CreateInterfaceTable (
  168. void
  169. ) {
  170. INT i;
  171. DWORD status;
  172. InitializeCriticalSection (&InterfaceList.IL_Lock);
  173. InitializeListHead (&InterfaceList.IL_Head);
  174. InitializeCriticalSection (&InterfaceTable.IT_Lock);
  175. for (i=0; i<IDB_NUM_OF_INTF_HASH_BUCKETS; i++)
  176. InitializeListHead (&InterfaceTable.IT_IntfHash[i]);
  177. for (i=0; i<IDB_NUM_OF_ADPT_HASH_BUCKETS; i++)
  178. InitializeListHead (&InterfaceTable.IT_AdptHash[i]);
  179. #if DBG
  180. InitializeListHead (&InterfaceTable.IT_DetachedIntf);
  181. #endif
  182. InterfaceTable.IT_NumOfActiveInterfaces = 0;
  183. return NO_ERROR;
  184. }
  185. /*++
  186. *******************************************************************
  187. S h u t d o w n I n t e r f a c e s
  188. Routine Description:
  189. Initiates orderly shutdown of SAP interfaces
  190. Stop reception of new packets
  191. Arguments:
  192. None
  193. Return Value:
  194. None
  195. *******************************************************************
  196. --*/
  197. VOID
  198. ShutdownInterfaces (
  199. HANDLE doneEvent
  200. ) {
  201. INT i;
  202. // Now for each active interface in the table
  203. // we'll start shoutdown worker which will broadcast
  204. // all 'deleted' servers and dispose of interface control block
  205. EnterCriticalSection (&InterfaceList.IL_Lock);
  206. EnterCriticalSection (&InterfaceTable.IT_Lock);
  207. ShutdownDoneEvent = doneEvent;
  208. if (InterfaceTable.IT_NumOfActiveInterfaces==0) {
  209. Trace (DEBUG_INTERFACES, "All interfaces have been shut down.");
  210. if (doneEvent!=NULL) {
  211. BOOL res = SetEvent (doneEvent);
  212. ASSERTERRMSG ("Could not set shutdown done event ", res);
  213. }
  214. }
  215. else {
  216. ShutdownDoneEvent = doneEvent;
  217. for (i=0; i<IDB_NUM_OF_INTF_HASH_BUCKETS; i++) {
  218. while (!IsListEmpty (&InterfaceTable.IT_IntfHash[i])) {
  219. PINTERFACE_NODE node = CONTAINING_RECORD (
  220. InterfaceTable.IT_IntfHash[i].Flink,
  221. INTERFACE_NODE,
  222. IN_IntfLink);
  223. if (node->IN_Stats.SapIfOperState==OPER_STATE_UP) {
  224. node->IN_Info.Listen = ADMIN_STATE_DISABLED; // This will prevent deletion
  225. // of all services associated with
  226. // interface when it is stopped (done by the caller)
  227. node->IN_Stats.SapIfOperState = OPER_STATE_STOPPING;
  228. StopInterface (node);
  229. }
  230. // Remove interface control block
  231. Trace (DEBUG_INTERFACES, "Invalidating interface block: %lX(%d).",
  232. node, node->IN_IntfIdx);
  233. RemoveEntryList (&node->IN_IntfLink);
  234. InvalidateInterface (node);
  235. RemoveEntryList (&node->IN_ListLink);
  236. // Dispose only if nobody uses it and not waiting on critical
  237. // section to dispose of it
  238. if ((node->IN_RefCount==0)
  239. && !node->IN_InUse) {
  240. Trace (DEBUG_INTERFACES, "Releasing interface block: %lX(%d).",
  241. node, node->IN_IntfIdx);
  242. GlobalFree (node);
  243. }
  244. // Otherwise, just leave it hang outside of the table
  245. // till last client releases reference to it
  246. #if DBG
  247. else // Keep track of all blocks in debugging mode
  248. InsertTailList (&InterfaceTable.IT_DetachedIntf,
  249. &node->IN_ListLink);
  250. #endif
  251. }
  252. }
  253. }
  254. LeaveCriticalSection (&InterfaceTable.IT_Lock);
  255. LeaveCriticalSection (&InterfaceList.IL_Lock);
  256. }
  257. /*++
  258. *******************************************************************
  259. S t o p I n t e r f a c e s
  260. Routine Description:
  261. Stops all sap interfaces if not already stopped.
  262. Arguments:
  263. None
  264. Return Value:
  265. None
  266. *******************************************************************
  267. --*/
  268. VOID
  269. StopInterfaces (
  270. void
  271. ) {
  272. INT i;
  273. // Delete all interface control blocks
  274. EnterCriticalSection (&InterfaceList.IL_Lock);
  275. EnterCriticalSection (&InterfaceTable.IT_Lock);
  276. for (i=0; i<IDB_NUM_OF_INTF_HASH_BUCKETS; i++) {
  277. while (!IsListEmpty (&InterfaceTable.IT_IntfHash[i])) {
  278. PINTERFACE_NODE node = CONTAINING_RECORD (
  279. InterfaceTable.IT_IntfHash[i].Flink,
  280. INTERFACE_NODE,
  281. IN_IntfLink);
  282. if (node->IN_Stats.SapIfOperState==OPER_STATE_UP) {
  283. // Stop all bound interfaces
  284. node->IN_Info.Listen = ADMIN_STATE_DISABLED; // This will prevent deletion
  285. // of all services associated with
  286. // interface when it is stopped (done by the caller)
  287. node->IN_Stats.SapIfOperState = OPER_STATE_STOPPING;
  288. StopInterface (node);
  289. }
  290. // Remove and dispose of original interface control block
  291. Trace (DEBUG_INTERFACES, "Invalidating interface block: %lX(%d).",
  292. node, node->IN_IntfIdx);
  293. RemoveEntryList (&node->IN_IntfLink);
  294. InvalidateInterface (node);
  295. RemoveEntryList (&node->IN_ListLink);
  296. // Dispose only if nobody uses it and not waiting on critical
  297. // section to dispose of it
  298. if ((node->IN_RefCount==0)
  299. && !node->IN_InUse) {
  300. Trace (DEBUG_INTERFACES, "Releasing interface block: %lX(%d).",
  301. node, node->IN_IntfIdx);
  302. GlobalFree (node);
  303. }
  304. // Otherwise, just leave it hang outside of the table
  305. // till last client releases reference to it
  306. #if DBG
  307. else // Keep track of all blocks in debugging mode
  308. InsertTailList (&InterfaceTable.IT_DetachedIntf,
  309. &node->IN_ListLink);
  310. #endif
  311. }
  312. }
  313. LeaveCriticalSection (&InterfaceTable.IT_Lock);
  314. LeaveCriticalSection (&InterfaceList.IL_Lock);
  315. }
  316. /*++
  317. *******************************************************************
  318. D e l e t e I n t e r f a c e T a b l e
  319. Routine Description:
  320. Release all resources associated with interface table
  321. Arguments:
  322. None
  323. Return Value:
  324. NO_ERROR - operation completed OK
  325. *******************************************************************
  326. --*/
  327. VOID
  328. DeleteInterfaceTable (
  329. void
  330. ) {
  331. DeleteCriticalSection (&InterfaceList.IL_Lock);
  332. DeleteCriticalSection (&InterfaceTable.IT_Lock);
  333. }
  334. /*++
  335. *******************************************************************
  336. A c q u i r e I n t e r f a c e R e f e n c e
  337. Routine Description:
  338. Increments reference count of interface block.
  339. If reference count is greater than 0, the externally visible
  340. data in the block are locked (can't be modified)
  341. Arguments:
  342. intf - pointer to externally visible part of interface control block
  343. Return Value:
  344. None
  345. *******************************************************************
  346. --*/
  347. VOID
  348. AcquireInterfaceReference (
  349. IN PINTERFACE_DATA intf
  350. ) {
  351. PINTERFACE_NODE node = CONTAINING_RECORD(intf,
  352. INTERFACE_NODE,
  353. IN_Data);
  354. InterlockedIncrement(&node->IN_RefCount);
  355. }
  356. /*++
  357. *******************************************************************
  358. R e l e a s e I n t e r f a c e R e f e n c e
  359. Routine Description:
  360. Decrements reference count of interface block.
  361. When reference count drops to 0, cleanup routine gets called to
  362. dispose of all resources allocated at bind time and if interface
  363. control block is already removed from the table it gets disposed of
  364. as well
  365. Arguments:
  366. intf - pointer to externally visible part of interface control block
  367. Return Value:
  368. None
  369. *******************************************************************
  370. --*/
  371. VOID
  372. ReleaseInterfaceReference (
  373. IN PINTERFACE_DATA intf
  374. ) {
  375. PINTERFACE_NODE node = CONTAINING_RECORD (intf,
  376. INTERFACE_NODE,
  377. IN_Data);
  378. if (InterlockedDecrement (&node->IN_RefCount)==0) {
  379. // This is the last client that refered to this interface block
  380. // It should cleanup all resources allocated at bind time
  381. // and possibly dispose of interface block itself
  382. EnterCriticalSection (&InterfaceTable.IT_Lock);
  383. FreeBindingResources (node);
  384. if (!IsInterfaceValid(node)) {
  385. Trace (DEBUG_INTERFACES, "Releasing interface block: %lX(%d).",
  386. node, node->IN_IntfIdx);
  387. #if DBG
  388. // Debugging mode code keeps all deleted nodes in
  389. // detached list
  390. RemoveEntryList (&node->IN_ListLink);
  391. #endif
  392. if (node->IN_Filters!=NULL) {
  393. if (node->IN_Filters->SupplyFilterCount>0)
  394. ReplaceFilters (
  395. FILTER_TYPE_SUPPLY,
  396. &node->IN_FilterNodes[0],
  397. node->IN_Filters->SupplyFilterCount,
  398. NULL,
  399. 0);
  400. if (node->IN_Filters->ListenFilterCount>0)
  401. ReplaceFilters (
  402. FILTER_TYPE_LISTEN,
  403. &node->IN_FilterNodes[node->IN_Filters->SupplyFilterCount],
  404. node->IN_Filters->ListenFilterCount,
  405. NULL,
  406. 0);
  407. GlobalFree (node->IN_Filters);
  408. }
  409. if (node->IN_Name!=NULL)
  410. SapFreeDuplicatedString (node->IN_Name);
  411. GlobalFree (node);
  412. }
  413. LeaveCriticalSection (&InterfaceTable.IT_Lock);
  414. }
  415. }
  416. /*++
  417. *******************************************************************
  418. F r e e B i n d i n g R e s o u r c e s
  419. Routine Description:
  420. Disposes of all resources allocated at bind time and marks interface
  421. block as not used.
  422. Interface Table must be locked when calling this routine (unless
  423. node is already removed from the table)
  424. Arguments:
  425. node - pointer to interface control block
  426. Return Value:
  427. None
  428. *******************************************************************
  429. --*/
  430. VOID
  431. FreeBindingResources (
  432. PINTERFACE_NODE node
  433. ) {
  434. Trace (DEBUG_INTERFACES,
  435. "Releasing binding resources for interface block: %lX(%d).",
  436. node, node->IN_IntfIdx);
  437. node->IN_InUse = FALSE;
  438. if (node->IN_Enabled
  439. && (node->IN_Info.AdminState==ADMIN_STATE_ENABLED))
  440. node->IN_Stats.SapIfOperState = OPER_STATE_SLEEPING;
  441. else
  442. node->IN_Stats.SapIfOperState = OPER_STATE_DOWN;
  443. InterfaceTable.IT_NumOfActiveInterfaces -= 1;
  444. if (InterfaceTable.IT_NumOfActiveInterfaces==0) {
  445. Trace (DEBUG_INTERFACES, "All interfaces have been shut down.");
  446. if (ShutdownDoneEvent!=NULL) {
  447. BOOL res = SetEvent (ShutdownDoneEvent);
  448. ASSERTERRMSG ("Could not set shutdown done event ", res);
  449. ShutdownDoneEvent = NULL;
  450. }
  451. }
  452. }
  453. /*++
  454. *******************************************************************
  455. G e t I n t e r f a c e R e f e r e n c e
  456. Routine Description:
  457. Finds interface control block that bound to adapter and increments reference
  458. count on it (to prevent it from deletion while it is used).
  459. Arguments:
  460. AdapterIndex - unique number that indentifies adapter
  461. Return Value:
  462. Pointer to externally visible part of interface control block
  463. NULL if no interface is bound to the adapter
  464. *******************************************************************
  465. --*/
  466. PINTERFACE_DATA
  467. GetInterfaceReference (
  468. ULONG AdapterIndex
  469. ) {
  470. PLIST_ENTRY HashList = &InterfaceTable.IT_AdptHash
  471. [AdptHashFunction(AdapterIndex)];
  472. PINTERFACE_NODE node;
  473. PLIST_ENTRY cur;
  474. EnterCriticalSection (&InterfaceTable.IT_Lock);
  475. cur = HashList->Flink;
  476. while (cur!=HashList) {
  477. node = CONTAINING_RECORD (cur, INTERFACE_NODE, IN_AdptLink);
  478. if (node->IN_AdptIdx==AdapterIndex) {
  479. InterlockedIncrement (&node->IN_RefCount);
  480. break;
  481. }
  482. cur = cur->Flink;
  483. }
  484. LeaveCriticalSection (&InterfaceTable.IT_Lock);
  485. if (cur!=HashList)
  486. return &node->IN_Data;
  487. else
  488. return NULL;
  489. }
  490. /*++
  491. *******************************************************************
  492. S t a r t I n t e r f a c e
  493. Routine Description:
  494. Initiate sap on interface
  495. Interface Table must be locked when calling this routine
  496. Arguments:
  497. node - pointer to interface control block
  498. Return Value:
  499. None
  500. *******************************************************************
  501. --*/
  502. DWORD
  503. StartInterface (
  504. PINTERFACE_NODE node
  505. ) {
  506. DWORD status = NO_ERROR;
  507. Trace (DEBUG_INTERFACES, "Starting SAP for interface block: %lX(%d,%d).",
  508. node, node->IN_IntfIdx, node->IN_AdptIdx);
  509. node->IN_Stats.SapIfOperState = OPER_STATE_UP;
  510. node->IN_InUse = TRUE;
  511. // Create binding reference
  512. InterlockedIncrement (&node->IN_RefCount);
  513. InsertTailList (
  514. &InterfaceTable.IT_AdptHash[AdptHashFunction(node->IN_AdptIdx)],
  515. &node->IN_AdptLink);
  516. InterfaceTable.IT_NumOfActiveInterfaces += 1;
  517. if ((status==NO_ERROR)
  518. && (node->IN_Info.UpdateMode==IPX_STANDARD_UPDATE)) {
  519. AddRecvRequests (NewRequestsPerInterface);
  520. if (node->IN_Info.Supply==ADMIN_STATE_ENABLED)
  521. status = InitBcastItem (&node->IN_Data);
  522. if ((status==NO_ERROR)
  523. && (node->IN_Info.Listen==ADMIN_STATE_ENABLED))
  524. status = InitSreqItem (&node->IN_Data);
  525. }
  526. if (status!=NO_ERROR) {
  527. node->IN_Stats.SapIfOperState = OPER_STATE_DOWN;
  528. RemoveEntryList (&node->IN_AdptLink);
  529. if (node->IN_Info.UpdateMode==IPX_STANDARD_UPDATE) {
  530. RemoveRecvRequests (NewRequestsPerInterface);
  531. }
  532. if (InterlockedDecrement (&node->IN_RefCount)==0)
  533. // Cleanup binding resources if this is the
  534. // last reference to the interface control block
  535. FreeBindingResources (node);
  536. }
  537. return status;
  538. }
  539. /*++
  540. *******************************************************************
  541. S t o p I n t e r f a c e
  542. Routine Description:
  543. Stop sap on interface
  544. Interface Table must be locked when calling this routine
  545. Arguments:
  546. node - pointer to interface control block
  547. Return Value:
  548. None
  549. *******************************************************************
  550. --*/
  551. DWORD
  552. StopInterface (
  553. PINTERFACE_NODE node
  554. ) {
  555. DWORD status=NO_ERROR;
  556. Trace (DEBUG_INTERFACES, "Stopping SAP for interface block: %lX(%d,%d).",
  557. node, node->IN_IntfIdx, node->IN_AdptIdx);
  558. if (node->IN_Stats.SapIfOperState==OPER_STATE_UP) {
  559. // Set the state of the interface if not already set.
  560. if (node->IN_Enabled
  561. && (node->IN_Info.AdminState==ADMIN_STATE_ENABLED)
  562. && (node->IN_Type!=PERMANENT))
  563. node->IN_Stats.SapIfOperState = OPER_STATE_SLEEPING;
  564. else
  565. node->IN_Stats.SapIfOperState = OPER_STATE_DOWN;
  566. }
  567. RemoveEntryList (&node->IN_AdptLink);
  568. if (node->IN_Info.UpdateMode==IPX_STANDARD_UPDATE) {
  569. RemoveRecvRequests (NewRequestsPerInterface);
  570. }
  571. if (InterlockedDecrement (&node->IN_RefCount)==0)
  572. // Cleanup binding resources if we released the
  573. // last reference to the interface control block
  574. FreeBindingResources (node);
  575. else // Have clients get in sync fast.
  576. ExpireLRRequests ((PVOID)UlongToPtr(node->IN_IntfIdx));
  577. // Delete all services obtained through SAP if we were actually
  578. // listening to SAP announcements on this interface
  579. if (node->IN_Info.Listen==ADMIN_STATE_ENABLED) {
  580. HANDLE enumHdl = CreateListEnumerator (SDB_INTF_LIST_LINK,
  581. 0xFFFF,
  582. NULL,
  583. node->IN_IntfIdx,
  584. IPX_PROTOCOL_SAP,
  585. SDB_DISABLED_NODE_FLAG);
  586. // Delete all services obtained through sap
  587. if (enumHdl!=NULL) {
  588. EnumerateServers (enumHdl, DeleteAllServersCB, enumHdl);
  589. DeleteListEnumerator (enumHdl);
  590. }
  591. else
  592. Trace (DEBUG_FAILURES, "File: %s, line %ld."
  593. " Could not create enumerator to delete"
  594. " sap servers for interface: %ld.",
  595. __FILE__, __LINE__, node->IN_IntfIdx);
  596. }
  597. return status;
  598. }
  599. DWORD WINAPI
  600. UnbindInterface(
  601. IN ULONG InterfaceIndex
  602. );
  603. SetInterfaceConfigInfo(
  604. IN ULONG InterfaceIndex,
  605. IN PVOID InterfaceInfo);
  606. DWORD
  607. UpdateInterfaceState (
  608. PINTERFACE_NODE node
  609. );
  610. DWORD SapUpdateLocalServers ();
  611. // Makes pnp changes to an interface
  612. DWORD SapReconfigureInterface (ULONG InterfaceIndex,
  613. PIPX_ADAPTER_BINDING_INFO pAdapter)
  614. {
  615. PLIST_ENTRY cur;
  616. PINTERFACE_NODE node;
  617. DWORD dwErr;
  618. Trace (DEBUG_INTERFACES, "SapReconfigureInterface: entered for %d", InterfaceIndex);
  619. // Lock the interface list and get reference to the
  620. // sought after control node.
  621. EnterCriticalSection (&InterfaceList.IL_Lock);
  622. if_IsInterfaceNode(InterfaceIndex, node, cur) {
  623. // Update the information maintained in the interfaces
  624. node->IN_Adpt = *pAdapter;
  625. UpdateInterfaceState ( node );
  626. }
  627. // Unlock
  628. LeaveCriticalSection (&InterfaceTable.IT_Lock);
  629. LeaveCriticalSection (&InterfaceList.IL_Lock);
  630. // If the internal network number was updated, go through all
  631. // local servers and update their control blocks accordingly.
  632. if (InterfaceIndex == INTERNAL_INTERFACE_INDEX) {
  633. if ((dwErr = SapUpdateLocalServers ()) != NO_ERROR) {
  634. Trace (DEBUG_INTERFACES, "ERR: SapUpdateLocalServers returned %x", dwErr);
  635. }
  636. }
  637. return NO_ERROR;
  638. }
  639. /*++
  640. *******************************************************************
  641. S a p C r e a t e S a p I n t e r f a c e
  642. Routine Description:
  643. Add interface control block for new interface
  644. Arguments:
  645. InterfaceIndex - unique number that indentifies new interface
  646. SapIfConfig - interface configuration info
  647. Return Value:
  648. NO_ERROR - interface was created OK
  649. ERROR_ALREADY_EXISTS - interface with this index already exists
  650. other - operation failed (windows error code)
  651. *******************************************************************
  652. --*/
  653. DWORD
  654. SapCreateSapInterface (
  655. LPWSTR InterfaceName,
  656. ULONG InterfaceIndex,
  657. NET_INTERFACE_TYPE InterfaceType,
  658. PSAP_IF_INFO SapIfConfig
  659. ) {
  660. PLIST_ENTRY cur;
  661. PINTERFACE_NODE node;
  662. DWORD status = NO_ERROR;
  663. EnterCriticalSection (&InterfaceList.IL_Lock);
  664. if_IsInterfaceNode(InterfaceIndex,node,cur) {
  665. Trace (DEBUG_INTERFACES, "Interface %ld already exists.",InterfaceIndex);
  666. status = ERROR_ALREADY_EXISTS;
  667. }
  668. else {
  669. node = (PINTERFACE_NODE)GlobalAlloc (GMEM_FIXED, sizeof (INTERFACE_NODE));
  670. if (node!=NULL) {
  671. node->IN_Name = SapDuplicateString (InterfaceName);
  672. if (node->IN_Name!=NULL) {
  673. node->IN_RefCount = 0;
  674. node->IN_InUse = FALSE;
  675. node->IN_Data.name = node->IN_Name;
  676. node->IN_IntfIdx = InterfaceIndex;
  677. node->IN_AdptIdx = INVALID_ADAPTER_INDEX;
  678. node->IN_Enabled = FALSE;
  679. node->IN_Type = InterfaceType;
  680. node->IN_Filters = NULL;
  681. node->IN_FilterNodes = NULL;
  682. node->IN_FilterIn = SAP_DONT_FILTER;
  683. node->IN_FilterOut = FilterOutMode;
  684. node->IN_Stats.SapIfInputPackets = 0;
  685. node->IN_Stats.SapIfOutputPackets = 0;
  686. if (ARGUMENT_PRESENT(SapIfConfig)) {
  687. node->IN_Info = *SapIfConfig;
  688. if (node->IN_Enabled
  689. && (node->IN_Info.AdminState==ADMIN_STATE_ENABLED))
  690. node->IN_Stats.SapIfOperState = OPER_STATE_SLEEPING;
  691. else
  692. node->IN_Stats.SapIfOperState = OPER_STATE_DOWN;
  693. }
  694. else
  695. node->IN_Stats.SapIfOperState = OPER_STATE_DOWN;
  696. InsertTailList (cur, &node->IN_IntfLink);
  697. cur = InterfaceList.IL_Head.Flink;
  698. while (cur!=&InterfaceList.IL_Head) {
  699. if (InterfaceIndex<CONTAINING_RECORD (
  700. cur,
  701. INTERFACE_NODE,
  702. IN_ListLink)->IN_IntfIdx)
  703. break;
  704. cur = cur->Flink;
  705. }
  706. InsertTailList (cur, &node->IN_ListLink);
  707. }
  708. else {
  709. GlobalFree (node);
  710. status = ERROR_NOT_ENOUGH_MEMORY;
  711. }
  712. }
  713. else
  714. status = ERROR_NOT_ENOUGH_MEMORY;
  715. }
  716. LeaveCriticalSection (&InterfaceTable.IT_Lock);
  717. LeaveCriticalSection (&InterfaceList.IL_Lock);
  718. return status;
  719. }
  720. /*++
  721. *******************************************************************
  722. S a p D e l e t e S a p I n t e r f a c e
  723. Routine Description:
  724. Delete existing interface control block
  725. Arguments:
  726. InterfaceIndex - unique number that indentifies the interface
  727. Return Value:
  728. NO_ERROR - interface was created OK
  729. ERROR_INVALID_PARAMETER - interface with this index does not exist
  730. other - operation failed (windows error code)
  731. *******************************************************************
  732. --*/
  733. DWORD
  734. SapDeleteSapInterface (
  735. ULONG InterfaceIndex
  736. ) {
  737. PLIST_ENTRY cur;
  738. PINTERFACE_NODE node;
  739. DWORD status;
  740. HANDLE enumHdl;
  741. EnterCriticalSection (&InterfaceList.IL_Lock);
  742. if_IsInterfaceNode (InterfaceIndex,node,cur) {
  743. if (node->IN_Stats.SapIfOperState==OPER_STATE_UP) {
  744. StopInterface (node);
  745. }
  746. // Remove and dispose of interface control block
  747. Trace (DEBUG_INTERFACES, "Invalidating interface block: %lX(%d).",
  748. node, node->IN_IntfIdx);
  749. RemoveEntryList (&node->IN_IntfLink);
  750. InvalidateInterface (node);
  751. RemoveEntryList (&node->IN_ListLink);
  752. // Dispose only if nobody uses it and not waiting on critical
  753. // section to dispose of it
  754. if ((node->IN_RefCount==0)
  755. && !node->IN_InUse) {
  756. Trace (DEBUG_INTERFACES, "Releasing interface block: %lX(%d).",
  757. node, node->IN_IntfIdx);
  758. if (node->IN_Filters!=NULL) {
  759. if (node->IN_Filters->SupplyFilterCount>0)
  760. ReplaceFilters (
  761. FILTER_TYPE_SUPPLY,
  762. &node->IN_FilterNodes[0],
  763. node->IN_Filters->SupplyFilterCount,
  764. NULL,
  765. 0);
  766. if (node->IN_Filters->ListenFilterCount>0)
  767. ReplaceFilters (
  768. FILTER_TYPE_LISTEN,
  769. &node->IN_FilterNodes[node->IN_Filters->SupplyFilterCount],
  770. node->IN_Filters->ListenFilterCount,
  771. NULL,
  772. 0);
  773. GlobalFree (node->IN_Filters);
  774. }
  775. if (node->IN_Name!=NULL)
  776. SapFreeDuplicatedString (node->IN_Name);
  777. GlobalFree (node);
  778. }
  779. // Otherwise, just leave it hang outside of the table
  780. // till last client releases reference to it
  781. #if DBG
  782. else // Keep track of all blocks in debugging mode
  783. InsertTailList (&InterfaceTable.IT_DetachedIntf,
  784. &node->IN_ListLink);
  785. #endif
  786. status = NO_ERROR;
  787. }
  788. else {
  789. Trace (DEBUG_FAILURES, "File: %s, line %ld."
  790. " Unknown interface: %ld.",
  791. __FILE__, __LINE__, InterfaceIndex);
  792. status = ERROR_INVALID_PARAMETER;
  793. }
  794. LeaveCriticalSection (&InterfaceTable.IT_Lock);
  795. LeaveCriticalSection (&InterfaceList.IL_Lock);
  796. return status;
  797. }
  798. /*++
  799. *******************************************************************
  800. U p d a t e I n t e r f a c e S t a t e
  801. Routine Description:
  802. Performs neccessary operations to syncronize interface operational state
  803. with externally set state
  804. Arguments:
  805. node - interface control block to update
  806. Return Value:
  807. NO_ERROR - interface was updated OK
  808. other - operation failed (windows error code)
  809. *******************************************************************
  810. --*/
  811. DWORD
  812. UpdateInterfaceState (
  813. PINTERFACE_NODE node
  814. ) {
  815. DWORD status=NO_ERROR;
  816. if (node->IN_IntfIdx!=INTERNAL_INTERFACE_INDEX) {
  817. if (node->IN_InUse
  818. && (node->IN_AdptIdx!=INVALID_ADAPTER_INDEX)
  819. && node->IN_Enabled
  820. && (node->IN_Info.AdminState==ADMIN_STATE_ENABLED)
  821. ) { // Interface data is in use and it is going to
  822. // stay active after the update: THIS IS A CONFIG
  823. // CHANGE ON THE FLY!!! We'll have to create a new
  824. // block and invalidate the old one
  825. PINTERFACE_NODE newNode = GlobalAlloc (GMEM_FIXED,
  826. sizeof (INTERFACE_NODE));
  827. if (newNode==NULL) {
  828. status = GetLastError ();
  829. Trace (DEBUG_FAILURES, "File: %s, line %ld."
  830. "Could not allocate memory to replace"
  831. " active interface block on set: %ld(gle:%ld).",
  832. __FILE__, __LINE__, node->IN_IntfIdx, status);
  833. return status;
  834. }
  835. // Transfer external parameters
  836. newNode->IN_Data = node->IN_Data;
  837. newNode->IN_Filters = node->IN_Filters;
  838. newNode->IN_FilterNodes = node->IN_FilterNodes;
  839. // Setup referencing parameters
  840. newNode->IN_RefCount = 0;
  841. newNode->IN_InUse = FALSE;
  842. // Insert in same place in tables
  843. InsertTailList (&node->IN_IntfLink, &newNode->IN_IntfLink);
  844. InsertTailList (&node->IN_ListLink, &newNode->IN_ListLink);
  845. // Will put in adapter table at start
  846. InitializeListEntry (&newNode->IN_AdptLink);
  847. Trace (DEBUG_INTERFACES,
  848. "Replacing interface block on SET: %lX(%d).",
  849. newNode, newNode->IN_IntfIdx);
  850. status = StartInterface (newNode);
  851. if (status != NO_ERROR)
  852. node = newNode; // If we failed we'll have to dispose
  853. // the new interface block and keep
  854. // the old one
  855. // Reset this flag to prevent deletion of all services
  856. // obtained through SAP (we want to keep them despite
  857. // the change to interface parameters)
  858. node->IN_Info.Listen = ADMIN_STATE_DISABLED;
  859. // Prevent deletion of transferred filters and name
  860. node->IN_Filters = NULL;
  861. node->IN_Name = NULL;
  862. // Shutdown interface if it is still active
  863. if (node->IN_Stats.SapIfOperState==OPER_STATE_UP) {
  864. node->IN_Stats.SapIfOperState = OPER_STATE_DOWN;
  865. StopInterface (node);
  866. }
  867. // Remove and dispose of original interface control block
  868. Trace (DEBUG_INTERFACES, "Invalidating interface block: %lX(%d).",
  869. node, node->IN_IntfIdx);
  870. RemoveEntryList (&node->IN_IntfLink);
  871. InvalidateInterface (node);
  872. RemoveEntryList (&node->IN_ListLink);
  873. // Dispose only if nobody uses it and not waiting on critical
  874. // section to dispose of it
  875. if ((node->IN_RefCount==0)
  876. && !node->IN_InUse) {
  877. Trace (DEBUG_INTERFACES, "Releasing interface block: %lX(%d).",
  878. node, node->IN_IntfIdx);
  879. GlobalFree (node);
  880. }
  881. // Otherwise, just leave it hang outside of the table
  882. // till last client releases reference to it
  883. #if DBG
  884. else // Keep track of all blocks in debugging mode
  885. InsertTailList (&InterfaceTable.IT_DetachedIntf,
  886. &node->IN_ListLink);
  887. #endif
  888. }
  889. else {
  890. if ((node->IN_Enabled
  891. && (node->IN_Info.AdminState==ADMIN_STATE_ENABLED)
  892. && (node->IN_AdptIdx!=INVALID_ADAPTER_INDEX))) {
  893. if (node->IN_Stats.SapIfOperState!=OPER_STATE_UP)
  894. status = StartInterface (node);
  895. }
  896. else {
  897. if (node->IN_Stats.SapIfOperState==OPER_STATE_UP)
  898. status = StopInterface (node);
  899. else {
  900. if (node->IN_Enabled
  901. && (node->IN_Info.AdminState==ADMIN_STATE_ENABLED)
  902. && (node->IN_Type!=PERMANENT))
  903. node->IN_Stats.SapIfOperState = OPER_STATE_SLEEPING;
  904. else
  905. node->IN_Stats.SapIfOperState = OPER_STATE_DOWN;
  906. }
  907. }
  908. }
  909. }
  910. else {
  911. Trace (DEBUG_INTERFACES, "Internal interface info updated.");
  912. IpxNetCpy (INTERNAL_IF_NET, node->IN_Adpt.Network);
  913. IpxNodeCpy (INTERNAL_IF_NODE, node->IN_Adpt.LocalNode);
  914. }
  915. return status;
  916. }
  917. /*++
  918. *******************************************************************
  919. S a p S e t I n t e r f a c e E n a b l e
  920. Routine Description:
  921. Enables/disables interface
  922. Arguments:
  923. InterfaceIndex - unique number that indentifies new interface
  924. Enable - TRUE-enable, FALSE-disable
  925. Return Value:
  926. NO_ERROR - config info was changed OK
  927. ERROR_INVALID_PARAMETER - interface with this index does not exist
  928. other - operation failed (windows error code)
  929. *******************************************************************
  930. --*/
  931. DWORD
  932. SapSetInterfaceEnable (
  933. ULONG InterfaceIndex,
  934. BOOL Enable
  935. ) {
  936. PLIST_ENTRY cur;
  937. PINTERFACE_NODE node;
  938. DWORD status=NO_ERROR;
  939. EnterCriticalSection (&InterfaceList.IL_Lock); // Don't allow any queries
  940. // in interface list
  941. // while we are doing this
  942. if_IsInterfaceNode (InterfaceIndex,node,cur) {
  943. HANDLE enumHdl;
  944. if (node->IN_Enabled!=Enable) {
  945. node->IN_Enabled = (UCHAR)Enable;
  946. status = UpdateInterfaceState (node);
  947. }
  948. LeaveCriticalSection (&InterfaceTable.IT_Lock);
  949. LeaveCriticalSection (&InterfaceList.IL_Lock);
  950. if (status==NO_ERROR) {
  951. enumHdl = CreateListEnumerator (SDB_INTF_LIST_LINK,
  952. 0xFFFF,
  953. NULL,
  954. node->IN_IntfIdx,
  955. 0xFFFFFFFF,
  956. Enable ? SDB_DISABLED_NODE_FLAG : 0);
  957. // Disable/Reenable all services
  958. if (enumHdl!=NULL) {
  959. EnumerateServers (enumHdl, Enable
  960. ? EnableAllServersCB
  961. : DisableAllServersCB, enumHdl);
  962. DeleteListEnumerator (enumHdl);
  963. }
  964. else
  965. Trace (DEBUG_FAILURES, "File: %s, line %ld."
  966. " Could not create enumerator to enable/disable"
  967. " sap servers for interface: %ld.",
  968. __FILE__, __LINE__, node->IN_IntfIdx);
  969. }
  970. }
  971. else {
  972. LeaveCriticalSection (&InterfaceTable.IT_Lock);
  973. LeaveCriticalSection (&InterfaceList.IL_Lock);
  974. Trace (DEBUG_FAILURES, "File: %s, line %ld."
  975. " Unknown interface: %ld.",
  976. __FILE__, __LINE__, InterfaceIndex);
  977. status = ERROR_INVALID_PARAMETER;
  978. }
  979. return status;
  980. }
  981. /*++
  982. *******************************************************************
  983. S a p S e t S a p I n t e r f a c e
  984. Routine Description:
  985. Compares existing interface configuration with the new one and
  986. performs an update if necessary.
  987. Arguments:
  988. InterfaceIndex - unique number that indentifies new interface
  989. SapIfConfig - new interface configuration info
  990. Return Value:
  991. NO_ERROR - config info was changed OK
  992. ERROR_INVALID_PARAMETER - interface with this index does not exist
  993. other - operation failed (windows error code)
  994. *******************************************************************
  995. --*/
  996. DWORD
  997. SapSetSapInterface (
  998. ULONG InterfaceIndex,
  999. PSAP_IF_INFO SapIfConfig
  1000. ) {
  1001. PLIST_ENTRY cur;
  1002. PINTERFACE_NODE node;
  1003. DWORD status=NO_ERROR;
  1004. EnterCriticalSection (&InterfaceList.IL_Lock); // Don't allow any queries
  1005. // in interface list
  1006. // while we are doing this
  1007. if_IsInterfaceNode (InterfaceIndex,node,cur) {
  1008. // memcmp on structures!!! may not work with all compilers
  1009. // but event if it fails, the result will be just an
  1010. // set extra operation
  1011. if (memcmp (&node->IN_Info, SapIfConfig, sizeof (node->IN_Info))!=0) {
  1012. node->IN_Info = *SapIfConfig;
  1013. status = UpdateInterfaceState (node);
  1014. }
  1015. }
  1016. else {
  1017. Trace (DEBUG_FAILURES, "File: %s, line %ld."
  1018. " Unknown interface: %ld.",
  1019. __FILE__, __LINE__, InterfaceIndex);
  1020. status = ERROR_INVALID_PARAMETER;
  1021. }
  1022. LeaveCriticalSection (&InterfaceTable.IT_Lock);
  1023. LeaveCriticalSection (&InterfaceList.IL_Lock);
  1024. return status;
  1025. }
  1026. /*++
  1027. *******************************************************************
  1028. S a p I s S a p I n t e r f a c e
  1029. Routine Description:
  1030. Checks if interface with given index exists
  1031. Arguments:
  1032. InterfaceIndex - unique number that indentifies new interface
  1033. Return Value:
  1034. TRUE - exist
  1035. FALSE - does not
  1036. *******************************************************************
  1037. --*/
  1038. BOOL
  1039. SapIsSapInterface (
  1040. IN ULONG InterfaceIndex
  1041. ) {
  1042. PINTERFACE_NODE node;
  1043. PLIST_ENTRY cur;
  1044. BOOL res;
  1045. if_IsInterfaceNode (InterfaceIndex,node,cur)
  1046. res = TRUE;
  1047. else
  1048. res = FALSE;
  1049. LeaveCriticalSection (&InterfaceTable.IT_Lock);
  1050. return res;
  1051. }
  1052. /*++
  1053. *******************************************************************
  1054. S a p G e t S a p I n t e r f a c e
  1055. Routine Description:
  1056. Retrieves configuration and statistic info associated with interface
  1057. Arguments:
  1058. InterfaceIndex - unique number that indentifies new interface
  1059. SapIfConfig - buffer to store configuration info
  1060. SapIfStats - buffer to store statistic info
  1061. Return Value:
  1062. NO_ERROR - info was retrieved OK
  1063. ERROR_INVALID_PARAMETER - interface with this index does not exist
  1064. other - operation failed (windows error code)
  1065. *******************************************************************
  1066. --*/
  1067. DWORD
  1068. SapGetSapInterface (
  1069. IN ULONG InterfaceIndex,
  1070. OUT PSAP_IF_INFO SapIfConfig OPTIONAL,
  1071. OUT PSAP_IF_STATS SapIfStats OPTIONAL
  1072. ) {
  1073. PINTERFACE_NODE node;
  1074. DWORD status;
  1075. PLIST_ENTRY cur;
  1076. if_IsInterfaceNode (InterfaceIndex,node,cur) {
  1077. if (ARGUMENT_PRESENT(SapIfConfig))
  1078. *SapIfConfig = node->IN_Info;
  1079. if (ARGUMENT_PRESENT(SapIfStats))
  1080. *SapIfStats = node->IN_Stats;
  1081. status = NO_ERROR;
  1082. }
  1083. else {
  1084. Trace (DEBUG_FAILURES, "File: %s, line %ld."
  1085. " Unknown interface: %ld.",
  1086. __FILE__, __LINE__, InterfaceIndex);
  1087. status = ERROR_INVALID_PARAMETER;
  1088. }
  1089. LeaveCriticalSection (&InterfaceTable.IT_Lock);
  1090. return status;
  1091. }
  1092. /*++
  1093. *******************************************************************
  1094. S a p G e t F i r s t S a p I n t e r f a c e
  1095. Routine Description:
  1096. Retrieves configuration and statistic info associated with first
  1097. interface in InterfaceIndex order
  1098. Arguments:
  1099. InterfaceIndex - buffer to store unique number that indentifies interface
  1100. SapIfConfig - buffer to store configuration info
  1101. SapIfStats - buffer to store statistic info
  1102. Return Value:
  1103. NO_ERROR - info was retrieved OK
  1104. ERROR_NO_MORE_ITEMS - no interfaces in the table
  1105. other - operation failed (windows error code)
  1106. *******************************************************************
  1107. --*/
  1108. DWORD
  1109. SapGetFirstSapInterface (
  1110. OUT PULONG InterfaceIndex,
  1111. OUT PSAP_IF_INFO SapIfConfig OPTIONAL,
  1112. OUT PSAP_IF_STATS SapIfStats OPTIONAL
  1113. ) {
  1114. PINTERFACE_NODE node;
  1115. DWORD status;
  1116. EnterCriticalSection (&InterfaceList.IL_Lock);
  1117. if (!IsListEmpty (&InterfaceList.IL_Head)) {
  1118. node = CONTAINING_RECORD (InterfaceList.IL_Head.Flink,
  1119. INTERFACE_NODE,
  1120. IN_ListLink);
  1121. // Lock the table to make sure nobody modifies data while
  1122. // we are accessing it
  1123. EnterCriticalSection (&InterfaceTable.IT_Lock);
  1124. *InterfaceIndex = node->IN_IntfIdx;
  1125. if (ARGUMENT_PRESENT(SapIfConfig))
  1126. *SapIfConfig = node->IN_Info;
  1127. if (ARGUMENT_PRESENT(SapIfStats))
  1128. *SapIfStats = node->IN_Stats;
  1129. LeaveCriticalSection (&InterfaceTable.IT_Lock);
  1130. status = NO_ERROR;
  1131. }
  1132. else {
  1133. Trace (DEBUG_FAILURES, "File: %s, line %ld."
  1134. " Unknown interface: %ld.",
  1135. __FILE__, __LINE__, InterfaceIndex);
  1136. status = ERROR_NO_MORE_ITEMS;
  1137. }
  1138. LeaveCriticalSection (&InterfaceList.IL_Lock);
  1139. return status;
  1140. }
  1141. /*++
  1142. *******************************************************************
  1143. S a p G e t N e x t S a p I n t e r f a c e
  1144. Routine Description:
  1145. Retrieves configuration and statistic info associated with first
  1146. interface in following interface with InterfaceIndex order in interface
  1147. index order
  1148. Arguments:
  1149. InterfaceIndex - on input - interface number to search from
  1150. on output - interface number of next interface
  1151. SapIfConfig - buffer to store configuration info
  1152. SapIfStats - buffer to store statistic info
  1153. Return Value:
  1154. NO_ERROR - info was retrieved OK
  1155. ERROR_NO_MORE_ITEMS - no more interfaces in the table
  1156. other - operation failed (windows error code)
  1157. *******************************************************************
  1158. --*/
  1159. DWORD
  1160. SapGetNextSapInterface (
  1161. IN OUT PULONG InterfaceIndex,
  1162. OUT PSAP_IF_INFO SapIfConfig OPTIONAL,
  1163. OUT PSAP_IF_STATS SapIfStats OPTIONAL
  1164. ) {
  1165. PINTERFACE_NODE node;
  1166. PLIST_ENTRY cur;
  1167. DWORD status=ERROR_NO_MORE_ITEMS;
  1168. EnterCriticalSection (&InterfaceList.IL_Lock);
  1169. if_IsInterfaceNode(*InterfaceIndex,node,cur) {
  1170. if (node->IN_ListLink.Flink!=&InterfaceList.IL_Head) {
  1171. node = CONTAINING_RECORD (node->IN_ListLink.Flink,
  1172. INTERFACE_NODE,
  1173. IN_ListLink);
  1174. *InterfaceIndex = node->IN_IntfIdx;
  1175. if (ARGUMENT_PRESENT(SapIfConfig))
  1176. *SapIfConfig = node->IN_Info;
  1177. if (ARGUMENT_PRESENT(SapIfStats))
  1178. *SapIfStats = node->IN_Stats;
  1179. status = NO_ERROR;
  1180. }
  1181. LeaveCriticalSection (&InterfaceTable.IT_Lock);
  1182. }
  1183. else {
  1184. LeaveCriticalSection (&InterfaceTable.IT_Lock);
  1185. cur = InterfaceList.IL_Head.Flink;
  1186. while (cur!=&InterfaceList.IL_Head) {
  1187. node = CONTAINING_RECORD (cur,
  1188. INTERFACE_NODE,
  1189. IN_ListLink);
  1190. if (*InterfaceIndex<node->IN_IntfIdx)
  1191. break;
  1192. }
  1193. if (cur!=&InterfaceList.IL_Head) {
  1194. EnterCriticalSection (&InterfaceTable.IT_Lock);
  1195. *InterfaceIndex = node->IN_IntfIdx;
  1196. if (ARGUMENT_PRESENT(SapIfConfig))
  1197. *SapIfConfig = node->IN_Info;
  1198. if (ARGUMENT_PRESENT(SapIfStats))
  1199. *SapIfStats = node->IN_Stats;
  1200. LeaveCriticalSection (&InterfaceTable.IT_Lock);
  1201. status = NO_ERROR;
  1202. }
  1203. }
  1204. LeaveCriticalSection (&InterfaceList.IL_Lock);
  1205. return status;
  1206. }
  1207. /*++
  1208. *******************************************************************
  1209. S a p S e t I n t e r f a c e F i l t e r s
  1210. Routine Description:
  1211. Compares existing interface configuration with the new one and
  1212. performs an update if necessary.
  1213. Arguments:
  1214. Return Value:
  1215. NO_ERROR - config info was changed OK
  1216. ERROR_INVALID_PARAMETER - interface with this index does not exist
  1217. other - operation failed (windows error code)
  1218. *******************************************************************
  1219. --*/
  1220. DWORD
  1221. SapSetInterfaceFilters (
  1222. IN ULONG InterfaceIndex,
  1223. IN PSAP_IF_FILTERS SapIfFilters
  1224. ) {
  1225. PLIST_ENTRY cur;
  1226. PINTERFACE_NODE node;
  1227. DWORD status=NO_ERROR;
  1228. EnterCriticalSection (&InterfaceList.IL_Lock); // Don't allow any queries
  1229. // in interface list
  1230. // while we are doing this
  1231. if_IsInterfaceNode (InterfaceIndex,node,cur) {
  1232. if ( ((node->IN_Filters!=NULL) && (SapIfFilters!=NULL)
  1233. // memcmp on structures!!! may not work with all compilers
  1234. // but event if it fails, the result will be just an
  1235. // set extra operation
  1236. && (memcmp (node->IN_Filters, SapIfFilters,
  1237. FIELD_OFFSET (SAP_IF_FILTERS,ServiceFilter))==0)
  1238. && (memcmp (&node->IN_Filters->ServiceFilter[0],
  1239. &SapIfFilters->ServiceFilter[0],
  1240. sizeof (SAP_SERVICE_FILTER_INFO)*
  1241. (SapIfFilters->SupplyFilterCount
  1242. +SapIfFilters->ListenFilterCount))==0))
  1243. // Filter info hasn't changed
  1244. || ((node->IN_Filters==NULL)
  1245. && ((SapIfFilters==NULL)
  1246. || (SapIfFilters->SupplyFilterCount
  1247. +SapIfFilters->ListenFilterCount==0))) )
  1248. // There are no filters
  1249. status = NO_ERROR;
  1250. else {
  1251. if ((SapIfFilters!=NULL)
  1252. && (SapIfFilters->SupplyFilterCount
  1253. +SapIfFilters->ListenFilterCount>0)) {
  1254. PFILTER_NODE newNodes;
  1255. PSAP_IF_FILTERS newFilters;
  1256. ULONG newTotal = SapIfFilters->SupplyFilterCount
  1257. +SapIfFilters->ListenFilterCount;
  1258. newFilters = (PSAP_IF_FILTERS) GlobalAlloc (GMEM_FIXED,
  1259. FIELD_OFFSET (SAP_IF_FILTERS,ServiceFilter[newTotal])
  1260. +sizeof (FILTER_NODE)*newTotal);
  1261. if (newFilters!=NULL) {
  1262. ULONG i;
  1263. memcpy (newFilters, SapIfFilters,
  1264. FIELD_OFFSET (SAP_IF_FILTERS,ServiceFilter[newTotal]));
  1265. newNodes = (PFILTER_NODE)&newFilters->ServiceFilter[newTotal];
  1266. for (i=0; i<newTotal; i++) {
  1267. newNodes[i].FN_Index = InterfaceIndex;
  1268. newNodes[i].FN_Filter = &newFilters->ServiceFilter[i];
  1269. }
  1270. }
  1271. else {
  1272. status = GetLastError ();
  1273. goto ExitSetFilters;
  1274. }
  1275. if (node->IN_Filters) {
  1276. ReplaceFilters (
  1277. FILTER_TYPE_SUPPLY,
  1278. &node->IN_FilterNodes[0],
  1279. node->IN_Filters->SupplyFilterCount,
  1280. &newNodes[0],
  1281. newFilters->SupplyFilterCount);
  1282. ReplaceFilters (
  1283. FILTER_TYPE_LISTEN,
  1284. &node->IN_FilterNodes[node->IN_Filters->SupplyFilterCount],
  1285. node->IN_Filters->ListenFilterCount,
  1286. &newNodes[newFilters->SupplyFilterCount],
  1287. newFilters->ListenFilterCount);
  1288. }
  1289. else {
  1290. ReplaceFilters (
  1291. FILTER_TYPE_SUPPLY,
  1292. NULL,
  1293. 0,
  1294. &newNodes[0],
  1295. newFilters->SupplyFilterCount);
  1296. ReplaceFilters (
  1297. FILTER_TYPE_LISTEN,
  1298. NULL,
  1299. 0,
  1300. &newNodes[newFilters->SupplyFilterCount],
  1301. newFilters->ListenFilterCount);
  1302. }
  1303. node->IN_Filters = newFilters;
  1304. node->IN_FilterNodes = newNodes;
  1305. node->IN_FilterOut = newFilters->SupplyFilterCount>0
  1306. ? (UCHAR)newFilters->SupplyFilterAction
  1307. : SAP_DONT_FILTER;
  1308. node->IN_FilterIn = newFilters->ListenFilterCount>0
  1309. ? (UCHAR)newFilters->ListenFilterAction
  1310. : SAP_DONT_FILTER;
  1311. }
  1312. else {
  1313. ReplaceFilters (
  1314. FILTER_TYPE_SUPPLY,
  1315. &node->IN_FilterNodes[0],
  1316. node->IN_Filters->SupplyFilterCount,
  1317. NULL, 0);
  1318. ReplaceFilters (
  1319. FILTER_TYPE_LISTEN,
  1320. &node->IN_FilterNodes[node->IN_Filters->SupplyFilterCount],
  1321. node->IN_Filters->ListenFilterCount,
  1322. NULL, 0);
  1323. GlobalFree (node->IN_Filters);
  1324. node->IN_Filters = NULL;
  1325. node->IN_FilterNodes = NULL;
  1326. node->IN_FilterIn = node->IN_FilterOut = SAP_DONT_FILTER;
  1327. }
  1328. status = NO_ERROR;
  1329. }
  1330. }
  1331. else {
  1332. Trace (DEBUG_FAILURES, "File: %s, line %ld."
  1333. " Unknown interface: %ld.",
  1334. __FILE__, __LINE__, InterfaceIndex);
  1335. status = ERROR_INVALID_PARAMETER;
  1336. }
  1337. ExitSetFilters:
  1338. LeaveCriticalSection (&InterfaceTable.IT_Lock);
  1339. LeaveCriticalSection (&InterfaceList.IL_Lock);
  1340. return status;
  1341. }
  1342. /*++
  1343. *******************************************************************
  1344. S a p G e t I n t e r f a c e F i l t e r s
  1345. Routine Description:
  1346. Compares existing interface configuration with the new one and
  1347. performs an update if necessary.
  1348. Arguments:
  1349. Return Value:
  1350. NO_ERROR - config info was changed OK
  1351. ERROR_INVALID_PARAMETER - interface with this index does not exist
  1352. other - operation failed (windows error code)
  1353. *******************************************************************
  1354. --*/
  1355. DWORD
  1356. SapGetInterfaceFilters (
  1357. IN ULONG InterfaceIndex,
  1358. OUT PSAP_IF_FILTERS SapIfFilters,
  1359. OUT PULONG FilterBufferSize
  1360. ) {
  1361. PINTERFACE_NODE node;
  1362. DWORD status;
  1363. PLIST_ENTRY cur;
  1364. if_IsInterfaceNode (InterfaceIndex,node,cur) {
  1365. if (node->IN_Filters!=NULL) {
  1366. PSAP_IF_FILTERS info = node->IN_Filters;
  1367. ULONG infoSize
  1368. = FIELD_OFFSET (SAP_IF_FILTERS,
  1369. ServiceFilter[info->SupplyFilterCount
  1370. +info->ListenFilterCount]);
  1371. if (*FilterBufferSize>=infoSize) {
  1372. memcpy (SapIfFilters, info, infoSize);
  1373. status = NO_ERROR;
  1374. }
  1375. else
  1376. status = ERROR_INSUFFICIENT_BUFFER;
  1377. *FilterBufferSize = infoSize;
  1378. }
  1379. else {
  1380. ULONG infoSize = FIELD_OFFSET (SAP_IF_FILTERS, ServiceFilter);
  1381. if (*FilterBufferSize>=infoSize) {
  1382. SapIfFilters->SupplyFilterCount = 0;
  1383. SapIfFilters->SupplyFilterAction = IPX_SERVICE_FILTER_DENY;
  1384. SapIfFilters->ListenFilterCount = 0;
  1385. SapIfFilters->ListenFilterAction = IPX_SERVICE_FILTER_DENY;
  1386. status = NO_ERROR;
  1387. }
  1388. else
  1389. status = ERROR_INSUFFICIENT_BUFFER;
  1390. *FilterBufferSize = infoSize;
  1391. }
  1392. }
  1393. else {
  1394. Trace (DEBUG_FAILURES, "File: %s, line %ld."
  1395. " Unknown interface: %ld.",
  1396. __FILE__, __LINE__, InterfaceIndex);
  1397. status = ERROR_INVALID_PARAMETER;
  1398. }
  1399. LeaveCriticalSection (&InterfaceTable.IT_Lock);
  1400. return status;
  1401. }
  1402. /*++
  1403. *******************************************************************
  1404. S a p B i n d S a p I n t e r f a c e T o A d a p t e r
  1405. Routine Description:
  1406. Establishes association between interface and physical adapter
  1407. and starts sap on the interface if its admin state is enabled
  1408. Arguments:
  1409. InterfaceIndex - unique number that indentifies new interface
  1410. AdapterInfo - info associated with adapter to bind to
  1411. Return Value:
  1412. NO_ERROR - interface was bound OK
  1413. ERROR_INVALID_PARAMETER - interface with this index does not exist
  1414. other - operation failed (windows error code)
  1415. *******************************************************************
  1416. --*/
  1417. DWORD
  1418. SapBindSapInterfaceToAdapter (
  1419. ULONG InterfaceIndex,
  1420. PIPX_ADAPTER_BINDING_INFO AdptInternInfo
  1421. ) {
  1422. PINTERFACE_NODE node;
  1423. DWORD status=NO_ERROR;
  1424. PLIST_ENTRY cur;
  1425. EnterCriticalSection (&InterfaceList.IL_Lock); // Don't allow any queries
  1426. // in interface list
  1427. // while we are doing this
  1428. if_IsInterfaceNode (InterfaceIndex,node,cur) {
  1429. ASSERTMSG ("Interface is already bound ",
  1430. node->IN_AdptIdx==INVALID_ADAPTER_INDEX);
  1431. node->IN_Adpt = *AdptInternInfo;
  1432. status = UpdateInterfaceState (node);
  1433. }
  1434. else {
  1435. Trace (DEBUG_FAILURES, "File: %s, line %ld."
  1436. " Unknown interface: %ld.",
  1437. __FILE__, __LINE__, InterfaceIndex);
  1438. status = ERROR_INVALID_PARAMETER;
  1439. }
  1440. LeaveCriticalSection (&InterfaceTable.IT_Lock);
  1441. LeaveCriticalSection (&InterfaceList.IL_Lock);
  1442. return status;
  1443. }
  1444. /*++
  1445. *******************************************************************
  1446. S a p U n b i n d S a p I n t e r f a c e F r o m A d a p t e r
  1447. Routine Description:
  1448. Breaks association between interface and physical adapter
  1449. and stops sap on the interface if it was on
  1450. Arguments:
  1451. InterfaceIndex - unique number that indentifies new interface
  1452. Return Value:
  1453. NO_ERROR - interface was bound OK
  1454. ERROR_INVALID_PARAMETER - interface with this index does not exist
  1455. other - operation failed (windows error code)
  1456. *******************************************************************
  1457. --*/
  1458. DWORD
  1459. SapUnbindSapInterfaceFromAdapter (
  1460. ULONG InterfaceIndex
  1461. ) {
  1462. PINTERFACE_NODE node;
  1463. DWORD status;
  1464. PLIST_ENTRY cur;
  1465. EnterCriticalSection (&InterfaceList.IL_Lock); // Don't allow any queries
  1466. // in interface list
  1467. // while we are doing this
  1468. if_IsInterfaceNode (InterfaceIndex,node,cur) {
  1469. node->IN_AdptIdx = INVALID_ADAPTER_INDEX;
  1470. if (node->IN_Stats.SapIfOperState==OPER_STATE_UP) {
  1471. status = StopInterface (node);
  1472. }
  1473. }
  1474. else {
  1475. Trace (DEBUG_FAILURES, "File: %s, line %ld."
  1476. " Unknown interface: %ld.",
  1477. __FILE__, __LINE__, InterfaceIndex);
  1478. status = ERROR_INVALID_PARAMETER;
  1479. }
  1480. LeaveCriticalSection (&InterfaceTable.IT_Lock);
  1481. LeaveCriticalSection (&InterfaceList.IL_Lock);
  1482. return status;
  1483. }
  1484. /*++
  1485. *******************************************************************
  1486. S a p R e q u e s t U p d a t e
  1487. Routine Description:
  1488. Initiates update of services information over the interface
  1489. Completion of this update will be indicated by signalling
  1490. NotificationEvent passed at StartProtocol. GetEventMessage
  1491. can be used then to get the results of autostatic update
  1492. Arguments:
  1493. InterfaceIndex - unique index identifying interface to do
  1494. update on
  1495. Return Value:
  1496. NO_ERROR - operation was initiated ok
  1497. ERROR_CAN_NOT_COMPLETE - the interface does not support updates
  1498. ERROR_INVALID_PARAMETER - interface with this index does not exist
  1499. other - operation failed (windows error code)
  1500. *******************************************************************
  1501. --*/
  1502. DWORD
  1503. SapRequestUpdate (
  1504. ULONG InterfaceIndex
  1505. ) {
  1506. PINTERFACE_NODE node;
  1507. DWORD status;
  1508. PLIST_ENTRY cur;
  1509. if_IsInterfaceNode (InterfaceIndex,node,cur) {
  1510. if ((node->IN_Info.UpdateMode==IPX_AUTO_STATIC_UPDATE)
  1511. && (node->IN_Stats.SapIfOperState==OPER_STATE_UP)) {
  1512. Trace (DEBUG_INTERFACES, "Starting update on interface: %ld.",
  1513. InterfaceIndex);
  1514. status = InitTreqItem (&node->IN_Data);
  1515. }
  1516. else {
  1517. Trace (DEBUG_FAILURES, "RequestUpdate called on unbound or"
  1518. " 'standard update mode' interface: %ld.",
  1519. InterfaceIndex);
  1520. status = ERROR_CAN_NOT_COMPLETE;
  1521. }
  1522. }
  1523. else {
  1524. Trace (DEBUG_FAILURES, "Unknown interface: %ld.", InterfaceIndex);
  1525. status = ERROR_INVALID_PARAMETER;
  1526. }
  1527. LeaveCriticalSection (&InterfaceTable.IT_Lock);
  1528. return status;
  1529. }