Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1393 lines
44 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. rplpush.c
  5. Abstract:
  6. This module contains functions of the PUSH handler component
  7. of the Replicator.
  8. These functions handle the pull requests from a Pull Partner
  9. Functions:
  10. RplPushInit
  11. ExecuteWrkItm
  12. HandleAddVersMapReq
  13. HandleSndEntriesReq
  14. HandleUpdNtf
  15. HandleUpdVersNoReq
  16. Portability:
  17. This module is portable
  18. Author:
  19. Pradeep Bahl (PradeepB) Jan-1993
  20. Revision History:
  21. Modification date Person Description of modification
  22. ----------------- ------- ----------------------------
  23. --*/
  24. /*
  25. * Includes
  26. */
  27. #include "wins.h"
  28. #include "nmsnmh.h"
  29. #include "nms.h"
  30. #include "rpl.h"
  31. #include "rplmsgf.h"
  32. #include "rplpush.h"
  33. #include "rplpull.h"
  34. #include "winsevt.h"
  35. #include "winsque.h"
  36. #include "nmsdb.h"
  37. #include "winsmsc.h"
  38. #include "winscnf.h"
  39. #include "comm.h"
  40. /*
  41. * Local Macro Declarations
  42. */
  43. //
  44. // The amount of time the push thread will wait after its last activity
  45. // before exiting. This is kept to be 5 mts for now.
  46. //
  47. // It is a good idea to keep it less than the Min. Replication time
  48. // interval
  49. //
  50. #define WAIT_TIME_BEFORE_EXITING (300000)
  51. /*
  52. * Local Typedef Declarations
  53. */
  54. /*
  55. * Global Variable Definitions
  56. */
  57. HANDLE RplPushCnfEvtHdl;
  58. BOOL fRplPushThdExists = FALSE;
  59. /*
  60. * Local Variable Definitions
  61. */
  62. /*
  63. * Local Function Prototype Declarations
  64. */
  65. STATIC
  66. STATUS
  67. HandleAddVersMapReq(
  68. PQUE_RPL_REQ_WRK_ITM_T pWrkItm
  69. );
  70. STATIC
  71. STATUS
  72. HandleSndEntriesReq(
  73. PQUE_RPL_REQ_WRK_ITM_T pWrkItm
  74. );
  75. STATIC
  76. VOID
  77. HandleUpdNtf(
  78. #if PRSCONN
  79. BOOL fPrsConn,
  80. #endif
  81. PQUE_RPL_REQ_WRK_ITM_T pWrkItm
  82. );
  83. STATIC
  84. VOID
  85. HandleUpdVersNoReq(
  86. PQUE_RPL_REQ_WRK_ITM_T pWrkItm
  87. );
  88. STATIC
  89. VOID
  90. ExecuteWrkItm(
  91. PQUE_RPL_REQ_WRK_ITM_T pWrkItm
  92. );
  93. /* prototypes for functions local to this module go here */
  94. STATUS
  95. RplPushInit(
  96. LPVOID pParam
  97. )
  98. /*++
  99. Routine Description:
  100. This function is the start function of the Push Thread.
  101. The function blocks on an auto-reset event variable until signalled
  102. When signalled it
  103. dequeues a work item from from its work queue and executes it
  104. Arguments:
  105. pParam
  106. Externals Used:
  107. None
  108. Return Value:
  109. Success status codes -- WINS_SUCCESS
  110. Error status codes -- WINS_FAILURE
  111. Error Handling:
  112. Called by:
  113. ERplInit
  114. Side Effects:
  115. Comments:
  116. None
  117. --*/
  118. {
  119. HANDLE ThdEvtArr[2];
  120. PQUE_RPL_REQ_WRK_ITM_T pWrkItm;
  121. DWORD ArrInd;
  122. DWORD RetVal;
  123. BOOL fSignaled;
  124. UNREFERENCED_PARAMETER(pParam);
  125. try {
  126. //
  127. // Initialize the thd
  128. //
  129. NmsDbThdInit(WINS_E_RPLPUSH);
  130. DBGMYNAME("Replicator Push Thread\n");
  131. //
  132. // We do this at each thread creation to save on STATIC storage. This
  133. // way when the thread is not there we don't consume resources.
  134. //
  135. ThdEvtArr[0] = NmsTermEvt;
  136. ThdEvtArr[1] = QueRplPushQueHd.EvtHdl;
  137. while(TRUE)
  138. {
  139. try {
  140. /*
  141. * Block until signaled or until timer expiry
  142. */
  143. WinsMscWaitTimedUntilSignaled(
  144. ThdEvtArr,
  145. 2,
  146. &ArrInd,
  147. WAIT_TIME_BEFORE_EXITING,
  148. &fSignaled
  149. );
  150. //
  151. // If the wait was interrupted due to a termination signal or
  152. // if the wait timed out, exit the thread.
  153. //
  154. if (!fSignaled || (ArrInd == 0))
  155. {
  156. //
  157. // if the thread has timed out, we need to exit it. Before
  158. // we do that, we check whether some thread sneaked in
  159. // a message after the timeout
  160. //
  161. if (!fSignaled)
  162. {
  163. PQUE_HD_T pQueHd = pWinsQueQueHd[QUE_E_RPLPUSH];
  164. //
  165. // QueGetWrkItm also enters the Push thread's critical
  166. // section. I don't want to write a separate function
  167. // or overload the QueGetWrkItem function to avoid
  168. // the double entry into the critical section.
  169. //
  170. EnterCriticalSection(&pQueHd->CrtSec);
  171. RetVal = QueGetWrkItm(
  172. QUE_E_RPLPUSH,
  173. (LPVOID)&pWrkItm
  174. );
  175. //
  176. // if we got a request execute it.
  177. //
  178. if (RetVal != WINS_NO_REQ)
  179. {
  180. LeaveCriticalSection(&pQueHd->CrtSec);
  181. NmsDbOpenTables(WINS_E_RPLPUSH);
  182. ExecuteWrkItm(pWrkItm);
  183. NmsDbCloseTables();
  184. }
  185. else
  186. {
  187. //
  188. // set the flag to FALSE so that if a message
  189. // comes for this Push thread, it is created.
  190. //
  191. fRplPushThdExists = FALSE;
  192. WinsThdPool.ThdCount--;
  193. WinsThdPool.RplThds[WINSTHD_RPL_PUSH_INDEX].
  194. fTaken = FALSE;
  195. //
  196. // Be sure to close the handle, otherwise
  197. // the thread object will stay.
  198. //
  199. CloseHandle(
  200. WinsThdPool.RplThds[WINSTHD_RPL_PUSH_INDEX].
  201. ThdHdl
  202. );
  203. LeaveCriticalSection(&pQueHd->CrtSec);
  204. WinsMscTermThd(WINS_SUCCESS,
  205. WINS_DB_SESSION_EXISTS);
  206. }
  207. }
  208. else //signaled for termination by the main thread
  209. {
  210. WinsMscTermThd(WINS_SUCCESS,
  211. WINS_DB_SESSION_EXISTS);
  212. }
  213. }
  214. /*
  215. *loop forever until all work items have been handled
  216. */
  217. while(TRUE)
  218. {
  219. /*
  220. * dequeue the request from the queue
  221. */
  222. RetVal = QueGetWrkItm(
  223. QUE_E_RPLPUSH,
  224. (LPVOID)&pWrkItm
  225. );
  226. if (RetVal == WINS_NO_REQ)
  227. {
  228. break;
  229. }
  230. NmsDbOpenTables(WINS_E_RPLPUSH);
  231. ExecuteWrkItm(pWrkItm);
  232. NmsDbCloseTables();
  233. //
  234. // Check for termination here since WINS could be under
  235. // stress with a large number of messages in the queue.
  236. // We don't want to delay the stop.
  237. //
  238. WinsMscChkTermEvt(
  239. #ifdef WINSDBG
  240. WINS_E_RPLPUSH,
  241. #endif
  242. FALSE
  243. );
  244. }
  245. } // end of try
  246. except(EXCEPTION_EXECUTE_HANDLER) {
  247. DBGPRINTEXC("Replicator Push thread");
  248. WINSEVT_LOG_M(GetExceptionCode(), WINS_EVT_RPLPUSH_EXC);
  249. }
  250. } // end of while
  251. } // end of try
  252. except (EXCEPTION_EXECUTE_HANDLER) {
  253. DBGPRINTEXC("Replicator Push thread");
  254. WINSEVT_LOG_M(GetExceptionCode(), WINS_EVT_RPLPUSH_ABNORMAL_SHUTDOWN);
  255. //
  256. // If NmsDbThdInit comes back with an exception, it is possible
  257. // that the session has not yet been started. Passing
  258. // WINS_DB_SESSION_EXISTS however is ok
  259. //
  260. WinsMscTermThd(WINS_FAILURE, WINS_DB_SESSION_EXISTS);
  261. }
  262. //
  263. // We should never get here.
  264. //
  265. return(WINS_FAILURE);
  266. }
  267. VOID
  268. ExecuteWrkItm(
  269. PQUE_RPL_REQ_WRK_ITM_T pWrkItm
  270. )
  271. /*++
  272. Routine Description:
  273. The function executes a work item. The work item can either be
  274. a push notification request from within this WINS (from an NBT thread)
  275. or a replication request (from a remote WINS)
  276. Arguments:
  277. pWrkItm - ptr to a work item
  278. Externals Used:
  279. None
  280. Return Value:
  281. None
  282. Error Handling:
  283. Called by:
  284. RplPushInit
  285. Side Effects:
  286. Comments:
  287. None
  288. --*/
  289. {
  290. RPLMSGF_MSG_OPCODE_E PullReqType_e;
  291. #if PRSCONN
  292. BOOL fPrsConn = FALSE;
  293. #endif
  294. BOOL fPushNtf = FALSE;
  295. //
  296. // get the opcode
  297. //
  298. RplMsgfUfmPullPnrReq(
  299. pWrkItm->pMsg,
  300. pWrkItm->MsgLen,
  301. &PullReqType_e
  302. );
  303. switch(PullReqType_e)
  304. {
  305. case(RPLMSGF_E_ADDVERSNO_MAP_REQ):
  306. HandleAddVersMapReq(pWrkItm);
  307. #ifdef WINSDBG
  308. NmsCtrs.RplPushCtrs.NoAddVersReq++;
  309. #endif
  310. break;
  311. case(RPLMSGF_E_SNDENTRIES_REQ):
  312. HandleSndEntriesReq(pWrkItm);
  313. #ifdef WINSDBG
  314. NmsCtrs.RplPushCtrs.NoSndEntReq++;
  315. #endif
  316. break;
  317. #if PRSCONN
  318. case(RPLMSGF_E_UPDATE_NTF_PRS):
  319. case(RPLMSGF_E_UPDATE_NTF_PROP_PRS):
  320. fPrsConn = TRUE;
  321. #endif
  322. case(RPLMSGF_E_UPDATE_NTF):
  323. case(RPLMSGF_E_UPDATE_NTF_PROP):
  324. fPushNtf = TRUE;
  325. #if PRSCONN
  326. HandleUpdNtf(fPrsConn, pWrkItm);
  327. #else
  328. HandleUpdNtf(pWrkItm);
  329. #endif
  330. #ifdef WINSDBG
  331. NmsCtrs.RplPushCtrs.NoUpdNtfReq++;
  332. #endif
  333. break;
  334. case(RPLMSGF_E_UPDVERSNO_REQ):
  335. #ifdef WINSDBG
  336. NmsCtrs.RplPushCtrs.NoUpdVersReq++;
  337. #endif
  338. HandleUpdVersNoReq(pWrkItm);
  339. break;
  340. default:
  341. #ifdef WINSDBG
  342. NmsCtrs.RplPushCtrs.NoInvReq++;
  343. #endif
  344. DBGPRINT1(ERR, "RplPush: ExecuteWrkItm: Invalid Opcode (%d)\n",
  345. PullReqType_e);
  346. WINSEVT_LOG_M(WINS_FAILURE, WINS_EVT_SFT_ERR);
  347. break;
  348. }
  349. //
  350. // If the message is not an update notification,
  351. // Free the message buffer. For an update
  352. // notification, the message is handed to
  353. // the PULL thread to handle. Therefore, we should not free it
  354. // The work items needs to be freed always since we always allocate
  355. // a new work item when queuing a request.
  356. //
  357. if ( !fPushNtf)
  358. {
  359. ECommFreeBuff(pWrkItm->pMsg - COMM_HEADER_SIZE);
  360. }
  361. //
  362. // Deallocate the work item
  363. //
  364. QueDeallocWrkItm( RplWrkItmHeapHdl, pWrkItm );
  365. return;
  366. }
  367. STATUS
  368. HandleAddVersMapReq(
  369. PQUE_RPL_REQ_WRK_ITM_T pWrkItm
  370. )
  371. /*++
  372. Routine Description:
  373. This function handles a "send address - version # " request
  374. Arguments:
  375. pWrkItm - Work item that carries the request and associated info
  376. Externals Used:
  377. None
  378. Return Value:
  379. Success status codes --
  380. Error status codes --
  381. Error Handling:
  382. Called by:
  383. Side Effects:
  384. Comments:
  385. None
  386. --*/
  387. {
  388. LPBYTE pRspBuff;
  389. DWORD RspMsgLen;
  390. PRPL_ADD_VERS_NO_T pPullAddNVersNo;
  391. DWORD i = 0;
  392. DWORD MaxNoOfOwners;
  393. PRPL_CONFIG_REC_T pPnr;
  394. COMM_ADD_T WinsAdd;
  395. BOOL fRplPnr = FALSE;
  396. BOOL fExc = FALSE;
  397. struct in_addr InAddr;
  398. PCOMM_ADD_T pWinsAdd;
  399. PNMSDB_WINS_STATE_E pWinsState_e;
  400. DWORD SizeOfBuff;
  401. BOOL fRspBuffAlloc = FALSE;
  402. #if SUPPORT612WINS > 0
  403. BOOL fIsPnrBeta1Wins;
  404. #endif
  405. DBGENTER("HandleAddVersMapReq\n");
  406. //
  407. // We need to handle this request only if
  408. // either the WINS that sent this message is one of our
  409. // pull pnrs or if the fRplOnlyWCnfPnrs in the registry is FALSE
  410. //
  411. EnterCriticalSection(&WinsCnfCnfCrtSec);
  412. try {
  413. if (WinsCnf.fRplOnlyWCnfPnrs)
  414. {
  415. if ((pPnr = WinsCnf.PushInfo.pPushCnfRecs) != NULL)
  416. {
  417. COMM_INIT_ADD_FR_DLG_HDL_M(&WinsAdd, &pWrkItm->DlgHdl);
  418. //
  419. // Search for the Cnf record for the WINS we want to
  420. // send the PUSH notification to/Replicate with.
  421. //
  422. for (
  423. ;
  424. (pPnr->WinsAdd.Add.IPAdd != INADDR_NONE)
  425. &&
  426. !fRplPnr;
  427. // no third expression
  428. )
  429. {
  430. //
  431. // Check if this is the one we want
  432. //
  433. if (pPnr->WinsAdd.Add.IPAdd == WinsAdd.Add.IPAdd)
  434. {
  435. //
  436. // We are done. Set the fRplPnr flag to TRUE so that
  437. // we break out of the loop.
  438. //
  439. // Note: Don't use break since that would cause
  440. // a search for a 'finally' block
  441. //
  442. fRplPnr = TRUE;
  443. continue; //so that we break out of the loop
  444. }
  445. //
  446. // Get the next record that follows this one sequentially
  447. //
  448. pPnr = WinsCnfGetNextRplCnfRec(
  449. pPnr,
  450. RPL_E_IN_SEQ //seq. traversal
  451. );
  452. }
  453. }
  454. }
  455. else
  456. {
  457. fRplPnr = TRUE;
  458. }
  459. }
  460. except(EXCEPTION_EXECUTE_HANDLER) {
  461. DBGPRINTEXC("HandleAddVersMapReq");
  462. WINSEVT_LOG_M(GetExceptionCode(), WINS_EVT_EXC_PULL_TRIG_PROC);
  463. fExc = TRUE;
  464. }
  465. LeaveCriticalSection(&WinsCnfCnfCrtSec);
  466. try {
  467. if (fRplPnr)
  468. {
  469. VERS_NO_T MinOwnVersNo;
  470. BOOL fOwnInited = FALSE;
  471. DWORD TotNoOfOwners;
  472. MaxNoOfOwners = 0;
  473. WINS_ASSIGN_INT_TO_LI_M(MinOwnVersNo, 1);
  474. DBGPRINT1(TMP, "HandleAddVersMap: WINS (%x) made an AddVersMap request\n", WinsAdd.Add.IPAdd);
  475. EnterCriticalSection(&NmsDbOwnAddTblCrtSec);
  476. TotNoOfOwners = NmsDbNoOfOwners;
  477. LeaveCriticalSection(&NmsDbOwnAddTblCrtSec);
  478. WinsMscAlloc(sizeof(RPL_ADD_VERS_NO_T) * TotNoOfOwners, &pPullAddNVersNo);
  479. //
  480. // If version counter value > 1, we will send it
  481. //
  482. EnterCriticalSection(&NmsNmhNamRegCrtSec);
  483. if (LiGtr(NmsNmhMyMaxVersNo, MinOwnVersNo))
  484. {
  485. /*
  486. * Get the max. version no for entries owned by self
  487. *
  488. * The reason we subtract 1 from NmsNmhMyMaxVersNo is because
  489. * it contains the version number to be given to the next record
  490. * to be registered/updated.
  491. */
  492. NMSNMH_DEC_VERS_NO_M(
  493. NmsNmhMyMaxVersNo,
  494. pPullAddNVersNo->VersNo
  495. );
  496. pPullAddNVersNo->OwnerWinsAdd = NmsLocalAdd;
  497. pPullAddNVersNo->StartVersNo = NmsDbStartVersNo;
  498. MaxNoOfOwners++;
  499. fOwnInited = TRUE;
  500. }
  501. LeaveCriticalSection(&NmsNmhNamRegCrtSec);
  502. //
  503. // BUG 26196
  504. // Note: These critical sections are taken in the order given below
  505. // by the RPC thread executing GetConfig
  506. //
  507. EnterCriticalSection(&NmsDbOwnAddTblCrtSec);
  508. EnterCriticalSection(&RplVersNoStoreCrtSec);
  509. try {
  510. for (i = 1; i < TotNoOfOwners; i++)
  511. {
  512. //
  513. // If the highest version number for an owner as identified
  514. // by the RplPullOwnerVersNo table is zero, there is no
  515. // need to send the mapping of this owner. The reason
  516. // we may have a such an entry in our in-memory table is
  517. // because 1)All records of the owner got deleted. Local
  518. // WINS got terminated and reinvoked. On reinvocation, it
  519. // did not find any records in the db.
  520. // 2)Local WINS received a Pull range
  521. // request for an owner that it did not know about.
  522. // Since Pull Range request comes in as a
  523. // "SndEntries" request, the Push thread has
  524. // no way of distinguishing it from a normal
  525. // 2 message pull request. For a 2 message
  526. // request, "SndEntries" request will always
  527. // have a subset of the WINS servers that
  528. // have records in our db.
  529. //
  530. if (LiGtrZero((pRplPullOwnerVersNo+i)->VersNo) &&
  531. (pNmsDbOwnAddTbl+i)->WinsState_e == NMSDB_E_WINS_ACTIVE)
  532. {
  533. PVERS_NO_T pStartVersNo;
  534. (pPullAddNVersNo+MaxNoOfOwners)->VersNo = (pRplPullOwnerVersNo+i)->VersNo;
  535. //
  536. // Note: Since RplPullOwnerVersNo[i] is > 0, the
  537. // State of the entry can not be deleted (see
  538. // RplPullPullEntrie)
  539. //
  540. RPL_FIND_ADD_BY_OWNER_ID_M(i, pWinsAdd, pWinsState_e,
  541. pStartVersNo);
  542. (pPullAddNVersNo+MaxNoOfOwners)->OwnerWinsAdd = *pWinsAdd;
  543. (pPullAddNVersNo+MaxNoOfOwners++)->StartVersNo = *pStartVersNo;
  544. DBGPRINT3(RPLPUSH, "HandleAddVersMap:Owner Add (%x) - Vers. No (%d %d)\n", pWinsAdd->Add.IPAdd, (pRplPullOwnerVersNo+i)->VersNo.HighPart, (pRplPullOwnerVersNo+i)->VersNo.LowPart);
  545. }
  546. PERF("Speed it up by using pointer arithmetic")
  547. }
  548. }
  549. except(EXCEPTION_EXECUTE_HANDLER) {
  550. DBGPRINTEXC("HandleAddVersMapReq");
  551. DBGPRINT1(EXC, "HandleAddVersMapReq: Exc. while checking vers. nos of owners\n", GetExceptionCode());
  552. WINSEVT_LOG_M(GetExceptionCode(), WINS_EVT_EXC_PULL_TRIG_PROC);
  553. }
  554. //
  555. // Let us initialize RplPullOwnerVersNo entry for the local WINS
  556. //
  557. // This is done so that if we later on pull from the remote WINS,
  558. // we don't end up pulling our own records
  559. //
  560. if (fOwnInited)
  561. {
  562. pRplPullOwnerVersNo->VersNo = pPullAddNVersNo->VersNo;
  563. pRplPullOwnerVersNo->StartVersNo = pPullAddNVersNo->StartVersNo;
  564. DBGPRINT3(RPLPUSH, "HandleAddVersMap: Owner Add (%x) - Vers. No (%d %d)\n", NmsLocalAdd.Add.IPAdd, (pRplPullOwnerVersNo+i)->VersNo.HighPart, (pRplPullOwnerVersNo+i)->VersNo.LowPart);
  565. }
  566. LeaveCriticalSection(&RplVersNoStoreCrtSec);
  567. LeaveCriticalSection(&NmsDbOwnAddTblCrtSec);
  568. #if SUPPORT612WINS > 0
  569. COMM_IS_PNR_BETA1_WINS_M(&pWrkItm->DlgHdl, fIsPnrBeta1Wins);
  570. #endif
  571. SizeOfBuff = RPLMSGF_ADDVERSMAP_RSP_SIZE_M(MaxNoOfOwners);
  572. WinsMscAlloc(SizeOfBuff, &pRspBuff);
  573. fRspBuffAlloc = TRUE;
  574. /*
  575. * format the response
  576. */
  577. RplMsgfFrmAddVersMapRsp(
  578. #if SUPPORT612WINS > 0
  579. fIsPnrBeta1Wins,
  580. #endif
  581. RPLMSGF_E_ADDVERSNO_MAP_RSP,
  582. pRspBuff + COMM_N_TCP_HDR_SZ,
  583. SizeOfBuff - COMM_N_TCP_HDR_SZ,
  584. pPullAddNVersNo,
  585. MaxNoOfOwners,
  586. 0,
  587. &RspMsgLen
  588. );
  589. //
  590. // Free the memory we allocated earlier
  591. //
  592. WinsMscDealloc(pPullAddNVersNo);
  593. /*
  594. * Send the response. We don't check the return code. ECommSndRsp
  595. * may have failed due to communication failure. There is nothing
  596. * more to be done for either the success of failure case.
  597. */
  598. (VOID)ECommSndRsp(
  599. &pWrkItm->DlgHdl,
  600. pRspBuff + COMM_N_TCP_HDR_SZ,
  601. RspMsgLen
  602. );
  603. //
  604. // We don't end the dialogue. It will get terminated when
  605. // the initiator terminates it.
  606. //
  607. }
  608. else
  609. {
  610. if (!fExc)
  611. {
  612. COMM_INIT_ADD_FR_DLG_HDL_M(&WinsAdd, &pWrkItm->DlgHdl);
  613. DBGPRINT1(RPLPUSH, "HandleAddVersMapReq: Got a pull request message from a WINS to which we are not allowed to push replicas. Address of WINS is (%x)\n",
  614. WinsAdd.Add.IPAdd
  615. );
  616. COMM_HOST_TO_NET_L_M(WinsAdd.Add.IPAdd,InAddr.s_addr);
  617. WinsMscLogEvtStrs(COMM_NETFORM_TO_ASCII_M(&InAddr),
  618. WINS_EVT_ADD_VERS_MAP_REQ_NOT_ACCEPTED,
  619. TRUE);
  620. }
  621. //
  622. // We need to end the dialogue. The work item and the message
  623. // will get deallocated by the caller
  624. //
  625. //
  626. // End the implicit dialogue
  627. //
  628. (VOID)ECommEndDlg(&pWrkItm->DlgHdl);
  629. }
  630. }
  631. except(EXCEPTION_EXECUTE_HANDLER) {
  632. DBGPRINTEXC("HandleAddVersMapReq");
  633. WINSEVT_LOG_M(GetExceptionCode(), WINS_EVT_RPLPUSH_EXC);
  634. }
  635. if (fRspBuffAlloc)
  636. {
  637. WinsMscDealloc(pRspBuff);
  638. }
  639. DBGLEAVE("HandleAddVersMapReq\n")
  640. return(WINS_SUCCESS);
  641. }
  642. STATUS
  643. HandleSndEntriesReq(
  644. PQUE_RPL_REQ_WRK_ITM_T pWrkItm
  645. )
  646. /*++
  647. Routine Description:
  648. This function handles the "send data entries req"
  649. Arguments:
  650. pWrkItm - Work item carrying info about the "Send Entries" request from
  651. a remote WINS
  652. Externals Used:
  653. None
  654. Return Value:
  655. Success status codes -- WINS_SUCCESS
  656. Error status codes -- WINS_FAILURE
  657. Error Handling:
  658. Called by:
  659. RplPushInit()
  660. Side Effects:
  661. Comments:
  662. None
  663. --*/
  664. {
  665. COMM_ADD_T WinsAdd; /*address of WINS server whose records
  666. *are being requested*/
  667. VERS_NO_T MaxVers, MinVers; /*max. amd min. versions of
  668. *records*/
  669. FUTURES("use NMSDB_ROW_INFO_T structure - Maybe")
  670. PRPL_REC_ENTRY_T pBuff;
  671. LPBYTE pStartBuff = NULL;
  672. DWORD RspBufLen;
  673. DWORD NoOfRecs = 0;
  674. DWORD i;
  675. LPBYTE pNewPos;
  676. LPBYTE pTxBuff;
  677. LPBYTE pStartTxBuff;
  678. STATUS RetStat;
  679. PWINSTHD_TLS_T pTls;
  680. PRPL_CONFIG_REC_T pPnr;
  681. BOOL fOnlyDynRecs = FALSE;
  682. DWORD RplType = WINSCNF_RPL_DEFAULT_TYPE;
  683. DWORD RplTypeFMsg;
  684. BYTE Name[1]; //dummy to prevent RtlCopyMemory from
  685. //barfing
  686. COMM_ADD_T ReqWinsAdd;
  687. #if SUPPORT612WINS > 0
  688. BOOL fIsPnrBeta1Wins;
  689. #endif
  690. DBGENTER("HandleSndEntriesReq\n");
  691. GET_TLS_M(pTls);
  692. pTls->HeapHdl = NULL;
  693. //#ifdef WINSDBG
  694. try {
  695. //#endif
  696. //
  697. // Check if this is one of our configured partners. If yes,
  698. // pass the value of fOnlyDynRecs to NmsDbGetDataRecs.
  699. //
  700. // We allow access to even those WINSs that are not partners since
  701. // we need to let them do revalidation of replicas (except for
  702. // this replication activity, all other from non-configured partners
  703. // is stopped at the first step - HandleAddVersMapReq).
  704. //
  705. if ((pPnr = RplGetConfigRec(RPL_E_PUSH, &pWrkItm->DlgHdl, NULL)) != NULL)
  706. {
  707. fOnlyDynRecs = pPnr->fOnlyDynRecs;
  708. RplType = pPnr->RplType;
  709. }
  710. else
  711. {
  712. // if this is not one of our replication partners, get the
  713. // generic (default) "OnlyDynRecs"
  714. EnterCriticalSection(&WinsCnfCnfCrtSec);
  715. fOnlyDynRecs = WinsCnf.PushInfo.fOnlyDynRecs;
  716. LeaveCriticalSection(&WinsCnfCnfCrtSec);
  717. }
  718. #if SUPPORT612WINS > 0
  719. COMM_IS_PNR_BETA1_WINS_M(&pWrkItm->DlgHdl, fIsPnrBeta1Wins);
  720. #endif
  721. /*
  722. * Unformat the request message
  723. */
  724. RplMsgfUfmSndEntriesReq(
  725. #if SUPPORT612WINS > 0
  726. fIsPnrBeta1Wins,
  727. #endif
  728. pWrkItm->pMsg + 4, /*past the
  729. *opcode */
  730. &WinsAdd,
  731. &MaxVers,
  732. &MinVers,
  733. &RplTypeFMsg
  734. );
  735. // ASSERTMSG("Min. Vers. No is >= Max. Vers. No", LiGeq(MaxVers, MinVers));
  736. FUTURES("Check if the request is a PULL RANGE request. If it is, honor it")
  737. FUTURES("only if the Requesting WINS is under the PUSH key or RplOnlyWCnfPnrs")
  738. FUTURES("is set to 0")
  739. COMM_INIT_ADD_FR_DLG_HDL_M(&ReqWinsAdd, &pWrkItm->DlgHdl);
  740. #ifdef WINSDBG
  741. DBGPRINT2(TMP, "HandleSndEntriesReq: WINS (%x) made a SndEntries request for Owner = (%x) \n", ReqWinsAdd.Add.IPAdd, WinsAdd.Add.IPAdd);
  742. DBGPRINT4(TMP, "HandleSndEntriesReq: Min Vers No (%d %d); Max Vers No = (%d %d)\n", MinVers.HighPart, MinVers.LowPart, MaxVers.HighPart, MaxVers.LowPart);
  743. #endif
  744. if (RplType == WINSCNF_RPL_DEFAULT_TYPE)
  745. {
  746. DBGPRINT2(RPLPUSH, "HandleSndEntriesReq: Pnr (%x) is requesting replication of type (%x)\n", ReqWinsAdd.Add.IPAdd, RplTypeFMsg);
  747. // WINSEVT_LOG_INFO_M(ReqWinsAdd.Add.IPAdd, WINS_EVT_PNR_PARTIAL_RPL_TYPE);
  748. RplType = RplTypeFMsg;
  749. }
  750. // make sure any previous thread heap is cleaned up - NmsDbGetDataRecs will
  751. // create a new heap and allocate memory.
  752. if (pTls->HeapHdl != NULL)
  753. {
  754. // destroying the heap deletes all the memory allocated in it
  755. WinsMscHeapDestroy(pTls->HeapHdl);
  756. pTls->HeapHdl = NULL;
  757. }
  758. /*
  759. *
  760. * Call database manager function to get the records. No need
  761. * to check the return status here
  762. */
  763. (VOID)NmsDbGetDataRecs(
  764. WINS_E_RPLPUSH,
  765. THREAD_PRIORITY_NORMAL, //not looked at
  766. MinVers,
  767. MaxVers,
  768. 0, //not of use here
  769. LiEqlZero(MaxVers) ? TRUE : FALSE, //if max. vers.
  770. //no. is zero,
  771. //we want all
  772. //recs.
  773. FALSE, //not looked at in this call
  774. NULL, //must be NULL since we are not
  775. //doing scavenging of clutter
  776. &WinsAdd,
  777. fOnlyDynRecs,
  778. RplType,
  779. (LPVOID *)&pStartBuff,
  780. &RspBufLen,
  781. &NoOfRecs
  782. );
  783. // NmsDbGetDataRecs from above is supposed to have already created the heap!
  784. ASSERT(pTls->HeapHdl != NULL);
  785. //
  786. // Allocate a buffer for transmitting the records. Even if the
  787. // above function failed, we still should have received a buffer
  788. // from it (pStartBuff). Note: RspBufLen contains the size of memory
  789. // required for a flattened stream of records.
  790. //
  791. pStartTxBuff = WinsMscHeapAlloc(pTls->HeapHdl, RspBufLen);
  792. pTxBuff = pStartTxBuff + COMM_N_TCP_HDR_SZ;
  793. pBuff = (PRPL_REC_ENTRY_T)pStartBuff;
  794. DBGPRINT4(RPLPUSH, "Formatting 1st record for sending --name (%s)\nfGrp (%d)\nVersNo (%d %d)\n", pBuff->pName/*pBuff->Name*/,
  795. pBuff->fGrp,
  796. pBuff->VersNo.HighPart,
  797. pBuff->VersNo.LowPart
  798. );
  799. /*
  800. * format the response
  801. *
  802. * Note: It is quite possible that NmsDbGetDataRecs retrieved 0
  803. * records. Even if it did, we are still assured of getting
  804. * a buffer of the RPL_CONFIG_REC_SIZE size. Since at the
  805. * time of allocation, memory is 'zero'ed by default, we
  806. * won't run into any problems in the following function
  807. * call. Check out this function to reassure yourself.
  808. *
  809. * Like mentioned in NmsDbGetDataRecs, the following call
  810. * will serve to format a valid response to the remote WINS
  811. */
  812. RplMsgfFrmSndEntriesRsp(
  813. #if SUPPORT612WINS > 0
  814. fIsPnrBeta1Wins,
  815. #endif
  816. pTxBuff,
  817. NoOfRecs,
  818. NOTE("expedient HACK - for now. Later on modify FrmSndEntriesRsp ")
  819. NoOfRecs ? pBuff->pName : Name,
  820. pBuff->NameLen,
  821. pBuff->fGrp,
  822. pBuff->NoOfAdds,
  823. pBuff->NodeAdd,
  824. pBuff->Flag,
  825. pBuff->VersNo,
  826. TRUE, /*First time*/
  827. &pNewPos
  828. );
  829. PERF("Change RplFrmSndEntriesRsp so that it does the looping itself")
  830. for (i = 1; i < NoOfRecs; i++)
  831. {
  832. pBuff = (PRPL_REC_ENTRY_T)((LPBYTE)pBuff + RPL_REC_ENTRY_SIZE);
  833. // DBGPRINT4(RPLPUSH, "Formatting record for sending --name (%s)\nfGrp (%d)\nVersNo (%d %d)\n", pBuff->pName/*pBuff->Name*/, pBuff->fGrp, pBuff->VersNo.HighPart, pBuff->VersNo.LowPart);
  834. /*
  835. * Format the response
  836. */
  837. RplMsgfFrmSndEntriesRsp(
  838. #if SUPPORT612WINS > 0
  839. fIsPnrBeta1Wins,
  840. #endif
  841. pNewPos,
  842. NoOfRecs, //not used by func
  843. pBuff->pName,
  844. pBuff->NameLen,
  845. pBuff->fGrp,
  846. pBuff->NoOfAdds,
  847. pBuff->NodeAdd,
  848. pBuff->Flag,
  849. pBuff->VersNo,
  850. FALSE, /*Not First time*/
  851. &pNewPos
  852. );
  853. }
  854. RspBufLen = (ULONG) (pNewPos - pTxBuff);
  855. /*
  856. * Call ECommSndRsp to send the response.
  857. */
  858. RetStat = ECommSndRsp(
  859. &pWrkItm->DlgHdl,
  860. pTxBuff,
  861. RspBufLen
  862. );
  863. #ifdef WINSDBG
  864. {
  865. // COMM_IP_ADD_T IPAdd;
  866. struct in_addr InAdd;
  867. // COMM_GET_IPADD_M(&pWrkItm->DlgHdl, &IPAdd);
  868. InAdd.s_addr = htonl(ReqWinsAdd.Add.IPAdd);
  869. if (RetStat != WINS_SUCCESS)
  870. {
  871. DBGPRINT2(RPLPUSH, "HandleSndEntriesReq: ERROR: Could not send (%d) records to WINS with address = (%s)\n",
  872. NoOfRecs,
  873. inet_ntoa(InAdd)
  874. );
  875. }
  876. else
  877. {
  878. DBGPRINT2(RPLPUSH, "HandleSndEntriesReq: Sent (%d) records to WINS with address = (%s)\n",
  879. NoOfRecs,
  880. inet_ntoa(InAdd)
  881. );
  882. }
  883. }
  884. #endif
  885. //#ifdef WINSDBG
  886. }
  887. except(EXCEPTION_EXECUTE_HANDLER) {
  888. DBGPRINTEXC("HandleSndEntriesReq");
  889. WINSEVT_LOG_M(GetExceptionCode(), WINS_EVT_RPLPUSH_EXC);
  890. } //end of exception handler
  891. //#endif
  892. // make sure any previous thread heap is cleaned up before getting out of this call
  893. if (pTls->HeapHdl != NULL)
  894. {
  895. // destroying the heap deletes all the memory allocated in it
  896. WinsMscHeapDestroy(pTls->HeapHdl);
  897. pTls->HeapHdl = NULL;
  898. }
  899. DBGLEAVE("HandleSndEntriesReq\n");
  900. return(WINS_SUCCESS);
  901. }
  902. VOID
  903. HandleUpdNtf(
  904. #if PRSCONN
  905. BOOL fPrsConn,
  906. #endif
  907. PQUE_RPL_REQ_WRK_ITM_T pWrkItm
  908. )
  909. /*++
  910. Routine Description:
  911. This function is called to handle an update notification message
  912. received from a remote WINS
  913. Arguments:
  914. fPrsConn - Indicates whether the connection is persistent or not
  915. pWrkItm - Work Item containing the message and other relevant info
  916. Externals Used:
  917. None
  918. Return Value:
  919. None
  920. Error Handling:
  921. Called by:
  922. RplPushInit()
  923. Side Effects:
  924. Comments:
  925. None
  926. --*/
  927. {
  928. PRPL_CONFIG_REC_T pPnr;
  929. COMM_ADD_T WinsAdd;
  930. BOOL fRplPnr = FALSE;
  931. BOOL fExc = FALSE;
  932. struct in_addr InAddr;
  933. DWORD RplType;
  934. DBGENTER("HandleUpdNtf - PUSH thread\n");
  935. //
  936. // We need to forward this request to the PULL thread only if
  937. // either the WINS that sent this notification is one of our
  938. // push pnrs or if the fRplOnlyWCnfPnrs in the registry is FALSE
  939. //
  940. FUTURES("user RplGetConfigRec instead of the following code")
  941. EnterCriticalSection(&WinsCnfCnfCrtSec);
  942. try {
  943. if (WinsCnf.fRplOnlyWCnfPnrs)
  944. {
  945. if ((pPnr = WinsCnf.PullInfo.pPullCnfRecs) != NULL)
  946. {
  947. COMM_INIT_ADD_FR_DLG_HDL_M(&WinsAdd, &pWrkItm->DlgHdl);
  948. //
  949. // Search for the Cnf record for the WINS we want to
  950. // send the PUSH notification to/Replicate with.
  951. //
  952. for (
  953. ;
  954. (pPnr->WinsAdd.Add.IPAdd != INADDR_NONE)
  955. &&
  956. !fRplPnr;
  957. // no third expression
  958. )
  959. {
  960. //
  961. // Check if this is the one we want
  962. //
  963. if (pPnr->WinsAdd.Add.IPAdd == WinsAdd.Add.IPAdd)
  964. {
  965. //
  966. // We are done. Set the fRplPnr flag to TRUE so that
  967. // we break out of the loop.
  968. //
  969. // Note: Don't use break since that would cause
  970. // a search for a 'finally' block
  971. //
  972. fRplPnr = TRUE;
  973. RplType = pPnr->RplType;
  974. continue; //so that we break out of the loop
  975. }
  976. //
  977. // Get the next record that follows this one sequentially
  978. //
  979. pPnr = WinsCnfGetNextRplCnfRec(
  980. pPnr,
  981. RPL_E_IN_SEQ //seq. traversal
  982. );
  983. }
  984. }
  985. }
  986. else
  987. {
  988. fRplPnr = TRUE;
  989. RplType = WinsCnf.PullInfo.RplType;
  990. }
  991. }
  992. except(EXCEPTION_EXECUTE_HANDLER) {
  993. DBGPRINTEXC("HandleUpdNtf");
  994. WINSEVT_LOG_M(GetExceptionCode(), WINS_EVT_EXC_PUSH_TRIG_PROC);
  995. fExc = TRUE;
  996. }
  997. LeaveCriticalSection(&WinsCnfCnfCrtSec);
  998. #ifdef WINSDBG
  999. try {
  1000. #endif
  1001. if (fRplPnr)
  1002. {
  1003. //
  1004. // Inform the TCP listener thread that it should stop
  1005. // monitoring the dialogue since we are handing it over to
  1006. // the PULL thread
  1007. //
  1008. #if PRSCONN
  1009. if (!fPrsConn)
  1010. #endif
  1011. {
  1012. if (!ECommProcessDlg(&pWrkItm->DlgHdl, COMM_E_NTF_STOP_MON))
  1013. {
  1014. //
  1015. // Free the buffer
  1016. //
  1017. ECommFreeBuff(pWrkItm->pMsg - COMM_HEADER_SIZE);
  1018. DBGPRINT0(ERR, "HandleUpdNtf - PUSH thread. No Upd Ntf could be sent. It could be because the link went down\n");
  1019. return;
  1020. }
  1021. else
  1022. {
  1023. COMM_INIT_ADD_FR_DLG_HDL_M(&WinsAdd, &pWrkItm->DlgHdl);
  1024. COMM_HOST_TO_NET_L_M(WinsAdd.Add.IPAdd,InAddr.s_addr);
  1025. WinsMscLogEvtStrs(COMM_NETFORM_TO_ASCII_M(&InAddr),
  1026. WINS_EVT_UPD_NTF_ACCEPTED, TRUE);
  1027. }
  1028. }
  1029. //
  1030. // Forward the request to the Pull thread
  1031. //
  1032. ERplInsertQue(
  1033. WINS_E_RPLPUSH,
  1034. QUE_E_CMD_HDL_PUSH_NTF,
  1035. &pWrkItm->DlgHdl,
  1036. pWrkItm->pMsg, //msg containing the push ntf
  1037. pWrkItm->MsgLen, //msg length
  1038. ULongToPtr(RplType), //context to pass
  1039. 0 //no magic no
  1040. );
  1041. //
  1042. // The Pull thread will now terminate the dlg
  1043. //
  1044. }
  1045. else //we need to reject this trigger
  1046. {
  1047. if (!fExc)
  1048. {
  1049. COMM_INIT_ADD_FR_DLG_HDL_M(&WinsAdd, &pWrkItm->DlgHdl);
  1050. DBGPRINT1(RPLPUSH, "HandleUpdNtf: Got a push trigger from a WINS with which we are not allowed to pull replicas. Address of WINS is (%d)\n",
  1051. WinsAdd.Add.IPAdd
  1052. );
  1053. COMM_HOST_TO_NET_L_M(WinsAdd.Add.IPAdd,InAddr.s_addr);
  1054. WinsMscLogEvtStrs(COMM_NETFORM_TO_ASCII_M(&InAddr),
  1055. WINS_EVT_UPD_NTF_NOT_ACCEPTED, TRUE);
  1056. }
  1057. //
  1058. // We need to first deallocate the message and then end the
  1059. // dialogue. The work item will get deallocated by the caller
  1060. //
  1061. //
  1062. // Free the buffer
  1063. //
  1064. ECommFreeBuff(pWrkItm->pMsg - COMM_HEADER_SIZE);
  1065. //
  1066. // End the implicit dialogue
  1067. //
  1068. (VOID)ECommEndDlg(&pWrkItm->DlgHdl);
  1069. }
  1070. #ifdef WINSDBG
  1071. }
  1072. except(EXCEPTION_EXECUTE_HANDLER) {
  1073. DBGPRINTEXC("HandleUpdNtf");
  1074. WINSEVT_LOG_M(GetExceptionCode(), WINS_EVT_RPLPUSH_EXC);
  1075. }
  1076. #endif
  1077. DBGLEAVE("HandleUpdNtf - PUSH thread\n");
  1078. return;
  1079. }
  1080. VOID
  1081. HandleUpdVersNoReq(
  1082. PQUE_RPL_REQ_WRK_ITM_T pWrkItm
  1083. )
  1084. /*++
  1085. Routine Description:
  1086. This function is called to handle an update version number
  1087. request received from a remote WINS
  1088. This message is sent by a remote WINS as a result of a clash
  1089. during replication.
  1090. Arguments:
  1091. pWrkItm - work item
  1092. Externals Used:
  1093. None
  1094. Return Value:
  1095. None
  1096. Error Handling:
  1097. Called by:
  1098. RplPushInit()
  1099. Side Effects:
  1100. Comments:
  1101. None
  1102. --*/
  1103. {
  1104. BYTE Name[NMSDB_MAX_NAM_LEN];
  1105. DWORD NameLen;
  1106. BYTE Rcode;
  1107. DWORD RspBuffLen;
  1108. BYTE RspBuff[RPLMSGF_UPDVERSNO_RSP_SIZE];
  1109. COMM_ADD_T WinsAdd;
  1110. struct in_addr InAddr;
  1111. DBGENTER("HandleUpdVerdNoReq\n");
  1112. #ifdef WINSDBG
  1113. try {
  1114. #endif
  1115. //
  1116. // log an event
  1117. //
  1118. COMM_GET_IPADD_M(&pWrkItm->DlgHdl, &WinsAdd.Add.IPAdd);
  1119. COMM_HOST_TO_NET_L_M(WinsAdd.Add.IPAdd,InAddr.s_addr);
  1120. WinsMscLogEvtStrs(COMM_NETFORM_TO_ASCII_M(&InAddr), WINS_EVT_REM_WINS_INF, TRUE);
  1121. /*
  1122. * Unformat the request message
  1123. */
  1124. RplMsgfUfmUpdVersNoReq(
  1125. pWrkItm->pMsg + 4, /*past the
  1126. *opcode */
  1127. Name,
  1128. &NameLen
  1129. );
  1130. //
  1131. // handle the request
  1132. //
  1133. NmsNmhUpdVersNo( Name, NameLen, &Rcode, &WinsAdd );
  1134. //
  1135. //Format the response
  1136. //
  1137. RplMsgfFrmUpdVersNoRsp(
  1138. RspBuff + COMM_N_TCP_HDR_SZ,
  1139. Rcode,
  1140. &RspBuffLen
  1141. );
  1142. //
  1143. // Send the response. No need to check the return code.
  1144. //
  1145. (VOID)ECommSndRsp(
  1146. &pWrkItm->DlgHdl,
  1147. RspBuff + COMM_N_TCP_HDR_SZ,
  1148. RspBuffLen
  1149. );
  1150. //
  1151. // No need to end the dialogue. The initiator of the dlg will end it.
  1152. //
  1153. #ifdef WINSDBG
  1154. }
  1155. except(EXCEPTION_EXECUTE_HANDLER) {
  1156. DBGPRINTEXC("HandleUpdVersNoReq");
  1157. WINSEVT_LOG_M(GetExceptionCode(), WINS_EVT_RPLPUSH_EXC);
  1158. }
  1159. #endif
  1160. DBGLEAVE("HandleUpdVerdNoReq\n");
  1161. return;
  1162. } // HandleUpdVersNoReq()
  1163.