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.

2424 lines
74 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. net\routing\ipx\sap\workers.c
  5. Abstract:
  6. This module implement all SAP agent work items
  7. Author:
  8. Vadim Eydelman 05-15-1995
  9. Revision History:
  10. --*/
  11. #include "sapp.h"
  12. // Max number of pending recv work items
  13. LONG MaxUnprocessedRequests=SAP_MAX_UNPROCESSED_REQUESTS_DEF;
  14. // Minimum number of queued recv requests
  15. LONG MinPendingRequests = SAP_MIN_REQUESTS_DEF;
  16. // How often to check on pending triggered update
  17. ULONG TriggeredUpdateCheckInterval=SAP_TRIGGERED_UPDATE_CHECK_INTERVAL_DEF;
  18. // How many requests to send if no response received within check interval
  19. ULONG MaxTriggeredUpdateRequests=SAP_MAX_TRIGGERED_UPDATE_REQUESTS_DEF;
  20. // Whether to respond for internal servers that are not registered with SAP
  21. // through the API calls (for standalone service only)
  22. ULONG RespondForInternalServers=SAP_RESPOND_FOR_INTERNAL_DEF;
  23. // Delay in response to general reguests for specific server type
  24. // if local servers are included in the packet
  25. ULONG DelayResponseToGeneral=SAP_DELAY_RESPONSE_TO_GENERAL_DEF;
  26. // Delay in sending change broadcasts if packet is not full
  27. ULONG DelayChangeBroadcast=SAP_DELAY_CHANGE_BROADCAST_DEF;
  28. UCHAR IPX_BCAST_NODE[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
  29. UCHAR IPX_SAP_SOCKET[2] = {0x04, 0x52};
  30. UCHAR IPX_INVALID_NET[4] = {0};
  31. UCHAR IPX_INVALID_NODE[6] = {0};
  32. #define SetupIpxSapPacket(packet,oper,net,node,sock) \
  33. (packet)->PacketType = IPX_SAP_PACKET_TYPE; \
  34. PUTUSHORT (oper, &(packet)->Operation); \
  35. IpxNetCpy ((packet)->Dst.Network, net); \
  36. IpxNodeCpy ((packet)->Dst.Node, node); \
  37. IpxSockCpy ((packet)->Dst.Socket, sock);
  38. typedef struct _WORKER_QUEUE {
  39. LONG WQ_WorkerCount;
  40. LONG WQ_RequestQuota;
  41. LONG WQ_RequestExtra;
  42. LIST_ENTRY WQ_Queue;
  43. HANDLE WQ_Heap;
  44. HANDLE WQ_DoneEvent;
  45. HANDLE WQ_RecvEvent;
  46. } WORKER_QUEUE, *PWORKER_QUEUE;
  47. WORKER_QUEUE WorkerQueue;
  48. // Work item that obtains and processes SAP requests
  49. typedef struct _REQ_ITEM {
  50. IO_WORKER iow;
  51. SAP_BUFFER packet;
  52. } REQ_ITEM, *PREQ_ITEM;
  53. // Work item that generates responses for SAP general requests
  54. typedef struct _RESP_ITEM {
  55. PINTERFACE_DATA intf;
  56. USHORT svrType; // Type of servers requested
  57. BOOLEAN bcast; // Is destination a broadcast
  58. // address ?
  59. HANDLE hEnum; // Enumeration handle to keep
  60. // track of sent servers
  61. IO_WORKER iow;
  62. TIMER_WORKER tmw;
  63. SAP_BUFFER packet;
  64. } RESP_ITEM, *PRESP_ITEM;
  65. // Work item that generates responses for SAP GETNEAREST requests
  66. typedef struct _GNEAR_ITEM {
  67. PINTERFACE_DATA intf;
  68. IO_WORKER iow;
  69. SAP_BUFFER packet;
  70. } GNEAR_ITEM, *PGNEAR_ITEM;
  71. // Work item that sends SAP general requests
  72. typedef struct _SREQ_ITEM {
  73. PINTERFACE_DATA intf;
  74. IO_WORKER iow;
  75. SAP_BUFFER packet;
  76. } SREQ_ITEM, *PSREQ_ITEM;
  77. // Work item that generates periodic and change broadcasts
  78. typedef struct _BCAST_ITEM {
  79. IO_WORKER iow;
  80. TIMER_WORKER tmw;
  81. PINTERFACE_DATA intf;
  82. DWORD nextBcast; // Time (windows time in msec) for
  83. // next broadcast
  84. INT delayedSvrCount; // Number of servers already
  85. // in the packet that were delayed because
  86. // packet wasn't full
  87. DWORD delayedSendTime; // Time until packet was delayed
  88. // because it wasn't full
  89. HANDLE chngEnum; // Enumeration hadnle that keeps
  90. // track of chnagd servers
  91. HANDLE perdEnum; // Enumeration handle that keeps
  92. // track of servers during periodic
  93. // broadcasts
  94. SAP_BUFFER packet;
  95. } BCAST_ITEM, *PBCAST_ITEM;
  96. // Work item that gets and processes LPC requests
  97. typedef struct _LPC_ITEM {
  98. LPC_WORKER lpcw;
  99. NWSAP_REQUEST_MESSAGE request;
  100. } LPC_ITEM, *PLPC_ITEM;
  101. typedef struct _TREQ_ITEM {
  102. IO_WORKER iow;
  103. TIMER_WORKER tmw;
  104. AR_PARAM_BLOCK ar;
  105. PINTERFACE_DATA intf;
  106. ULONG pktCount;
  107. ULONG resend;
  108. ULONG listenSave;
  109. ULONG intervalSave;
  110. SAP_BUFFER packet;
  111. } TREQ_ITEM, *PTREQ_ITEM;
  112. typedef union _WORK_ITEM {
  113. REQ_ITEM req;
  114. LPC_ITEM lpc;
  115. BCAST_ITEM bcast;
  116. SREQ_ITEM sreq;
  117. TREQ_ITEM treq;
  118. GNEAR_ITEM gnear;
  119. RESP_ITEM resp;
  120. } WORK_ITEM, *PWORK_ITEM;
  121. // Parameter block passed to enumeration call back filter procedures
  122. typedef struct _GR_FILTER_PARAMS {
  123. INT svrIdx; // Index of server info in SAP packet
  124. BOOLEAN localSvr; // Local server included in the packet
  125. USHORT localHopCount; // Hop count used to track servers local
  126. // to the interface that may prevent use from broad-
  127. // casting info of same server obtained on different
  128. // interface
  129. PINTERFACE_DATA intf; // Pointer to interface data
  130. PSAP_BUFFER packet; // Packet to be filled
  131. } GR_FILTER_PARAMS, *PGR_FILTER_PARAMS;
  132. typedef struct _GN_FILTER_PARAMS {
  133. BOOLEAN found; // flag indicating the one server was found
  134. USHORT localHopCount; // Hop count used to track servers local
  135. // to the interface that may prevent use from broad-
  136. // casting info of same server obtained on different
  137. // interface
  138. PINTERFACE_DATA intf; // Pointer to interface data
  139. PSAP_BUFFER packet; // Packet to be filled
  140. } GN_FILTER_PARAMS, *PGN_FILTER_PARAMS;
  141. // Parameters used to construct a list of servers that
  142. // need their internal network information updated.
  143. typedef struct _SERVER_INTERNAL_UPDATE_NODE {
  144. ULONG InterfaceIndex;
  145. ULONG Protocol;
  146. PUCHAR AdvertisingNode;
  147. INT Flags;
  148. IPX_SERVER_ENTRY_P Server;
  149. struct _SERVER_INTERNAL_UPDATE_NODE * pNext;
  150. } SERVER_INTERNAL_UPDATE_NODE;
  151. #define AllocateWorker(worker,type) \
  152. ((worker=(type *)HeapAlloc(WorkerQueue.WQ_Heap, 0, sizeof (WORK_ITEM))) \
  153. ? InterlockedIncrement (&WorkerQueue.WQ_WorkerCount) \
  154. : 0)
  155. #define DeallocateWorker(worker) { \
  156. HeapFree (WorkerQueue.WQ_Heap, 0, worker); \
  157. if (InterlockedDecrement (&WorkerQueue.WQ_WorkerCount)<0) { \
  158. BOOL res = SetEvent (WorkerQueue.WQ_DoneEvent); \
  159. ASSERTERRMSG ("Can't set workers done event ", res); \
  160. } \
  161. }
  162. // Local prototypes
  163. VOID APIENTRY
  164. ProcessReqItem (
  165. PVOID worker
  166. );
  167. VOID APIENTRY
  168. ProcessRespIOItem (
  169. PVOID worker
  170. );
  171. VOID APIENTRY
  172. ProcessRespTMItem (
  173. PVOID worker
  174. );
  175. VOID APIENTRY
  176. ProcessGnearItem (
  177. PVOID worker
  178. );
  179. VOID APIENTRY
  180. ProcessBcastIOItem (
  181. PVOID worker
  182. );
  183. VOID APIENTRY
  184. ProcessBcastTMItem (
  185. PVOID worker
  186. );
  187. VOID APIENTRY
  188. ProcessShutItem (
  189. PVOID worker
  190. );
  191. VOID APIENTRY
  192. ProcessSreqItem (
  193. PVOID worker
  194. );
  195. VOID APIENTRY
  196. ProcessSreqItem (
  197. PVOID worker
  198. );
  199. VOID APIENTRY
  200. ProcessLPCItem (
  201. PVOID worker
  202. );
  203. VOID APIENTRY
  204. ProcessTreqIOItem (
  205. PVOID worker
  206. );
  207. VOID APIENTRY
  208. ProcessTreqTMItem (
  209. PVOID worker
  210. );
  211. VOID APIENTRY
  212. FreeTreqItem (
  213. PAR_PARAM_BLOCK rslt
  214. );
  215. /*++
  216. *******************************************************************
  217. I n i t i a l i z e W o r k e r s
  218. Routine Description:
  219. Initialize heap to be used for allocation of work items
  220. Arguments:
  221. None
  222. Return Value:
  223. NO_ERROR - heap was initialized OK
  224. other - operation failed (windows error code)
  225. *******************************************************************
  226. --*/
  227. DWORD
  228. InitializeWorkers (
  229. HANDLE RecvEvent
  230. ) {
  231. DWORD status;
  232. if (MaxUnprocessedRequests<(MinPendingRequests*11/10)) {
  233. MaxUnprocessedRequests = MinPendingRequests*11/10;
  234. Trace (DEBUG_FAILURES,
  235. "Set "SAP_MAX_UNPROCESSED_REQUESTS_STR" to %d (10%% above "
  236. SAP_MIN_REQUESTS_STR")", MaxUnprocessedRequests);
  237. }
  238. WorkerQueue.WQ_WorkerCount = 0;
  239. WorkerQueue.WQ_RequestQuota = MaxUnprocessedRequests;
  240. WorkerQueue.WQ_RequestExtra = -MinPendingRequests;
  241. WorkerQueue.WQ_DoneEvent = NULL;
  242. WorkerQueue.WQ_RecvEvent = RecvEvent;
  243. WorkerQueue.WQ_Heap = HeapCreate (0, 0, 0);
  244. if (WorkerQueue.WQ_Heap!=NULL) {
  245. return NO_ERROR;
  246. }
  247. else {
  248. status = GetLastError ();
  249. Trace (DEBUG_FAILURES,
  250. "File: %s, line %ld. Could not allocate worker's heap (gle:%ld).",
  251. __FILE__, __LINE__, status);
  252. }
  253. return status;
  254. }
  255. /*++
  256. *******************************************************************
  257. S h u t d o w n W o r k e r s
  258. Routine Description:
  259. Stops new worker creation and signals event when all
  260. workers are deleted
  261. Arguments:
  262. doneEvent - event to be signalled when all workers are deleted
  263. Return Value:
  264. None
  265. *******************************************************************
  266. --*/
  267. VOID
  268. ShutdownWorkers (
  269. IN HANDLE doneEvent
  270. ) {
  271. WorkerQueue.WQ_DoneEvent = doneEvent;
  272. if (InterlockedDecrement (&WorkerQueue.WQ_WorkerCount)<0) {
  273. BOOL res = SetEvent (WorkerQueue.WQ_DoneEvent);
  274. ASSERTERRMSG ("Can't set workers done event ", res);
  275. }
  276. }
  277. /*++
  278. *******************************************************************
  279. D e l e t e W o r k e r s
  280. Routine Description:
  281. Deletes heap used for work items (and thus all work items as well)
  282. Arguments:
  283. None
  284. Return Value:
  285. None
  286. *******************************************************************
  287. --*/
  288. VOID
  289. DeleteWorkers (
  290. void
  291. ) {
  292. ASSERT (WorkerQueue.WQ_WorkerCount==-1);
  293. HeapDestroy (WorkerQueue.WQ_Heap);
  294. }
  295. /*++
  296. *******************************************************************
  297. H o p C o u n t F i l t e r
  298. Routine Description:
  299. Server enumeration callback proc that filters out servers with high hop
  300. (<=15 for same interface, <15 for rest)
  301. Arguments:
  302. CBParam - enumeration callback parameter (param block above)
  303. Server, InterfaceIndex, Protocol, AdvertisingNode, Flags - server info
  304. Return Value:
  305. TRUE (to stop enumeration) when sap packet gets filled up,
  306. FALSE otherwise
  307. *******************************************************************
  308. --*/
  309. BOOL
  310. HopCountFilter (
  311. IN LPVOID CBParam,
  312. IN PIPX_SERVER_ENTRY_P Server,
  313. IN ULONG InterfaceIndex,
  314. IN ULONG Protocol,
  315. IN PUCHAR AdvertisingNode,
  316. IN INT Flags
  317. ) {
  318. #define params ((PGR_FILTER_PARAMS)CBParam)
  319. ASSERTMSG ("To many servers ", params->svrIdx<IPX_SAP_MAX_ENTRY);
  320. if ((InterfaceIndex!=INTERNAL_INTERFACE_INDEX)
  321. || (IpxNetCmp (Server->Network, IPX_INVALID_NET)!=0)
  322. && ((Protocol==IPX_PROTOCOL_LOCAL)
  323. || Routing
  324. || RespondForInternalServers)) {
  325. if ((Server->HopCount<IPX_MAX_HOP_COUNT-1)
  326. || ((InterfaceIndex==params->intf->index)
  327. && (Server->HopCount<IPX_MAX_HOP_COUNT)) ) {
  328. if ((params->intf->filterOut==SAP_DONT_FILTER)
  329. || ((params->intf->filterOut==SAP_FILTER_PERMIT)
  330. && Filter (FILTER_TYPE_SUPPLY,
  331. params->intf->index, Server->Type, Server->Name))
  332. || ((params->intf->filterOut==SAP_FILTER_DENY)
  333. && !Filter (FILTER_TYPE_SUPPLY,
  334. params->intf->index, Server->Type, Server->Name))) {
  335. IpxServerCpy (&params->packet->Entries[params->svrIdx], Server);
  336. PUTUSHORT (Server->Type, &params->packet->Entries[params->svrIdx].Type);
  337. if (InterfaceIndex==params->intf->index) {
  338. PUTUSHORT (Server->HopCount,
  339. &params->packet->Entries[params->svrIdx].HopCount);
  340. }
  341. else {
  342. PUTUSHORT (Server->HopCount+1,
  343. &params->packet->Entries[params->svrIdx].HopCount);
  344. }
  345. params->svrIdx += 1;
  346. if (InterfaceIndex==INTERNAL_INTERFACE_INDEX)
  347. params->localSvr = TRUE;
  348. // Trace (DEBUG_ENTRIES, "\tAdding server, type: %04x, name: %.48s, hops: %d.",
  349. // Server->Type, Server->Name, Server->HopCount);
  350. if (params->svrIdx>=IPX_SAP_MAX_ENTRY)
  351. return TRUE;
  352. }
  353. }
  354. }
  355. #undef params
  356. return FALSE;
  357. }
  358. /*++
  359. *******************************************************************
  360. S p l i t H o r i z o n H o p C o u n t F i l t e r
  361. Routine Description:
  362. Server enumeration callback proc that filters out servers with high hop
  363. (<15) and applies split horizon algorithm based on interface index
  364. Arguments:
  365. CBParam - enumeration callback parameter (param block above)
  366. Server, InterfaceIndex, Protocol, AdvertisingNode, Flags - server info
  367. Return Value:
  368. TRUE (to stop enumeration) when sap packet gets filled up,
  369. FALSE otherwise
  370. *******************************************************************
  371. --*/
  372. BOOL
  373. SplitHorizonHopCountFilter (
  374. IN LPVOID CBParam,
  375. IN OUT PIPX_SERVER_ENTRY_P Server,
  376. IN ULONG InterfaceIndex,
  377. IN ULONG Protocol,
  378. IN PUCHAR AdvertisingNode,
  379. IN INT Flags
  380. ) {
  381. #define params ((PGR_FILTER_PARAMS)CBParam)
  382. ASSERTMSG ("To many servers ", params->svrIdx<IPX_SAP_MAX_ENTRY);
  383. if (Flags & SDB_MAIN_NODE_FLAG) {
  384. // Only send entries that are not received through local interface
  385. // and that do not have entry with equal hop count on local interface
  386. if (((InterfaceIndex!=INTERNAL_INTERFACE_INDEX)
  387. || (IpxNetCmp (Server->Network, IPX_INVALID_NET)!=0)
  388. && ((Protocol==IPX_PROTOCOL_LOCAL)
  389. || Routing
  390. || RespondForInternalServers))
  391. && (InterfaceIndex!=params->intf->index)
  392. && (Server->HopCount<params->localHopCount)
  393. && ((params->intf->filterOut==SAP_DONT_FILTER)
  394. || ((params->intf->filterOut==SAP_FILTER_PERMIT)
  395. && Filter (FILTER_TYPE_SUPPLY,
  396. params->intf->index, Server->Type, Server->Name))
  397. || ((params->intf->filterOut==SAP_FILTER_DENY)
  398. && !Filter (FILTER_TYPE_SUPPLY,
  399. params->intf->index, Server->Type, Server->Name)))) {
  400. IpxServerCpy (&params->packet->Entries[params->svrIdx], Server);
  401. PUTUSHORT (Server->Type,
  402. &params->packet->Entries[params->svrIdx].Type);
  403. PUTUSHORT (Server->HopCount+1,
  404. &params->packet->Entries[params->svrIdx].HopCount);
  405. if (InterfaceIndex==INTERNAL_INTERFACE_INDEX)
  406. params->localSvr = TRUE;
  407. params->svrIdx += 1;
  408. // Trace (DEBUG_ENTRIES, "\tAdding server, type: %04x, name: %.48s, hops: %d.",
  409. // Server->Type, Server->Name, Server->HopCount);
  410. if (params->svrIdx>=IPX_SAP_MAX_ENTRY)
  411. return TRUE;
  412. }
  413. // Make sure we won't send deleted servers
  414. params->localHopCount = IPX_MAX_HOP_COUNT-1;
  415. }
  416. else if (InterfaceIndex==params->intf->index) {
  417. params->localHopCount = Server->HopCount; // Remember hop count of entry
  418. // on local interface
  419. // Trace (DEBUG_ENTRIES, "\tBackup server entry, type: %04x, name: %.48s, hops: %d.",
  420. // Server->Type, Server->Name, Server->HopCount);
  421. }
  422. #undef params
  423. return FALSE;
  424. }
  425. /*++
  426. *******************************************************************
  427. S p l i t H o r i z o n F i l t e r
  428. Routine Description:
  429. Server enumeration callback proc that applies split horizon algorithm
  430. based on interface index to filter out enumerated servers
  431. Arguments:
  432. CBParam - enumeration callback parameter (param block above)
  433. Server, InterfaceIndex, Protocol, AdvertisingNode, Flags - server info
  434. Return Value:
  435. TRUE (to stop enumeration) when sap packet gets filled up,
  436. FALSE otherwise
  437. *******************************************************************
  438. --*/
  439. BOOL
  440. SplitHorizonFilter (
  441. IN LPVOID CBParam,
  442. IN OUT PIPX_SERVER_ENTRY_P Server,
  443. IN ULONG InterfaceIndex,
  444. IN ULONG Protocol,
  445. IN PUCHAR AdvertisingNode,
  446. IN INT Flags
  447. ) {
  448. #define params ((PGR_FILTER_PARAMS)CBParam)
  449. ASSERTMSG ("To many servers ", params->svrIdx<IPX_SAP_MAX_ENTRY);
  450. if (Flags&SDB_MAIN_NODE_FLAG) {
  451. // Only send entries that are not received through local interface
  452. // and that do not have entry with equal hop count on local interface
  453. if ( (((InterfaceIndex==INTERNAL_INTERFACE_INDEX)
  454. && (IpxNetCmp (Server->Network, IPX_INVALID_NET)!=0)
  455. && ((Protocol==IPX_PROTOCOL_LOCAL)
  456. || Routing
  457. || RespondForInternalServers))
  458. || (InterfaceIndex!=params->intf->index))
  459. && (Server->HopCount<params->localHopCount)
  460. && ((params->intf->filterOut==SAP_DONT_FILTER)
  461. || ((params->intf->filterOut==SAP_FILTER_PERMIT)
  462. && Filter (FILTER_TYPE_SUPPLY,
  463. params->intf->index, Server->Type, Server->Name))
  464. || ((params->intf->filterOut==SAP_FILTER_DENY)
  465. && !Filter (FILTER_TYPE_SUPPLY,
  466. params->intf->index, Server->Type, Server->Name))) ){
  467. IpxServerCpy (&params->packet->Entries[params->svrIdx], Server);
  468. PUTUSHORT (Server->Type,
  469. &params->packet->Entries[params->svrIdx].Type);
  470. if ((Server->HopCount<IPX_MAX_HOP_COUNT)
  471. && !(Flags&SDB_DISABLED_NODE_FLAG)) {
  472. PUTUSHORT (Server->HopCount+1,
  473. &params->packet->Entries[params->svrIdx].HopCount);
  474. }
  475. else {
  476. PUTUSHORT (IPX_MAX_HOP_COUNT,
  477. &params->packet->Entries[params->svrIdx].HopCount);
  478. }
  479. if (InterfaceIndex==INTERNAL_INTERFACE_INDEX)
  480. params->localSvr = TRUE;
  481. params->svrIdx += 1;
  482. // Trace (DEBUG_ENTRIES, "\tAdding server, type: %04x, name: %.48s, hops: %d.",
  483. // Server->Type, Server->Name, Server->HopCount);
  484. if (params->svrIdx>=IPX_SAP_MAX_ENTRY)
  485. return TRUE;
  486. }
  487. params->localHopCount = IPX_MAX_HOP_COUNT+1;
  488. }
  489. else if ((InterfaceIndex==params->intf->index)
  490. && !(Flags&SDB_DISABLED_NODE_FLAG)) {
  491. params->localHopCount = Server->HopCount;
  492. // Trace (DEBUG_ENTRIES,"\tBackup server entry, type: %04x, name: %.48s, hops: %d.",
  493. // Server->Type, Server->Name, Server->HopCount);
  494. }
  495. #undef params
  496. return FALSE;
  497. }
  498. /*++
  499. *******************************************************************
  500. S p l i t H o r i z o n F i l t e r
  501. Routine Description:
  502. Server enumeration callback proc that applies split horizon algorithm
  503. based on interface index to filter out enumerated servers
  504. and only gets deleted servers (HopCount=16)
  505. Arguments:
  506. CBParam - enumeration callback parameter (param block above)
  507. Server, InterfaceIndex, Protocol, AdvertisingNode, Flags - server info
  508. Return Value:
  509. TRUE (to stop enumeration) when sap packet gets filled up,
  510. FALSE otherwise
  511. *******************************************************************
  512. --*/
  513. BOOL
  514. SplitHorizonDeletedFilter (
  515. IN LPVOID CBParam,
  516. IN OUT PIPX_SERVER_ENTRY_P Server,
  517. IN ULONG InterfaceIndex,
  518. IN ULONG Protocol,
  519. IN PUCHAR AdvertisingNode,
  520. IN INT Flags
  521. ) {
  522. #define params ((PGR_FILTER_PARAMS)CBParam)
  523. ASSERTMSG ("To many servers ", params->svrIdx<IPX_SAP_MAX_ENTRY);
  524. if (Flags&SDB_MAIN_NODE_FLAG) {
  525. // Only send entries that are not received through local interface
  526. // and that do not have entry with equal hop count on local interface
  527. if (((Server->HopCount>=IPX_MAX_HOP_COUNT)
  528. || (Flags&SDB_DISABLED_NODE_FLAG))
  529. && (((InterfaceIndex==INTERNAL_INTERFACE_INDEX)
  530. && (IpxNetCmp (Server->Network, IPX_INVALID_NET)!=0)
  531. && ((Protocol==IPX_PROTOCOL_LOCAL)
  532. || Routing
  533. || RespondForInternalServers))
  534. || (InterfaceIndex!=params->intf->index))
  535. && ((params->intf->filterOut==SAP_DONT_FILTER)
  536. || ((params->intf->filterOut==SAP_FILTER_PERMIT)
  537. && Filter (FILTER_TYPE_SUPPLY,
  538. params->intf->index, Server->Type, Server->Name))
  539. || ((params->intf->filterOut==SAP_FILTER_DENY)
  540. && !Filter (FILTER_TYPE_SUPPLY,
  541. params->intf->index, Server->Type, Server->Name))) ){
  542. IpxServerCpy (&params->packet->Entries[params->svrIdx], Server);
  543. PUTUSHORT (Server->Type,
  544. &params->packet->Entries[params->svrIdx].Type);
  545. PUTUSHORT (IPX_MAX_HOP_COUNT,
  546. &params->packet->Entries[params->svrIdx].HopCount);
  547. params->svrIdx += 1;
  548. // Trace (DEBUG_ENTRIES, "\tAdding server, type: %04x, name: %.48s, hops: %d.",
  549. // Server->Type, Server->Name, Server->HopCount);
  550. if (params->svrIdx>=IPX_SAP_MAX_ENTRY)
  551. return TRUE;
  552. }
  553. }
  554. #undef params
  555. return FALSE;
  556. }
  557. /*++
  558. *******************************************************************
  559. G e t N e a r e s t F i l t e r
  560. Routine Description:
  561. Server enumeration callback proc that gets internal server if there is one or
  562. server with lowest hop count not on the local interface
  563. Arguments:
  564. CBParam - enumeration callback parameter (param block above)
  565. Server, InterfaceIndex, Protocol, AdvertisingNode, Flags - server info
  566. Return Value:
  567. TRUE (to stop enumeration) when it finds first internal server,
  568. FALSE otherwise
  569. *******************************************************************
  570. --*/
  571. BOOL
  572. GetNearestFilter (
  573. IN LPVOID CBParam,
  574. IN OUT PIPX_SERVER_ENTRY_P Server,
  575. IN ULONG InterfaceIndex,
  576. IN ULONG Protocol,
  577. IN PUCHAR AdvertisingNode,
  578. IN INT Flags
  579. ) {
  580. #define params ((PGN_FILTER_PARAMS)CBParam)
  581. if (((InterfaceIndex==INTERNAL_INTERFACE_INDEX)
  582. && !(Flags&SDB_DONT_RESPOND_NODE_FLAG)
  583. && (IpxNetCmp (Server->Network, IPX_INVALID_NET)!=0)
  584. && ((Protocol==IPX_PROTOCOL_LOCAL)
  585. || Routing
  586. || RespondForInternalServers))
  587. || ((InterfaceIndex!=params->intf->index)
  588. && (Server->HopCount<params->localHopCount))) {
  589. if ((params->intf->filterOut==SAP_DONT_FILTER)
  590. || ((params->intf->filterOut==SAP_FILTER_PERMIT)
  591. && Filter (FILTER_TYPE_SUPPLY,
  592. params->intf->index, Server->Type, Server->Name))
  593. || ((params->intf->filterOut==SAP_FILTER_DENY)
  594. && !Filter (FILTER_TYPE_SUPPLY,
  595. params->intf->index, Server->Type, Server->Name))) {
  596. IpxServerCpy (&params->packet->Entries[0], Server);
  597. PUTUSHORT (Server->Type, &params->packet->Entries[0].Type);
  598. PUTUSHORT (Server->HopCount+1,
  599. &params->packet->Entries[0].HopCount);
  600. // Trace (DEBUG_ENTRIES, "\tGetting server, type: %04x, name: %.48s, hops: %d.",
  601. // Server->Type, Server->Name, Server->HopCount);
  602. params->found = TRUE;
  603. params->localHopCount = Server->HopCount;
  604. if (InterfaceIndex==INTERNAL_INTERFACE_INDEX)
  605. return TRUE;
  606. }
  607. }
  608. #undef params
  609. return FALSE;
  610. }
  611. /*++
  612. *******************************************************************
  613. C o u n t S e r v e r s F i l t e r
  614. Routine Description:
  615. Server enumeration callback proc that count servers with which it
  616. is called back
  617. Arguments:
  618. CBParam - pointer to counter
  619. Server, InterfaceIndex, Protocol, AdvertisingNode, Flags - server info
  620. Return Value:
  621. FALSE to tell SDB to continue enumeration
  622. *******************************************************************
  623. --*/
  624. BOOL
  625. CountServersFilter (
  626. IN LPVOID CBParam,
  627. IN OUT PIPX_SERVER_ENTRY_P Server,
  628. IN ULONG InterfaceIndex,
  629. IN ULONG Protocol,
  630. IN PUCHAR AdvertisingNode,
  631. IN INT Flags
  632. ) {
  633. #define count ((ULONG *)CBParam)
  634. if (Protocol==IPX_PROTOCOL_SAP)
  635. *count += 1;
  636. return FALSE;
  637. #undef count
  638. }
  639. VOID
  640. AddRecvRequests (
  641. LONG count
  642. ) {
  643. InterlockedExchangeAdd (&WorkerQueue.WQ_RequestQuota, count);
  644. if (InterlockedExchangeAdd (&WorkerQueue.WQ_RequestExtra, (-count))<count) {
  645. BOOL res = SetEvent (WorkerQueue.WQ_RecvEvent);
  646. ASSERTMSG ("Could not set recv event ", res);
  647. }
  648. else {
  649. BOOL res = ResetEvent (WorkerQueue.WQ_RecvEvent);
  650. ASSERTMSG ("Could not reset recv event ", res);
  651. }
  652. }
  653. VOID
  654. RemoveRecvRequests (
  655. LONG count
  656. ) {
  657. InterlockedExchangeAdd (&WorkerQueue.WQ_RequestQuota, (-count));
  658. if (InterlockedExchangeAdd (&WorkerQueue.WQ_RequestExtra, count)>(-count)) {
  659. BOOL res = ResetEvent (WorkerQueue.WQ_RecvEvent);
  660. ASSERTMSG ("Could not reset recv event ", res);
  661. }
  662. }
  663. /*++
  664. *******************************************************************
  665. I n i t R e q I t e m
  666. Routine Description:
  667. Allocate and initialize IO request item
  668. Enqueue the request
  669. Arguments:
  670. None
  671. Return Value:
  672. NO_ERROR - item was initialized and enqueued OK
  673. other - operation failed (windows error code)
  674. *******************************************************************
  675. --*/
  676. DWORD
  677. InitReqItem (
  678. VOID
  679. ) {
  680. PREQ_ITEM reqItem;
  681. do {
  682. if (InterlockedDecrement (&WorkerQueue.WQ_RequestQuota)<0) {
  683. InterlockedIncrement (&WorkerQueue.WQ_RequestQuota);
  684. return NO_ERROR;
  685. }
  686. if (!AllocateWorker (reqItem, REQ_ITEM)) {
  687. Trace (DEBUG_FAILURES,
  688. "File: %s, line %ld. Could not allocate request item (gle:%ld).",
  689. __FILE__, __LINE__, GetLastError ());
  690. InterlockedIncrement (&WorkerQueue.WQ_RequestQuota);
  691. return ERROR_NOT_ENOUGH_MEMORY;
  692. }
  693. reqItem->iow.worker = ProcessReqItem;
  694. reqItem->iow.io.buffer = (PUCHAR)&reqItem->packet;
  695. reqItem->iow.io.cbBuffer = sizeof (reqItem->packet);
  696. Trace (DEBUG_REQ, "Generated receive request: %08lx.", reqItem);
  697. EnqueueRecvRequest (&reqItem->iow.io);
  698. }
  699. while (InterlockedIncrement (&WorkerQueue.WQ_RequestExtra)<0);
  700. return NO_ERROR;
  701. }
  702. /*++
  703. *******************************************************************
  704. P r o c e s s R e q I t e m
  705. Routine Description:
  706. Process received request
  707. Arguments:
  708. worker - pointer to work item to process
  709. Return Value:
  710. None
  711. *******************************************************************
  712. --*/
  713. VOID APIENTRY
  714. ProcessReqItem (
  715. PVOID worker
  716. ) {
  717. PREQ_ITEM reqItem = CONTAINING_RECORD (worker, REQ_ITEM, iow.worker);
  718. INT i;
  719. PINTERFACE_DATA intf;
  720. LONG count;
  721. Trace (DEBUG_REQ, "Processing received request item %08lx on adpt: %d.",
  722. reqItem, reqItem->iow.io.adpt);
  723. count = InterlockedDecrement (&WorkerQueue.WQ_RequestExtra);
  724. if ((OperationalState==OPER_STATE_UP)
  725. && (reqItem->iow.io.status==NO_ERROR)) {
  726. if (count<0) {
  727. BOOL res = SetEvent (WorkerQueue.WQ_RecvEvent);
  728. ASSERTMSG ("Failed to set recv event ", res);
  729. }
  730. intf = GetInterfaceReference (reqItem->iow.io.adpt);
  731. if (intf!=NULL) {
  732. PSAP_BUFFER packet = &reqItem->packet;
  733. if ((IpxNodeCmp (packet->Src.Node, intf->adapter.LocalNode)!=0)
  734. || (IpxSockCmp (packet->Src.Socket, IPX_SAP_SOCKET)!=0)
  735. || (IpxNetCmp (packet->Src.Network, intf->adapter.Network)!=0)) {
  736. InterlockedIncrement (&intf->stats.SapIfInputPackets);
  737. packet->Length = GETUSHORT(&packet->Length);
  738. if (packet->Length>reqItem->iow.io.cbBuffer)
  739. packet->Length = (USHORT)reqItem->iow.io.cbBuffer;
  740. if (reqItem->iow.io.status==NO_ERROR) {
  741. if (packet->Length
  742. >= (FIELD_OFFSET (SAP_BUFFER, Operation)
  743. +sizeof(packet->Operation))) {
  744. packet->Operation = GETUSHORT(&packet->Operation);
  745. switch (packet->Operation) {
  746. case SAP_GENERAL_REQ:
  747. Trace (DEBUG_REQ, "\tGeneral request received for type: %04x.",
  748. GETUSHORT (&packet->Entries[0].Type));
  749. if (intf->info.Supply==ADMIN_STATE_ENABLED) {
  750. PIPX_SERVER_ENTRY_P pEntry = packet->Entries;
  751. if (packet->Length >= (FIELD_OFFSET (
  752. SAP_BUFFER, Entries[0].Type)
  753. +sizeof (pEntry->Type))) {
  754. pEntry->Type = GETUSHORT (&pEntry->Type);
  755. InitRespItem (intf,
  756. pEntry->Type,
  757. &packet->Src,
  758. memcmp (
  759. packet->Dst.Node,
  760. IPX_BCAST_NODE,
  761. sizeof (IPX_BCAST_NODE))
  762. ==0);
  763. }
  764. }
  765. break;
  766. case SAP_GENERAL_RESP:
  767. Trace (DEBUG_REQ, "\tGeneral response received.");
  768. if (intf->info.Listen==ADMIN_STATE_ENABLED) {
  769. PIPX_SERVER_ENTRY_P pEntry = packet->Entries;
  770. for (i=0; (i<IPX_SAP_MAX_ENTRY)
  771. && ((PUCHAR)&pEntry[1]-(PUCHAR)packet
  772. <=packet->Length);
  773. i++,pEntry++) {
  774. pEntry->Type = GETUSHORT (&pEntry->Type);
  775. if ((intf->filterIn==SAP_DONT_FILTER)
  776. || ((intf->filterIn==SAP_FILTER_PERMIT)
  777. && Filter (FILTER_TYPE_LISTEN,
  778. intf->index,
  779. pEntry->Type, pEntry->Name))
  780. || ((intf->filterIn==SAP_FILTER_DENY)
  781. && !Filter (FILTER_TYPE_LISTEN,
  782. intf->index,
  783. pEntry->Type, pEntry->Name))) {
  784. if ((IpxNodeCmp (packet->Src.Node, intf->adapter.LocalNode)!=0)
  785. || (IpxNetCmp (packet->Src.Network, intf->adapter.Network)!=0)) {
  786. USHORT Metric;
  787. if (GetServerMetric (pEntry, &Metric)==NO_ERROR)
  788. pEntry->HopCount = GETUSHORT (&pEntry->HopCount);
  789. else
  790. pEntry->HopCount = IPX_MAX_HOP_COUNT;
  791. UpdateServer (
  792. pEntry,
  793. intf->index,
  794. IPX_PROTOCOL_SAP,
  795. (intf->info.PeriodicUpdateInterval!=MAXULONG)
  796. ? (intf->info.PeriodicUpdateInterval
  797. *intf->info.AgeIntervalMultiplier)
  798. : INFINITE,
  799. packet->Src.Node,
  800. 0,
  801. NULL
  802. );
  803. }
  804. else {
  805. if (GETUSHORT (&pEntry->HopCount)<IPX_MAX_HOP_COUNT)
  806. pEntry->HopCount = 0;
  807. else
  808. pEntry->HopCount = IPX_MAX_HOP_COUNT;
  809. IpxNetCpy (pEntry->Network, INTERNAL_IF_NET);
  810. IpxNodeCpy (pEntry->Node, INTERNAL_IF_NODE);
  811. UpdateServer (
  812. pEntry,
  813. INTERNAL_INTERFACE_INDEX,
  814. IPX_PROTOCOL_SAP,
  815. ServerAgingTimeout*60,
  816. IPX_BCAST_NODE,
  817. 0,
  818. NULL
  819. );
  820. }
  821. // Trace (DEBUG_ENTRIES, "\tInserting server,"
  822. // " type: %04x, hops: %d, name: %.48s.",
  823. // pEntry->Type,
  824. // pEntry->HopCount,
  825. // pEntry->Name);
  826. if (((intf->stats.SapIfOperState!=OPER_STATE_UP)
  827. || (OperationalState!=OPER_STATE_UP))
  828. && (IpxNetCmp (pEntry->Network, INTERNAL_IF_NET)!=0)) {
  829. pEntry->HopCount = IPX_MAX_HOP_COUNT;
  830. UpdateServer (
  831. pEntry,
  832. intf->index,
  833. IPX_PROTOCOL_SAP,
  834. INFINITE,
  835. packet->Src.Node,
  836. 0,
  837. NULL
  838. );
  839. break;
  840. }
  841. } // End if filter path
  842. } // end for
  843. } // end if Listening
  844. break;
  845. case SAP_GET_NEAREST_REQ:
  846. Trace (DEBUG_REQ, "\tGet nearest server request received.");
  847. if (intf->info.GetNearestServerReply==ADMIN_STATE_ENABLED) {
  848. PIPX_SERVER_ENTRY_P pEntry = packet->Entries;
  849. if (packet->Length >= (FIELD_OFFSET (
  850. SAP_BUFFER, Entries[0].Type)
  851. +sizeof (pEntry->Type))) {
  852. pEntry->Type = GETUSHORT (&pEntry->Type);
  853. InitGnearItem (intf, pEntry->Type, &packet->Src);
  854. }
  855. }
  856. break;
  857. case SAP_GET_NEAREST_RESP:
  858. Trace (DEBUG_FAILURES, "\tGet nearest server response received"
  859. " from %.2x%.2x%.2x%.2x.%.2x%.2x%.2x%.2x%.2x%.2x.%.2x%.2x"
  860. " (I never ask for it).",
  861. packet->Src.Network[0], packet->Src.Network[1],
  862. packet->Src.Network[2], packet->Src.Network[3],
  863. packet->Src.Node[0], packet->Src.Node[1],
  864. packet->Src.Node[2], packet->Src.Node[3],
  865. packet->Src.Node[4], packet->Src.Node[5],
  866. packet->Src.Socket[0], packet->Src.Socket[1]);
  867. break;
  868. default:
  869. Trace (DEBUG_FAILURES, "Packet with operation %d"
  870. " from %.2x%.2x%.2x%.2x.%.2x%.2x%.2x%.2x%.2x%.2x.%.2x%.2x ignored.",
  871. packet->Operation,
  872. packet->Src.Network[0], packet->Src.Network[1],
  873. packet->Src.Network[2], packet->Src.Network[3],
  874. packet->Src.Node[0], packet->Src.Node[1],
  875. packet->Src.Node[2], packet->Src.Node[3],
  876. packet->Src.Node[4], packet->Src.Node[5],
  877. packet->Src.Socket[0], packet->Src.Socket[1]);
  878. break;
  879. }
  880. }
  881. else
  882. Trace (DEBUG_FAILURES, "File: %s, line %ld. Invalid packet.", __FILE__, __LINE__);
  883. }
  884. // else Receive failure - reported by io layer
  885. }
  886. // else Loopback packet
  887. ReleaseInterfaceReference (intf);
  888. }
  889. // else Unknown interface - reported by io layer
  890. if (InterlockedIncrement (&WorkerQueue.WQ_RequestExtra)<=0) {
  891. Trace (DEBUG_REQ, "Requeing receive request item %08lx.", reqItem);
  892. reqItem->iow.io.cbBuffer = sizeof (reqItem->packet);
  893. EnqueueRecvRequest (&reqItem->iow.io);
  894. return;
  895. }
  896. else
  897. InterlockedDecrement (&WorkerQueue.WQ_RequestExtra);
  898. }
  899. // else Packet received with error or OperationalState is not UP
  900. Trace (DEBUG_REQ, "Freeing receive request item %08lx.", reqItem);
  901. InterlockedIncrement (&WorkerQueue.WQ_RequestQuota);
  902. DeallocateWorker (reqItem);
  903. }
  904. VOID APIENTRY
  905. SendResponse (
  906. PRESP_ITEM respItem
  907. ) {
  908. GR_FILTER_PARAMS params;
  909. if (respItem->iow.io.status==NO_ERROR) {
  910. Trace (DEBUG_RESP,
  911. "Filling response item %08lx on interface: %d, for type: %04x.",
  912. respItem,
  913. respItem->intf->index,
  914. respItem->svrType);
  915. params.svrIdx = 0;
  916. params.intf = respItem->intf;
  917. params.packet = &respItem->packet;
  918. params.localHopCount = IPX_MAX_HOP_COUNT-1;
  919. params.localSvr = FALSE;
  920. EnumerateServers (respItem->hEnum,
  921. respItem->bcast
  922. ? SplitHorizonHopCountFilter // Bcast - use split horizon
  923. : HopCountFilter, // Send all best servers (except duplicate entries
  924. // on looped networks)
  925. (LPVOID)&params);
  926. respItem->iow.io.cbBuffer = FIELD_OFFSET (SAP_BUFFER, Entries[params.svrIdx]);
  927. PUTUSHORT (respItem->iow.io.cbBuffer, &respItem->packet.Length);
  928. respItem->iow.io.adpt = respItem->intf->adapter.AdapterIndex;
  929. if ((params.svrIdx!=0)
  930. && (respItem->intf->stats.SapIfOperState==OPER_STATE_UP)
  931. && (OperationalState==OPER_STATE_UP)) {
  932. EnqueueSendRequest (&respItem->iow.io);
  933. return;
  934. }
  935. }
  936. Trace (DEBUG_RESP,
  937. "Freeing general response item %08lx for interface: %d.",
  938. respItem, respItem->intf->index);
  939. ReleaseInterfaceReference (respItem->intf);
  940. DeleteListEnumerator (respItem->hEnum);
  941. DeallocateWorker (respItem);
  942. }
  943. /*++
  944. *******************************************************************
  945. I n i t R e s p I t e m
  946. Routine Description:
  947. Allocate and initialize SAP response item
  948. Calls ProcessRespIOItem to fill the packet and send it
  949. Arguments:
  950. intf - pointer to interface control block to send on
  951. svrType - type of servers to put in response packet
  952. dst - where to send the response packet
  953. bcast - are we responding to broadcasted request
  954. Return Value:
  955. NO_ERROR - item was initialized and enqueued OK
  956. other - operation failed (windows error code)
  957. *******************************************************************
  958. --*/
  959. DWORD
  960. InitRespItem (
  961. PINTERFACE_DATA intf,
  962. USHORT svrType,
  963. PIPX_ADDRESS_BLOCK dst,
  964. BOOL bcast
  965. ) {
  966. PRESP_ITEM respItem;
  967. DWORD status;
  968. if (!AllocateWorker (respItem, RESP_ITEM)) {
  969. Trace (DEBUG_FAILURES,
  970. "File: %s, line %ld. Could not allocate response item (gle:%ld).",
  971. __FILE__, __LINE__, GetLastError ());
  972. return ERROR_NOT_ENOUGH_MEMORY;
  973. }
  974. AcquireInterfaceReference (intf); // Make sure interface block is locked
  975. respItem->hEnum = CreateListEnumerator (
  976. (svrType!=0xFFFF)
  977. ? SDB_TYPE_LIST_LINK // Just servers of one type
  978. : SDB_HASH_TABLE_LINK, // All servers
  979. svrType,
  980. NULL,
  981. (!Routing && bcast) // Respond with only local
  982. // servers if not routing and
  983. // request was a broadcast
  984. ? INTERNAL_INTERFACE_INDEX
  985. : INVALID_INTERFACE_INDEX,
  986. 0xFFFFFFFF,
  987. 0); // All entries, so we can
  988. // detect duplicate servers on looped networks
  989. if (respItem->hEnum==NULL) {
  990. status = GetLastError ();
  991. ReleaseInterfaceReference (intf);
  992. DeallocateWorker (respItem);
  993. return status;
  994. }
  995. respItem->iow.worker = ProcessRespIOItem;
  996. respItem->iow.io.buffer = (PUCHAR)&respItem->packet;
  997. respItem->iow.io.status = NO_ERROR;
  998. respItem->tmw.worker = ProcessRespTMItem;
  999. respItem->tmw.tm.ExpirationCheckProc = NULL;
  1000. respItem->intf = intf;
  1001. SetupIpxSapPacket(&respItem->packet, SAP_GENERAL_RESP,
  1002. dst->Network, dst->Node, dst->Socket);
  1003. respItem->svrType = svrType;
  1004. respItem->bcast = (UCHAR)bcast;
  1005. Trace (DEBUG_RESP, "Generated general response item %08lx for interface %d.",
  1006. respItem, respItem->intf->index);
  1007. if (DelayResponseToGeneral>0) {
  1008. Trace (DEBUG_RESP,
  1009. "Delaying general response item %08lx for interface: %d.",
  1010. respItem, respItem->intf->index);
  1011. respItem->tmw.tm.dueTime = GetTickCount ()+DelayResponseToGeneral;
  1012. AddHRTimerRequest (&respItem->tmw.tm);
  1013. }
  1014. else
  1015. SendResponse (respItem);
  1016. return NO_ERROR;
  1017. }
  1018. /*++
  1019. *******************************************************************
  1020. P r o c e s s R e s p I O I t e m
  1021. Routine Description:
  1022. Generate and send response packet
  1023. Arguments:
  1024. worker - pointer to work item to process
  1025. Return Value:
  1026. None
  1027. *******************************************************************
  1028. --*/
  1029. VOID APIENTRY
  1030. ProcessRespIOItem (
  1031. PVOID worker
  1032. ) {
  1033. PRESP_ITEM respItem = CONTAINING_RECORD (worker, RESP_ITEM, iow.worker);
  1034. Trace (DEBUG_RESP,
  1035. "Processing general response tm item %08lx on interface: %d.",
  1036. respItem, respItem->intf->index);
  1037. if (respItem->iow.io.status==NO_ERROR)
  1038. InterlockedIncrement (&respItem->intf->stats.SapIfOutputPackets);
  1039. if ( (respItem->intf->stats.SapIfOperState==OPER_STATE_UP)
  1040. && (OperationalState==OPER_STATE_UP)) {
  1041. if (GetTickCount()-respItem->iow.io.compTime<IPX_SAP_INTERPACKET_GAP) {
  1042. respItem->tmw.tm.dueTime = respItem->iow.io.compTime
  1043. + IPX_SAP_INTERPACKET_GAP;
  1044. AddHRTimerRequest (&respItem->tmw.tm);
  1045. }
  1046. else
  1047. SendResponse (respItem);
  1048. }
  1049. else {
  1050. Trace (DEBUG_RESP,
  1051. "Freeing general response item %08lx for interface: %d.",
  1052. respItem, respItem->intf->index);
  1053. ReleaseInterfaceReference (respItem->intf);
  1054. DeleteListEnumerator (respItem->hEnum);
  1055. DeallocateWorker (respItem);
  1056. }
  1057. }
  1058. VOID APIENTRY
  1059. ProcessRespTMItem (
  1060. PVOID worker
  1061. ) {
  1062. PRESP_ITEM respItem = CONTAINING_RECORD (worker, RESP_ITEM, tmw.worker);
  1063. Trace (DEBUG_RESP,
  1064. "Processing general response tm item %08lx on interface: %d.",
  1065. respItem, respItem->intf->index);
  1066. if ( (respItem->intf->stats.SapIfOperState==OPER_STATE_UP)
  1067. && (OperationalState==OPER_STATE_UP)) {
  1068. SendResponse (respItem);
  1069. }
  1070. else {
  1071. Trace (DEBUG_RESP,
  1072. "Freeing general response item %08lx for interface: %d.",
  1073. respItem, respItem->intf->index);
  1074. ReleaseInterfaceReference (respItem->intf);
  1075. DeleteListEnumerator (respItem->hEnum);
  1076. DeallocateWorker (respItem);
  1077. }
  1078. }
  1079. /*++
  1080. *******************************************************************
  1081. D e l e t e B c a s t I t e m
  1082. Routine Description:
  1083. Disposes of resources associated with broadcast work item
  1084. Arguments:
  1085. bcastItem - pointer to broadcast work item
  1086. Return Value:
  1087. None
  1088. *******************************************************************
  1089. --*/
  1090. VOID
  1091. DeleteBcastItem (
  1092. PBCAST_ITEM bcastItem
  1093. ) {
  1094. Trace (DEBUG_BCAST, "Freeing broadcast item %08lx for interface: %d.",
  1095. bcastItem, bcastItem->intf->index);
  1096. if (bcastItem->chngEnum!=NULL)
  1097. DeleteListEnumerator (bcastItem->chngEnum);
  1098. if ((bcastItem->perdEnum!=NULL)
  1099. && (bcastItem->perdEnum!=INVALID_HANDLE_VALUE))
  1100. DeleteListEnumerator (bcastItem->perdEnum);
  1101. ReleaseInterfaceReference (bcastItem->intf);
  1102. DeallocateWorker (bcastItem);
  1103. }
  1104. /*++
  1105. *******************************************************************
  1106. D o B r o a d c a s t
  1107. Routine Description:
  1108. Check for and broadcast changed servers
  1109. Check if it is time to do periodic broadcast and start it if so
  1110. Arguments:
  1111. bcastItem - pointer to broadcast work item
  1112. Return Value:
  1113. None
  1114. *******************************************************************
  1115. --*/
  1116. VOID
  1117. DoBroadcast (
  1118. PBCAST_ITEM bcastItem
  1119. ) {
  1120. GR_FILTER_PARAMS params;
  1121. BOOLEAN periodic;
  1122. params.svrIdx = bcastItem->delayedSvrCount;
  1123. params.intf = bcastItem->intf;
  1124. params.packet = &bcastItem->packet;
  1125. if ( ((bcastItem->intf->stats.SapIfOperState==OPER_STATE_UP)
  1126. && ((bcastItem->perdEnum!=NULL) // we are already in the middle of
  1127. // broadcast
  1128. || IsLater(GetTickCount (),bcastItem->nextBcast))) // or it is
  1129. // time to start a new one
  1130. || ((bcastItem->intf->stats.SapIfOperState==OPER_STATE_STOPPING)
  1131. // or interface is being stopped, so
  1132. // we need to broadcast the whole
  1133. // table as deleted
  1134. && (bcastItem->perdEnum!=INVALID_HANDLE_VALUE))
  1135. // This value in the periodic
  1136. // enumeration handle field means
  1137. // that we are already done
  1138. // with this broadcast
  1139. ) {
  1140. Trace (DEBUG_BCAST, "Checking for deleted servers on interface: %d.",
  1141. params.intf->index);
  1142. EnumerateServers (bcastItem->chngEnum, SplitHorizonDeletedFilter, &params);
  1143. if (bcastItem->perdEnum==NULL) { // Need to start new boradcast
  1144. Trace (DEBUG_BCAST, "Starting broadcast enumeration on interface: %d (@ %ld).",
  1145. bcastItem->intf->index, bcastItem->nextBcast);
  1146. if (Routing) // Router installation: broadcast all servers
  1147. bcastItem->perdEnum = CreateListEnumerator (
  1148. SDB_HASH_TABLE_LINK,
  1149. 0xFFFF,
  1150. NULL,
  1151. INVALID_INTERFACE_INDEX,
  1152. 0xFFFFFFFF,
  1153. 0);
  1154. else // Standalone SAP agent: only internal servers
  1155. bcastItem->perdEnum = CreateListEnumerator (
  1156. SDB_INTF_LIST_LINK,
  1157. 0xFFFF,
  1158. NULL,
  1159. INTERNAL_INTERFACE_INDEX,
  1160. 0xFFFFFFFF,
  1161. 0);
  1162. // Set the time for next broadcast
  1163. bcastItem->nextBcast +=
  1164. bcastItem->intf->info.PeriodicUpdateInterval*1000;
  1165. }
  1166. if ((params.svrIdx<IPX_SAP_MAX_ENTRY)
  1167. && (bcastItem->perdEnum!=NULL)
  1168. && (bcastItem->perdEnum!=INVALID_HANDLE_VALUE)) {
  1169. Trace (DEBUG_BCAST, "Adding broadcast servers on interface: %d.",
  1170. params.intf->index);
  1171. params.localHopCount = IPX_MAX_HOP_COUNT-1;
  1172. params.localSvr = FALSE;
  1173. if (!EnumerateServers (bcastItem->perdEnum,
  1174. SplitHorizonHopCountFilter,
  1175. &params)) {
  1176. // All broadcast servers sent, dispose enumeration handle
  1177. DeleteListEnumerator (bcastItem->perdEnum);
  1178. Trace (DEBUG_BCAST, "Broadcast enumeration finished on interface:"
  1179. " %d (@ %ld, next @ %ld).",
  1180. bcastItem->intf->index,
  1181. GetTickCount (),
  1182. bcastItem->nextBcast);
  1183. if (bcastItem->intf->stats.SapIfOperState==OPER_STATE_UP)
  1184. bcastItem->perdEnum = NULL;
  1185. else // Nore that broadcast of the whole table is done
  1186. bcastItem->perdEnum = INVALID_HANDLE_VALUE;
  1187. }
  1188. }
  1189. if (bcastItem->intf->stats.SapIfOperState==OPER_STATE_STOPPING) {
  1190. INT i;
  1191. for (i=0; i<params.svrIdx; i++) {
  1192. PUTUSHORT (IPX_MAX_HOP_COUNT, &bcastItem->packet.Entries[i].HopCount);
  1193. }
  1194. }
  1195. periodic = TRUE;
  1196. }
  1197. else
  1198. periodic = FALSE;
  1199. if ((params.svrIdx<IPX_SAP_MAX_ENTRY)
  1200. && (bcastItem->intf->stats.SapIfOperState==OPER_STATE_UP)) {
  1201. if (bcastItem->delayedSvrCount==0)
  1202. bcastItem->delayedSendTime = GetTickCount ()+DelayChangeBroadcast*1000;
  1203. Trace (DEBUG_BCAST, "Checking for changed servers on interface: %d.",
  1204. params.intf->index);
  1205. params.localHopCount = IPX_MAX_HOP_COUNT+1;
  1206. EnumerateServers (bcastItem->chngEnum, SplitHorizonFilter, &params);
  1207. }
  1208. if ((params.svrIdx>0)
  1209. && (periodic
  1210. || (params.svrIdx==IPX_SAP_MAX_ENTRY)
  1211. || IsLater (GetTickCount (), bcastItem->delayedSendTime))) {
  1212. bcastItem->iow.io.cbBuffer = FIELD_OFFSET (SAP_BUFFER, Entries[params.svrIdx]);
  1213. PUTUSHORT (bcastItem->iow.io.cbBuffer, &bcastItem->packet.Length);
  1214. bcastItem->iow.io.adpt = bcastItem->intf->adapter.AdapterIndex;
  1215. bcastItem->delayedSvrCount = 0;
  1216. Trace (DEBUG_BCAST, "Broadcasting %d servers on interface: %d.",
  1217. params.svrIdx, params.intf->index);
  1218. EnqueueSendRequest (&bcastItem->iow.io);
  1219. }
  1220. else if (bcastItem->intf->stats.SapIfOperState==OPER_STATE_UP) {
  1221. // Nothing to send, go wait in the timer queue
  1222. bcastItem->delayedSvrCount = params.svrIdx;
  1223. if (bcastItem->delayedSvrCount>0) {
  1224. Trace (DEBUG_BCAST, "Delaying change broadcast on interface: %d (%d servers in the packet).",
  1225. params.intf->index, bcastItem->delayedSvrCount);
  1226. bcastItem->tmw.tm.dueTime = bcastItem->delayedSendTime;
  1227. }
  1228. else {
  1229. bcastItem->tmw.tm.dueTime = bcastItem->nextBcast;
  1230. Trace (DEBUG_BCAST, "Nothing to send, waiting for next broadcast time on interface: %d.",
  1231. params.intf->index);
  1232. }
  1233. AddLRTimerRequest (&bcastItem->tmw.tm);
  1234. }
  1235. else
  1236. // Interface is down or stopping and there are no more stuff to
  1237. // broadcast, -> go away
  1238. DeleteBcastItem (bcastItem);
  1239. }
  1240. BOOL
  1241. CheckBcastInterface (
  1242. PTM_PARAM_BLOCK tm,
  1243. PVOID context
  1244. ) {
  1245. PBCAST_ITEM bcastItem = CONTAINING_RECORD (tm, BCAST_ITEM, tmw.tm);
  1246. if (bcastItem->intf->stats.SapIfOperState!=OPER_STATE_UP)
  1247. return TRUE;
  1248. else if (bcastItem->intf->index!=PtrToUlong(context))
  1249. return TRUE;
  1250. else
  1251. return FALSE;
  1252. }
  1253. /*++
  1254. *******************************************************************
  1255. I n i t B c a s t I t e m
  1256. Routine Description:
  1257. Allocate and initialize broadcast item
  1258. Arguments:
  1259. intf - pointer to interface control block to send on
  1260. Return Value:
  1261. NO_ERROR - item was initialized and enqueued OK
  1262. other - operation failed (windows error code)
  1263. *******************************************************************
  1264. --*/
  1265. DWORD
  1266. InitBcastItem (
  1267. PINTERFACE_DATA intf
  1268. ) {
  1269. PBCAST_ITEM bcastItem;
  1270. DWORD status;
  1271. if (!AllocateWorker (bcastItem, BCAST_ITEM)) {
  1272. Trace (DEBUG_FAILURES,
  1273. "File: %s, line %ld. Could not allocate broadcast item (gle:%ld).",
  1274. __FILE__, __LINE__, GetLastError ());
  1275. return ERROR_NOT_ENOUGH_MEMORY;
  1276. }
  1277. bcastItem->chngEnum = CreateListEnumerator (
  1278. SDB_CHANGE_QUEUE_LINK,
  1279. 0xFFFF,
  1280. NULL,
  1281. Routing
  1282. ? INVALID_INTERFACE_INDEX
  1283. : INTERNAL_INTERFACE_INDEX,
  1284. 0xFFFFFFFF,
  1285. SDB_DISABLED_NODE_FLAG);
  1286. if (bcastItem->chngEnum==NULL) {
  1287. status = GetLastError ();
  1288. DeallocateWorker (bcastItem);
  1289. return status;
  1290. }
  1291. AcquireInterfaceReference (intf);
  1292. bcastItem->intf = intf;
  1293. bcastItem->iow.worker = ProcessBcastIOItem;
  1294. bcastItem->iow.io.buffer = (PUCHAR)&bcastItem->packet;
  1295. bcastItem->tmw.worker = ProcessBcastTMItem;
  1296. bcastItem->tmw.tm.ExpirationCheckProc = CheckBcastInterface;
  1297. bcastItem->perdEnum = NULL;
  1298. bcastItem->delayedSvrCount = 0;
  1299. SetupIpxSapPacket(&bcastItem->packet, SAP_GENERAL_RESP,
  1300. bcastItem->intf->adapter.Network,
  1301. IPX_BCAST_NODE,
  1302. IPX_SAP_SOCKET);
  1303. bcastItem->nextBcast = GetTickCount ();
  1304. Trace (DEBUG_BCAST, "Generated broadcast item %08lx for interface %d.",
  1305. bcastItem, bcastItem->intf->index);
  1306. DoBroadcast (bcastItem);
  1307. return NO_ERROR;
  1308. }
  1309. /*++
  1310. *******************************************************************
  1311. P r o c e s s B c a s t I O I t e m
  1312. Routine Description:
  1313. Processes broadcast work item that just completed send
  1314. Arguments:
  1315. worker - pointer to work item to process
  1316. Return Value:
  1317. None
  1318. *******************************************************************
  1319. --*/
  1320. VOID APIENTRY
  1321. ProcessBcastIOItem (
  1322. PVOID worker
  1323. ) {
  1324. PBCAST_ITEM bcastItem = CONTAINING_RECORD (worker, BCAST_ITEM, iow.worker);
  1325. ULONG curTime = GetTickCount ();
  1326. Trace (DEBUG_BCAST, "Processing broadcast io item for interface: %d.",
  1327. bcastItem->intf->index);
  1328. // Make sure interface is still up
  1329. if (bcastItem->iow.io.status==NO_ERROR) {
  1330. InterlockedIncrement (&bcastItem->intf->stats.SapIfOutputPackets);
  1331. // Make sure we do not send periodic broadcast packets to fast
  1332. if ((curTime-bcastItem->iow.io.compTime<IPX_SAP_INTERPACKET_GAP)
  1333. && (bcastItem->perdEnum!=NULL)) {
  1334. bcastItem->tmw.tm.dueTime = bcastItem->iow.io.compTime
  1335. + IPX_SAP_INTERPACKET_GAP;
  1336. AddHRTimerRequest (&bcastItem->tmw.tm);
  1337. }
  1338. else
  1339. DoBroadcast (bcastItem);
  1340. }
  1341. else if (bcastItem->intf->stats.SapIfOperState==OPER_STATE_UP) {
  1342. // Last sent io failed, we better wait before sending next one
  1343. bcastItem->tmw.tm.dueTime = curTime+SAP_ERROR_COOL_OFF_TIME;
  1344. AddLRTimerRequest (&bcastItem->tmw.tm);
  1345. }
  1346. else
  1347. // Interface is stopping or down on error, go away
  1348. DeleteBcastItem (bcastItem);
  1349. }
  1350. /*++
  1351. *******************************************************************
  1352. P r o c e s s B c a s t T M I t e m
  1353. Routine Description:
  1354. Processes broadcast work item that just completed wait in timer queue
  1355. Arguments:
  1356. worker - pointer to work item to process
  1357. Return Value:
  1358. None
  1359. *******************************************************************
  1360. --*/
  1361. VOID APIENTRY
  1362. ProcessBcastTMItem (
  1363. PVOID worker
  1364. ) {
  1365. PBCAST_ITEM bcastItem = CONTAINING_RECORD (worker, BCAST_ITEM, tmw.worker);
  1366. Trace (DEBUG_BCAST, "Processing broadcast tm item for interface: %d.",
  1367. bcastItem->intf->index);
  1368. if ((bcastItem->intf->stats.SapIfOperState==OPER_STATE_UP)
  1369. || (bcastItem->intf->stats.SapIfOperState==OPER_STATE_STOPPING))
  1370. DoBroadcast (bcastItem);
  1371. else // Interface is down, go away
  1372. DeleteBcastItem (bcastItem);
  1373. }
  1374. /*++
  1375. *******************************************************************
  1376. I n i t S r e q I t e m
  1377. Routine Description:
  1378. Allocate and initialize send request item (send SAP request on interface)
  1379. Arguments:
  1380. intf - pointer to interface control block to send on
  1381. Return Value:
  1382. NO_ERROR - item was initialized and enqueued OK
  1383. other - operation failed (windows error code)
  1384. *******************************************************************
  1385. --*/
  1386. DWORD
  1387. InitSreqItem (
  1388. PINTERFACE_DATA intf
  1389. ) {
  1390. PSREQ_ITEM sreqItem;
  1391. if (!AllocateWorker (sreqItem, SREQ_ITEM)) {
  1392. Trace (DEBUG_FAILURES,
  1393. "File: %s, line %ld. Could not allocate send request item (gle:%ld.",
  1394. __FILE__, __LINE__, GetLastError ());
  1395. return ERROR_NOT_ENOUGH_MEMORY;
  1396. }
  1397. AcquireInterfaceReference (intf);
  1398. sreqItem->intf = intf;
  1399. sreqItem->iow.worker = ProcessSreqItem;
  1400. sreqItem->iow.io.buffer = (PUCHAR)&sreqItem->packet;
  1401. SetupIpxSapPacket(&sreqItem->packet, SAP_GENERAL_REQ,
  1402. sreqItem->intf->adapter.Network,
  1403. IPX_BCAST_NODE,
  1404. IPX_SAP_SOCKET);
  1405. sreqItem->packet.Entries[0].Type = 0xFFFF;
  1406. sreqItem->iow.io.cbBuffer = FIELD_OFFSET (SAP_BUFFER, Entries[0].Type)
  1407. +sizeof (sreqItem->packet.Entries[0].Type);
  1408. PUTUSHORT (sreqItem->iow.io.cbBuffer, &sreqItem->packet.Length);
  1409. sreqItem->iow.io.adpt = sreqItem->intf->adapter.AdapterIndex;
  1410. Trace (DEBUG_SREQ, "Generated general request item: %08lx on interface: %d.",
  1411. sreqItem, sreqItem->intf->index);
  1412. if ((sreqItem->intf->stats.SapIfOperState==OPER_STATE_UP)
  1413. && (OperationalState==OPER_STATE_UP)) {
  1414. EnqueueSendRequest (&sreqItem->iow.io);
  1415. return NO_ERROR;
  1416. }
  1417. else {
  1418. // Interface got changed or deleted
  1419. Trace (DEBUG_SREQ,
  1420. "Freing general request item: %08lx for changed or deleted interface %ld.",
  1421. sreqItem, sreqItem->intf->index);
  1422. ReleaseInterfaceReference (sreqItem->intf);
  1423. DeallocateWorker (sreqItem);
  1424. return ERROR_INVALID_HANDLE;
  1425. }
  1426. }
  1427. /*++
  1428. *******************************************************************
  1429. P r o c e s s S r e q I t e m
  1430. Routine Description:
  1431. Processes send request work item that just completed io
  1432. Arguments:
  1433. worker - pointer to work item to process
  1434. Return Value:
  1435. None
  1436. *******************************************************************
  1437. --*/
  1438. VOID APIENTRY
  1439. ProcessSreqItem (
  1440. PVOID worker
  1441. ) {
  1442. PSREQ_ITEM sreqItem = CONTAINING_RECORD (worker, SREQ_ITEM, iow.worker);
  1443. if (sreqItem->iow.io.status==NO_ERROR)
  1444. InterlockedIncrement (&sreqItem->intf->stats.SapIfOutputPackets);
  1445. Trace (DEBUG_SREQ, "Freeing general request item %08lx.", sreqItem);
  1446. // Just release all resources
  1447. ReleaseInterfaceReference (sreqItem->intf);
  1448. DeallocateWorker (sreqItem);
  1449. }
  1450. /*++
  1451. *******************************************************************
  1452. I n i t L P C I t e m
  1453. Routine Description:
  1454. Allocate and initialize LPC work item
  1455. Arguments:
  1456. None
  1457. Return Value:
  1458. NO_ERROR - item was initialized and enqueued OK
  1459. other - operation failed (windows error code)
  1460. *******************************************************************
  1461. --*/
  1462. DWORD
  1463. InitLPCItem (
  1464. void
  1465. ) {
  1466. PLPC_ITEM lpcItem;
  1467. if (!AllocateWorker (lpcItem, LPC_ITEM)) {
  1468. Trace (DEBUG_FAILURES, "File: %s, line %ld. Could not allocate lpc item (gle:%ld.",
  1469. __FILE__, __LINE__, GetLastError ());
  1470. return ERROR_NOT_ENOUGH_MEMORY;
  1471. }
  1472. lpcItem->lpcw.lpc.request = &lpcItem->request;
  1473. lpcItem->lpcw.worker = ProcessLPCItem;
  1474. Trace (DEBUG_LPCREQ, "Generated lpc request item %08lx.", lpcItem);
  1475. // Posts request and awaits completion
  1476. return ProcessLPCRequests (&lpcItem->lpcw.lpc);
  1477. }
  1478. /*++
  1479. *******************************************************************
  1480. P r o c e s s L P C I t e m
  1481. Routine Description:
  1482. Processes LPC request and sends reply
  1483. Arguments:
  1484. worker - pointer to work item to process
  1485. Return Value:
  1486. None
  1487. *******************************************************************
  1488. --*/
  1489. VOID APIENTRY
  1490. ProcessLPCItem (
  1491. PVOID worker
  1492. ) {
  1493. PLPC_ITEM lpcItem = CONTAINING_RECORD (worker, LPC_ITEM, lpcw.worker);
  1494. IPX_SERVER_ENTRY_P server;
  1495. NWSAP_REPLY_MESSAGE reply;
  1496. DWORD status;
  1497. BOOL newServer;
  1498. Trace (DEBUG_LPCREQ, "Processing lpc request for client: %08lx.",
  1499. lpcItem->lpcw.lpc.client);
  1500. if (lpcItem->lpcw.lpc.client==NULL) {
  1501. Trace (DEBUG_LPCREQ, "Freeing lpc item %08lx.", lpcItem);
  1502. DeallocateWorker (lpcItem);
  1503. return;
  1504. }
  1505. switch (lpcItem->request.MessageType) {
  1506. case NWSAP_LPCMSG_ADDADVERTISE:
  1507. server.Type = lpcItem->request.Message.AdvApi.ServerType;
  1508. IpxNameCpy (server.Name, lpcItem->request.Message.AdvApi.ServerName);
  1509. IpxAddrCpy (&server, (PIPX_ADDRESS_BLOCK)lpcItem->request.Message.AdvApi.ServerAddr);
  1510. // If net or node number are not set, use internal network
  1511. // parameters that we obtained from the adapter
  1512. if ((IpxNetCmp (server.Network, IPX_INVALID_NET)==0)
  1513. || (IpxNodeCmp (server.Node, IPX_INVALID_NODE)==0)) {
  1514. IpxNetCpy (server.Network, INTERNAL_IF_NET);
  1515. IpxNodeCpy (server.Node, INTERNAL_IF_NODE);
  1516. }
  1517. server.HopCount = 0;
  1518. status = UpdateServer (&server,
  1519. INTERNAL_INTERFACE_INDEX,
  1520. IPX_PROTOCOL_LOCAL,
  1521. INFINITE,
  1522. IPX_BCAST_NODE,
  1523. lpcItem->request.Message.AdvApi.RespondNearest
  1524. ? 0
  1525. : SDB_DONT_RESPOND_NODE_FLAG,
  1526. &newServer);
  1527. switch (status) {
  1528. case NO_ERROR:
  1529. if (newServer)
  1530. reply.Error = SAPRETURN_SUCCESS;
  1531. else
  1532. reply.Error = SAPRETURN_EXISTS;
  1533. IpxAddrCpy ((PIPX_ADDRESS_BLOCK)reply.Message.AdvApi.ServerAddr, &server);
  1534. Trace (DEBUG_LPCREQ, "\t%s server: type %04x, name %.48s.",
  1535. newServer ? "added" : "updated",
  1536. server.Type, server.Name);
  1537. break;
  1538. case ERROR_NOT_ENOUGH_MEMORY:
  1539. default:
  1540. reply.Error = SAPRETURN_NOMEMORY;
  1541. break;
  1542. }
  1543. break;
  1544. case NWSAP_LPCMSG_REMOVEADVERTISE:
  1545. server.Type = lpcItem->request.Message.AdvApi.ServerType;
  1546. IpxNameCpy (server.Name, lpcItem->request.Message.AdvApi.ServerName);
  1547. IpxAddrCpy (&server, (PIPX_ADDRESS_BLOCK)lpcItem->request.Message.AdvApi.ServerAddr);
  1548. // If net or node number are not set, use internal network
  1549. // parameters that we obtained from the adapter
  1550. if ((IpxNetCmp (server.Network, IPX_INVALID_NET)==0)
  1551. || (IpxNodeCmp (server.Node, IPX_INVALID_NODE)==0)) {
  1552. IpxNetCpy (server.Network, INTERNAL_IF_NET);
  1553. IpxNodeCpy (server.Node, INTERNAL_IF_NODE);
  1554. }
  1555. server.HopCount = IPX_MAX_HOP_COUNT;
  1556. Trace (DEBUG_LPCREQ, "About to call UpdateServer because of NWSAP_LPCMSG_REMOVEADVERTISE");
  1557. status = UpdateServer (&server,
  1558. INTERNAL_INTERFACE_INDEX,
  1559. IPX_PROTOCOL_LOCAL,
  1560. INFINITE,
  1561. IPX_BCAST_NODE,
  1562. 0,
  1563. &newServer);
  1564. switch (status) {
  1565. case NO_ERROR:
  1566. if (newServer)
  1567. reply.Error = SAPRETURN_NOTEXIST;
  1568. else
  1569. reply.Error = SAPRETURN_SUCCESS;
  1570. Trace (DEBUG_LPCREQ, "\t%s server: type %04x, name %.48s.",
  1571. newServer ? "already gone" : "deleted",
  1572. server.Type, server.Name);
  1573. break;
  1574. case ERROR_NOT_ENOUGH_MEMORY:
  1575. default:
  1576. reply.Error = SAPRETURN_NOMEMORY;
  1577. break;
  1578. }
  1579. break;
  1580. case NWSAP_LPCMSG_GETOBJECTID:
  1581. if (QueryServer(
  1582. lpcItem->request.Message.BindLibApi.ObjectType,
  1583. lpcItem->request.Message.BindLibApi.ObjectName,
  1584. NULL,
  1585. NULL,
  1586. NULL,
  1587. &reply.Message.BindLibApi.ObjectID)) {
  1588. // Trace (DEBUG_ENTRIES, "\tgot id %0lx for server: type %04x, name %.48s.",
  1589. // reply.Message.BindLibApi.ObjectID,
  1590. // lpcItem->request.Message.BindLibApi.ObjectType,
  1591. // lpcItem->request.Message.BindLibApi.ObjectName);
  1592. reply.Message.BindLibApi.ObjectID |= BINDLIB_NCP_SAP;
  1593. reply.Error = SAPRETURN_SUCCESS;
  1594. }
  1595. else {
  1596. Trace (DEBUG_LPCREQ, "\tno server: type %04x, name %.48s.",
  1597. lpcItem->request.Message.BindLibApi.ObjectType,
  1598. lpcItem->request.Message.BindLibApi.ObjectName);
  1599. switch (GetLastError ()) {
  1600. case NO_ERROR:
  1601. reply.Error = SAPRETURN_NOTEXIST;
  1602. break;
  1603. case ERROR_NOT_ENOUGH_MEMORY:
  1604. default:
  1605. reply.Error = SAPRETURN_NOMEMORY;
  1606. break;
  1607. }
  1608. }
  1609. break;
  1610. case NWSAP_LPCMSG_GETOBJECTNAME:
  1611. if (((lpcItem->request.Message.BindLibApi.ObjectID
  1612. & BINDLIB_NCP_SAP)==BINDLIB_NCP_SAP)
  1613. && (lpcItem->request.Message.BindLibApi.ObjectID
  1614. <BINDLIB_NCP_MAX_SAP)) {
  1615. reply.Message.BindLibApi.ObjectID =
  1616. lpcItem->request.Message.BindLibApi.ObjectID
  1617. & SDB_OBJECT_ID_MASK;
  1618. if (GetServerFromID(
  1619. reply.Message.BindLibApi.ObjectID,
  1620. &server,
  1621. NULL,
  1622. NULL)) {
  1623. reply.Error = SAPRETURN_SUCCESS;
  1624. reply.Message.BindLibApi.ObjectID |= BINDLIB_NCP_SAP;
  1625. reply.Message.BindLibApi.ObjectType = server.Type;
  1626. IpxNameCpy (reply.Message.BindLibApi.ObjectName, server.Name);
  1627. IpxAddrCpy ((PIPX_ADDRESS_BLOCK)reply.Message.BindLibApi.ObjectAddr, &server);
  1628. // Trace (DEBUG_ENTRIES,
  1629. // "\tgot server: type %04x, name %.48s from id %0lx.",
  1630. // reply.Message.BindLibApi.ObjectType,
  1631. // reply.Message.BindLibApi.ObjectName,
  1632. // lpcItem->request.Message.BindLibApi.ObjectID);
  1633. }
  1634. else {
  1635. switch (GetLastError ()) {
  1636. case NO_ERROR:
  1637. Trace (DEBUG_LPCREQ, "\tno server for id %0lx.",
  1638. lpcItem->request.Message.BindLibApi.ObjectID);
  1639. reply.Error = SAPRETURN_NOTEXIST;
  1640. break;
  1641. case ERROR_NOT_ENOUGH_MEMORY:
  1642. default:
  1643. reply.Error = SAPRETURN_NOMEMORY;
  1644. break;
  1645. }
  1646. }
  1647. }
  1648. else {
  1649. Trace (DEBUG_LPCREQ, "\tInvalid object id in get name request %0lx.",
  1650. lpcItem->request.Message.BindLibApi.ObjectID);
  1651. reply.Error = SAPRETURN_NOTEXIST;
  1652. }
  1653. break;
  1654. case NWSAP_LPCMSG_SEARCH:
  1655. if ((lpcItem->request.Message.BindLibApi.ObjectID
  1656. == SDB_INVALID_OBJECT_ID)
  1657. || (((lpcItem->request.Message.BindLibApi.ObjectID
  1658. & BINDLIB_NCP_SAP)==BINDLIB_NCP_SAP)
  1659. && (lpcItem->request.Message.BindLibApi.ObjectID
  1660. <BINDLIB_NCP_MAX_SAP))) {
  1661. if (lpcItem->request.Message.BindLibApi.ObjectID
  1662. == SDB_INVALID_OBJECT_ID)
  1663. reply.Message.BindLibApi.ObjectID = SDB_INVALID_OBJECT_ID;
  1664. else
  1665. reply.Message.BindLibApi.ObjectID =
  1666. lpcItem->request.Message.BindLibApi.ObjectID
  1667. & SDB_OBJECT_ID_MASK;
  1668. if (GetNextServerFromID (
  1669. &reply.Message.BindLibApi.ObjectID,
  1670. lpcItem->request.Message.BindLibApi.ScanType,
  1671. &server,
  1672. NULL,
  1673. NULL)) {
  1674. reply.Message.BindLibApi.ObjectID |= BINDLIB_NCP_SAP;
  1675. reply.Error = SAPRETURN_SUCCESS;
  1676. reply.Message.BindLibApi.ObjectType = server.Type;
  1677. IpxNameCpy (reply.Message.BindLibApi.ObjectName, server.Name);
  1678. IpxAddrCpy ((PIPX_ADDRESS_BLOCK)reply.Message.BindLibApi.ObjectAddr, &server);
  1679. // Trace (DEBUG_ENTRIES,
  1680. // "\tgot next server: type %04x, name %.48s, id %0lx from id %0lx.",
  1681. // reply.Message.BindLibApi.ObjectType,
  1682. // reply.Message.BindLibApi.ObjectName,
  1683. // reply.Message.BindLibApi.ObjectID,
  1684. // lpcItem->request.Message.BindLibApi.ObjectID);
  1685. }
  1686. else {
  1687. switch (GetLastError ()) {
  1688. case NO_ERROR:
  1689. Trace (DEBUG_LPCREQ, "\tno next server for id %0lx.",
  1690. lpcItem->request.Message.BindLibApi.ObjectID);
  1691. reply.Error = SAPRETURN_NOTEXIST;
  1692. break;
  1693. case ERROR_NOT_ENOUGH_MEMORY:
  1694. default:
  1695. reply.Error = SAPRETURN_NOMEMORY;
  1696. break;
  1697. }
  1698. }
  1699. }
  1700. else {
  1701. Trace (DEBUG_LPCREQ, "\tInvalid object id in get next request %0lx.",
  1702. lpcItem->request.Message.BindLibApi.ObjectID);
  1703. reply.Error = SAPRETURN_NOTEXIST;
  1704. }
  1705. break;
  1706. default:
  1707. Trace (DEBUG_FAILURES, "Got unknown LPC SAP msg: %d.",
  1708. lpcItem->request.MessageType );
  1709. reply.Error = 1;
  1710. break;
  1711. }
  1712. SendLPCReply (lpcItem->lpcw.lpc.client, &lpcItem->request, &reply);
  1713. Trace (DEBUG_LPCREQ, "Freeing lpc item %08lx.", lpcItem);
  1714. DeallocateWorker (lpcItem);
  1715. }
  1716. /*++
  1717. *******************************************************************
  1718. I n i t G n e a r I t e m
  1719. Routine Description:
  1720. Allocate and initialize GETNEAREST response work item
  1721. Arguments:
  1722. intf - pointer to interface control block to send on
  1723. svrType - type of servers to put in response packet
  1724. dst - where to send the response packet
  1725. Return Value:
  1726. NO_ERROR - item was initialized and enqueued OK
  1727. other - operation failed (windows error code)
  1728. *******************************************************************
  1729. --*/
  1730. DWORD
  1731. InitGnearItem (
  1732. PINTERFACE_DATA intf,
  1733. USHORT svrType,
  1734. PIPX_ADDRESS_BLOCK dst
  1735. ) {
  1736. DWORD status;
  1737. GN_FILTER_PARAMS params;
  1738. HANDLE hEnum;
  1739. PGNEAR_ITEM gnearItem;
  1740. if (!AllocateWorker (gnearItem, GNEAR_ITEM)) {
  1741. Trace (DEBUG_FAILURES,
  1742. "File: %s, line %ld. Could not allocate get nearest response item (gle:%ld.",
  1743. __FILE__, __LINE__, GetLastError ());
  1744. return ERROR_NOT_ENOUGH_MEMORY;
  1745. }
  1746. AcquireInterfaceReference (intf);
  1747. gnearItem->intf = intf;
  1748. Trace (DEBUG_GET_NEAREST,
  1749. "Generated get nearest response item %08lx for server of type: %04x on interface: %ld.",
  1750. gnearItem, svrType, intf->index);
  1751. hEnum = CreateListEnumerator (
  1752. SDB_TYPE_LIST_LINK,
  1753. svrType,
  1754. NULL,
  1755. Routing
  1756. ? INVALID_INTERFACE_INDEX
  1757. : INTERNAL_INTERFACE_INDEX,
  1758. 0xFFFFFFFF,
  1759. SDB_MAIN_NODE_FLAG);
  1760. if (hEnum==NULL) {
  1761. status = GetLastError ();
  1762. ReleaseInterfaceReference (intf);
  1763. DeallocateWorker (gnearItem);
  1764. return status;
  1765. }
  1766. params.found = FALSE;
  1767. params.intf = gnearItem->intf;
  1768. params.packet = &gnearItem->packet;
  1769. params.localHopCount = IPX_MAX_HOP_COUNT-1;
  1770. EnumerateServers (hEnum, GetNearestFilter, (LPVOID)&params);
  1771. DeleteListEnumerator (hEnum);
  1772. if (params.found) {
  1773. gnearItem->iow.worker = ProcessGnearItem;
  1774. gnearItem->iow.io.buffer = (PUCHAR)&gnearItem->packet;
  1775. gnearItem->intf = intf;
  1776. SetupIpxSapPacket(&gnearItem->packet, SAP_GET_NEAREST_RESP,
  1777. dst->Network, dst->Node, dst->Socket);
  1778. gnearItem->iow.io.cbBuffer = FIELD_OFFSET (SAP_BUFFER, Entries[1]);
  1779. PUTUSHORT (gnearItem->iow.io.cbBuffer, &gnearItem->packet.Length);
  1780. gnearItem->iow.io.adpt = gnearItem->intf->adapter.AdapterIndex;
  1781. Trace (DEBUG_GET_NEAREST,
  1782. "Sending get nearest reply (type %04x, name:%.48s, hops:%d) on interface %ld.",
  1783. GETUSHORT (&gnearItem->packet.Entries[0].Type),
  1784. gnearItem->packet.Entries[0].Name,
  1785. GETUSHORT (&gnearItem->packet.Entries[0].HopCount),
  1786. intf->index);
  1787. if ((gnearItem->intf->stats.SapIfOperState==OPER_STATE_UP)
  1788. && (OperationalState==OPER_STATE_UP)) {
  1789. EnqueueSendRequest (&gnearItem->iow.io);
  1790. return NO_ERROR;
  1791. }
  1792. }
  1793. Trace (DEBUG_GET_NEAREST,
  1794. "Freeing get nearest response item %08lx (nothing to reply) for interface %ld.",
  1795. gnearItem, gnearItem->intf->index);
  1796. ReleaseInterfaceReference (gnearItem->intf);
  1797. DeallocateWorker (gnearItem);
  1798. return NO_ERROR;
  1799. }
  1800. /*++
  1801. *******************************************************************
  1802. P r o c e s s G n e a r I t e m
  1803. Routine Description:
  1804. Processes completed GETNEAREST work item
  1805. Arguments:
  1806. worker - pointer to work item to process
  1807. Return Value:
  1808. None
  1809. *******************************************************************
  1810. --*/
  1811. VOID APIENTRY
  1812. ProcessGnearItem (
  1813. PVOID worker
  1814. ) {
  1815. PGNEAR_ITEM gnearItem = CONTAINING_RECORD (worker, GNEAR_ITEM, iow.worker);
  1816. if (gnearItem->iow.io.status==NO_ERROR)
  1817. InterlockedIncrement (&gnearItem->intf->stats.SapIfOutputPackets);
  1818. Trace (DEBUG_GET_NEAREST, "Freeing get nearest response item %08lx for interface %ld.",
  1819. gnearItem, gnearItem->intf->index);
  1820. ReleaseInterfaceReference (gnearItem->intf);
  1821. DeallocateWorker (gnearItem);
  1822. }
  1823. BOOL
  1824. CheckInterfaceDown (
  1825. PTM_PARAM_BLOCK tm,
  1826. PVOID context
  1827. ) {
  1828. PTREQ_ITEM treqItem = CONTAINING_RECORD (tm, TREQ_ITEM, tmw.tm);
  1829. return treqItem->intf->stats.SapIfOperState!=OPER_STATE_UP;
  1830. }
  1831. /*++
  1832. *******************************************************************
  1833. I n i t T r e q I t e m
  1834. Routine Description:
  1835. Allocate and initialize triggered request item (send SAP request on interface
  1836. and wait for responces to arrive)
  1837. Arguments:
  1838. intf - pointer to interface control block to send on
  1839. Return Value:
  1840. NO_ERROR - item was initialized and enqueued OK
  1841. other - operation failed (windows error code)
  1842. *******************************************************************
  1843. --*/
  1844. DWORD
  1845. InitTreqItem (
  1846. PINTERFACE_DATA intf
  1847. ) {
  1848. PTREQ_ITEM treqItem;
  1849. HANDLE enumHdl;
  1850. enumHdl = CreateListEnumerator (
  1851. SDB_INTF_LIST_LINK,
  1852. 0xFFFF,
  1853. NULL,
  1854. intf->index,
  1855. IPX_PROTOCOL_SAP,
  1856. SDB_DISABLED_NODE_FLAG);
  1857. if (enumHdl==NULL)
  1858. return GetLastError ();
  1859. EnumerateServers (enumHdl, DeleteAllServersCB, enumHdl);
  1860. DeleteListEnumerator (enumHdl);
  1861. if (!AllocateWorker (treqItem, TREQ_ITEM)) {
  1862. Trace (DEBUG_FAILURES,
  1863. "File: %s, line %ld. Could not allocate triggered request item (gle:%ld).",
  1864. __FILE__, __LINE__, GetLastError ());
  1865. return ERROR_NOT_ENOUGH_MEMORY;
  1866. }
  1867. AcquireInterfaceReference (intf);
  1868. treqItem->intf = intf;
  1869. treqItem->iow.worker = ProcessTreqIOItem;
  1870. treqItem->iow.io.buffer = (PUCHAR)&treqItem->packet;
  1871. treqItem->tmw.worker = ProcessTreqTMItem;
  1872. treqItem->tmw.tm.ExpirationCheckProc = CheckInterfaceDown;
  1873. SetupIpxSapPacket(&treqItem->packet, SAP_GENERAL_REQ,
  1874. treqItem->intf->adapter.Network,
  1875. IPX_BCAST_NODE,
  1876. IPX_SAP_SOCKET);
  1877. treqItem->packet.Entries[0].Type = 0xFFFF;
  1878. treqItem->iow.io.cbBuffer = FIELD_OFFSET (SAP_BUFFER, Entries[0].Type)
  1879. +sizeof (treqItem->packet.Entries[0].Type);
  1880. PUTUSHORT (treqItem->iow.io.cbBuffer, &treqItem->packet.Length);
  1881. treqItem->iow.io.adpt = treqItem->intf->adapter.AdapterIndex;
  1882. treqItem->listenSave = treqItem->intf->info.Listen;
  1883. treqItem->intf->info.Listen = ADMIN_STATE_ENABLED;
  1884. treqItem->intervalSave = treqItem->intf->info.PeriodicUpdateInterval;
  1885. treqItem->intf->info.PeriodicUpdateInterval = MAXULONG;
  1886. treqItem->resend = 0;
  1887. treqItem->pktCount = treqItem->intf->stats.SapIfInputPackets;
  1888. Trace (DEBUG_TREQ, "Generated triggered request item %08lx on interface %d.",
  1889. treqItem, treqItem->intf->index);
  1890. if ((treqItem->intf->stats.SapIfOperState==OPER_STATE_UP)
  1891. && (OperationalState==OPER_STATE_UP)) {
  1892. EnqueueSendRequest (&treqItem->iow.io);
  1893. return NO_ERROR;
  1894. }
  1895. else {
  1896. // Interface got changed or deleted
  1897. Trace (DEBUG_TREQ,
  1898. "Freeing triggered request item %08lx for changed or deleted interface %ld.",
  1899. treqItem, treqItem->intf->index);
  1900. treqItem->intf->info.Listen = treqItem->listenSave;
  1901. treqItem->intf->info.PeriodicUpdateInterval = treqItem->intervalSave;
  1902. ReleaseInterfaceReference (treqItem->intf);
  1903. DeallocateWorker (treqItem);
  1904. return ERROR_CAN_NOT_COMPLETE;
  1905. }
  1906. }
  1907. /*++
  1908. *******************************************************************
  1909. R e t u r n U p d a t e R e s u l t
  1910. Routine Description:
  1911. Sets up parameter block and enquues results of update to
  1912. async result queue
  1913. Arguments:
  1914. treqItem - pointer to triggered request item that has completed the update
  1915. status - result of update performted by treqItem
  1916. Return Value:
  1917. NO_ERROR - item was initialized and enqueued OK
  1918. other - operation failed (windows error code)
  1919. *******************************************************************
  1920. --*/
  1921. VOID
  1922. ReturnUpdateResult (
  1923. PTREQ_ITEM treqItem,
  1924. DWORD status
  1925. ) {
  1926. Trace (DEBUG_TREQ, "Reporting triggered request result (res:%d, count:%d)"
  1927. " for interface: %d.",
  1928. status,
  1929. treqItem->pktCount,
  1930. treqItem->intf->index);
  1931. treqItem->ar.event = UPDATE_COMPLETE;
  1932. treqItem->ar.message.UpdateCompleteMessage.InterfaceIndex
  1933. = treqItem->intf->index;
  1934. treqItem->ar.message.UpdateCompleteMessage.UpdateType = DEMAND_UPDATE_SERVICES;
  1935. treqItem->ar.message.UpdateCompleteMessage.UpdateStatus = status;
  1936. treqItem->ar.freeRsltCB = &FreeTreqItem;
  1937. treqItem->intf->info.Listen = treqItem->listenSave;
  1938. treqItem->intf->info.PeriodicUpdateInterval = treqItem->intervalSave;
  1939. ReleaseInterfaceReference (treqItem->intf);
  1940. EnqueueResult (&treqItem->ar);
  1941. }
  1942. /*++
  1943. *******************************************************************
  1944. P r o c e s s T r e q I O I t e m
  1945. Routine Description:
  1946. Processes triggered request work item that just completed io
  1947. Arguments:
  1948. worker - pointer to work item to process
  1949. Return Value:
  1950. None
  1951. *******************************************************************
  1952. --*/
  1953. VOID APIENTRY
  1954. ProcessTreqIOItem (
  1955. PVOID worker
  1956. ) {
  1957. PTREQ_ITEM treqItem = CONTAINING_RECORD (worker, TREQ_ITEM, iow.worker);
  1958. HANDLE hEnum;
  1959. if (treqItem->iow.io.status==NO_ERROR)
  1960. InterlockedIncrement (&treqItem->intf->stats.SapIfOutputPackets);
  1961. Trace (DEBUG_TREQ, "Processing triggered request io item for interface: %d.",
  1962. treqItem->intf->index);
  1963. if ((treqItem->intf->stats.SapIfOperState==OPER_STATE_UP)
  1964. && (OperationalState==OPER_STATE_UP)) {
  1965. treqItem->resend += 1;
  1966. treqItem->tmw.tm.dueTime = GetTickCount ()
  1967. + TriggeredUpdateCheckInterval*1000;
  1968. AddLRTimerRequest (&treqItem->tmw.tm);
  1969. return;
  1970. }
  1971. ReturnUpdateResult (treqItem, ERROR_CAN_NOT_COMPLETE);
  1972. }
  1973. /*++
  1974. *******************************************************************
  1975. P r o c e s s T r e q T M I t e m
  1976. Routine Description:
  1977. Processes triggered request work item that just completed timer wait
  1978. Arguments:
  1979. worker - pointer to work item to process
  1980. Return Value:
  1981. None
  1982. *******************************************************************
  1983. --*/
  1984. VOID APIENTRY
  1985. ProcessTreqTMItem (
  1986. PVOID worker
  1987. ) {
  1988. PTREQ_ITEM treqItem = CONTAINING_RECORD (worker, TREQ_ITEM, tmw.worker);
  1989. ULONG count = treqItem->intf->stats.SapIfInputPackets;
  1990. Trace (DEBUG_TREQ, "Processing triggered request tm item for interface: %d.",
  1991. treqItem->intf->index);
  1992. if ((treqItem->intf->stats.SapIfOperState==OPER_STATE_UP)
  1993. && (OperationalState==OPER_STATE_UP)) {
  1994. if (treqItem->pktCount!=count) {
  1995. Trace (DEBUG_TREQ,
  1996. "\t%d more packets received during last check period.",
  1997. treqItem->intf->stats.SapIfInputPackets - treqItem->pktCount);
  1998. treqItem->pktCount = count;
  1999. treqItem->tmw.tm.dueTime = GetTickCount ()
  2000. + TriggeredUpdateCheckInterval*1000;
  2001. AddLRTimerRequest (&treqItem->tmw.tm);
  2002. }
  2003. else if (treqItem->resend<MaxTriggeredUpdateRequests) {
  2004. Trace (DEBUG_TREQ,
  2005. "\tresending update request (%d request).",
  2006. treqItem->resend+1);
  2007. treqItem->iow.io.cbBuffer = FIELD_OFFSET (SAP_BUFFER, Entries[0].Type)
  2008. +sizeof (treqItem->packet.Entries[0].Type);
  2009. EnqueueSendRequest (&treqItem->iow.io);
  2010. }
  2011. else
  2012. ReturnUpdateResult (treqItem, NO_ERROR);
  2013. return;
  2014. }
  2015. ReturnUpdateResult (treqItem, ERROR_CAN_NOT_COMPLETE);
  2016. }
  2017. /*++
  2018. *******************************************************************
  2019. P r o c e s s T r e q A R I t e m
  2020. Routine Description:
  2021. Processes triggered request work item that was reported to client
  2022. in result queue
  2023. Arguments:
  2024. worker - pointer to work item to process
  2025. Return Value:
  2026. None
  2027. *******************************************************************
  2028. --*/
  2029. VOID
  2030. FreeTreqItem (
  2031. PAR_PARAM_BLOCK rslt
  2032. ) {
  2033. PTREQ_ITEM treqItem = CONTAINING_RECORD (rslt, TREQ_ITEM, ar);
  2034. Trace (DEBUG_TREQ, "Freeing triggered request item %08lx.", treqItem);
  2035. DeallocateWorker (treqItem);
  2036. }
  2037. /*++
  2038. *******************************************************************
  2039. S a p B u i l d I n t e r n a l U p d a t e L i s t F i l t e r
  2040. Routine Description:
  2041. Server enumeration callback proc createas a list of local servers
  2042. that need to have their internal network numbers updated.
  2043. Arguments:
  2044. CBParam - pointer to a list of SERVER_INTERNAL_UPDATE_NODE's
  2045. Return Value:
  2046. TRUE (to stop enumeration)
  2047. FALSE otherwise
  2048. *******************************************************************
  2049. --*/
  2050. BOOL SapBuildInternalUpdateListFilter (
  2051. IN LPVOID CBParam,
  2052. IN OUT PIPX_SERVER_ENTRY_P Server,
  2053. IN ULONG InterfaceIndex,
  2054. IN ULONG Protocol,
  2055. IN PUCHAR AdvertisingNode,
  2056. IN INT Flags)
  2057. {
  2058. IPX_SERVER_ENTRY_P TempServer;
  2059. SERVER_INTERNAL_UPDATE_NODE * pNew, **ppList;
  2060. // Get the list that we're dealing with
  2061. ppList = (SERVER_INTERNAL_UPDATE_NODE**)CBParam;
  2062. // If this is a local server with an out of date network number
  2063. // stored, then add it to the list of servers to update.
  2064. if (InterfaceIndex == INTERNAL_INTERFACE_INDEX) {
  2065. if (IpxNetCmp (Server->Network, INTERNAL_IF_NET) != 0) {
  2066. // Send some trace
  2067. Trace (DEBUG_SERVERDB, "Updating local server: %s %x%x%x%x:%x%x%x%x%x%x:%x%x",
  2068. Server->Name,
  2069. Server->Network[0], Server->Network[1], Server->Network[2], Server->Network[3],
  2070. Server->Node[0], Server->Node[1], Server->Node[2], Server->Node[3], Server->Node[4], Server->Node[5],
  2071. Server->Socket[0], Server->Socket[1]
  2072. );
  2073. // Create and initialize the new node
  2074. pNew = HeapAlloc (ServerTable.ST_Heap, 0, sizeof (SERVER_INTERNAL_UPDATE_NODE));
  2075. if (!pNew)
  2076. return TRUE;
  2077. CopyMemory (&(pNew->Server), Server, sizeof (IPX_SERVER_ENTRY_P));
  2078. pNew->InterfaceIndex = InterfaceIndex;
  2079. pNew->Protocol = Protocol;
  2080. pNew->AdvertisingNode = AdvertisingNode;
  2081. pNew->Flags = Flags;
  2082. // Insert the flag in the list
  2083. if (*ppList)
  2084. pNew->pNext = *ppList;
  2085. else
  2086. pNew->pNext = NULL;
  2087. *ppList = pNew;
  2088. }
  2089. }
  2090. return FALSE;
  2091. }
  2092. //
  2093. // When the internal network number changes, we need to update the
  2094. // control blocks of the internal servers.
  2095. //
  2096. DWORD SapUpdateLocalServers () {
  2097. SERVER_INTERNAL_UPDATE_NODE * pList = NULL, * pCur;
  2098. BOOL bNewServer = FALSE;
  2099. HANDLE hEnum;
  2100. Trace (DEBUG_SERVERDB, "SapUpdateLocalServers: entered.");
  2101. // Create a list enumerator that goes through all
  2102. // servers in the table.
  2103. hEnum = CreateListEnumerator (
  2104. SDB_HASH_TABLE_LINK,
  2105. 0xFFFF,
  2106. NULL,
  2107. INVALID_INTERFACE_INDEX,
  2108. 0xFFFFFFFF,
  2109. 0);
  2110. if (hEnum == NULL)
  2111. return GetLastError ();
  2112. // Enumerate the servers sending them through a filter
  2113. // that updates their network number and node
  2114. EnumerateServers (hEnum, SapBuildInternalUpdateListFilter, (LPVOID)&pList);
  2115. DeleteListEnumerator (hEnum);
  2116. // pList will now point to a list of servers that need to have
  2117. // their information updated.
  2118. while (pList) {
  2119. pCur = pList;
  2120. // Send out a broadcast that the local server is now
  2121. // unreachable
  2122. pCur->Server.HopCount = IPX_MAX_HOP_COUNT;
  2123. UpdateServer ( &(pCur->Server),
  2124. pCur->InterfaceIndex,
  2125. pCur->Protocol,
  2126. INFINITE,
  2127. pCur->AdvertisingNode,
  2128. pCur->Flags,
  2129. &bNewServer );
  2130. Trace (DEBUG_SERVERDB, "%s has been marked with hop count 16", pCur->Server.Name);
  2131. // Update the network and node number and advertise that
  2132. // it is available
  2133. IpxNetCpy (pCur->Server.Network, INTERNAL_IF_NET);
  2134. IpxNodeCpy (pCur->Server.Node, INTERNAL_IF_NODE);
  2135. pCur->Server.HopCount = 0;
  2136. UpdateServer ( &(pCur->Server),
  2137. pCur->InterfaceIndex,
  2138. pCur->Protocol,
  2139. INFINITE,
  2140. pCur->AdvertisingNode,
  2141. pCur->Flags,
  2142. &bNewServer );
  2143. Trace (DEBUG_SERVERDB, "%s has been updated.", pCur->Server.Name);
  2144. // Cleanup
  2145. pList = pList->pNext;
  2146. HeapFree (ServerTable.ST_Heap, 0, pCur);
  2147. }
  2148. return NO_ERROR;
  2149. }