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.

5990 lines
236 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. nmsnmh.c
  5. Abstract:
  6. This module contains functions of the name handler component of the
  7. name space manager of WINS.
  8. The name handler is responsible for handling all name registrations,
  9. name refreshes, name requests, and name releases.
  10. Functions:
  11. NmsNmhNamRegInd - Register Unique Name
  12. NmsNmhNamRegGrp - Register Group Name
  13. NmsNmhNamRelease - Release a name
  14. NmsNmhNamQuery - Query a name
  15. .....
  16. .....
  17. Portability:
  18. This module is portable
  19. Author:
  20. Pradeep Bahl (PradeepB) Dec-1992
  21. Revision History:
  22. Modification date Person Description of modification
  23. ----------------- ------- ----------------------------
  24. --*/
  25. /*
  26. Includes
  27. */
  28. #include <time.h>
  29. #include <string.h>
  30. #include <stdlib.h>
  31. #include <stdio.h>
  32. #include "wins.h"
  33. #include "nmsdb.h"
  34. #include "comm.h"
  35. #include "nms.h"
  36. #include "nmsnmh.h"
  37. #include "nmsmsgf.h"
  38. #include "nmschl.h"
  39. #include "winsevt.h"
  40. #include "winscnf.h"
  41. #include "winsmsc.h"
  42. #include "winsque.h"
  43. #include "rpl.h"
  44. #include "winsintf.h"
  45. /*
  46. * Local Macro Declarations
  47. */
  48. /*
  49. * Local Typedef Declarations
  50. */
  51. /*
  52. * Global Variable Definitions
  53. */
  54. VERS_NO_T NmsNmhMyMaxVersNo; //max. vers. no of entries owned
  55. //by this wins
  56. VERS_NO_T NmsNmhIncNo; //a large integer initialized to 1
  57. CRITICAL_SECTION NmsNmhNamRegCrtSec; //for name registrations and
  58. //refreshes
  59. /*
  60. * Local Variable Definitions
  61. */
  62. /*
  63. * Local Function Prototype Declarations
  64. */
  65. /* prototypes for functions local to this module go here */
  66. //
  67. // Send response to name release request
  68. //
  69. STATIC
  70. STATUS
  71. SndNamRelRsp(
  72. PCOMM_HDL_T pDlgHdl,
  73. PNMSMSGF_RSP_INFO_T pRspInfo
  74. );
  75. //
  76. // Send response to name query request
  77. //
  78. STATIC
  79. STATUS
  80. SndNamQueryRsp(
  81. PCOMM_HDL_T pDlgHdl,
  82. PNMSMSGF_RSP_INFO_T pRspInfo
  83. );
  84. //
  85. // handle clash at name registration of a unique entry
  86. //
  87. STATIC
  88. STATUS
  89. ClashAtRegInd (
  90. IN PNMSDB_ROW_INFO_T pEntryToReg,
  91. IN PNMSDB_STAT_INFO_T pEntryInCnf,
  92. IN BOOL fRefresh,
  93. OUT PBOOL pfUpdate,
  94. OUT PBOOL pfUpdVersNo,
  95. OUT PBOOL pfChallenge,
  96. OUT PBOOL pfAddMem,
  97. OUT PBOOL pfAddDiff,
  98. OUT PBOOL pfRetPosRsp
  99. );
  100. //
  101. // handle clash at name registration of a group entry
  102. //
  103. STATIC
  104. STATUS
  105. ClashAtRegGrp (
  106. IN PNMSDB_ROW_INFO_T pEntryToReg,
  107. IN PNMSDB_STAT_INFO_T pEntryInCnf,
  108. IN BOOL fRefresh,
  109. OUT PBOOL pfAddMem,
  110. OUT PBOOL pfUpdate,
  111. OUT PBOOL pfUpdVersNo,
  112. OUT PBOOL pfChallenge,
  113. OUT PBOOL pfRetPosRsp
  114. );
  115. //
  116. // handle clash at the name registration of unique entry's replica
  117. //
  118. STATIC
  119. VOID
  120. ClashAtReplUniqueR (
  121. IN PNMSDB_ROW_INFO_T pEntryToReg,
  122. IN PNMSDB_STAT_INFO_T pEntryInCnf,
  123. OUT PBOOL pfUpdate,
  124. OUT PBOOL pfUpdVersNo,
  125. OUT PBOOL pfChallenge,
  126. OUT PBOOL pfRelease,
  127. OUT PBOOL pfInformWins
  128. );
  129. //
  130. // handle clash at the name registration of group entry's replica
  131. //
  132. STATIC
  133. VOID
  134. ClashAtReplGrpR (
  135. IN PNMSDB_ROW_INFO_T pEntryToReg,
  136. IN PNMSDB_STAT_INFO_T pEntryInCnf,
  137. OUT PBOOL pfAddMem,
  138. OUT PBOOL pfUpdate,
  139. OUT PBOOL pfUpdVersNo,
  140. OUT PBOOL pfRelease,
  141. OUT PBOOL pfChallenge,
  142. OUT PBOOL pfUpdTimeStamp,
  143. OUT PBOOL pfInformWins
  144. );
  145. //
  146. // check if the entry to register is a member of the special group found in
  147. // the db
  148. //
  149. STATIC
  150. BOOL
  151. MemInGrp(
  152. IN PCOMM_ADD_T pAddToReg,
  153. IN PNMSDB_STAT_INFO_T pEntryInCnf,
  154. IN PBOOL pfOwned,
  155. IN BOOL fRemoveReplica
  156. );
  157. STATIC
  158. VOID
  159. RemoveAllMemOfOwner(
  160. PNMSDB_STAT_INFO_T pEntry,
  161. DWORD OwnerId
  162. );
  163. //
  164. // Do a union of two special groups
  165. //
  166. STATIC
  167. BOOL
  168. UnionGrps(
  169. IN PNMSDB_ROW_INFO_T pEntryToReg,
  170. IN PNMSDB_STAT_INFO_T pEntryInCnf
  171. );
  172. FUTURES("use when internet group masks are used")
  173. #if 0
  174. STATIC
  175. BYTE
  176. HexAsciiToBinary(
  177. LPBYTE pByte
  178. );
  179. STATIC
  180. BOOL
  181. IsItSpecGrpNm(
  182. LPBYTE pName
  183. );
  184. #endif
  185. //
  186. // Function definitions
  187. //
  188. STATUS
  189. NmsNmhNamRegInd(
  190. IN PCOMM_HDL_T pDlgHdl,
  191. IN LPBYTE pName,
  192. IN DWORD NameLen,
  193. IN PCOMM_ADD_T pNodeAdd,
  194. IN BYTE NodeTyp, //change to take Flag byte
  195. IN MSG_T pMsg,
  196. IN MSG_LEN_T MsgLen,
  197. IN DWORD QuesNamSecLen,
  198. IN BOOL fRefresh,
  199. IN BOOL fStatic,
  200. IN BOOL fAdmin
  201. )
  202. /*++
  203. Routine Description:
  204. This function registers a unique name in the directory database.
  205. Arguments:
  206. pDlgHdl - Dialogue Handle
  207. pName - Name to be registered
  208. NameLen - Length of Name
  209. NodeTyp - Whether nbt node doing the registration is a P or M node
  210. pNodeAdd - NBT node's address
  211. NodeTyp - Type of Node (B, M, P)
  212. pMsg - Datagram received (i.e. the name request)
  213. Msglen - Length of message
  214. QuesNamSecLen - Length of the Question Name Section in the RFC packet
  215. fRefresh - Is it a refresh request
  216. fStatic - Is it a STATIC entry
  217. fAdmin - Is it an administrative action
  218. Externals Used:
  219. NmsNmhNamRegCrtSec, NmsNmhMyMaxVersNo
  220. Return Value:
  221. Success status codes -- WINS_SUCCESS
  222. Error status codes -- WINS_FAILURE
  223. Error Handling:
  224. Called by:
  225. NmsMsgfProcNbtReq, WinsRecordAction
  226. Side Effects:
  227. Comments:
  228. None
  229. --*/
  230. {
  231. NMSDB_ROW_INFO_T RowInfo; // contains row info
  232. NMSDB_STAT_INFO_T StatusInfo; /* error status and associated
  233. * info returned by the NmsDb func
  234. */
  235. BOOL fChlBeingDone = FALSE; //indicates whether
  236. //challenge is being
  237. //done
  238. BOOL fUpdate; //indicates whether conflicting entry
  239. //needs to be overwritten
  240. BOOL fUpdVersNo; //indicates whether version number
  241. //needs to be incremented
  242. BOOL fChallenge; //indicates whether a challenge needs
  243. //to be done
  244. time_t ltime; //stores time since Jan 1, 1970
  245. //is a browser name
  246. BOOL fAddDiff; //indicates that the address is diff
  247. BOOL fAddMem; //indicates whether member should be
  248. //added to the multihomed entry
  249. BOOL fRetPosRsp;
  250. NMSMSGF_ERR_CODE_E Rcode_e = NMSMSGF_E_SUCCESS;
  251. STATUS RetStat = WINS_SUCCESS;
  252. NMSMSGF_RSP_INFO_T RspInfo;
  253. #ifdef WINSDBG
  254. DWORD StartTimeInMsec;
  255. // DWORD EndTimeInMsec;
  256. #endif
  257. //DBG_PERFMON_VAR
  258. /*
  259. * initialize the row info. data structure with the data to insert into
  260. * the row. The data passed is
  261. *
  262. * Name, NameLen, address, group/unique status,
  263. * timestamp, version number
  264. */
  265. DBGENTER("NmsNmhNamRegInd\n");
  266. //
  267. // if the 16th char is 0x1C or 0x1E, reject the registration
  268. // since these names are reserved.
  269. //
  270. if ((*(pName + 15) == 0x1C) || (*(pName + 15) == 0x1E))
  271. {
  272. RspInfo.RefreshInterval = 0;
  273. Rcode_e = NMSMSGF_E_RFS_ERR;
  274. goto SNDRSP;
  275. }
  276. RowInfo.pName = pName;
  277. DBGPRINT3(FLOW, "NmsNmhNamRegInd: %s name to register -- (%s). 16th char is (%x)\n", fStatic ? "STATIC" : "DYNAMIC", RowInfo.pName, *(RowInfo.pName+15));
  278. RowInfo.NameLen = NameLen;
  279. RowInfo.pNodeAdd = pNodeAdd;
  280. RowInfo.NodeTyp = NodeTyp; //Node type (B, P or M node)
  281. RowInfo.EntTyp = NMSDB_UNIQUE_ENTRY; // this is a unique
  282. //registration
  283. (void)time(&ltime); //time() does not return any error code
  284. RowInfo.EntryState_e = NMSDB_E_ACTIVE;
  285. RowInfo.OwnerId = NMSDB_LOCAL_OWNER_ID;
  286. RowInfo.fUpdVersNo = TRUE;
  287. RowInfo.fUpdTimeStamp = TRUE;
  288. RowInfo.fLocal = !(fStatic || fAdmin) ? COMM_IS_IT_LOCAL_M(pDlgHdl) : FALSE;
  289. RowInfo.fStatic = fStatic;
  290. RowInfo.fAdmin = fAdmin;
  291. // RowInfo.CommitGrBit = 0;
  292. FUTURES("Currently there we don't check to see whether the address in the")
  293. FUTURES("packet is same as the address of the node that sent this request")
  294. FUTURES("RFCs are silent about this. Investigate")
  295. //
  296. // Check if it is a browser name. If yes, it requires
  297. // special handling
  298. //
  299. if (!NMSDB_IS_IT_BROWSER_NM_M(RowInfo.pName))
  300. {
  301. /*
  302. * Enter Critical Section
  303. */
  304. EnterCriticalSection(&NmsNmhNamRegCrtSec);
  305. //DBG_START_PERF_MONITORING
  306. //
  307. // Put expiry time here
  308. //
  309. ltime += WinsCnf.RefreshInterval;
  310. RowInfo.TimeStamp = (fStatic ? MAXLONG_PTR: ltime);
  311. PERF("Adds to critical section code. Improve perf by getting rid of this")
  312. PERF("Administrator would then get a cumulative count of reg and ref")
  313. if (!fRefresh)
  314. {
  315. WinsIntfStat.Counters.NoOfUniqueReg++;
  316. }
  317. else
  318. {
  319. WinsIntfStat.Counters.NoOfUniqueRef++;
  320. }
  321. //
  322. // Set the refresh interval field. We must do this
  323. // from within the WinsCnfCnfCrtSec or NmsNmhNamRegCrtSec
  324. // critical section (synchronize with main thread doing
  325. // reinitialization or with an RPC thread)
  326. //
  327. RspInfo.RefreshInterval = WinsCnf.RefreshInterval;
  328. /*
  329. * Store version number
  330. */
  331. RowInfo.VersNo = NmsNmhMyMaxVersNo;
  332. try {
  333. #ifdef WINSDBG
  334. IF_DBG(TM) { StartTimeInMsec = GetTickCount(); }
  335. #endif
  336. /*
  337. * Insert record in the directory
  338. */
  339. RetStat = NmsDbInsertRowInd(
  340. &RowInfo,
  341. &StatusInfo
  342. );
  343. #ifdef WINSDBG
  344. IF_DBG(TM) { DBGPRINT2(TM, "NmsNmhNamRegInd: Time in NmsDbInsertRowInd is = (%d msecs). RetStat is (%d)\n", GetTickCount() - StartTimeInMsec,
  345. RetStat); }
  346. #endif
  347. if (RetStat == WINS_SUCCESS)
  348. {
  349. /*
  350. * If there is a conflict, do the appropriate
  351. * processing
  352. */
  353. if (StatusInfo.StatCode == NMSDB_CONFLICT)
  354. {
  355. DBGPRINT0(FLOW, "NmsNmhNamRegInd: Name Conflict\n");
  356. ClashAtRegInd(
  357. &RowInfo,
  358. &StatusInfo,
  359. fRefresh,
  360. &fUpdate,
  361. &fUpdVersNo,
  362. &fChallenge,
  363. &fAddMem,
  364. &fAddDiff,
  365. &fRetPosRsp
  366. );
  367. PERF("Change the order of if tests to improve performance")
  368. if (fChallenge)
  369. {
  370. DBGPRINT0(FLOW,
  371. "NmsNmhNamRegInd: Handing name registration to challenge manager\n");
  372. WinsIntfStat.Counters.NoOfUniqueCnf++;
  373. //
  374. //Ask the Name Challenge component to take
  375. //it from here
  376. //
  377. NmsChlHdlNamReg(
  378. NMSCHL_E_CHL,
  379. WINS_E_NMSNMH,
  380. pDlgHdl,
  381. pMsg,
  382. MsgLen,
  383. QuesNamSecLen,
  384. &RowInfo,
  385. &StatusInfo,
  386. NULL
  387. );
  388. fChlBeingDone = TRUE;
  389. }
  390. else
  391. {
  392. if (fUpdate)
  393. {
  394. if (!fUpdVersNo)
  395. {
  396. RowInfo.fUpdVersNo = FALSE;
  397. }
  398. else
  399. {
  400. WinsIntfStat.Counters.NoOfUniqueCnf++;
  401. }
  402. // RowInfo.CommitGrBit = JET_bitCommitLazyFlush;
  403. RetStat = NmsDbUpdateRow(
  404. &RowInfo,
  405. &StatusInfo
  406. );
  407. FUTURES("Use WINS status codes. Get rid of NMSDB status codes - Maybe")
  408. if ((RetStat != WINS_SUCCESS) || (StatusInfo.StatCode != NMSDB_SUCCESS))
  409. {
  410. Rcode_e = NMSMSGF_E_SRV_ERR;
  411. }
  412. else //we succeeded in inserting the row
  413. {
  414. DBGPRINT1(FLOW,
  415. "%s Registration Done after conflict \n",
  416. fStatic ? "STATIC" : "DYNAMIC");
  417. if (fUpdVersNo)
  418. {
  419. NMSNMH_INC_VERS_COUNTER_M(
  420. NmsNmhMyMaxVersNo,
  421. NmsNmhMyMaxVersNo
  422. );
  423. //
  424. // Send a Push Notification if required
  425. //
  426. DBGIF(fWinsCnfRplEnabled)
  427. RPL_PUSH_NTF_M(
  428. (WinsCnf.PushInfo.fAddChgTrigger == TRUE) ? fAddDiff : RPL_PUSH_NO_PROP, NULL, NULL, NULL);
  429. }
  430. }
  431. }
  432. else // no simple update required
  433. {
  434. if (fRetPosRsp)
  435. {
  436. Rcode_e = NMSMSGF_E_SUCCESS;
  437. }
  438. else
  439. {
  440. if (fAddMem)
  441. {
  442. DWORD i;
  443. PNMSDB_GRP_MEM_ENTRY_T pRowMem =
  444. &RowInfo.NodeAdds.Mem[1];
  445. PNMSDB_GRP_MEM_ENTRY_T pCnfMem =
  446. StatusInfo.NodeAdds.Mem;
  447. //
  448. // Add the new member
  449. //
  450. // Note: first member in RowInfo.NodeAdds is the
  451. // one we tried to register. We tack on
  452. // all the members found in the conflicting
  453. // record to it
  454. //
  455. RowInfo.NodeAdds.Mem[0].OwnerId =
  456. NMSDB_LOCAL_OWNER_ID;
  457. RowInfo.NodeAdds.Mem[0].TimeStamp =
  458. ltime;
  459. RowInfo.NodeAdds.Mem[0].Add = *pNodeAdd;
  460. for (
  461. i = 0;
  462. i < min(StatusInfo.NodeAdds.NoOfMems,
  463. (NMSDB_MAX_MEMS_IN_GRP - 1));
  464. i++, pRowMem++, pCnfMem++)
  465. {
  466. *pRowMem = *pCnfMem;
  467. }
  468. RowInfo.NodeAdds.NoOfMems =
  469. StatusInfo.NodeAdds.NoOfMems + 1;
  470. RowInfo.EntTyp = NMSDB_MULTIHOMED_ENTRY;
  471. RowInfo.pNodeAdd = NULL;
  472. if (!fUpdVersNo)
  473. {
  474. RowInfo.fUpdVersNo = FALSE;
  475. }
  476. RetStat = NmsDbUpdateRow(
  477. &RowInfo,
  478. &StatusInfo
  479. );
  480. if ((RetStat == WINS_SUCCESS) && (StatusInfo.StatCode == NMSDB_SUCCESS))
  481. {
  482. if (fUpdVersNo)
  483. {
  484. NMSNMH_INC_VERS_COUNTER_M(
  485. NmsNmhMyMaxVersNo,
  486. NmsNmhMyMaxVersNo
  487. );
  488. //
  489. // Send a Push notification if required
  490. //
  491. DBGIF(fWinsCnfRplEnabled)
  492. RPL_PUSH_NTF_M(RPL_PUSH_NO_PROP, NULL, NULL,
  493. NULL);
  494. }
  495. }
  496. else
  497. {
  498. Rcode_e = NMSMSGF_E_SRV_ERR;
  499. }
  500. }
  501. else
  502. {
  503. DBGPRINT1(FLOW,
  504. " %s Registration Failed. Conflict\n",
  505. fStatic ? "STATIC" : "DYNAMIC"
  506. );
  507. DBGPRINT1(DET, "%s Registration Failed. Conflict\n",
  508. fStatic ? "STATIC" : "DYNAMIC");
  509. Rcode_e = NMSMSGF_E_ACT_ERR;
  510. }
  511. }
  512. }
  513. }
  514. }
  515. else //no conflict means success
  516. {
  517. DBGPRINT1(FLOW,
  518. "%s Registration Done. No conflict\n",
  519. fStatic ? "STATIC" : "DYNAMIC");
  520. #if 0
  521. DBGPRINT1(SPEC,
  522. " %s Registration Done. No conflict\n",
  523. fStatic ? "STATIC" : "DYNAMIC");
  524. #endif
  525. NMSNMH_INC_VERS_COUNTER_M(
  526. NmsNmhMyMaxVersNo,
  527. NmsNmhMyMaxVersNo
  528. );
  529. //
  530. // Send a Push Notification if required
  531. //
  532. DBGIF(fWinsCnfRplEnabled)
  533. RPL_PUSH_NTF_M(RPL_PUSH_NO_PROP, NULL, NULL, NULL);
  534. }
  535. }
  536. else //RetStat != WINS_SUCCESS
  537. {
  538. Rcode_e = NMSMSGF_E_SRV_ERR;
  539. }
  540. } // end of try block
  541. except (EXCEPTION_EXECUTE_HANDLER) {
  542. DBGPRINTEXC("NmsNmhNamRegInd");
  543. DBGPRINT3(EXC, "NmsNmhNamRegInd. Name is (%s), Version No (%d %d)\n", RowInfo.pName, RowInfo.VersNo.HighPart, RowInfo.VersNo.LowPart);
  544. WinsEvtLogDetEvt(FALSE, WINS_EVT_REG_UNIQUE_ERR,
  545. NULL, __LINE__, "sddd", RowInfo.pName,
  546. GetExceptionCode(),
  547. RowInfo.VersNo.LowPart, RowInfo.VersNo.HighPart);
  548. Rcode_e = NMSMSGF_E_SRV_ERR;
  549. }
  550. LeaveCriticalSection(&NmsNmhNamRegCrtSec);
  551. // DBG_PRINT_PERF_DATA
  552. }
  553. else
  554. {
  555. /*
  556. * Enter Critical Section
  557. */
  558. EnterCriticalSection(&NmsNmhNamRegCrtSec);
  559. //
  560. // Set the refresh interval field
  561. //
  562. RspInfo.RefreshInterval = WinsCnf.RefreshInterval;
  563. LeaveCriticalSection(&NmsNmhNamRegCrtSec);
  564. //
  565. // The name registration was for a browser name.
  566. // We always return a positive response
  567. //
  568. Rcode_e = NMSMSGF_E_SUCCESS;
  569. }
  570. SNDRSP:
  571. //
  572. // Send a response only if we did not hand over the request to the
  573. // name challenge manager and if it is neither a STATIC initialization
  574. // request nor a rpc request
  575. //
  576. if ((!fChlBeingDone) && (!fStatic) && (!fAdmin))
  577. {
  578. DBGPRINT1(FLOW,
  579. "NmsNmhNamRegInd: Sending %s name registration response\n",
  580. Rcode_e == NMSMSGF_E_SUCCESS ? "positive" :
  581. "negative" );
  582. RspInfo.Rcode_e = Rcode_e;
  583. RspInfo.pMsg = pMsg;
  584. RspInfo.MsgLen = MsgLen;
  585. RspInfo.QuesNamSecLen = QuesNamSecLen;
  586. NmsNmhSndNamRegRsp( pDlgHdl, &RspInfo );
  587. }
  588. //
  589. // If it is an RPC request, we need to return a success or a failure
  590. // indication.
  591. //
  592. if (fAdmin)
  593. {
  594. if (Rcode_e != NMSMSGF_E_SUCCESS)
  595. {
  596. DBGLEAVE("NmsNmhNamRegInd\n");
  597. return(WINS_FAILURE);
  598. }
  599. }
  600. DBGLEAVE("NmsNmhNamRegInd\n");
  601. return(WINS_SUCCESS);
  602. }
  603. STATUS
  604. NmsNmhNamRegGrp(
  605. IN PCOMM_HDL_T pDlgHdl,
  606. IN PBYTE pName,
  607. IN DWORD NameLen,
  608. IN PNMSMSGF_CNT_ADD_T pCntAdd,
  609. IN BYTE NodeTyp, //change to take Flag byte
  610. IN MSG_T pMsg,
  611. IN MSG_LEN_T MsgLen,
  612. IN DWORD QuesNamSecLen,
  613. IN DWORD TypeOfRec,
  614. IN BOOL fRefresh,
  615. IN BOOL fStatic,
  616. IN BOOL fAdmin
  617. )
  618. /*++
  619. Routine Description:
  620. This function registers a group record.
  621. Special group:
  622. the name is registered with the IP address in the member list
  623. Normal group
  624. the name is registered with single address (to avoid
  625. special casing. The address is not used)
  626. In case the group registration succeeds, a positive name registration
  627. response is sent, else a negative name registration response is sent.
  628. Arguments:
  629. pDlgHdl - Dialogue Handle
  630. pName - Name to be registered
  631. NameLen - Length of Name
  632. pNodeAdd - NBT node's address
  633. pMsg - Datagram received (i.e. the name request)
  634. Msglen - Length of message
  635. QuesNamSecLen - Length of the Question Name Section in the RFC packet
  636. fStatic - Is it a STATIC entry
  637. fAdmin - Is it an administrative action
  638. Externals Used:
  639. NmsNmhNamRegCrtSec, NmsNmhMyMaxVersNo
  640. Return Value:
  641. Success status codes -- WINS_SUCCESS
  642. Error status codes -- WINS_FAILURE
  643. Error Handling:
  644. Called by:
  645. NmsMsgfProcNbtReq, WinsRecordAction
  646. Side Effects:
  647. Comments:
  648. None
  649. --*/
  650. {
  651. NMSDB_ROW_INFO_T RowInfo; // contains row info
  652. NMSDB_STAT_INFO_T StatusInfo; /* error status and associated
  653. * info returned by the NmsDb func
  654. */
  655. BOOL fChlBeingDone = FALSE; //indicates whether
  656. //challenge is being
  657. //done
  658. BOOL fAddMem; //indicates whether member should be
  659. //added to the group
  660. BOOL fUpdate; //indicates whether conflicting entry
  661. //needs to be overwritten
  662. BOOL fUpdVersNo; //inidicates whether version number
  663. //needs to be incremented
  664. BOOL fChallenge; //indicates whether a challenge needs
  665. //to be done
  666. time_t ltime; //stores time since Jan 1, 1970
  667. BOOL fIsSpecial = FALSE; //Is this a special group
  668. NMSMSGF_ERR_CODE_E Rcode_e = NMSMSGF_E_SUCCESS;
  669. STATUS RetStat = WINS_SUCCESS;
  670. BOOL fRetPosRsp;
  671. NMSMSGF_RSP_INFO_T RspInfo;
  672. #ifdef WINSDBG
  673. DWORD StartTimeInMsec;
  674. // DWORD EndTimeInMsec;
  675. #endif
  676. //DBG_PERFMON_VAR
  677. DBGENTER("NmsNmhNamRegGrp\n");
  678. /*
  679. * initialize the row info. data structure with the data to insert into
  680. * the row. The data passed is
  681. * Name, NameLen, IP address, group/unique status,
  682. * timestamp, version number
  683. */
  684. RowInfo.pName = pName;
  685. RowInfo.pNodeAdd = NULL;
  686. DBGPRINT4(FLOW, "NmsNmhNamRegGrp: %s Name (%s) to register -- (%s). 16th char is (%x)\n", fStatic ? "STATIC" : "DYNAMIC", RowInfo.pName, TypeOfRec == NMSDB_MULTIHOMED_ENTRY ? "MULTIHOMED" : "NORMAL/SPECIAL GROUP", *(RowInfo.pName + 15));
  687. RowInfo.NameLen = NameLen;
  688. (void)time(&ltime); //time does not return any error code
  689. EnterCriticalSection(&NmsNmhNamRegCrtSec);
  690. ltime += WinsCnf.RefreshInterval;
  691. LeaveCriticalSection(&NmsNmhNamRegCrtSec);
  692. //Initialize this
  693. RspInfo.RefreshInterval = 0;
  694. PERF("Stop checking for 1B name in nmsmsgf.c. Do the switch in RegInd and ")
  695. PERF("RegGrp function. That way, we will save some cycles for the grp reg/ref")
  696. //
  697. // do the initialization based on the type of group.
  698. //
  699. // Note: If the name qualifies as a special group name, then
  700. // even if it is a multihomed, we mark it as a special group
  701. //
  702. if (NMSDB_IS_IT_SPEC_GRP_NM_M(pName) || (TypeOfRec == NMSDB_SPEC_GRP_ENTRY))
  703. // if (IsItSpecGrpNm(pName))
  704. {
  705. DWORD i;
  706. RowInfo.EntTyp = NMSDB_SPEC_GRP_ENTRY; // this is a special grp
  707. //registration
  708. RowInfo.NodeAdds.NoOfMems = pCntAdd->NoOfAdds;
  709. for (i = 0; i < pCntAdd->NoOfAdds; i++)
  710. {
  711. RowInfo.NodeAdds.Mem[i].Add = pCntAdd->Add[i];
  712. RowInfo.NodeAdds.Mem[i].OwnerId = NMSDB_LOCAL_OWNER_ID;
  713. //
  714. // Put expiration time here. WE PUT A MAXULONG FOR A STATIC
  715. // SPECIAL GROUP MEMBER ONLY (I.E. NOT FOR MH NAMES). This
  716. // would require changes to MemInGrp().
  717. //
  718. FUTURES("set MAXULONG for mh members also")
  719. RowInfo.NodeAdds.Mem[i].TimeStamp = ((fStatic && (TypeOfRec == NMSDB_SPEC_GRP_ENTRY)) ? MAXLONG_PTR : ltime);
  720. }
  721. //
  722. // Init pNodeAdd field to NULL. This field is checked by
  723. // QueInsertChlReqWrkItm called by NmsChlHdlNamReg (called
  724. // to hand over a challenge request to the name challenge mgr).
  725. //
  726. RowInfo.pNodeAdd = NULL;
  727. }
  728. else // normal group or a multi-homed registration
  729. {
  730. //
  731. // if the name is not mh, it means that it is a group. The
  732. // registration for this group may have come with the MULTIHOMED
  733. // opcode (meaning it is a multihomed node registering the group)
  734. // (see nmsmsgf.c)
  735. //
  736. if (TypeOfRec != NMSDB_MULTIHOMED_ENTRY)
  737. {
  738. if (*pName != 0x1B)
  739. {
  740. RowInfo.pNodeAdd = &pCntAdd->Add[0];
  741. RowInfo.EntTyp = NMSDB_NORM_GRP_ENTRY;
  742. RowInfo.NodeAdds.NoOfMems = pCntAdd->NoOfAdds;
  743. RowInfo.NodeAdds.Mem[0].Add = pCntAdd->Add[0];
  744. RowInfo.NodeAdds.Mem[0].OwnerId = NMSDB_LOCAL_OWNER_ID;
  745. RowInfo.NodeAdds.Mem[0].TimeStamp = ltime; // put current time
  746. }
  747. else
  748. {
  749. //
  750. // a 1B name is for browser use. We can not let this one
  751. // preempt it
  752. //
  753. NOTE("TTL is not being set. This shouldn't break UB nodes, but you never know")
  754. Rcode_e = NMSMSGF_E_RFS_ERR;
  755. goto SNDRSP;
  756. }
  757. }
  758. else
  759. {
  760. //
  761. // It is a multihomed entry
  762. //
  763. if (NMSDB_IS_IT_BROWSER_NM_M(RowInfo.pName))
  764. {
  765. /*
  766. * Enter Critical Section
  767. */
  768. EnterCriticalSection(&NmsNmhNamRegCrtSec);
  769. //
  770. // Set the refresh interval field
  771. //
  772. RspInfo.RefreshInterval = WinsCnf.RefreshInterval;
  773. LeaveCriticalSection(&NmsNmhNamRegCrtSec);
  774. //
  775. // The name registration was for a browser name.
  776. // We always return a positive response
  777. //
  778. Rcode_e = NMSMSGF_E_SUCCESS;
  779. goto SNDRSP;
  780. }
  781. else
  782. {
  783. DWORD i;
  784. if (*(RowInfo.pName+15) == 0x1E)
  785. {
  786. Rcode_e = NMSMSGF_E_RFS_ERR;
  787. goto SNDRSP;
  788. }
  789. RowInfo.NodeAdds.NoOfMems = pCntAdd->NoOfAdds;
  790. for (i = 0; i < pCntAdd->NoOfAdds; i++)
  791. {
  792. RowInfo.NodeAdds.Mem[i].Add = pCntAdd->Add[i];
  793. RowInfo.NodeAdds.Mem[i].OwnerId = NMSDB_LOCAL_OWNER_ID;
  794. RowInfo.NodeAdds.Mem[i].TimeStamp = ltime; // put current time
  795. }
  796. RowInfo.EntTyp = NMSDB_MULTIHOMED_ENTRY;
  797. }
  798. }
  799. }
  800. RowInfo.TimeStamp = (fStatic ? MAXLONG_PTR: ltime);
  801. RowInfo.OwnerId = NMSDB_LOCAL_OWNER_ID;
  802. RowInfo.EntryState_e = NMSDB_E_ACTIVE;
  803. RowInfo.fUpdVersNo = TRUE;
  804. RowInfo.fUpdTimeStamp = TRUE;
  805. RowInfo.fLocal = !(fStatic || fAdmin) ? COMM_IS_IT_LOCAL_M(pDlgHdl) : FALSE;
  806. RowInfo.fStatic = fStatic;
  807. RowInfo.fAdmin = fAdmin;
  808. // RowInfo.CommitGrBit = 0;
  809. //
  810. // Put this initialization here even though it is not required for
  811. // special group groups. This is to save cycles in
  812. // the critical section (check UpdateDb in nmsdb.c; if
  813. // we don't initialize this for special groups, we have to
  814. // put an if test (with associated & to get the type of record
  815. // bits) versus an or.
  816. //
  817. RowInfo.NodeTyp = NodeTyp; //Node type (B, P or M node)
  818. /*
  819. * Enter Critical Section
  820. */
  821. EnterCriticalSection(&NmsNmhNamRegCrtSec);
  822. //DBG_START_PERF_MONITORING
  823. PERF("Adds to critical section code. Improve perf by getting rid of this")
  824. PERF("Administrator would then get a cumulative count of reg and ref")
  825. if (!fRefresh)
  826. {
  827. WinsIntfStat.Counters.NoOfGroupReg++;
  828. }
  829. else
  830. {
  831. WinsIntfStat.Counters.NoOfGroupRef++;
  832. }
  833. //
  834. // Set the refresh interval field. We must do this
  835. // from within the WinsCnfCnfCrtSec or NmsNmhNamRegCrtSec
  836. // critical section
  837. //
  838. RspInfo.RefreshInterval = WinsCnf.RefreshInterval;
  839. /*
  840. * Store version number
  841. */
  842. RowInfo.VersNo = NmsNmhMyMaxVersNo;
  843. try
  844. {
  845. #ifdef WINSDBG
  846. IF_DBG(TM) { StartTimeInMsec = GetTickCount(); }
  847. #endif
  848. /*
  849. * Insert record in the directory
  850. */
  851. RetStat = NmsDbInsertRowGrp(
  852. &RowInfo,
  853. &StatusInfo
  854. );
  855. #ifdef WINSDBG
  856. IF_DBG(TM) { DBGPRINT2(TM, "NmsNmhNamRegGrp: Time in NmsDbInsertRowGrp is = (%d msecs). RetStat is (%d)\n", GetTickCount() - StartTimeInMsec, RetStat); }
  857. #endif
  858. if (RetStat == WINS_SUCCESS)
  859. {
  860. /*
  861. * If there is a conflict, do the appropriate processing
  862. */
  863. if (StatusInfo.StatCode == NMSDB_CONFLICT)
  864. {
  865. RetStat = ClashAtRegGrp(
  866. &RowInfo,
  867. &StatusInfo,
  868. fRefresh, // will never be TRUE for a multihomed reg
  869. &fAddMem,
  870. &fUpdate,
  871. &fUpdVersNo,
  872. &fChallenge,
  873. &fRetPosRsp
  874. );
  875. if (RetStat == WINS_SUCCESS)
  876. {
  877. //
  878. // If fChallenge is set, it means that we should challenge the
  879. // node in conflict.
  880. //
  881. if (fChallenge)
  882. {
  883. WinsIntfStat.Counters.NoOfGroupCnf++;
  884. fChlBeingDone = TRUE;
  885. NmsChlHdlNamReg(
  886. NMSCHL_E_CHL,
  887. WINS_E_NMSNMH,
  888. pDlgHdl,
  889. pMsg,
  890. MsgLen,
  891. QuesNamSecLen,
  892. &RowInfo,
  893. &StatusInfo,
  894. // &StatusInfo.NodeAdds.Mem[0].Add,
  895. NULL
  896. );
  897. }
  898. else
  899. {
  900. if (fUpdate)
  901. {
  902. //
  903. // In case of a special group, we could
  904. // be updating the row without incrementing
  905. // its version number (the row is not owned
  906. // by us)
  907. //
  908. if (!fUpdVersNo)
  909. {
  910. RowInfo.fUpdVersNo = FALSE;
  911. }
  912. else
  913. {
  914. WinsIntfStat.Counters.NoOfGroupCnf++;
  915. }
  916. FUTURES("Check return status of NmsDbUpdateRow instead of checking StatCode")
  917. RetStat = NmsDbUpdateRow(
  918. &RowInfo,
  919. &StatusInfo
  920. );
  921. FUTURES("Use WINS status codes. Get rid of NMSDB status codes - Maybe")
  922. if ((RetStat != WINS_SUCCESS) || (StatusInfo.StatCode != NMSDB_SUCCESS))
  923. {
  924. Rcode_e = NMSMSGF_E_SRV_ERR;
  925. }
  926. else //we succeeded in inserting the row
  927. {
  928. DBGPRINT1(FLOW,
  929. "%s Registration Done after conflict.\n",
  930. fStatic ? "STATIC" : "DYNAMIC");
  931. if (fUpdVersNo)
  932. {
  933. NMSNMH_INC_VERS_COUNTER_M(
  934. NmsNmhMyMaxVersNo,
  935. NmsNmhMyMaxVersNo
  936. );
  937. //
  938. // Send a Push notification if
  939. // required
  940. //
  941. DBGIF(fWinsCnfRplEnabled)
  942. RPL_PUSH_NTF_M(RPL_PUSH_NO_PROP, NULL, NULL,
  943. NULL);
  944. }
  945. }
  946. }
  947. else
  948. {
  949. //
  950. // if a member needs to be added
  951. //
  952. if (fAddMem)
  953. {
  954. DWORD i;
  955. PNMSDB_GRP_MEM_ENTRY_T pRegMem = &RowInfo.NodeAdds.Mem[RowInfo.NodeAdds.NoOfMems];
  956. PNMSDB_GRP_MEM_ENTRY_T pCnfMem = StatusInfo.NodeAdds.Mem;
  957. PERF("Needs to be optimized")
  958. //
  959. // Add the new member
  960. //
  961. // Note: Members in RowInfo.NodeAdds are the
  962. // ones we tried to register. We tack on
  963. // all the members found in the conflicting
  964. // record to it. A special group will have
  965. // just one member; a multihomed record can
  966. // have 1-NMSDB_MAX_MEMS_IN_GRP members.
  967. //
  968. // We always prefer locally registered
  969. // group members to those that registered at
  970. // other name servers.
  971. //
  972. for (
  973. i = 0;
  974. i < min(StatusInfo.NodeAdds.NoOfMems,
  975. (NMSDB_MAX_MEMS_IN_GRP - RowInfo.NodeAdds.NoOfMems));
  976. i++)
  977. {
  978. *pRegMem++ = *pCnfMem++;
  979. }
  980. RowInfo.NodeAdds.NoOfMems += i;
  981. RowInfo.pNodeAdd = NULL;
  982. //
  983. // The situations where this would be
  984. // FALSE is 1) when the member already exists,
  985. // is owned by us and is in a record owned
  986. // by us also. 2) a MH record clashes with a
  987. // non-owned MH record
  988. //
  989. if (!fUpdVersNo)
  990. {
  991. RowInfo.fUpdVersNo = FALSE;
  992. // ASSERT(StatusInfo.OwnerId == NMSDB_LOCAL_OWNER_ID);
  993. }
  994. // RowInfo.CommitGrBit = JET_bitCommitLazyFlush;
  995. RetStat = NmsDbUpdateRow(
  996. &RowInfo,
  997. &StatusInfo
  998. );
  999. if ((RetStat == WINS_SUCCESS) && (StatusInfo.StatCode == NMSDB_SUCCESS))
  1000. {
  1001. if (fUpdVersNo)
  1002. {
  1003. NMSNMH_INC_VERS_COUNTER_M(
  1004. NmsNmhMyMaxVersNo,
  1005. NmsNmhMyMaxVersNo
  1006. );
  1007. //
  1008. // Send a Push notification if required
  1009. //
  1010. DBGIF(fWinsCnfRplEnabled)
  1011. RPL_PUSH_NTF_M(RPL_PUSH_NO_PROP, NULL, NULL,
  1012. NULL);
  1013. }
  1014. }
  1015. else
  1016. {
  1017. DBGPRINT3(ERR, "NmsNmhNamRegGrp: Could not add member to the special group (%s[%x]). No Of Members existent are (%d)\n", RowInfo.pName, RowInfo.pName[15], RowInfo.NodeAdds.NoOfMems - 1);
  1018. Rcode_e = NMSMSGF_E_SRV_ERR;
  1019. }
  1020. }
  1021. else
  1022. {
  1023. if (!fRetPosRsp)
  1024. {
  1025. DBGPRINT1(FLOW,
  1026. " %s Registration Failed. Conflict\n",
  1027. fStatic ? "STATIC" : "DYNAMIC"
  1028. );
  1029. Rcode_e = NMSMSGF_E_ACT_ERR;
  1030. }
  1031. }
  1032. }
  1033. }
  1034. } //RetStat from ClashAtRegGrp != WINS_SUCCESS
  1035. else
  1036. {
  1037. Rcode_e = NMSMSGF_E_SRV_ERR;
  1038. }
  1039. }
  1040. else //no conflict means success
  1041. {
  1042. DBGPRINT2(FLOW, "%s %s Registration Done. No conflict\n",
  1043. fStatic ? "STATIC" : "DYNAMIC",
  1044. TypeOfRec == NMSDB_MULTIHOMED_ENTRY ? "MULTIHOMED" : "GROUP");
  1045. NMSNMH_INC_VERS_COUNTER_M(
  1046. NmsNmhMyMaxVersNo,
  1047. NmsNmhMyMaxVersNo
  1048. );
  1049. DBGIF(fWinsCnfRplEnabled)
  1050. RPL_PUSH_NTF_M(RPL_PUSH_NO_PROP, NULL, NULL, NULL);
  1051. }
  1052. }
  1053. else //RetStat != SUCCESS
  1054. {
  1055. Rcode_e = NMSMSGF_E_SRV_ERR;
  1056. }
  1057. } // end of try block
  1058. except (EXCEPTION_EXECUTE_HANDLER) {
  1059. DBGPRINTEXC("NmsNmhNamRegGrp");
  1060. WinsEvtLogDetEvt(FALSE, WINS_EVT_REG_GRP_ERR,
  1061. NULL, __LINE__, "sddd", RowInfo.pName,
  1062. GetExceptionCode(),
  1063. RowInfo.VersNo.LowPart, RowInfo.VersNo.HighPart);
  1064. // WINSEVT_LOG_D_M(GetExceptionCode(), WINS_EVT_REG_GRP_ERR);
  1065. Rcode_e = NMSMSGF_E_SRV_ERR;
  1066. }
  1067. LeaveCriticalSection(&NmsNmhNamRegCrtSec);
  1068. //DBG_PRINT_PERF_DATA;
  1069. SNDRSP:
  1070. //
  1071. // Send a response only if we did not hand over the request to the
  1072. // name challenge manager and if it is neither a STATIC initialization
  1073. // request nor a rpc request
  1074. //
  1075. if ((!fChlBeingDone) && (!fStatic) && (!fAdmin))
  1076. {
  1077. DBGPRINT1(FLOW,
  1078. "NmsNmhNamRegGrp: Sending %s name registration response\n",
  1079. Rcode_e == NMSMSGF_E_SUCCESS ? "positive" :
  1080. "negative" );
  1081. RspInfo.Rcode_e = Rcode_e;
  1082. RspInfo.pMsg = pMsg;
  1083. RspInfo.MsgLen = MsgLen;
  1084. RspInfo.QuesNamSecLen = QuesNamSecLen;
  1085. NmsNmhSndNamRegRsp( pDlgHdl, &RspInfo );
  1086. }
  1087. //
  1088. // If it is an RPC request, we need to return a success or a failure
  1089. // indication.
  1090. //
  1091. if (fAdmin)
  1092. {
  1093. if (Rcode_e != NMSMSGF_E_SUCCESS)
  1094. {
  1095. DBGLEAVE("NmsNmhNamRegGrp\n");
  1096. return(WINS_FAILURE);
  1097. }
  1098. }
  1099. DBGLEAVE("NmsNmhNamRegGrp\n");
  1100. return(WINS_SUCCESS);
  1101. }
  1102. #if 0
  1103. __inline
  1104. BYTE
  1105. HexAsciiToBinary(
  1106. LPBYTE pByte
  1107. )
  1108. /*++
  1109. Routine Description:
  1110. This function converts two bytes (each byte contains the ascii
  1111. equivalent of a hex character in the range 0-F) to a binary
  1112. representation
  1113. Arguments:
  1114. Externals Used:
  1115. None
  1116. Return Value:
  1117. Error Handling:
  1118. Called by:
  1119. Side Effects:
  1120. Comments:
  1121. None
  1122. --*/
  1123. {
  1124. BYTE Byte = 0;
  1125. DWORD Nibbles = 0;
  1126. do
  1127. {
  1128. if (*pByte >= '0' && *pByte <= '9')
  1129. {
  1130. Byte += (*pByte - '0') << (Nibbles * 4);
  1131. }
  1132. else
  1133. {
  1134. Byte += (*pByte - 'A') << (Nibbles * 4);
  1135. }
  1136. pByte++;
  1137. } while (++Nibbles < 2);
  1138. return(Byte);
  1139. }
  1140. BOOL
  1141. IsItSpecGrpNm(
  1142. LPBYTE pName
  1143. )
  1144. /*++
  1145. Routine Description:
  1146. This function is called to check whether the name is a special
  1147. (internel group)
  1148. Arguments:
  1149. Externals Used:
  1150. None
  1151. Return Value:
  1152. Success status codes --
  1153. Error status codes --
  1154. Error Handling:
  1155. Called by:
  1156. Side Effects:
  1157. Comments:
  1158. None
  1159. --*/
  1160. {
  1161. DWORD Index;
  1162. DWORD ByteIndex;
  1163. BYTE TmpName[16];
  1164. LPBYTE pTmpName = TmpName;
  1165. LPBYTE pSpecGrpMaskByte;
  1166. LPBYTE pSpecGrpMask;
  1167. if (NMSDB_IS_IT_DOMAIN_NM_M((pName)))
  1168. {
  1169. return(TRUE);
  1170. }
  1171. else
  1172. {
  1173. //
  1174. // if spec. grp mask were specified in the registry
  1175. //
  1176. if (WinsCnf.SpecGrpMasks.NoOfSpecGrpMasks > 0)
  1177. {
  1178. //
  1179. // for each spec. grp mask, && it with the name
  1180. // and then see if the result is same as
  1181. // the mask. If yes, then the name is a special group
  1182. //
  1183. for (
  1184. Index = 0,
  1185. pSpecGrpMask =
  1186. WinsCnf.SpecGrpMasks.pSpecGrpMasks;
  1187. Index < WinsCnf.SpecGrpMasks.NoOfSpecGrpMasks;
  1188. Index++, pSpecGrpMask += WINSCNF_SPEC_GRP_MASK_SZ + 1
  1189. )
  1190. {
  1191. for (
  1192. ByteIndex = 0, pSpecGrpMaskByte =
  1193. pSpecGrpMask;
  1194. ByteIndex < WINSCNF_SPEC_GRP_MASK_SZ;
  1195. ByteIndex++, pName++
  1196. )
  1197. {
  1198. *pTmpName++ = *pName &&
  1199. HexAsciiToBinary(pSpecGrpMaskByte);
  1200. //
  1201. // Increment by 2 since we have two
  1202. // bytes in the mask for each
  1203. // character in the name
  1204. //
  1205. pSpecGrpMaskByte += 2;
  1206. }
  1207. if (WINSMSC_COMPARE_MEMORY_M(TmpName, pSpecGrpMask, WINSCNF_SPEC_GRP_MASK_SZ) == WINSCNF_SPEC_GRP_MASK_SZ)
  1208. {
  1209. return(TRUE);
  1210. }
  1211. //
  1212. // iterate in order to get the next mask
  1213. //
  1214. }
  1215. }
  1216. }
  1217. return(FALSE);
  1218. }
  1219. #endif
  1220. STATUS
  1221. NmsNmhNamRel(
  1222. IN PCOMM_HDL_T pDlgHdl,
  1223. IN LPBYTE pName,
  1224. IN DWORD NameLen,
  1225. IN PCOMM_ADD_T pNodeAdd,
  1226. IN BOOL fGrp,
  1227. IN MSG_T pMsg,
  1228. IN MSG_LEN_T MsgLen,
  1229. IN DWORD QuesNamSecLen,
  1230. IN BOOL fAdmin
  1231. )
  1232. /*++
  1233. Routine Description:
  1234. This function releases a record.
  1235. In case the release succeeds, a positive name release
  1236. response is sent, else a negative name release response is sent.
  1237. Arguments:
  1238. pDlgHdl - Dialogue Handle
  1239. pName - Name to be registered
  1240. NameLen - Length of Name
  1241. pMsg - Datagram received (i.e. the name request)
  1242. Msglen - Length of message
  1243. QuesNamSecLen - Length of the Question Name Section in the RFC packet
  1244. fAdmin - Is it an administrative action
  1245. Externals Used:
  1246. NmsNmhNamRegCrtSec
  1247. Return Value:
  1248. Success status codes -- WINS_SUCCESS
  1249. Error status codes -- WINS_FAILURE
  1250. Error Handling:
  1251. Called by:
  1252. NmsMsgfProcNbtReq, WinsRecordAction
  1253. Side Effects:
  1254. Comments:
  1255. None
  1256. --*/
  1257. {
  1258. NMSDB_ROW_INFO_T RowInfo; // contains row info
  1259. NMSDB_STAT_INFO_T StatusInfo; /* error status and associated
  1260. * info returned by the NmsDb func
  1261. */
  1262. time_t ltime; //stores time since Jan 1, 1970
  1263. STATUS RetStat = WINS_FAILURE;
  1264. NMSMSGF_RSP_INFO_T RspInfo;
  1265. BOOL fBrowser = FALSE;
  1266. BOOL fExcRecd = FALSE;
  1267. #ifdef WINSDBG
  1268. DWORD StartTimeInMsec;
  1269. // DWORD EndTimeInMsec;
  1270. #endif
  1271. //DBG_PERFMON_VAR
  1272. DBGENTER("NmsNmhNamRel\n");
  1273. /*
  1274. * Initialize the row info. data structure with the data to insert
  1275. * into the row. The data passed is Name, NameLen, IP address,
  1276. * group/unique status, timestamp, version number
  1277. */
  1278. RowInfo.pName = pName;
  1279. RowInfo.NameLen = NameLen;
  1280. DBGPRINT2(FLOW,
  1281. "NmsNmhNamRel: Name To Release = %s. 16th char is (%x)\n",
  1282. RowInfo.pName, *(RowInfo.pName+15));
  1283. (void)time(&ltime); //time does not return any error code
  1284. RowInfo.TimeStamp = ltime; //put the current time here
  1285. RowInfo.OwnerId = NMSDB_LOCAL_OWNER_ID;
  1286. RowInfo.pNodeAdd = pNodeAdd;
  1287. RowInfo.fAdmin = fAdmin;
  1288. //
  1289. //
  1290. // If the release is for a group, mark it as a NORMAL or a SPECIAL
  1291. // GROUP.
  1292. //
  1293. if (fGrp)
  1294. {
  1295. //
  1296. // Since the group bit was set in the release request pkt
  1297. // set the EntTyp field of RowInfo to NORM_GRP (or SPEC_GRP)
  1298. // to indicate to the callee that we want to release a group
  1299. //
  1300. RowInfo.EntTyp = NMSDB_NORM_GRP_ENTRY;
  1301. }
  1302. else
  1303. {
  1304. //
  1305. // The entry to release can be a unique or multihomed. We
  1306. // put UNIQUE for lack of knowing better.
  1307. //
  1308. RowInfo.EntTyp = NMSDB_UNIQUE_ENTRY;
  1309. if (NMSDB_IS_IT_BROWSER_NM_M(RowInfo.pName))
  1310. {
  1311. //
  1312. // It is a browser name. We always return a positive
  1313. // name release response.
  1314. //
  1315. fBrowser = TRUE;
  1316. StatusInfo.StatCode = NMSDB_SUCCESS;
  1317. StatusInfo.fLocal = FALSE;
  1318. RetStat = WINS_SUCCESS;
  1319. }
  1320. }
  1321. //
  1322. // If it is a browser name that needs to be released, we just send
  1323. // a positive response
  1324. //
  1325. if (!fBrowser)
  1326. {
  1327. //
  1328. // Enter the critical section since we will be updating the record
  1329. //
  1330. EnterCriticalSection(&NmsNmhNamRegCrtSec);
  1331. /*
  1332. * Store version number (in case we change ownership to self)
  1333. */
  1334. RowInfo.VersNo = NmsNmhMyMaxVersNo;
  1335. //DBG_START_PERF_MONITORING
  1336. // WinsIntfStat.Counters.NoOfRel++;
  1337. try {
  1338. //
  1339. // Release the record in the directory.
  1340. //
  1341. #ifdef WINSDBG
  1342. IF_DBG(TM) { StartTimeInMsec = GetTickCount(); }
  1343. #endif
  1344. StatusInfo.fLocal = FALSE;
  1345. RetStat = NmsDbRelRow( &RowInfo, &StatusInfo );
  1346. #ifdef WINSDBG
  1347. IF_DBG(TM) { DBGPRINT2(TM, "NmsNmhNamRelRow: Time in NmsDbRelRow is = (%d). RetStat is (%d msecs)\n", GetTickCount() - StartTimeInMsec,
  1348. RetStat); }
  1349. #endif
  1350. }
  1351. except (EXCEPTION_EXECUTE_HANDLER) {
  1352. DBGPRINTEXC("NmsNmhNamRel");
  1353. WINSEVT_LOG_D_M(GetExceptionCode(), WINS_EVT_NAM_REL_ERR);
  1354. RspInfo.Rcode_e = NMSMSGF_E_SRV_ERR;
  1355. fExcRecd = TRUE;
  1356. }
  1357. if (!fExcRecd && (StatusInfo.StatCode == NMSDB_SUCCESS))
  1358. {
  1359. WinsIntfStat.Counters.NoOfSuccRel++;
  1360. }
  1361. else
  1362. {
  1363. WinsIntfStat.Counters.NoOfFailRel++;
  1364. }
  1365. LeaveCriticalSection(&NmsNmhNamRegCrtSec);
  1366. //DBG_PRINT_PERF_DATA
  1367. }
  1368. //
  1369. // Send a response only it is not an administrator initiated request
  1370. //
  1371. if (!fAdmin)
  1372. {
  1373. if (!fExcRecd)
  1374. {
  1375. RspInfo.Rcode_e =
  1376. ((StatusInfo.StatCode == NMSDB_SUCCESS)
  1377. && (RetStat == WINS_SUCCESS)) ?
  1378. NMSMSGF_E_SUCCESS :
  1379. NMSMSGF_E_ACT_ERR;
  1380. }
  1381. RspInfo.pMsg = pMsg;
  1382. RspInfo.MsgLen = MsgLen;
  1383. RspInfo.QuesNamSecLen = QuesNamSecLen;
  1384. //
  1385. // If it is a locally registered name, mark it as such
  1386. //
  1387. if (StatusInfo.fLocal)
  1388. {
  1389. COMM_SET_LOCAL_M(pDlgHdl);
  1390. }
  1391. //
  1392. //Note: We always return the NodeType and Address that we got
  1393. //in the request pkt. So the above fields are all that
  1394. //need to be initialized
  1395. //
  1396. DBGPRINT1(FLOW, "NmsNmhNamRel: Name Release was %s\n",
  1397. RspInfo.Rcode_e == NMSMSGF_E_SUCCESS ?
  1398. "SUCCESSFUL" : "FAILURE" );
  1399. #if 0
  1400. WINSEVT_LOG_IF_ERR_M(
  1401. SndNamRelRsp(
  1402. pDlgHdl,
  1403. &RspInfo
  1404. ),
  1405. WINS_EVT_SND_REL_RSP_ERR
  1406. );
  1407. #endif
  1408. SndNamRelRsp( pDlgHdl, &RspInfo);
  1409. }
  1410. else // an RPC request
  1411. {
  1412. if (
  1413. (StatusInfo.StatCode != NMSDB_SUCCESS)
  1414. ||
  1415. (RetStat != WINS_SUCCESS)
  1416. )
  1417. {
  1418. DBGLEAVE("NmsNmhNamRel\n");
  1419. return(WINS_FAILURE);
  1420. }
  1421. }
  1422. DBGLEAVE("NmsNmhNamRel\n");
  1423. return(WINS_SUCCESS);
  1424. } //NmsNmhNamRel()
  1425. STATUS
  1426. NmsNmhNamQuery(
  1427. IN PCOMM_HDL_T pDlgHdl, //dlg handle
  1428. IN LPBYTE pName, //Name to release
  1429. IN DWORD NameLen, //length of name to release
  1430. IN MSG_T pMsg, //length of message
  1431. IN MSG_LEN_T MsgLen, //length of message
  1432. IN DWORD QuesNamSecLen, //length of question name
  1433. //sec. in msg
  1434. IN BOOL fAdmin,
  1435. OUT PNMSDB_STAT_INFO_T pStatInfo
  1436. )
  1437. /*++
  1438. Routine Description:
  1439. This function queries a record.
  1440. In case the query succeeds, a positive name query
  1441. response is sent, else a negative name query response is sent.
  1442. Arguments:
  1443. pDlgHdl - Dialogue Handle
  1444. pName - Name to be registered
  1445. NameLen - Length of Name
  1446. pMsg - Datagram received (i.e. the name request)
  1447. Msglen - Length of message
  1448. QuesNamSecLen - Length of the Question Name Section in the RFC packet
  1449. fAdmin - Is it an administrative action
  1450. pStatInfo - ptr to row information retrieved by this function
  1451. Externals Used:
  1452. None
  1453. Return Value:
  1454. Success status codes -- WINS_SUCCESS
  1455. Error status codes -- WINS_FAILURE
  1456. Error Handling:
  1457. Called by:
  1458. NmsMsgfProcNbtReq, WinsRecordAction
  1459. Side Effects:
  1460. Comments:
  1461. None
  1462. --*/
  1463. {
  1464. NMSDB_ROW_INFO_T RowInfo; // contains row info
  1465. NMSDB_STAT_INFO_T StatusInfo; /* error status and associated
  1466. *info returned by the NmsDb func
  1467. */
  1468. time_t ltime;
  1469. STATUS RetStat = WINS_SUCCESS;
  1470. BOOL fBrowser = FALSE;
  1471. BOOL fExcRecd = FALSE;
  1472. NMSMSGF_RSP_INFO_T RspInfo;
  1473. #ifdef WINSDBG
  1474. DWORD StartTimeInMsec;
  1475. // DWORD EndTimeInMsec;
  1476. #endif
  1477. DBGENTER("NmsNmhNamQuery\n");
  1478. /*
  1479. * Initialize the row info. data structure with the
  1480. * name of the entry to query
  1481. *
  1482. */
  1483. RowInfo.pName = pName;
  1484. RowInfo.NameLen = NameLen;
  1485. RowInfo.fAdmin = fAdmin;
  1486. DBGPRINT2(FLOW,
  1487. "NmsNmhNamQuery: Name To Query = %s. 16th char is (%x)\n",
  1488. RowInfo.pName, *(RowInfo.pName+15));
  1489. //
  1490. // get the current time.
  1491. //
  1492. // This is required when querying special groups
  1493. //
  1494. (void)time(&ltime); //time does not return any error code
  1495. RowInfo.TimeStamp = ltime; // put current time here
  1496. //
  1497. // This initialization is required when query is for a special group
  1498. //
  1499. CHECK("I don't think this is required now. Check NmsDbQueryRow")
  1500. RowInfo.NodeAdds.Mem[0].Add.Add.IPAdd = 0; //init to 0 since GetGrpMem
  1501. //looks at it
  1502. FUTURES("Don't check. Let it query. The query will fail")
  1503. if (NMSDB_IS_IT_BROWSER_NM_M(RowInfo.pName))
  1504. {
  1505. //
  1506. // It is a browser name. We always return a negative
  1507. // name query response.
  1508. //
  1509. fBrowser = TRUE;
  1510. StatusInfo.StatCode = NMSDB_SUCCESS;
  1511. RetStat = WINS_FAILURE;
  1512. }
  1513. else
  1514. {
  1515. try {
  1516. #ifdef WINSDBG
  1517. IF_DBG(TM) { StartTimeInMsec = GetTickCount(); }
  1518. #endif
  1519. //
  1520. // Query the record in the directory.
  1521. //
  1522. RetStat = NmsDbQueryRow(
  1523. &RowInfo,
  1524. &StatusInfo
  1525. );
  1526. #ifdef WINSDBG
  1527. IF_DBG(TM) { DBGPRINT2(TM, "NmsNmhNamQuery: Time in NmsDbQueryRow is = (%d). RetStat is (%d msecs)\n", GetTickCount() - StartTimeInMsec, RetStat); }
  1528. #endif
  1529. } // end of try block
  1530. except (EXCEPTION_EXECUTE_HANDLER) {
  1531. DBGPRINTEXC("NmsNmhNamQuery");
  1532. WINSEVT_LOG_D_M(GetExceptionCode(), WINS_EVT_NAM_QUERY_ERR);
  1533. RspInfo.Rcode_e = NMSMSGF_E_SRV_ERR;
  1534. fExcRecd = TRUE;
  1535. }
  1536. }
  1537. //
  1538. // Do the following only if not invoked in an RPC thread (i.e. via
  1539. // an administrator)
  1540. //
  1541. if (!fAdmin)
  1542. {
  1543. //
  1544. // if no exception was raised
  1545. //
  1546. if (!fExcRecd)
  1547. {
  1548. FUTURES("Rcode for neg, response should be different for different error cases")
  1549. RspInfo.Rcode_e =
  1550. ((StatusInfo.StatCode == NMSDB_SUCCESS)
  1551. && (RetStat == WINS_SUCCESS)) ?
  1552. NMSMSGF_E_SUCCESS :
  1553. NMSMSGF_E_NAM_ERR;
  1554. if (RspInfo.Rcode_e == NMSMSGF_E_SUCCESS)
  1555. {
  1556. DBGPRINT1(SPEC,
  1557. "Name queried has the fLocal flag set to %d\n",
  1558. StatusInfo.fLocal);
  1559. if (!StatusInfo.fLocal)
  1560. {
  1561. //
  1562. // if this was a query for a special group, we
  1563. // need to query the corresponding 1B name
  1564. //
  1565. #ifdef WINSDBG
  1566. if (NMSDB_IS_IT_DOMAIN_NM_M(RowInfo.pName))
  1567. {
  1568. DBGPRINT2(SPEC,
  1569. "Answer 1C query (%d members). %s1B prepended\n",
  1570. StatusInfo.NodeAdds.NoOfMems,
  1571. WinsCnf.fAdd1Bto1CQueries ? "" : "No ");
  1572. }
  1573. #endif
  1574. if (NMSDB_IS_IT_DOMAIN_NM_M(RowInfo.pName) &&
  1575. WinsCnf.fAdd1Bto1CQueries)
  1576. {
  1577. NMSDB_ROW_INFO_T StatusInfo2;
  1578. BOOL fExc = FALSE;
  1579. *(RowInfo.pName+15) = 0x1B;
  1580. WINS_SWAP_BYTES_M(RowInfo.pName, RowInfo.pName+15);
  1581. try {
  1582. //
  1583. // Query the record in the directory.
  1584. //
  1585. RetStat = NmsDbQueryRow(
  1586. &RowInfo,
  1587. &StatusInfo2
  1588. );
  1589. } // end of try block
  1590. except (EXCEPTION_EXECUTE_HANDLER) {
  1591. DBGPRINTEXC("NmsNmhNamQuery: Querying 1B name");
  1592. WINSEVT_LOG_D_M(
  1593. GetExceptionCode(),
  1594. WINS_EVT_NAM_QUERY_ERR
  1595. );
  1596. fExc = TRUE;
  1597. }
  1598. //
  1599. // If there was no exception or failure, add the
  1600. // address for the 1B name to the list. Ideally,
  1601. // we should check if the address is already there
  1602. // and if so not add it. If not there but the
  1603. // number of members is < NMSDB_MAX_MEMS_IN_GRP, we
  1604. // should add the address at the begining shifting
  1605. // the other members one slot to the right (
  1606. // instead of replacing the last member with the
  1607. // first). Checking for presence or doing the
  1608. // shifting will consume a lot of cycles, so it
  1609. // is not being done.
  1610. //
  1611. if ((RetStat != WINS_FAILURE) && !fExc)
  1612. {
  1613. if (
  1614. StatusInfo.NodeAdds.NoOfMems <
  1615. NMSDB_MAX_MEMS_IN_GRP
  1616. )
  1617. {
  1618. StatusInfo.NodeAdds.Mem[
  1619. StatusInfo.NodeAdds.NoOfMems++] =
  1620. StatusInfo.NodeAdds.Mem[0];
  1621. StatusInfo.NodeAdds.Mem[0] =
  1622. StatusInfo2.NodeAdds.Mem[0];
  1623. }
  1624. else
  1625. {
  1626. StatusInfo.NodeAdds.Mem[NMSDB_MAX_MEMS_IN_GRP- 1]
  1627. = StatusInfo.NodeAdds.Mem[0];
  1628. StatusInfo.NodeAdds.Mem[0] =
  1629. StatusInfo2.NodeAdds.Mem[0];
  1630. }
  1631. }
  1632. }
  1633. } //if (!StatusInfo.fLocal)
  1634. else
  1635. {
  1636. COMM_SET_LOCAL_M(pDlgHdl);
  1637. }
  1638. } //if (RspInfo.Rcode_e == NMSMSGF_E_SUCCESS)
  1639. } //if (!ExcCode)
  1640. RspInfo.pMsg = pMsg;
  1641. RspInfo.MsgLen = MsgLen;
  1642. RspInfo.QuesNamSecLen = QuesNamSecLen;
  1643. RspInfo.NodeTyp_e = StatusInfo.NodeTyp;
  1644. RspInfo.EntTyp = StatusInfo.EntTyp;
  1645. RspInfo.pNodeAdds = &StatusInfo.NodeAdds;
  1646. //
  1647. // NOTE: Multiple NBT threads could be doing this simultaneously
  1648. //
  1649. // This is the best I can do without a critical section
  1650. //
  1651. NOTE("The count may not be correct if we have multiple worker threads")
  1652. if (RspInfo.Rcode_e == NMSMSGF_E_SUCCESS)
  1653. {
  1654. WinsIntfStat.Counters.NoOfSuccQueries++;
  1655. }
  1656. else
  1657. {
  1658. #if TEST_DATA > 0
  1659. DWORD BytesWritten;
  1660. if (NmsFileHdl != INVALID_HANDLE_VALUE)
  1661. {
  1662. pName[NameLen - 1] = '\n';
  1663. pName[NameLen] = '\0';
  1664. if (!WriteFile(NmsFileHdl,
  1665. pName,
  1666. NameLen + 1,
  1667. &BytesWritten,
  1668. NULL
  1669. )
  1670. )
  1671. {
  1672. DBGPRINT1(ERR, "Could not write name (%s) to file\n", pName);
  1673. }
  1674. }
  1675. #endif
  1676. WinsIntfStat.Counters.NoOfFailQueries++;
  1677. }
  1678. DBGPRINT1(FLOW, "NmsNmhNamQuery: %s in querying record\n",
  1679. RspInfo.Rcode_e == NMSMSGF_E_SUCCESS ?
  1680. "SUCCEEDED" : "FAILED" );
  1681. WINSEVT_LOG_IF_ERR_M(
  1682. SndNamQueryRsp(
  1683. pDlgHdl,
  1684. &RspInfo
  1685. ),
  1686. WINS_EVT_SND_QUERY_RSP_ERR
  1687. );
  1688. }
  1689. else
  1690. {
  1691. //
  1692. // We are in an RPC thread.
  1693. //
  1694. if (
  1695. (RetStat != WINS_SUCCESS)
  1696. ||
  1697. (StatusInfo.StatCode != NMSDB_SUCCESS)
  1698. )
  1699. {
  1700. DBGLEAVE("NmsNmhNamQuery\n");
  1701. return(WINS_FAILURE);
  1702. }
  1703. else
  1704. {
  1705. DWORD i;
  1706. pStatInfo->NodeAdds.NoOfMems =
  1707. StatusInfo.NodeAdds.NoOfMems;
  1708. for (i=0; i < StatusInfo.NodeAdds.NoOfMems; i++)
  1709. {
  1710. pStatInfo->NodeAdds.Mem[i].Add =
  1711. StatusInfo.NodeAdds.Mem[i].Add;
  1712. pStatInfo->NodeAdds.Mem[i].OwnerId =
  1713. StatusInfo.NodeAdds.Mem[i].OwnerId;
  1714. pStatInfo->NodeAdds.Mem[i].TimeStamp =
  1715. StatusInfo.NodeAdds.Mem[i].TimeStamp;
  1716. }
  1717. pStatInfo->VersNo = StatusInfo.VersNo;
  1718. pStatInfo->OwnerId = StatusInfo.OwnerId;
  1719. pStatInfo->EntTyp = StatusInfo.EntTyp;
  1720. pStatInfo->TimeStamp = StatusInfo.TimeStamp;
  1721. pStatInfo->NodeTyp = StatusInfo.NodeTyp;
  1722. pStatInfo->EntryState_e = StatusInfo.EntryState_e;
  1723. pStatInfo->fStatic = StatusInfo.fStatic;
  1724. }
  1725. }
  1726. DBGLEAVE("NmsNmhNamQuery\n");
  1727. return(WINS_SUCCESS);
  1728. } //NmsNmhNamQuery()
  1729. VOID
  1730. NmsNmhSndNamRegRsp(
  1731. IN PCOMM_HDL_T pDlgHdl,
  1732. IN PNMSMSGF_RSP_INFO_T pRspInfo
  1733. )
  1734. /*++
  1735. Routine Description:
  1736. This function sends the name registration response to the nbt client.
  1737. Arguments:
  1738. pDlgHdl - Dialogue Handle
  1739. pRspInfo - pointer to the response info structure
  1740. Externals Used:
  1741. None
  1742. Return Value:
  1743. None
  1744. Error Handling:
  1745. Called by:
  1746. Side Effects:
  1747. Comments:
  1748. None
  1749. --*/
  1750. {
  1751. DBGENTER("NmsNmhSndNamRegRsp\n");
  1752. /*
  1753. * format the name registration response packet
  1754. */
  1755. NmsMsgfFrmNamRspMsg(
  1756. pDlgHdl,
  1757. NMSMSGF_E_NAM_REG,
  1758. pRspInfo
  1759. );
  1760. /*
  1761. * Call COMM to send it. No need to check the return status
  1762. */
  1763. (VOID)ECommSndRsp(
  1764. pDlgHdl,
  1765. pRspInfo->pMsg,
  1766. pRspInfo->MsgLen
  1767. );
  1768. /*
  1769. * Deallocate the Buffer
  1770. */
  1771. ECommFreeBuff(pRspInfo->pMsg);
  1772. DBGLEAVE("NmsNmhSndNamRegRsp\n");
  1773. return;
  1774. } //NmsNmhSndNamRegRsp()
  1775. FUTURES("change return type of this function to VOID")
  1776. STATUS
  1777. SndNamRelRsp(
  1778. IN PCOMM_HDL_T pDlgHdl,
  1779. IN PNMSMSGF_RSP_INFO_T pRspInfo
  1780. )
  1781. /*++
  1782. Routine Description:
  1783. This function sends the name release response to the nbt client.
  1784. Arguments:
  1785. pDlgHdl - Dialogue Handle
  1786. pRspInfo - Response Info
  1787. Externals Used:
  1788. None
  1789. Return Value:
  1790. Success status codes --
  1791. Error status codes --
  1792. Error Handling:
  1793. Called by:
  1794. Side Effects:
  1795. Comments:
  1796. None
  1797. --*/
  1798. {
  1799. DBGENTER("SndNamRelRsp\n");
  1800. /*
  1801. format the name registration response packet
  1802. */
  1803. NmsMsgfFrmNamRspMsg(
  1804. pDlgHdl,
  1805. NMSMSGF_E_NAM_REL,
  1806. pRspInfo
  1807. );
  1808. /*
  1809. * Call COMM to send it. No need to check the return status
  1810. */
  1811. (VOID)ECommSndRsp(
  1812. pDlgHdl,
  1813. pRspInfo->pMsg,
  1814. pRspInfo->MsgLen
  1815. );
  1816. /*
  1817. * Deallocate the Buffer
  1818. */
  1819. ECommFreeBuff(pRspInfo->pMsg);
  1820. DBGLEAVE("SndNamRelRsp\n");
  1821. return(WINS_SUCCESS);
  1822. } // SndNamRelRsp()
  1823. STATUS
  1824. SndNamQueryRsp(
  1825. IN PCOMM_HDL_T pDlgHdl,
  1826. IN PNMSMSGF_RSP_INFO_T pRspInfo
  1827. )
  1828. /*++
  1829. Routine Description:
  1830. This function sends the name registration response to the nbt client.
  1831. Arguments:
  1832. pDlgHdl - Dialogue Handle
  1833. pRspInfo - Response Info
  1834. Externals Used:
  1835. None
  1836. Return Value:
  1837. Success status codes --
  1838. Error status codes --
  1839. Error Handling:
  1840. Called by:
  1841. Side Effects:
  1842. Comments:
  1843. None
  1844. --*/
  1845. {
  1846. DBGENTER("SndNamQueryRsp\n");
  1847. /*
  1848. format the name registration response packet
  1849. */
  1850. NmsMsgfFrmNamRspMsg(
  1851. pDlgHdl,
  1852. NMSMSGF_E_NAM_QUERY,
  1853. pRspInfo
  1854. );
  1855. /*
  1856. * Call COMM to send it. No need to check the return status
  1857. */
  1858. (VOID)ECommSndRsp(
  1859. pDlgHdl,
  1860. pRspInfo->pMsg,
  1861. pRspInfo->MsgLen
  1862. );
  1863. FUTURES("When we start supporting responses > COMM_DATAGRAM_SIZE, the ")
  1864. FUTURES("deallocation call will have to change")
  1865. /*
  1866. * Deallocate the Buffer
  1867. */
  1868. ECommFreeBuff(pRspInfo->pMsg);
  1869. DBGLEAVE("SndNamQueryRsp\n");
  1870. return(WINS_SUCCESS);
  1871. } // SndNamQueryRsp()
  1872. STATUS
  1873. ClashAtRegInd (
  1874. IN PNMSDB_ROW_INFO_T pEntryToReg,
  1875. IN PNMSDB_STAT_INFO_T pEntryInCnf,
  1876. IN BOOL fRefresh,
  1877. OUT PBOOL pfUpdate,
  1878. OUT PBOOL pfUpdVersNo,
  1879. OUT PBOOL pfChallenge,
  1880. OUT PBOOL pfAddMem,
  1881. OUT PBOOL pfAddDiff,
  1882. OUT PBOOL pfRetPosRsp
  1883. )
  1884. /*++
  1885. Routine Description:
  1886. This function is called when there is a clash at the registrationo of a unique entry sent by an NBT node
  1887. Arguments:
  1888. pEntryToReg -- Entry that couldn't be registered due to conflict
  1889. pEntryInCnf -- Entry in conflict
  1890. fRefresh -- indicates whether it is a registration or a refresh
  1891. (used only when the clash is with a multihomed entry)
  1892. pfUpdate -- TRUE means Entry should overwrite the conflicting one
  1893. pfUpdVersNo -- TRUE means Entry's version number should be incremented
  1894. This arg. can never be TRUE if *pfUpdate is not TRUE
  1895. pfChallenge -- TRUE means that conflicting entry should be challenged
  1896. pfAddDiff -- TRUE means that the address of the conflicting entry
  1897. needs to be changed (besides other fields like timestamp owner id, etc). If *pfChallenge is TRUE, this field
  1898. is FALSE since *pfChallenge of TRUE implies address
  1899. change when the challenge succeeds
  1900. Externals Used:
  1901. None
  1902. Return Value:
  1903. Success status codes -- WINS_SUCCESS
  1904. Error status codes -- WINS_FAILURE
  1905. Error Handling:
  1906. Called by:
  1907. NmsNmhNamRegInd, NmsNmhNamRegGrp
  1908. Side Effects:
  1909. Comments:
  1910. None
  1911. --*/
  1912. {
  1913. NMSDB_ENTRY_STATE_E StateOfEntryToReg_e = pEntryToReg->EntryState_e;
  1914. NMSDB_ENTRY_STATE_E StateOfEntryInCnf_e = pEntryInCnf->EntryState_e;
  1915. STATUS RetStat = WINS_SUCCESS;
  1916. DWORD CompAddRes; /*Result of comparing addresses*/
  1917. BOOL fOwned;
  1918. BOOL fFound;
  1919. //
  1920. // We are reading a long value. This operation is atomic
  1921. //
  1922. BOOL fPStatic = WinsCnf.fPStatic;
  1923. BOOL fContToDyn = FALSE;
  1924. DBGENTER("ClashAtRegInd\n");
  1925. *pfUpdate = FALSE;
  1926. *pfUpdVersNo = FALSE;
  1927. *pfChallenge = FALSE;
  1928. *pfAddMem = FALSE;
  1929. *pfAddDiff = FALSE;
  1930. *pfRetPosRsp = FALSE;
  1931. //
  1932. // If the conflicting record was statically initialized and
  1933. //
  1934. if ( pEntryInCnf->fStatic )
  1935. {
  1936. DBGPRINT0(FLOW, "ClashAtRegInd: Clash with a STATIC record\n");
  1937. //
  1938. // If entry in conflict is a unique/multihomd entry, we
  1939. // compare the address.
  1940. //
  1941. //
  1942. // Since in the majority of cases, the conflict will be
  1943. // with a unique record, we first check whether the
  1944. // conflicting record is unique. This saves some cyles.
  1945. // The alternative way would have been to check whether
  1946. // conflicting record is a group and if not do the for loop
  1947. // For the case where the record was unique, the for loop
  1948. // would have executed only once.
  1949. //
  1950. if (NMSDB_ENTRY_UNIQUE_M(pEntryInCnf->EntTyp))
  1951. {
  1952. CompAddRes = ECommCompAdd(
  1953. &pEntryInCnf->NodeAdds.Mem[0].Add,
  1954. pEntryToReg->pNodeAdd
  1955. );
  1956. }
  1957. else
  1958. {
  1959. DWORD NoOfEnt;
  1960. PNMSDB_GRP_MEM_ENTRY_T pCnfMem;
  1961. //
  1962. // Entry in conflict is a group or a mh entry
  1963. //
  1964. CompAddRes = COMM_DIFF_ADD;
  1965. if (fRefresh &&
  1966. NMSDB_ENTRY_MULTIHOMED_M(pEntryInCnf->EntTyp))
  1967. {
  1968. pCnfMem = pEntryInCnf->NodeAdds.Mem;
  1969. for (NoOfEnt = 0;
  1970. NoOfEnt < pEntryInCnf->NodeAdds.NoOfMems;
  1971. pCnfMem++, NoOfEnt++)
  1972. {
  1973. //
  1974. // save on cycles by comparing just the IP
  1975. // address.
  1976. //
  1977. NONPORT("Change to stuff within #if 0 #endif when more than one transport")
  1978. NONPORT("is supported")
  1979. if (pCnfMem->Add.Add.IPAdd ==
  1980. pEntryToReg->pNodeAdd->Add.IPAdd)
  1981. {
  1982. CompAddRes = COMM_SAME_ADD;
  1983. break;
  1984. }
  1985. } // compare refresh add. with each add in the static
  1986. // mh entry
  1987. } //a refresh clashed with a static mh entry
  1988. } // conflicting entry is either multihomed or a group
  1989. #if 0
  1990. //
  1991. // Compare with address when the entry in conflict is
  1992. // not a group.
  1993. //
  1994. // NOTE: For multihomed entry, we are comparing with the
  1995. // first (perhaps only) address. Strictly speaking, we
  1996. // should compare with all addresses, but this will add
  1997. // to overhead for the majority of cases. See FUTURES
  1998. // above.
  1999. //
  2000. if (!NMSDB_ENTRY_GRP_M(pEntryInCnf->EntTyp))
  2001. {
  2002. CompAddRes = ECommCompAdd(
  2003. &pEntryInCnf->NodeAdds.Mem[0].Add,
  2004. pEntryToReg->pNodeAdd
  2005. );
  2006. }
  2007. else
  2008. {
  2009. CompAddRes = COMM_DIFF_ADD;
  2010. }
  2011. #endif
  2012. //
  2013. // If the record to register is not a STATIC record, we
  2014. // return right away. We don't update a STATIC record with a
  2015. // dynamic record in this function (do it in NmsDbQueryNUpd when
  2016. // called in an RPC thread -- see winsintf.c)
  2017. //
  2018. // If however the record to register is also STATIC, then we
  2019. // overwrite the one in the db with it.
  2020. //
  2021. if (pEntryToReg->fStatic)
  2022. {
  2023. //
  2024. // If addresses are different, we need to propagate
  2025. // the change right away. So, set the fAddDiff flag.
  2026. //
  2027. if (CompAddRes == COMM_DIFF_ADD)
  2028. {
  2029. *pfAddDiff = TRUE;
  2030. }
  2031. *pfUpdate = TRUE;
  2032. //
  2033. // If the address changed or if we replaced a STATIC
  2034. // replica, we should update the version number
  2035. // to initiate replication
  2036. //
  2037. if (
  2038. (pEntryInCnf->OwnerId != NMSDB_LOCAL_OWNER_ID)
  2039. ||
  2040. *pfAddDiff
  2041. )
  2042. {
  2043. *pfUpdVersNo = TRUE;
  2044. }
  2045. }
  2046. else // entry to register is dynamic
  2047. {
  2048. //
  2049. // If addresses are the same, we return a positive
  2050. // response
  2051. //
  2052. if (CompAddRes == COMM_SAME_ADD)
  2053. {
  2054. *pfRetPosRsp = TRUE;
  2055. }
  2056. else
  2057. {
  2058. if (fPStatic &&
  2059. !NMSDB_ENTRY_GRP_M(pEntryInCnf->EntTyp))
  2060. {
  2061. fContToDyn = TRUE;
  2062. }
  2063. }
  2064. }
  2065. //
  2066. // If we don't need to conduct the tests meant for dynamic
  2067. // records, return
  2068. //
  2069. if (!fContToDyn)
  2070. {
  2071. DBGLEAVE("ClashAtRegInd\n");
  2072. return(WINS_SUCCESS);
  2073. }
  2074. }
  2075. if (pEntryInCnf->EntTyp == NMSDB_UNIQUE_ENTRY)
  2076. {
  2077. switch(StateOfEntryInCnf_e)
  2078. {
  2079. case(NMSDB_E_TOMBSTONE):
  2080. *pfUpdate = TRUE;
  2081. *pfUpdVersNo = TRUE;
  2082. CompAddRes = ECommCompAdd(
  2083. &pEntryInCnf->NodeAdds.Mem[0].Add,
  2084. pEntryToReg->pNodeAdd
  2085. );
  2086. if (CompAddRes == COMM_DIFF_ADD)
  2087. {
  2088. *pfAddDiff = TRUE;
  2089. }
  2090. break;
  2091. case(NMSDB_E_RELEASED):
  2092. CompAddRes = ECommCompAdd(
  2093. &pEntryInCnf->NodeAdds.Mem[0].Add,
  2094. pEntryToReg->pNodeAdd
  2095. );
  2096. switch(CompAddRes)
  2097. {
  2098. case(COMM_SAME_ADD):
  2099. *pfUpdate = TRUE;
  2100. #if 0
  2101. //
  2102. // If database record is a replica, we need
  2103. // to overwrite it with the new one (owned by
  2104. // the local WINS). This means that we must
  2105. // update the version number to cause
  2106. // propagation
  2107. //
  2108. if (
  2109. pEntryInCnf->OwnerId !=
  2110. pEntryToReg->OwnerId
  2111. )
  2112. {
  2113. *pfUpdVersNo = TRUE;
  2114. }
  2115. #endif
  2116. //
  2117. // update the version number. Maybe this
  2118. // record never replicated to one or more
  2119. // WINS servers before. We should
  2120. // update the version number so that it gets
  2121. // replicated
  2122. //
  2123. *pfUpdVersNo = TRUE;
  2124. break;
  2125. //
  2126. // address is not same
  2127. //
  2128. default:
  2129. *pfUpdate = TRUE;
  2130. *pfUpdVersNo = TRUE;
  2131. *pfAddDiff = TRUE;
  2132. break;
  2133. }
  2134. break;
  2135. case(NMSDB_E_ACTIVE):
  2136. //
  2137. // We do the following only if the entry in
  2138. // conflict is a unique entry
  2139. //
  2140. // If it is a group entry (normal group), we give
  2141. // up trying to register.
  2142. //
  2143. CompAddRes = ECommCompAdd(
  2144. &pEntryInCnf->NodeAdds.Mem[0].Add,
  2145. pEntryToReg->pNodeAdd
  2146. );
  2147. switch(CompAddRes)
  2148. {
  2149. case(COMM_SAME_ADD):
  2150. //
  2151. // If it is a repeat name reg.
  2152. // just update the timestamp
  2153. //
  2154. if (pEntryInCnf->OwnerId ==
  2155. pEntryToReg->OwnerId)
  2156. {
  2157. *pfUpdate = TRUE;
  2158. }
  2159. else
  2160. {
  2161. //
  2162. // Clash is with a replica
  2163. // Update both the owner id and
  2164. // and the version number
  2165. //
  2166. *pfUpdate = TRUE;
  2167. *pfUpdVersNo = TRUE;
  2168. }
  2169. break;
  2170. default:
  2171. *pfChallenge = TRUE;
  2172. //
  2173. // No need to set the pAddDiff
  2174. // flag. The above flag implies that
  2175. //
  2176. break;
  2177. }
  2178. break;
  2179. default:
  2180. DBGPRINT1(ERR,
  2181. "ClashAtRegInd: Weird state of entry in cnf (%d)\n",
  2182. StateOfEntryInCnf_e
  2183. );
  2184. WINSEVT_LOG_M(WINS_FAILURE, WINS_EVT_SFT_ERR);
  2185. RetStat = WINS_FAILURE;
  2186. break;
  2187. }
  2188. }
  2189. else //conflicting entry is a group or a multihomed entry
  2190. {
  2191. //
  2192. // There are two type of group records
  2193. //
  2194. // Normal group -- do not contain any addresses in them so there
  2195. // is no challenge to be done here.
  2196. // Special group -- store addresses in them but the members are
  2197. // not supposed to be challenged.
  2198. //
  2199. CHECK("According to the Func. Spec. Page 14, footnote 3, we are supposed")
  2200. CHECK("to reject the unique registration regardless of the state of a group")
  2201. CHECK("--Normal or Special. Think this one through")
  2202. if (
  2203. (NMSDB_ENTRY_GRP_M(pEntryInCnf->EntTyp))
  2204. &&
  2205. (StateOfEntryInCnf_e == NMSDB_E_TOMBSTONE)
  2206. )
  2207. {
  2208. *pfUpdate = TRUE;
  2209. *pfUpdVersNo = TRUE;
  2210. }
  2211. else // conflicting record is not a tombstone special group
  2212. {
  2213. if (NMSDB_ENTRY_MULTIHOMED_M(pEntryInCnf->EntTyp))
  2214. {
  2215. //
  2216. // If the multihomed entry is active
  2217. //
  2218. if(StateOfEntryInCnf_e == NMSDB_E_ACTIVE)
  2219. {
  2220. DBGPRINT3(SPEC, "ClashAtRegInd: Name to reg = (%s), Vers. No (%d, %d)\n", pEntryToReg->pName, pEntryToReg->VersNo.HighPart, pEntryToReg->VersNo.LowPart);
  2221. //
  2222. // MemInGrp will remove the entry from the
  2223. // conflicting record if present. That is what
  2224. // we want.
  2225. //
  2226. fFound = MemInGrp(
  2227. pEntryToReg->pNodeAdd,
  2228. pEntryInCnf,
  2229. &fOwned, FALSE);
  2230. //
  2231. // If this is a refresh
  2232. //
  2233. if (fFound && fRefresh)
  2234. {
  2235. DBGPRINT0(DET, "ClashAtRegInd: Refresh of a multihomed entry. Simple Update will be done\n");
  2236. *pfAddMem = TRUE;
  2237. if (!fOwned)
  2238. {
  2239. //
  2240. // It is a refresh for an
  2241. // address that is not owned
  2242. // by the local WINS
  2243. //
  2244. *pfUpdVersNo = TRUE;
  2245. }
  2246. }
  2247. else //either address was not found or it
  2248. //is a registration
  2249. {
  2250. //
  2251. // It is a registration, or a refresh
  2252. // for an address not found in the
  2253. // multihomed record.
  2254. //
  2255. // The active multihomed entry needs to
  2256. // be challenged if there is atleast one // address left in it.
  2257. //
  2258. if (pEntryInCnf->NodeAdds.NoOfMems > 0)
  2259. {
  2260. DBGPRINT0(DET, "ClashAtRegInd: Clash with a multihomed entry. Atleast one address is different. Resorting to challenge\n");
  2261. *pfChallenge = TRUE;
  2262. }
  2263. else
  2264. {
  2265. DBGPRINT0(DET, "ClashAtRegInd: Clash with a multihomed entry. Addresses match. Will do simple update\n");
  2266. //ASSERT(fFound);
  2267. if (!fOwned)
  2268. {
  2269. *pfUpdVersNo = TRUE;
  2270. }
  2271. //
  2272. // Update the entry
  2273. //
  2274. *pfUpdate = TRUE;
  2275. }
  2276. }
  2277. }
  2278. else //multihomed entry in conflict is a
  2279. //tombstone or released
  2280. {
  2281. *pfUpdate = TRUE;
  2282. *pfUpdVersNo = TRUE;
  2283. }
  2284. }
  2285. //
  2286. // if the conflicting entry is not a tombstone special
  2287. // group and is not multihomed (i.e. it is a normal
  2288. // group or active/released special group), we
  2289. // do nothing (i.e. reject the registration)
  2290. //
  2291. }
  2292. }
  2293. DBGLEAVE("ClashAtRegInd\n");
  2294. return(RetStat);
  2295. } // ClashAtRegInd()
  2296. STATUS
  2297. ClashAtRegGrp (
  2298. IN PNMSDB_ROW_INFO_T pEntryToReg,
  2299. IN PNMSDB_STAT_INFO_T pEntryInCnf,
  2300. IN BOOL fRefresh,
  2301. OUT PBOOL pfAddMem,
  2302. OUT PBOOL pfUpdate,
  2303. OUT PBOOL pfUpdVersNo,
  2304. OUT PBOOL pfChallenge,
  2305. OUT PBOOL pfRetPosRsp
  2306. )
  2307. /*++
  2308. Routine Description:
  2309. This function is called when there is a clash at registration time
  2310. of a group entry
  2311. Arguments:
  2312. pEntryToReg -- Entry that couldn't be registered due to conflict
  2313. pEntryInCnf -- Entry in conflict
  2314. pfAddMem -- TRUE means that the member should be added to group
  2315. pfUpdate -- TRUE means Entry should overwrite the conflicting one
  2316. pfUpdVersNo -- TRUE means Entry's version number should be incremented
  2317. This arg. can never be TRUE if *pfUpdate is not TRUE
  2318. pfChallenge -- TRUE means that conflicting entry should be challenged
  2319. pfRetPosRsp -- TRUE means that we should return a positive response.
  2320. This will be TRUE only if all other flags are
  2321. FALSE
  2322. Externals Used:
  2323. None
  2324. Return Value:
  2325. Success status codes -- WINS_SUCCESS
  2326. Error status codes -- WINS_FAILURE
  2327. Error Handling:
  2328. Called by:
  2329. NmsNmhNamRegGrp
  2330. Side Effects:
  2331. Comments:
  2332. None
  2333. --*/
  2334. {
  2335. NMSDB_ENTRY_STATE_E StateOfEntryToReg_e = pEntryToReg->EntryState_e;
  2336. NMSDB_ENTRY_STATE_E StateOfEntryInCnf_e = pEntryInCnf->EntryState_e;
  2337. STATUS RetStat = WINS_SUCCESS;
  2338. BOOL fOwned;
  2339. DWORD i;
  2340. BOOL fFound;
  2341. //
  2342. // We are reading a long value. This operation is atomic
  2343. //
  2344. BOOL fPStatic = WinsCnf.fPStatic;
  2345. BOOL fContToDyn = FALSE;
  2346. DBGENTER("ClashAtRegGrp\n");
  2347. *pfAddMem = FALSE;
  2348. *pfUpdate = FALSE;
  2349. *pfUpdVersNo = FALSE;
  2350. *pfChallenge = FALSE;
  2351. *pfRetPosRsp = FALSE;
  2352. //
  2353. // If the conflicting record was statically initialized and
  2354. // we haven't been told to treat static records as P-static or
  2355. // if the record to register is also a static record, do the following.
  2356. //
  2357. if ( pEntryInCnf->fStatic )
  2358. {
  2359. DBGPRINT0(FLOW, "ClashAtRegGrp: Clash with a STATIC record\n");
  2360. if (pEntryToReg->fStatic)
  2361. {
  2362. if (
  2363. ((pEntryToReg->EntTyp == NMSDB_SPEC_GRP_ENTRY)
  2364. &&
  2365. (pEntryInCnf->EntTyp == NMSDB_SPEC_GRP_ENTRY))
  2366. ||
  2367. ((pEntryToReg->EntTyp == NMSDB_MULTIHOMED_ENTRY)
  2368. &&
  2369. (pEntryInCnf->EntTyp == NMSDB_MULTIHOMED_ENTRY))
  2370. )
  2371. {
  2372. // *pfAddMem = TRUE;
  2373. //
  2374. // We are not interested in finding out whether
  2375. // the address exists or not. If it exists, it
  2376. // won't after the following call.
  2377. //
  2378. for (i=0; i < pEntryToReg->NodeAdds.NoOfMems; i++)
  2379. {
  2380. (VOID)MemInGrp(&pEntryToReg->NodeAdds.Mem[i].Add,
  2381. pEntryInCnf,
  2382. &fOwned, FALSE);
  2383. //
  2384. //fOwned will be FALSE if either the address does
  2385. //not exist or if it existed but was owned by
  2386. //another WINS server. For both cases, we update
  2387. //the version number.
  2388. //NOTE: In case the address exists but is a
  2389. //permanent one (TimeStamp == MAXULONG), fOwned
  2390. //returned will be TRUE. This will result
  2391. //in us skipping the update.
  2392. //Currently MAXULONG is there only for static
  2393. //SG members.
  2394. //
  2395. if (!*pfUpdVersNo && !fOwned)
  2396. {
  2397. *pfUpdVersNo = TRUE;
  2398. *pfAddMem = TRUE;
  2399. }
  2400. }
  2401. if (!*pfUpdVersNo)
  2402. {
  2403. *pfRetPosRsp = TRUE;
  2404. }
  2405. } // both are special groups or mh names
  2406. else
  2407. {
  2408. *pfUpdate = TRUE;
  2409. *pfUpdVersNo = TRUE;
  2410. }
  2411. }
  2412. else // entry to register is a dynamic entry
  2413. {
  2414. //
  2415. // We send a positive response if a normal group
  2416. // clashes with a statically initialized normal group
  2417. //
  2418. if ( NMSDB_ENTRY_NORM_GRP_M(pEntryToReg->EntTyp) )
  2419. {
  2420. if (NMSDB_ENTRY_NORM_GRP_M(pEntryInCnf->EntTyp))
  2421. {
  2422. *pfRetPosRsp = TRUE;
  2423. }
  2424. //
  2425. // if the entry in conflict is a special group, we add
  2426. // this (potential) new group member to the list of members.
  2427. // Note: we do not touch multi-homed or unique static
  2428. // entry.
  2429. //
  2430. else if ( NMSDB_ENTRY_SPEC_GRP_M(pEntryInCnf->EntTyp) )
  2431. {
  2432. //
  2433. //NOTE: In case the address exists but is a
  2434. // perm. one (TimeStamp == MAXULONG), fOwned
  2435. // returned will be TRUE. This will result
  2436. // in us skipping the update. Currently
  2437. // MAXULONG is there only for static
  2438. // SG members.
  2439. //
  2440. (VOID)MemInGrp(
  2441. &pEntryToReg->NodeAdds.Mem[0].Add,
  2442. pEntryInCnf,
  2443. &fOwned, TRUE);
  2444. if (!fOwned)
  2445. {
  2446. *pfUpdVersNo = TRUE;
  2447. *pfAddMem = TRUE;
  2448. pEntryToReg->fStatic = TRUE;
  2449. pEntryToReg->EntTyp = NMSDB_SPEC_GRP_ENTRY;
  2450. }
  2451. } else {
  2452. //
  2453. // the entry in conflict is either unique or multihomed
  2454. //
  2455. DBGPRINT1(FLOW, "ClashAtRegGrp: Conflict of a NORM. GRP (to reg) with a STATIC ACTIVE %s entry.\n",
  2456. NMSDB_ENTRY_MULTIHOMED_M(pEntryInCnf->EntTyp) ? "MULTIHOMED" : "UNIQUE");
  2457. //
  2458. // if we are told to treat static as P-Static, then do the challenge etc.
  2459. //
  2460. if (fPStatic)
  2461. {
  2462. fContToDyn = TRUE;
  2463. }
  2464. }
  2465. }
  2466. else
  2467. {
  2468. if (
  2469. (NMSDB_ENTRY_SPEC_GRP_M(pEntryInCnf->EntTyp))
  2470. &&
  2471. (NMSDB_ENTRY_SPEC_GRP_M(pEntryToReg->EntTyp))
  2472. )
  2473. {
  2474. //
  2475. // Always send a positive response, even
  2476. // though we are not adding the address to
  2477. // the list
  2478. //
  2479. *pfRetPosRsp = TRUE;
  2480. } // both entries are special group entries
  2481. else
  2482. {
  2483. if (fPStatic && !NMSDB_ENTRY_GRP_M(pEntryInCnf->EntTyp))
  2484. {
  2485. fContToDyn = TRUE;
  2486. }
  2487. else
  2488. {
  2489. if (
  2490. NMSDB_ENTRY_MULTIHOMED_M(pEntryToReg->EntTyp)
  2491. &&
  2492. (NMSDB_ENTRY_MULTIHOMED_M(pEntryInCnf->EntTyp) ||
  2493. NMSDB_ENTRY_UNIQUE_M(pEntryInCnf->EntTyp))
  2494. )
  2495. {
  2496. DWORD NoOfMem;
  2497. PNMSDB_GRP_MEM_ENTRY_T pCnfMem =
  2498. pEntryInCnf->NodeAdds.Mem;
  2499. for (NoOfMem=0;
  2500. NoOfMem < pEntryInCnf->NodeAdds.NoOfMems;
  2501. pCnfMem++, NoOfMem++)
  2502. {
  2503. //
  2504. // if addresses are same, break out of
  2505. // the loop
  2506. //
  2507. if (pCnfMem->Add.Add.IPAdd ==
  2508. pEntryToReg->NodeAdds.Mem[0].Add.Add.IPAdd)
  2509. {
  2510. *pfRetPosRsp = TRUE;
  2511. break;
  2512. } //addresses match
  2513. } //for loop over all members
  2514. } //both entries are multihomed
  2515. } // Either PStatic flag is not set or the
  2516. // conflicting entry is not a group
  2517. } //one of the entries is not a special group
  2518. } //one of the entries is not a normal group
  2519. } //entry to reg is dynamic
  2520. //
  2521. // If we don't need to conduct the tests meant for dynamic
  2522. // records, return
  2523. //
  2524. if (!fContToDyn)
  2525. {
  2526. DBGLEAVE("ClashAtRegGrp\n");
  2527. return(WINS_SUCCESS);
  2528. }
  2529. }
  2530. //
  2531. // We are here means that entry in conflict is either dynamic or
  2532. // should be treated as a dynamic entry (p-dynamic)
  2533. //
  2534. if (pEntryToReg->EntTyp == NMSDB_SPEC_GRP_ENTRY)
  2535. {
  2536. if (pEntryInCnf->EntTyp == NMSDB_SPEC_GRP_ENTRY)
  2537. {
  2538. //
  2539. // If the entry is not active it means that it has
  2540. // no members.
  2541. //
  2542. // If it is active, we add the member if
  2543. // not there already.
  2544. //
  2545. if (StateOfEntryInCnf_e != NMSDB_E_ACTIVE)
  2546. {
  2547. *pfUpdate = TRUE;
  2548. *pfUpdVersNo = TRUE;
  2549. }
  2550. else // entry in conflict is an ACTIVE dynamic SG entry
  2551. {
  2552. //
  2553. // If Entry to register is static, we have got to
  2554. // do an update if for no other reason than to change
  2555. // the flags.
  2556. //
  2557. if (pEntryToReg->fStatic)
  2558. {
  2559. *pfAddMem = TRUE;
  2560. *pfUpdVersNo = TRUE;
  2561. for (i = 0;i < pEntryToReg->NodeAdds.NoOfMems;i++)
  2562. {
  2563. (VOID)MemInGrp(
  2564. &pEntryToReg->NodeAdds.Mem[i].Add,
  2565. pEntryInCnf,
  2566. &fOwned,
  2567. FALSE // no need to remove replica
  2568. );
  2569. }
  2570. }
  2571. else // entry to register is a dynamic SG entry
  2572. {
  2573. //
  2574. // We need to update the entry if for no other
  2575. // reason than to update the time stamp
  2576. //
  2577. *pfAddMem = TRUE;
  2578. //
  2579. // We are not interested in finding out whether
  2580. // the address exists or not. If it exists, it
  2581. // won't after the following call.
  2582. //
  2583. fFound = MemInGrp(&pEntryToReg->NodeAdds.Mem[0].Add,
  2584. pEntryInCnf,
  2585. &fOwned,
  2586. FALSE //no need to remove replica
  2587. //mem. That will be high
  2588. //overhead
  2589. );
  2590. //
  2591. // If entry is either not there or the record is
  2592. // a replica increment the version number.
  2593. //
  2594. if (!fFound ||
  2595. (pEntryInCnf->OwnerId != NMSDB_LOCAL_OWNER_ID))
  2596. {
  2597. *pfUpdVersNo = TRUE;
  2598. }
  2599. }
  2600. }
  2601. }
  2602. else //entry in conflict is a normal group or a
  2603. //unique/multihomed entry
  2604. {
  2605. if (pEntryInCnf->EntTyp == NMSDB_NORM_GRP_ENTRY)
  2606. {
  2607. CHECK("I may not want to update it. Check it")
  2608. *pfUpdate = TRUE;
  2609. *pfUpdVersNo = TRUE;
  2610. }
  2611. else //conflicting entry is a unique/multihomed entry
  2612. {
  2613. if (StateOfEntryInCnf_e == NMSDB_E_ACTIVE)
  2614. {
  2615. DBGPRINT1(FLOW, "ClashAtRegGrp: Conflict of a SPEC. GRP (to reg) with an ACTIVE %s entry. Resorting to challenge\n",
  2616. NMSDB_ENTRY_MULTIHOMED_M(pEntryInCnf->EntTyp) ?
  2617. "MULTIHOMED" : "UNIQUE");
  2618. if (
  2619. (NMSDB_ENTRY_MULTIHOMED_M(
  2620. pEntryInCnf->EntTyp)
  2621. &&
  2622. (pEntryInCnf->NodeAdds.NoOfMems > 0))
  2623. ||
  2624. NMSDB_ENTRY_UNIQUE_M(
  2625. pEntryInCnf->EntTyp)
  2626. )
  2627. {
  2628. *pfChallenge = TRUE;
  2629. }
  2630. else
  2631. {
  2632. *pfUpdate = TRUE;
  2633. *pfUpdVersNo = TRUE;
  2634. }
  2635. }
  2636. else // unique/multihomed entry is either released
  2637. // or a tombstone
  2638. {
  2639. *pfUpdate = TRUE;
  2640. *pfUpdVersNo = TRUE;
  2641. }
  2642. }
  2643. }
  2644. }
  2645. else // Entry to register is a normal group/multihomed entry
  2646. {
  2647. //
  2648. // If entry is a normal group
  2649. //
  2650. if (NMSDB_ENTRY_NORM_GRP_M(pEntryToReg->EntTyp))
  2651. {
  2652. switch(StateOfEntryInCnf_e)
  2653. {
  2654. case(NMSDB_E_TOMBSTONE):
  2655. *pfUpdate = TRUE;
  2656. *pfUpdVersNo = TRUE;
  2657. break;
  2658. case(NMSDB_E_RELEASED):
  2659. if (pEntryInCnf->EntTyp != NMSDB_NORM_GRP_ENTRY)
  2660. {
  2661. *pfUpdate = TRUE;
  2662. *pfUpdVersNo = TRUE;
  2663. }
  2664. else //Normal group entry
  2665. {
  2666. //
  2667. // If the owner id is the same (i.e.
  2668. // local WINS is the owner)
  2669. //
  2670. if (pEntryInCnf->OwnerId ==
  2671. pEntryToReg->OwnerId)
  2672. {
  2673. *pfUpdate = TRUE; //this should
  2674. //update the
  2675. //time stamp
  2676. }
  2677. else
  2678. {
  2679. //
  2680. // Update the owner id., timestamp
  2681. // and version number
  2682. //
  2683. *pfUpdate = TRUE;
  2684. *pfUpdVersNo = TRUE;
  2685. }
  2686. }
  2687. break;
  2688. //
  2689. // Entry to register is an ACTIVE normal group entry
  2690. // and it is clashing with an ACTIVE records in the db
  2691. //
  2692. case(NMSDB_E_ACTIVE):
  2693. if (
  2694. (pEntryInCnf->EntTyp == NMSDB_UNIQUE_ENTRY)
  2695. ||
  2696. (pEntryInCnf->EntTyp == NMSDB_MULTIHOMED_ENTRY)
  2697. )
  2698. {
  2699. DBGPRINT1(FLOW, "ClashAtRegGrp: Normal Grp (to Reg) Conflicting with an ACTIVE %s entry. Resorting to Challenge\n",
  2700. pEntryInCnf->EntTyp == NMSDB_UNIQUE_ENTRY ? "UNIQUE" : "MULTIHOMED");
  2701. if (
  2702. (NMSDB_ENTRY_MULTIHOMED_M(
  2703. pEntryInCnf->EntTyp)
  2704. &&
  2705. (pEntryInCnf->NodeAdds.NoOfMems > 0))
  2706. ||
  2707. NMSDB_ENTRY_UNIQUE_M(
  2708. pEntryInCnf->EntTyp)
  2709. )
  2710. {
  2711. *pfChallenge = TRUE;
  2712. }
  2713. else
  2714. {
  2715. *pfUpdate = TRUE;
  2716. *pfUpdVersNo = TRUE;
  2717. }
  2718. }
  2719. else
  2720. {
  2721. if (pEntryInCnf->EntTyp == NMSDB_SPEC_GRP_ENTRY)
  2722. {
  2723. DBGPRINT0(FLOW, "ClashAtRegGrp: Conflicting entry is an ACTIVE spec. group entry. NO UPDATE WILL BE DONE \n");
  2724. }
  2725. else //entry in cnf is an active normal group entry
  2726. {
  2727. DBGPRINT0(FLOW, "ClashAtRegGrp: Conflicting entry is an ACTIVE normal group entry. Do a simple update \n");
  2728. *pfUpdate = TRUE;
  2729. if (pEntryInCnf->OwnerId !=
  2730. NMSDB_LOCAL_OWNER_ID)
  2731. {
  2732. *pfUpdVersNo = TRUE;
  2733. }
  2734. }
  2735. }
  2736. break;
  2737. default:
  2738. //
  2739. // Something really wrong here. Maybe the
  2740. // database got corrupted.
  2741. //
  2742. DBGPRINT1(ERR,
  2743. "ClashAtRegGrp: Weird state of entry in cnf (%d)\n",
  2744. StateOfEntryInCnf_e
  2745. );
  2746. WINSEVT_LOG_M(WINS_FAILURE, WINS_EVT_SFT_ERR);
  2747. RetStat = WINS_FAILURE;
  2748. break;
  2749. } // end of switch
  2750. }
  2751. else // entry to register is a multihomed entry
  2752. {
  2753. switch(StateOfEntryInCnf_e)
  2754. {
  2755. //
  2756. // If entry in database is a tombstone, we overwrite it
  2757. //
  2758. case(NMSDB_E_TOMBSTONE):
  2759. *pfUpdate = TRUE;
  2760. *pfUpdVersNo = TRUE;
  2761. break;
  2762. //
  2763. // A released entry unless it is a normal group is
  2764. // overwritten
  2765. //
  2766. case(NMSDB_E_RELEASED):
  2767. if (pEntryInCnf->EntTyp != NMSDB_NORM_GRP_ENTRY)
  2768. {
  2769. *pfUpdate = TRUE;
  2770. //
  2771. // Even if the entry in conflict is a multihomed // entry, we update the version number.
  2772. //
  2773. *pfUpdVersNo = TRUE;
  2774. }
  2775. break;
  2776. case(NMSDB_E_ACTIVE):
  2777. //
  2778. // we resort to a challenge only if the
  2779. // conflicting entry is a unique or
  2780. // multihomed entry
  2781. //
  2782. if (
  2783. NMSDB_ENTRY_MULTIHOMED_M(
  2784. pEntryInCnf->EntTyp
  2785. )
  2786. ||
  2787. NMSDB_ENTRY_UNIQUE_M(
  2788. pEntryInCnf->EntTyp
  2789. )
  2790. )
  2791. {
  2792. if (NMSDB_ENTRY_MULTIHOMED_M(
  2793. pEntryInCnf->EntTyp)
  2794. )
  2795. {
  2796. BOOL fFound;
  2797. DWORD i;
  2798. for ( i = 0;
  2799. i < pEntryToReg->NodeAdds.NoOfMems; i++
  2800. )
  2801. {
  2802. //
  2803. // If found, MemInGrp will
  2804. // remove the address from
  2805. // the Mem array of the
  2806. // conflicting record
  2807. //
  2808. fFound = MemInGrp(
  2809. &pEntryToReg->NodeAdds.Mem[i].Add,
  2810. pEntryInCnf,
  2811. &fOwned,
  2812. FALSE);
  2813. //
  2814. // Address not found,
  2815. // continue to the next
  2816. // address
  2817. //
  2818. if (!fFound)
  2819. {
  2820. continue;
  2821. }
  2822. //
  2823. // if not owned by this WINS
  2824. // the version number must
  2825. // be updated if we end up
  2826. // just updating the entry (
  2827. // i.e. if fAddMem gets set
  2828. // to TRUE down below)
  2829. //
  2830. if (!fOwned)
  2831. {
  2832. *pfUpdVersNo = TRUE;
  2833. }
  2834. }
  2835. //
  2836. // If all addresses to register
  2837. // are already there in the
  2838. // conflicting record and it
  2839. // is a refresh or if the
  2840. // addresses to register are
  2841. // same as in the conflicting
  2842. // record, we need to update
  2843. // the timestamp and possibly
  2844. // the version number (see
  2845. // above). There is no need to
  2846. // do any challenge
  2847. // here.
  2848. //
  2849. if (
  2850. //
  2851. // Note the following code would be executed only
  2852. // if we start supporting our own opcode for multihomed
  2853. // refresh (the need for this will arise if we go
  2854. // with the approach of refreshing multiple addresses
  2855. // simultaneously).
  2856. //
  2857. FUTURES("May need the code within #if 0 and #endif in the future. See ")
  2858. FUTURES("the comment above")
  2859. #if 0
  2860. (
  2861. (i == pEntryToReg->NodeAdds.NoOfMems)
  2862. &&
  2863. fRefresh
  2864. )
  2865. ||
  2866. #endif
  2867. (pEntryInCnf->NodeAdds.NoOfMems == 0)
  2868. )
  2869. {
  2870. DBGPRINT0(DET, "ClashAtRegGrp: Clash between two multihomed entries. The addresses are the same. Simple update will be done\n");
  2871. *pfAddMem = TRUE;
  2872. }
  2873. else
  2874. {
  2875. //
  2876. // We do a challenge even
  2877. // if the conflicting entry's
  2878. // addresses are a superset
  2879. // of the addresses in the
  2880. // entry to register
  2881. //
  2882. DBGPRINT0(DET, "ClashAtRegGrp: Clash between two multihomed entries. Atleast one address is different. Resorting to a challenge\n");
  2883. //
  2884. // The multihomed entry
  2885. // needs to be challenged
  2886. //
  2887. *pfChallenge = TRUE;
  2888. }
  2889. }
  2890. else
  2891. {
  2892. //
  2893. // If there is any address in
  2894. // the multihomed entry to
  2895. // register that is different
  2896. // than the address in the unique
  2897. // entry, we need to challenge
  2898. // the unique entry
  2899. //
  2900. if (
  2901. (pEntryToReg->NodeAdds.NoOfMems > 1)
  2902. ||
  2903. (WINSMSC_COMPARE_MEMORY_M(
  2904. &pEntryToReg->NodeAdds.Mem[0].Add.Add.IPAdd,
  2905. &pEntryInCnf->NodeAdds.Mem[0].Add.Add.IPAdd, sizeof(COMM_IP_ADD_T))
  2906. != sizeof(COMM_IP_ADD_T) )
  2907. )
  2908. {
  2909. DBGPRINT0(DET, "ClashAtRegGrp: Clash between multihomed entry (to reg) and active unique entry. At least one address differs. Resorting to challenge\n");
  2910. //
  2911. // The unique entry
  2912. // needs to be challenged
  2913. //
  2914. *pfChallenge = TRUE;
  2915. }
  2916. else
  2917. {
  2918. DBGPRINT0(DET, "ClashAtRegGrp: Clash between multihomed entry (to reg) and active unique entry. Addresses same. Simple update will be done\n");
  2919. //
  2920. // Update the entry in the db
  2921. //
  2922. *pfUpdate = TRUE;
  2923. *pfUpdVersNo = TRUE;
  2924. }
  2925. }
  2926. }
  2927. #ifdef WINSDBG
  2928. else
  2929. {
  2930. DBGPRINT1(FLOW, "ClashAtRegGrp: CLASH OF A MULTIHOMED ENTRY WITH AN ACTIVE %s GROUP ENTRY. NO UPDATE WILL BE DONE\n", NMSDB_ENTRY_NORM_GRP_M(pEntryInCnf->EntTyp) ? "NORMAL" : "SPECIAL");
  2931. }
  2932. #endif
  2933. break;
  2934. }
  2935. }
  2936. }
  2937. DBGLEAVE("ClashAtRegGrp\n");
  2938. return(RetStat);
  2939. } //ClashAtRegGrp()
  2940. BOOL
  2941. MemInGrp(
  2942. IN PCOMM_ADD_T pAddToReg,
  2943. IN PNMSDB_STAT_INFO_T pEntryInCnf,
  2944. IN PBOOL pfOwned,
  2945. IN BOOL fRemoveReplica
  2946. )
  2947. /*++
  2948. Routine Description:
  2949. This function is called to check if the address of the entry to register
  2950. is in the list of addresses in the conflicting entry.
  2951. Arguments:
  2952. pAddToReg - Address to Register
  2953. pEntryInCnf - Entry in conflict
  2954. fRemoveReplica - This will be set if the caller wants this function
  2955. to remove a replica member.
  2956. A replica (the last one in the list) will be replaced
  2957. only if there is no match and the number of members
  2958. in the list is hitting the limit.
  2959. Externals Used:
  2960. None
  2961. Return Value:
  2962. TRUE if the entry to register is a member of the group
  2963. FALSE otherwise
  2964. Error Handling:
  2965. Called by:
  2966. ClashAtRegGrp
  2967. Side Effects:
  2968. Comments:
  2969. The two entries in conflict are special group entries.
  2970. fRemoveReplica will be set to TRUE only by ClashAtRegGrp when
  2971. registering a special group (because we prefer a local member to a
  2972. replica)
  2973. NOTE: if the member that matches is a permanent member as indicated
  2974. by the timestamp (== MAXULONG), then it is not replaced.
  2975. --*/
  2976. {
  2977. DWORD no;
  2978. BOOL fFound = FALSE;
  2979. DWORD RetVal;
  2980. DWORD i;
  2981. PNMSDB_GRP_MEM_ENTRY_T pMem = pEntryInCnf->NodeAdds.Mem;
  2982. BOOL fRplFound = FALSE;
  2983. DWORD RplId = 0; // id. of replica to
  2984. // remove.
  2985. DWORD NoOfMem;
  2986. DBGENTER("MemInGrp\n");
  2987. *pfOwned = FALSE;
  2988. #ifdef WINSDBG
  2989. if (pEntryInCnf->NodeAdds.NoOfMems > NMSDB_MAX_MEMS_IN_GRP)
  2990. {
  2991. DBGPRINT2(EXC, "MemInGrp: No of Mems in Cnf entry = (%d); Add of entry to reg. is (%x)\n", pEntryInCnf->NodeAdds.NoOfMems, pAddToReg->Add.IPAdd);
  2992. }
  2993. #endif
  2994. ASSERT(pEntryInCnf->NodeAdds.NoOfMems <= NMSDB_MAX_MEMS_IN_GRP);
  2995. NoOfMem = min(pEntryInCnf->NodeAdds.NoOfMems, NMSDB_MAX_MEMS_IN_GRP);
  2996. //
  2997. // Compare each member in the conflicting record against the member to
  2998. // be registered
  2999. //
  3000. for (no = 0; no < NoOfMem ; no++, pMem++ )
  3001. {
  3002. //
  3003. // if the caller wants us to remove a replica member
  3004. // for the case where there is no match
  3005. //
  3006. if (fRemoveReplica)
  3007. {
  3008. //
  3009. // If the member in the conflicting record is a
  3010. // replica, save its index if it is more than
  3011. // the one we saved earlier.
  3012. //
  3013. if (pMem->OwnerId != NMSDB_LOCAL_OWNER_ID)
  3014. {
  3015. fRplFound = TRUE;
  3016. if (no > RplId)
  3017. {
  3018. RplId = no;
  3019. }
  3020. }
  3021. }
  3022. RetVal = (ULONG) WINSMSC_COMPARE_MEMORY_M(
  3023. pAddToReg,
  3024. &pMem->Add,
  3025. sizeof(COMM_ADD_T)
  3026. );
  3027. if (RetVal == sizeof(COMM_ADD_T))
  3028. {
  3029. //
  3030. // if this is a permanent member, let us set
  3031. // fOwned to TRUE since we do not want to
  3032. // replace this member. The caller will check
  3033. // fOwned and if TRUE will not replace it.
  3034. // Currently, MAXULONG can be there only for
  3035. // static SG members
  3036. if (pMem->TimeStamp == MAXLONG_PTR)
  3037. {
  3038. ASSERT(NMSDB_ENTRY_SPEC_GRP_M(pEntryInCnf->EntTyp));
  3039. *pfOwned = TRUE;
  3040. break;
  3041. }
  3042. fFound = TRUE;
  3043. PERF("The following is a convoluted and potentially high overhead way")
  3044. PERF("to handle a refresh for a member (i.e. when member is owned by us")
  3045. PERF("We take it out here and then add it later (with current time stamp)")
  3046. PERF("in NmsNmhNamRegGrp. Improve this by using the code that is between.")
  3047. PERF("#if 0 and #endif. Also, when updating db, just overwrite the affected")
  3048. PERF("entry instead of writing the whole record")
  3049. //
  3050. //if the member is owned by us, *pfOwned is set to
  3051. //TRUE
  3052. //
  3053. if ( pMem->OwnerId == NMSDB_LOCAL_OWNER_ID )
  3054. {
  3055. *pfOwned = TRUE;
  3056. }
  3057. //
  3058. // Get rid of the member whose address is the
  3059. // same. The client will insert an entry for the
  3060. // member with the local WINS as the owner
  3061. // and the current timestamp.
  3062. //
  3063. for(
  3064. i = no;
  3065. i < (NoOfMem - 1);
  3066. i++, pMem++
  3067. )
  3068. {
  3069. *pMem = *(pMem + 1);
  3070. }
  3071. --NoOfMem;
  3072. break;
  3073. }
  3074. }
  3075. pEntryInCnf->NodeAdds.NoOfMems = NoOfMem;
  3076. //
  3077. // if we were asked to remove replica on no match, check if a
  3078. // replica member was found. Note: We remove a replica to make
  3079. // space for a member that we got. We don't need to remove a replica
  3080. // if there is space left in the group
  3081. //
  3082. if (
  3083. fRemoveReplica &&
  3084. !fFound &&
  3085. fRplFound &&
  3086. (pEntryInCnf->NodeAdds.NoOfMems == NMSDB_MAX_MEMS_IN_GRP)
  3087. )
  3088. {
  3089. //
  3090. // Remove the replica
  3091. //
  3092. for (
  3093. i = RplId, pMem = &pEntryInCnf->NodeAdds.Mem[RplId];
  3094. i < (pEntryInCnf->NodeAdds.NoOfMems - 1);
  3095. i++, pMem++
  3096. )
  3097. {
  3098. *pMem = *(pMem + 1);
  3099. }
  3100. --(pEntryInCnf->NodeAdds.NoOfMems);
  3101. // fFound = TRUE;
  3102. }
  3103. DBGLEAVE("MemInGrp\n");
  3104. return(fFound);
  3105. } //MemInGrp()
  3106. VOID
  3107. RemoveAllMemOfOwner(
  3108. PNMSDB_STAT_INFO_T pEntry,
  3109. DWORD OwnerId
  3110. )
  3111. /*++
  3112. Routine Description:
  3113. Removes all members that are owned by OwnerId
  3114. Arguments:
  3115. Externals Used:
  3116. None
  3117. Return Value:
  3118. Success status codes --
  3119. Error status codes --
  3120. Error Handling:
  3121. Called by:
  3122. Side Effects:
  3123. Comments:
  3124. None
  3125. --*/
  3126. {
  3127. DWORD NoOfMems = pEntry->NodeAdds.NoOfMems;
  3128. PNMSDB_GRP_MEM_ENTRY_T pMem = &pEntry->NodeAdds.Mem[NoOfMems-1];
  3129. DBGPRINT1(FLOW, "ENTER: RemoveAllMemOfOwner: Owner Id= (%d)\n", OwnerId);
  3130. //
  3131. // loop over all members of the entry starting from the last one
  3132. //
  3133. for (; NoOfMems > 0; NoOfMems--, pMem--)
  3134. {
  3135. //
  3136. // If owner id matches, we need to remove it and decrement the
  3137. // count
  3138. //
  3139. if (pMem->OwnerId == OwnerId)
  3140. {
  3141. DWORD No;
  3142. DBGPRINT1(DET, "RemoveAllMemOfOwner: Removing Member with address = (%x)\n", pMem->Add.Add.IPAdd);
  3143. //
  3144. // shift all following members one position to the left
  3145. //
  3146. memcpy( pMem, (pMem + 1),
  3147. sizeof(NMSDB_GRP_MEM_ENTRY_T)*(pEntry->NodeAdds.NoOfMems - NoOfMems));
  3148. pEntry->NodeAdds.NoOfMems--;
  3149. }
  3150. }
  3151. DBGPRINT1(FLOW, "LEAVE: RemoveAllMemOfOwner. No Of Mems in Conflicting record = (%d)\n", pEntry->NodeAdds.NoOfMems);
  3152. return;
  3153. }
  3154. VOID
  3155. ClashAtReplUniqueR (
  3156. IN PNMSDB_ROW_INFO_T pEntryToReg,
  3157. IN PNMSDB_STAT_INFO_T pEntryInCnf,
  3158. OUT PBOOL pfUpdate,
  3159. OUT PBOOL pfUpdVersNo,
  3160. OUT PBOOL pfChallenge,
  3161. OUT PBOOL pfRelease,
  3162. OUT PBOOL pfInformWins
  3163. )
  3164. /*++
  3165. Routine Description:
  3166. This function is called when there is a clash at replication time
  3167. between a replica that is unique and an entry in the database
  3168. Arguments:
  3169. pReplToReg -- Replica that couldn't be registered due to conflict
  3170. pEntryInCnf -- Entry in conflict
  3171. pfUpdate -- TRUE means Entry should overwrite the conflicting one
  3172. pfUpdVersNo -- TRUE means Entry's version number should be incremented
  3173. This arg. can never be TRUE if *pfUpdate is not TRUE
  3174. pfChallenge -- TRUE means that conflicting entry should be challenged
  3175. pfRelease -- TRUE means that conflicting entry's node should be
  3176. asked to release the name.
  3177. If both pfChallenge and pfRelease are TRUE, then it
  3178. means that the conflicting entry should first be
  3179. challenged. If the challenge fails, the node should
  3180. be asked to release the name. If the challenge succeeds,
  3181. no release need be sent
  3182. pfInformWins -- Inform remote WINS from which we received the replica
  3183. about the outcome
  3184. pfAddChgd -- Indicates that the address got changed
  3185. Externals Used:
  3186. None
  3187. Return Value:
  3188. None
  3189. Error Handling:
  3190. Called by:
  3191. NmsNmhReplRegInd
  3192. Side Effects:
  3193. Comments:
  3194. None
  3195. --*/
  3196. {
  3197. NMSDB_ENTRY_STATE_E StateOfEntryToReg_e = pEntryToReg->EntryState_e;
  3198. NMSDB_ENTRY_STATE_E StateOfEntryInCnf_e = pEntryInCnf->EntryState_e;
  3199. DWORD CompAddRes; /*Result of comparing addresses*/
  3200. //
  3201. // We are reading a long value. This operation is atomic
  3202. //
  3203. BOOL fPStatic = WinsCnf.fPStatic;
  3204. DBGENTER("ClashAtReplUniqueR\n");
  3205. *pfUpdate = FALSE;
  3206. *pfUpdVersNo = FALSE;
  3207. *pfChallenge = FALSE;
  3208. *pfRelease = FALSE;
  3209. *pfInformWins = FALSE;
  3210. if (pEntryInCnf->OwnerId == pEntryToReg->OwnerId) {
  3211. *pfUpdate = TRUE;
  3212. DBGPRINT0(DET,
  3213. "ClashAtUniqueR: overwrite replica by same owner replica \n");
  3214. return;
  3215. }
  3216. //
  3217. // If the conflicting record was statically initialized we
  3218. // return right away, unless the replica is also a STATIC or
  3219. // belongs to the same owner.
  3220. //
  3221. if (pEntryInCnf->fStatic)
  3222. {
  3223. DBGPRINT0(DET, "ClashAtReplUniqueR: Clash with a STATIC record\n");
  3224. //
  3225. // If we have been asked to treat static records as
  3226. // P-Static, then if the conflicting entry is not a group
  3227. // we continue on, else we return.
  3228. //
  3229. if (!(fPStatic && !NMSDB_ENTRY_GRP_M(pEntryInCnf->EntTyp)))
  3230. {
  3231. // WINSEVT_LOG_INFO_D_M(WINS_FAILURE, WINS_EVT_REPLICA_CLASH_W_STATIC);
  3232. if (WinsCnf.LogDetailedEvts > 0)
  3233. {
  3234. WinsEvtLogDetEvt(FALSE, WINS_EVT_REPLICA_CLASH_W_STATIC,
  3235. NULL, __LINE__, "s", pEntryToReg->pName);
  3236. }
  3237. return;
  3238. }
  3239. }
  3240. else
  3241. {
  3242. //
  3243. // a STATIC replica always replaces a dynamic entry.
  3244. //
  3245. if (pEntryToReg->fStatic)
  3246. {
  3247. *pfUpdate = TRUE;
  3248. return;
  3249. }
  3250. }
  3251. if (pEntryInCnf->EntTyp == NMSDB_UNIQUE_ENTRY)
  3252. {
  3253. switch(StateOfEntryInCnf_e)
  3254. {
  3255. case(NMSDB_E_TOMBSTONE): //fall through
  3256. case(NMSDB_E_RELEASED):
  3257. *pfUpdate = TRUE;
  3258. break;
  3259. case(NMSDB_E_ACTIVE):
  3260. if (StateOfEntryToReg_e == NMSDB_E_ACTIVE)
  3261. {
  3262. CompAddRes = ECommCompAdd(
  3263. &pEntryInCnf->NodeAdds.Mem[0].Add,
  3264. pEntryToReg->pNodeAdd
  3265. );
  3266. switch(CompAddRes)
  3267. {
  3268. case(COMM_DIFF_ADD):
  3269. //
  3270. // If entry in conflict is active
  3271. // and owned by us,
  3272. // tell the node of the entry to
  3273. // release the name. In other
  3274. // words we always replace it
  3275. // with the replica.
  3276. //
  3277. if (pEntryInCnf->OwnerId
  3278. == NMSDB_LOCAL_OWNER_ID)
  3279. {
  3280. *pfChallenge = TRUE;
  3281. *pfRelease = TRUE;
  3282. // *pfInformWins = TRUE;
  3283. }
  3284. else //D is a replica
  3285. {
  3286. //
  3287. // replace with replica
  3288. //
  3289. // *pfChallenge = TRUE;
  3290. *pfUpdate = TRUE;
  3291. }
  3292. break;
  3293. //
  3294. // D and R (database entry and replica
  3295. // have same address)
  3296. //
  3297. default:
  3298. *pfUpdate = TRUE;
  3299. break;
  3300. }
  3301. }
  3302. else //entry to register is a Tombstone (has to be)
  3303. {
  3304. ASSERT(StateOfEntryToReg_e == NMSDB_E_TOMBSTONE);
  3305. //
  3306. // If we own the entry in the db, we need to
  3307. // increment its version number
  3308. //
  3309. if (pEntryInCnf->OwnerId
  3310. == NMSDB_LOCAL_OWNER_ID)
  3311. {
  3312. //
  3313. // We update the version number of the
  3314. // entry in the database
  3315. //
  3316. *pfUpdVersNo = TRUE;
  3317. }
  3318. else //the entry in conflict is a replica
  3319. {
  3320. //
  3321. // Both replicas have the same owner.
  3322. //
  3323. if (
  3324. pEntryInCnf->OwnerId ==
  3325. pEntryToReg->OwnerId
  3326. )
  3327. {
  3328. *pfUpdate = TRUE;
  3329. }
  3330. #ifdef WINSDBG
  3331. else
  3332. {
  3333. DBGPRINT0(FLOW, "ClashAtReplUniqueR: Clash between two replicas with different owner ids. Replica in db is active while one received is a tombstone. Db will not be updated\n");
  3334. }
  3335. #endif
  3336. }
  3337. }
  3338. break;
  3339. default:
  3340. //
  3341. // Some weirdness.
  3342. // Set this the pfUpdate to TRUE so that we overwrite this record.
  3343. *pfUpdate = TRUE;
  3344. DBGPRINT1(ERR,
  3345. "ClashAtReplUniqueR: Weird state of entry in cnf (%d)\n",
  3346. StateOfEntryInCnf_e
  3347. );
  3348. WINSEVT_LOG_M(WINS_FAILURE, WINS_EVT_SFT_ERR);
  3349. WINS_RAISE_EXC_M(WINS_EXC_BAD_RECORD);
  3350. break;
  3351. }
  3352. }
  3353. else // the entry in conflict is a group (normal or special) entry or
  3354. // a multihomed entry
  3355. {
  3356. //
  3357. // do nothing if it is a normal group or if it is an active
  3358. // special group. If it is a special group and it is not
  3359. // active, it can be replaced
  3360. //
  3361. if (
  3362. (pEntryInCnf->EntTyp == NMSDB_SPEC_GRP_ENTRY)
  3363. &&
  3364. (StateOfEntryInCnf_e != NMSDB_E_ACTIVE)
  3365. )
  3366. {
  3367. CHECK("Check with the latest spec. to make sure the following is correct")
  3368. //
  3369. // Replace with replica
  3370. //
  3371. *pfUpdate = TRUE;
  3372. }
  3373. else
  3374. {
  3375. if (pEntryInCnf->EntTyp == NMSDB_MULTIHOMED_ENTRY)
  3376. {
  3377. if (StateOfEntryInCnf_e == NMSDB_E_ACTIVE)
  3378. {
  3379. if (StateOfEntryToReg_e ==
  3380. NMSDB_E_ACTIVE)
  3381. {
  3382. if (pEntryInCnf->OwnerId ==
  3383. pEntryToReg->OwnerId
  3384. )
  3385. {
  3386. DBGPRINT0(DET, "ClashAtReplUniqueR: ACTIVE unique replica with an ACTIVE MULTIHOMED replica (same owner). Update will be done\n");
  3387. *pfUpdate = TRUE;
  3388. }
  3389. else
  3390. {
  3391. //
  3392. // Put within #if 0 and #endif if we want to challenge an entry regardless of
  3393. // who owns it (can result in challenges across WAN lines)
  3394. //
  3395. //#if 0
  3396. if (pEntryInCnf->OwnerId == NMSDB_LOCAL_OWNER_ID)
  3397. //#endif
  3398. {
  3399. BOOL fOwned;
  3400. //
  3401. // If found, MemInGrp
  3402. // will remove the
  3403. // address from
  3404. // the Mem array of the
  3405. // conflicting record
  3406. //
  3407. (VOID) MemInGrp(
  3408. pEntryToReg->
  3409. pNodeAdd,
  3410. pEntryInCnf,
  3411. &fOwned,
  3412. FALSE);
  3413. if (pEntryInCnf->NodeAdds.NoOfMems != 0)
  3414. {
  3415. RemoveAllMemOfOwner(
  3416. pEntryInCnf,
  3417. pEntryToReg->OwnerId);
  3418. }
  3419. //
  3420. // Active unique replica
  3421. // has the same address as
  3422. // the owned active
  3423. // multihomed record.Replace
  3424. //
  3425. if (pEntryInCnf->NodeAdds.NoOfMems == 0)
  3426. {
  3427. *pfUpdate = TRUE;
  3428. }
  3429. else
  3430. {
  3431. //
  3432. // An active unique
  3433. // replica has clashed
  3434. // with an active
  3435. // owned multihomed entry.
  3436. // The multihomed entry
  3437. // needs to be challenged
  3438. //
  3439. *pfChallenge = TRUE;
  3440. //
  3441. // Comment out #if 0 if we want to challenge regardless of ownership
  3442. //
  3443. #if 0
  3444. if (pEntryInCnf->OwnerId == NMSDB_LOCAL_OWNER_ID)
  3445. {
  3446. #endif
  3447. *pfRelease = TRUE;
  3448. #if 0
  3449. }
  3450. #endif
  3451. // *pfInformWins = TRUE;
  3452. }
  3453. }
  3454. //
  3455. // Put within #if 0 and #endif if we want to challenge an entry regardless of
  3456. // who owns it (can result in challenges across WAN lines). See above
  3457. //
  3458. //#if 0
  3459. else
  3460. {
  3461. CHECK("Maybe, we should not do any update in this case")
  3462. DBGPRINT0(DET, "ClashAtReplUniqueR: ACTIVE unique replica with an ACTIVE MULTIHOMED replica (diff owner). Simple Update will be done\n");
  3463. *pfUpdate = TRUE;
  3464. }
  3465. //#endif
  3466. }
  3467. }
  3468. else // entry to register is a TOMBSTONE
  3469. {
  3470. if (pEntryInCnf->OwnerId ==
  3471. pEntryToReg->OwnerId
  3472. )
  3473. {
  3474. DBGPRINT0(DET, "ClashAtReplUniqueR: TOMBSTONE unique replica with an ACTIVE MULTIHOMED replica (same owner). Update will be done\n");
  3475. *pfUpdate = TRUE;
  3476. }
  3477. else
  3478. {
  3479. DBGPRINT0(DET, "ClashAtReplUniqueR: TOMBSTONE unique replica with an ACTIVE MULTIHOMED entry (different owners). No Update will be done\n");
  3480. }
  3481. }
  3482. }
  3483. else // state of multihomed entry in Db is
  3484. // not active. We need to replace it
  3485. // with the replica
  3486. {
  3487. *pfUpdate = TRUE;
  3488. }
  3489. }
  3490. else
  3491. {
  3492. DBGPRINT0(FLOW,
  3493. "ClashAtReplUniqueR: Clash is either with a normal group or an active special group. No update will be done to the db\n");
  3494. }
  3495. }
  3496. }
  3497. DBGLEAVE("ClashAtReplUniqueR\n");
  3498. return;
  3499. } //ClashAtReplUniqueR()
  3500. VOID
  3501. ClashAtReplGrpR (
  3502. IN PNMSDB_ROW_INFO_T pEntryToReg,
  3503. IN PNMSDB_STAT_INFO_T pEntryInCnf,
  3504. OUT PBOOL pfAddMem,
  3505. OUT PBOOL pfUpdate,
  3506. OUT PBOOL pfUpdVersNo,
  3507. OUT PBOOL pfRelease,
  3508. OUT PBOOL pfChallenge,
  3509. OUT PBOOL pfUpdTimeStamp,
  3510. OUT PBOOL pfInformWins
  3511. )
  3512. /*++
  3513. Routine Description:
  3514. This function is called when there is a clash at replication time
  3515. betweeen a replica that is a group and an entry in the database.
  3516. Arguments:
  3517. pEntryToReg -- Entry that couldn't be registered due to conflict
  3518. pEntryInCnf -- Entry in conflict
  3519. pfAddMem -- TRUE means that the members in the replica should be
  3520. added to the group entry in the database
  3521. pfUpdate -- TRUE means Entry should overwrite the conflicting one
  3522. pfUpdVersNo -- TRUE means Entry's version number should be incremented
  3523. This arg. can never be TRUE if *pfUpdate is not TRUE
  3524. Externals Used:
  3525. None
  3526. Return Value:
  3527. None
  3528. Error Handling:
  3529. Called by:
  3530. NmsNmhNamRegGrp
  3531. Side Effects:
  3532. Comments:
  3533. None
  3534. --*/
  3535. {
  3536. NMSDB_ENTRY_STATE_E StateOfEntryToReg_e = pEntryToReg->EntryState_e;
  3537. NMSDB_ENTRY_STATE_E StateOfEntryInCnf_e = pEntryInCnf->EntryState_e;
  3538. BOOL fMemInGrp = FALSE;
  3539. DWORD i;
  3540. //
  3541. // We are reading a long value. This operation is atomic
  3542. //
  3543. BOOL fPStatic = WinsCnf.fPStatic;
  3544. DBGENTER("ClashAtReplGrpR\n");
  3545. *pfAddMem = FALSE;
  3546. *pfUpdate = FALSE;
  3547. *pfUpdVersNo = FALSE;
  3548. *pfRelease = FALSE;
  3549. *pfChallenge = FALSE;
  3550. *pfUpdTimeStamp = TRUE;
  3551. *pfInformWins = FALSE;
  3552. if (pEntryInCnf->OwnerId == pEntryToReg->OwnerId) {
  3553. *pfUpdate = TRUE;
  3554. DBGPRINT0(DET,
  3555. "ClashAtReplGrpR: overwrite replica by same owner replica \n");
  3556. return;
  3557. }
  3558. //
  3559. // If the conflicting record was statically initialized we
  3560. // return right away unless the replica and the conflicting
  3561. // entry belong to the same owner and the replica is also a
  3562. // STATIC record.
  3563. //
  3564. if (pEntryInCnf->fStatic)
  3565. {
  3566. DBGPRINT0(DET,
  3567. "ClashAtReplGrpR: Conflict with a STATIC entry\n");
  3568. //
  3569. // if both records are user defined special groups, do
  3570. // same conflict handling as you would when a
  3571. // the conflicting record is a dynamic record
  3572. //
  3573. if (!((NMSDB_ENTRY_USER_SPEC_GRP_M(pEntryToReg->pName, pEntryToReg->EntTyp)) &&
  3574. (NMSDB_ENTRY_SPEC_GRP_M(pEntryInCnf->EntTyp))))
  3575. {
  3576. if ((NMSDB_ENTRY_NORM_GRP_M(pEntryToReg->EntTyp)) &&
  3577. (NMSDB_ENTRY_USER_SPEC_GRP_M(pEntryToReg->pName, pEntryInCnf->EntTyp)))
  3578. {
  3579. NOTE("Currently, NORM GRP can have the wrong owner id. since this is not")
  3580. NOTE("replicated. The owner id. of the WINS being pulled from is used")
  3581. *pfAddMem = UnionGrps(
  3582. pEntryToReg,
  3583. pEntryInCnf
  3584. );
  3585. if (pEntryInCnf->OwnerId == NMSDB_LOCAL_OWNER_ID)
  3586. {
  3587. *pfUpdVersNo = *pfAddMem;
  3588. }
  3589. pEntryToReg->EntTyp = NMSDB_SPEC_GRP_ENTRY;
  3590. return;
  3591. }
  3592. else
  3593. {
  3594. //
  3595. // If static records need to be treated as P-static and
  3596. // the conflicting entry as well as the entry to register
  3597. // are multihomed, we continue on, else we return
  3598. //
  3599. if (!(fPStatic && (NMSDB_ENTRY_MULTIHOMED_M(pEntryInCnf->EntTyp)) && (NMSDB_ENTRY_MULTIHOMED_M(pEntryToReg->EntTyp))))
  3600. {
  3601. if (WinsCnf.LogDetailedEvts > 0)
  3602. {
  3603. WinsEvtLogDetEvt(FALSE, WINS_EVT_REPLICA_CLASH_W_STATIC,
  3604. NULL, __LINE__, "s", pEntryToReg->pName);
  3605. // WINSEVT_LOG_INFO_D_M(WINS_FAILURE, WINS_EVT_REPLICA_CLASH_W_STATIC);
  3606. }
  3607. return;
  3608. }
  3609. }
  3610. }
  3611. }
  3612. if (pEntryToReg->EntTyp == NMSDB_SPEC_GRP_ENTRY)
  3613. {
  3614. switch(StateOfEntryInCnf_e)
  3615. {
  3616. case(NMSDB_E_TOMBSTONE):
  3617. *pfUpdate = TRUE;
  3618. break;
  3619. case(NMSDB_E_RELEASED):
  3620. if (pEntryInCnf->EntTyp != NMSDB_NORM_GRP_ENTRY)
  3621. {
  3622. *pfUpdate = TRUE;
  3623. }
  3624. break;
  3625. case(NMSDB_E_ACTIVE):
  3626. if (pEntryInCnf->EntTyp == NMSDB_SPEC_GRP_ENTRY)
  3627. {
  3628. if (StateOfEntryToReg_e == NMSDB_E_TOMBSTONE)
  3629. {
  3630. if (pEntryInCnf->OwnerId == NMSDB_LOCAL_OWNER_ID)
  3631. {
  3632. *pfUpdTimeStamp = FALSE;
  3633. *pfUpdVersNo = TRUE;
  3634. // we should propagate this change right away
  3635. // because others think this is a tombstone
  3636. // record.
  3637. RPL_PUSH_NTF_M(RPL_PUSH_PROP, NULL, NULL, NULL);
  3638. }
  3639. else
  3640. {
  3641. //
  3642. // SG Tombstone replica clashed with a SG
  3643. // Active replica. We
  3644. // replace it (in other words, make it a
  3645. // tombstone). It makes sense since if this
  3646. // SG was really active, it would be owned
  3647. // by another owner (any time a member is
  3648. // registered, the ownership becomes that
  3649. // of the registering WINS).
  3650. // and so if this name is really active,
  3651. // the owner wins will push it back
  3652. // as active.
  3653. //
  3654. *pfUpdate = TRUE;
  3655. // In order to propagate this
  3656. // conflict to the owner quickly, trigger
  3657. // push with propagation unless owner himself
  3658. // sent this tombstone.
  3659. if (pEntryInCnf->OwnerId == pEntryToReg->OwnerId) {
  3660. RPL_PUSH_NTF_M(RPL_PUSH_PROP, NULL, NULL, NULL);
  3661. }
  3662. DBGPRINT0(FLOW, "ClashAtReplGrpR: TOMBSTONE spec. grp. replica clashed with ACTIVE spec. grp replica. No update will be done\n");
  3663. }
  3664. }
  3665. else //EntryToReg is ACTIVE
  3666. {
  3667. *pfAddMem = UnionGrps(
  3668. pEntryToReg,
  3669. pEntryInCnf
  3670. );
  3671. if (pEntryInCnf->OwnerId ==
  3672. NMSDB_LOCAL_OWNER_ID)
  3673. {
  3674. *pfUpdVersNo = *pfAddMem;
  3675. }
  3676. }
  3677. }
  3678. else //Entry in conflict is an active normal group
  3679. //or unique/multihomed entry
  3680. {
  3681. if (
  3682. (pEntryInCnf->EntTyp == NMSDB_UNIQUE_ENTRY)
  3683. ||
  3684. (pEntryInCnf->EntTyp == NMSDB_MULTIHOMED_ENTRY)
  3685. )
  3686. {
  3687. //
  3688. // The following means that we are overwriting
  3689. // an active unique entry with an active or
  3690. // tombstone special group replica.
  3691. //
  3692. if (
  3693. (pEntryInCnf->OwnerId ==
  3694. NMSDB_LOCAL_OWNER_ID)
  3695. &&
  3696. (StateOfEntryToReg_e == NMSDB_E_ACTIVE)
  3697. )
  3698. {
  3699. DBGPRINT0(DET, "ClashAtReplGrpR: Active spec. grp replica clashed with owned active unique/multihomed entry. Owned entry will be released\n");
  3700. *pfRelease = TRUE;
  3701. }
  3702. else
  3703. {
  3704. if (pEntryInCnf->OwnerId ==
  3705. pEntryToReg->OwnerId)
  3706. {
  3707. DBGPRINT0(DET, "ClashAtReplGrpR: Spec. grp replica clashed with same owner's active/multihomed entry. Simple update will be done\n");
  3708. *pfUpdate = TRUE;
  3709. }
  3710. }
  3711. }
  3712. #ifdef WINSDBG
  3713. else
  3714. {
  3715. DBGPRINT0(FLOW, "ClashAtReplGrpR: Clash is with an active normal group. No change needs to be made to the db\n");
  3716. }
  3717. #endif
  3718. }
  3719. break;
  3720. default:
  3721. //
  3722. // Something really wrong here. Maybe the
  3723. // database got corrupted.
  3724. // Set this the pfUpdate to TRUE so that we overwrite this record.
  3725. *pfUpdate = TRUE;
  3726. DBGPRINT1(ERR,
  3727. "ClashAtReplGrpR: Weird state of entry in cnf (%d)\n",
  3728. StateOfEntryInCnf_e
  3729. );
  3730. WINSEVT_LOG_M(WINS_FAILURE, WINS_EVT_SFT_ERR);
  3731. WINS_RAISE_EXC_M(WINS_EXC_BAD_RECORD);
  3732. break;
  3733. } //end of switch
  3734. }
  3735. else // Entry to register is a normal group entry or a multihomed
  3736. // entry
  3737. {
  3738. if (pEntryToReg->EntTyp == NMSDB_MULTIHOMED_ENTRY)
  3739. {
  3740. switch(StateOfEntryInCnf_e)
  3741. {
  3742. case(NMSDB_E_TOMBSTONE):
  3743. *pfUpdate = TRUE;
  3744. break;
  3745. case(NMSDB_E_RELEASED):
  3746. if (pEntryInCnf->EntTyp != NMSDB_NORM_GRP_ENTRY)
  3747. {
  3748. *pfUpdate = TRUE;
  3749. }
  3750. break;
  3751. case(NMSDB_E_ACTIVE):
  3752. if (
  3753. (pEntryInCnf->EntTyp == NMSDB_UNIQUE_ENTRY)
  3754. ||
  3755. (pEntryInCnf->EntTyp == NMSDB_MULTIHOMED_ENTRY)
  3756. )
  3757. {
  3758. if (StateOfEntryToReg_e == NMSDB_E_TOMBSTONE)
  3759. {
  3760. //
  3761. // if Db entry is a replica
  3762. //
  3763. if (
  3764. pEntryInCnf->OwnerId !=
  3765. NMSDB_LOCAL_OWNER_ID
  3766. )
  3767. {
  3768. //
  3769. // if replica to reg and replica in
  3770. // in db have the same owner,
  3771. // we replace the active db entry
  3772. // with the tombstone replica
  3773. //
  3774. if (pEntryInCnf->OwnerId
  3775. == pEntryToReg->OwnerId)
  3776. {
  3777. *pfUpdate = TRUE;
  3778. }
  3779. #ifdef WINSDBG
  3780. else
  3781. {
  3782. DBGPRINT1(DET, "ClashAtReplGrpR:CLASH BETWEEN TOMBSTONE MULTIHOMED REPLICA WITH AN ACTIVE %s REPLICA IN DB. REPLICAS HAVE DIFFERENT OWNERS. DB REPLICA WILL NOT BE UPDATED\n",
  3783. NMSDB_ENTRY_UNIQUE_M(pEntryInCnf->EntTyp) ? "UNIQUE" : "MULTIHOMED");
  3784. }
  3785. #endif
  3786. }
  3787. else //db entry is active and is owned
  3788. //by us.
  3789. {
  3790. //
  3791. // Remove all members owned by the
  3792. // WINS server that owns this
  3793. // Tombstone replica from the
  3794. // entry in conflict.
  3795. if (NMSDB_ENTRY_MULTIHOMED_M(pEntryInCnf->EntTyp))
  3796. {
  3797. BOOL fFound = FALSE;
  3798. BOOL fAtLeastOneRm = FALSE;
  3799. BOOL fOwned;
  3800. PNMSDB_GRP_MEM_ENTRY_T pMem =
  3801. pEntryToReg->NodeAdds.Mem;
  3802. for ( i = 0;
  3803. i < pEntryToReg->NodeAdds.NoOfMems; i++, pMem++
  3804. )
  3805. {
  3806. if (pMem->OwnerId == pEntryToReg->OwnerId)
  3807. {
  3808. PERF("Actually, we should only remove those members that are owned by the")
  3809. PERF("remote WINS server. The current way (members with same address removed")
  3810. PERF("is less efficient since it can result in challenges when the members")
  3811. PERF("that are removed refresh with the local WINS server")
  3812. //
  3813. // If found, MemInGrp will
  3814. // remove the address from
  3815. // the Mem array of the
  3816. // conflicting record
  3817. //
  3818. fFound = MemInGrp(
  3819. &pMem->Add,
  3820. pEntryInCnf,
  3821. &fOwned,
  3822. FALSE);
  3823. }
  3824. if (!fAtLeastOneRm && fFound)
  3825. {
  3826. fAtLeastOneRm = TRUE;
  3827. }
  3828. }
  3829. //
  3830. // If atleast one member was
  3831. // found, put in the new member
  3832. // list in the db.
  3833. //
  3834. if (fAtLeastOneRm)
  3835. {
  3836. PNMSDB_GRP_MEM_ENTRY_T pCnfMem, pRegMem;
  3837. pCnfMem = pEntryInCnf->NodeAdds.Mem;
  3838. pRegMem = pEntryToReg->NodeAdds.Mem;
  3839. for (i=0;
  3840. i < pEntryInCnf->NodeAdds.NoOfMems; i++, pRegMem++,pCnfMem++
  3841. )
  3842. {
  3843. *pRegMem = *pCnfMem;
  3844. }
  3845. pEntryToReg->NodeAdds.NoOfMems =
  3846. pEntryInCnf->NodeAdds.NoOfMems;
  3847. //
  3848. // if no. of mems left is > 0, it
  3849. // means that the record is
  3850. // still active.
  3851. //
  3852. if (pEntryToReg->NodeAdds.NoOfMems != 0)
  3853. {
  3854. pEntryToReg->EntryState_e = NMSDB_E_ACTIVE;
  3855. }
  3856. //
  3857. // Setting *pfAddMem to TRUE
  3858. // ensures that the new list
  3859. // gets in
  3860. //
  3861. *pfAddMem = TRUE;
  3862. }
  3863. }
  3864. //
  3865. //
  3866. // We update the version number
  3867. // of the entry in the database
  3868. // to cause propagation
  3869. //
  3870. *pfUpdVersNo = TRUE;
  3871. }
  3872. }
  3873. else //State Of Entry to Reg has to be ACTIVE
  3874. {
  3875. //
  3876. // Clash of an ACTIVE multihomed replica
  3877. // with an active unique/multihomed
  3878. // entry. We need to challenge the
  3879. // conflicting
  3880. // entry
  3881. //
  3882. if (pEntryInCnf->OwnerId ==
  3883. pEntryToReg->OwnerId)
  3884. {
  3885. DBGPRINT0(DET, "ClashAtReplGrpR: ACTIVE unique/multihomed replica with an ACTIVE MULTIHOMED replica (same owner). Update will be done\n");
  3886. *pfUpdate = TRUE;
  3887. }
  3888. else
  3889. {
  3890. //
  3891. // Uncomment if challenge is desired instead of a simple update
  3892. //
  3893. //#if 0
  3894. if (pEntryInCnf->OwnerId ==
  3895. NMSDB_LOCAL_OWNER_ID)
  3896. //#endif
  3897. {
  3898. DWORD i;
  3899. BOOL fOwned;
  3900. PNMSDB_GRP_MEM_ENTRY_T pRegMem= pEntryToReg->NodeAdds.Mem;
  3901. for ( i = 0;
  3902. i <
  3903. pEntryToReg->NodeAdds.NoOfMems;
  3904. i++, pRegMem++ )
  3905. {
  3906. //
  3907. //If found, MemInGrp
  3908. // will remove the
  3909. // address from
  3910. // the Mem array of
  3911. // the conflicting
  3912. // record
  3913. //
  3914. (VOID) MemInGrp(
  3915. &pRegMem->Add,
  3916. pEntryInCnf, &fOwned,
  3917. FALSE);
  3918. }
  3919. if (pEntryInCnf->NodeAdds.NoOfMems != 0)
  3920. {
  3921. RemoveAllMemOfOwner(
  3922. pEntryInCnf,
  3923. pEntryToReg->OwnerId);
  3924. }
  3925. if (pEntryInCnf->NodeAdds.NoOfMems == 0)
  3926. {
  3927. DBGPRINT0(DET, "ClashAtReplGrpR: Clash between active unique/multihomed with an owned unique/multihomed entry with subset/same address(es). Simple update will be done\n");
  3928. *pfUpdate = TRUE;
  3929. }
  3930. else
  3931. {
  3932. //
  3933. //An active mh. rpl
  3934. //clashed with an
  3935. //active owned unique
  3936. //or multih entry.
  3937. //The multih entry
  3938. //needs to be
  3939. //challenged
  3940. //
  3941. DBGPRINT0(DET, "ClashAtReplGrpR: Active multihomed replica with an owned unique/multihomed entry with one or more different address(es). Challenge of owned entry will be done\n");
  3942. *pfChallenge = TRUE;
  3943. //
  3944. // Uncomment if challenge is desired instead of a simple update
  3945. //
  3946. #if 0
  3947. if (pEntryInCnf->OwnerId ==
  3948. NMSDB_LOCAL_OWNER_ID)
  3949. {
  3950. #endif
  3951. *pfRelease = TRUE;
  3952. //*pfInformWins = TRUE;
  3953. #if 0
  3954. }
  3955. #endif
  3956. }
  3957. }
  3958. //
  3959. // comment if challenge is desired instead of a simple update
  3960. //
  3961. //#if 0
  3962. else
  3963. {
  3964. DBGPRINT0(DET, "ClashAtReplGrpR: ACTIVE multihomed replica with an ACTIVE MULTIHOMED/UNIQUE replica (diff owner). Update will be done\n");
  3965. *pfUpdate = TRUE;
  3966. }
  3967. //#endif
  3968. } // end of else (Entry to reg has
  3969. // different owner than
  3970. // conflicting entry
  3971. } // end of else (EntryToReg is ACTIVE)
  3972. } //end of if entry in conflict is a unique/multihomed
  3973. #ifdef WINSDBG
  3974. else
  3975. {
  3976. DBGPRINT0(DET, "ClashAtReplGrpR: Clash of an active multihomed entry with an active group entry. No Update will be done\n");
  3977. }
  3978. #endif
  3979. break;
  3980. }
  3981. }
  3982. else //entry to register is a normal group entry
  3983. {
  3984. switch(StateOfEntryInCnf_e)
  3985. {
  3986. case(NMSDB_E_RELEASED):
  3987. // fall through
  3988. case(NMSDB_E_TOMBSTONE):
  3989. *pfUpdate = TRUE;
  3990. break;
  3991. case(NMSDB_E_ACTIVE):
  3992. if (
  3993. (pEntryInCnf->EntTyp == NMSDB_UNIQUE_ENTRY)
  3994. ||
  3995. (pEntryInCnf->EntTyp == NMSDB_MULTIHOMED_ENTRY)
  3996. )
  3997. {
  3998. //
  3999. // replace unique entry with this normal
  4000. // group only if the group is active
  4001. //
  4002. if (StateOfEntryToReg_e == NMSDB_E_ACTIVE)
  4003. {
  4004. DBGPRINT0(DET, "ClashAtReplGrpR: Clash of ACTIVE normal group entry with an owned unique/multihomed entry in db. It will be released\n");
  4005. if (pEntryInCnf->OwnerId == NMSDB_LOCAL_OWNER_ID)
  4006. {
  4007. *pfRelease = TRUE;
  4008. }
  4009. else
  4010. {
  4011. DBGPRINT0(DET, "ClashAtReplGrpR: Clash of ACTIVE normal group entry with a replica unique/multihomed entry in db. Simple update will be done\n");
  4012. *pfUpdate = TRUE;
  4013. }
  4014. }
  4015. }
  4016. else // entry in conflict is a normal or special group
  4017. {
  4018. if (pEntryInCnf->EntTyp == NMSDB_NORM_GRP_ENTRY)
  4019. {
  4020. //
  4021. // We own it but so does another WINS.
  4022. // We store the replica just in
  4023. // case, all the clients have started
  4024. // registering with other WINS servers.
  4025. //
  4026. //
  4027. // Aside: It is possible that members of
  4028. // the normal group are going to us and to
  4029. // another WINS. This is the worst case as
  4030. // far as replication traffic is concerned.
  4031. //
  4032. //
  4033. //If the owned entry is ACTIVE and the
  4034. //pulled entry an out of date TOMBSTONE
  4035. //(will only happen if WINS server we are
  4036. //pulling from was down for a while), we
  4037. //will not replace the record
  4038. //
  4039. if (pEntryInCnf->OwnerId ==
  4040. NMSDB_LOCAL_OWNER_ID)
  4041. {
  4042. if (StateOfEntryToReg_e !=
  4043. NMSDB_E_TOMBSTONE)
  4044. {
  4045. *pfUpdate = TRUE;
  4046. }
  4047. }
  4048. #if 0
  4049. if (pEntryInCnf->OwnerId == NMSDB_LOCAL_OWNER_ID)
  4050. {
  4051. //
  4052. // update the version number to
  4053. // cause propagation
  4054. //
  4055. *pfUpdVersNo = TRUE;
  4056. }
  4057. #endif
  4058. else
  4059. {
  4060. //
  4061. // Entry owned is a replica.
  4062. // We need to update it with
  4063. // the new replica if the
  4064. // owner id is the same.
  4065. //
  4066. if (pEntryInCnf->OwnerId == pEntryToReg->OwnerId)
  4067. {
  4068. *pfUpdate = TRUE;
  4069. }
  4070. else
  4071. {
  4072. DBGPRINT0(DET, "ClastAtReplGrpR: Clash between two normal group replicas owned by different owners. No update is needed\n");
  4073. }
  4074. }
  4075. }
  4076. #ifdef WINSDBG
  4077. //
  4078. // Actually we should never have a normal group
  4079. // clashing with a special group since only
  4080. // a name ending with 1c is a special group.
  4081. //
  4082. else // entry in conflict is a special group
  4083. {
  4084. //
  4085. // Since it is an active special
  4086. // group entry there is no need to update it
  4087. //
  4088. if (StateOfEntryToReg_e == NMSDB_E_ACTIVE)
  4089. {
  4090. DBGPRINT0(DET, "ClashAtReplGrpR: Clash between an ACTIVE normal group replica and an active special group entry in the db. No Update will be done\n");
  4091. }
  4092. else
  4093. {
  4094. DBGPRINT0(DET, "ClashAtReplGrpR: Clash between a TOMBSTONE normal and an active SPEC GRP entry. Db won't be updated\n");
  4095. }
  4096. }
  4097. #endif
  4098. }
  4099. break;
  4100. default:
  4101. //
  4102. // Something really wrong here. Maybe the
  4103. // database got corrupted.
  4104. //
  4105. DBGPRINT1(ERR,
  4106. "ClashAtReplGrpR: Weird state of entry in cnf (%d)\n",
  4107. StateOfEntryInCnf_e
  4108. );
  4109. WINSEVT_LOG_M(WINS_FAILURE, WINS_EVT_SFT_ERR);
  4110. WINS_RAISE_EXC_M(WINS_EXC_FAILURE);
  4111. break;
  4112. }
  4113. }
  4114. }
  4115. DBGLEAVE("ClashAtReplGrpR\n");
  4116. return;
  4117. } //ClashAtReplGrpR()
  4118. STATUS
  4119. NmsNmhReplRegInd(
  4120. IN LPBYTE pName,
  4121. IN DWORD NameLen,
  4122. IN PCOMM_ADD_T pNodeAdd,
  4123. IN DWORD Flag,
  4124. IN DWORD OwnerId,
  4125. IN VERS_NO_T VersNo,
  4126. IN PCOMM_ADD_T pAddOfRemWins
  4127. )
  4128. /*++
  4129. Routine Description:
  4130. This function registers a replica in the directory database.
  4131. A record in the database comprises of the following fields
  4132. name
  4133. IP address
  4134. time stamp
  4135. owner id.
  4136. flags byte that contain the following information
  4137. group/unique status
  4138. node type (P or M)
  4139. version number
  4140. Arguments:
  4141. pName - Name to be registered
  4142. NameLen - Length of Name
  4143. Flag - Flag word
  4144. pNodeAdd - NBT node's address
  4145. OwnerId - Owner if the record (WINS that registered it)
  4146. VersNo - Version Number
  4147. Externals Used:
  4148. None
  4149. Return Value:
  4150. Success status codes -- WINS_SUCCESS
  4151. Error status codes -- WINS_FAILURE
  4152. Error Handling:
  4153. Called by:
  4154. PullEntries in rplpull.c
  4155. Side Effects:
  4156. Comments:
  4157. None
  4158. --*/
  4159. {
  4160. NMSDB_ROW_INFO_T RowInfo; // contains row info
  4161. NMSDB_STAT_INFO_T StatusInfo; /* error status and associated
  4162. * info returned by the NmsDb func
  4163. */
  4164. BOOL fUpdate; //indicates whether conflicting entry
  4165. //needs to be overwritten
  4166. BOOL fUpdVersNo; //indicates whether version number
  4167. //needs to be incremented
  4168. BOOL fChallenge; //indicates whether a challenge needs
  4169. //to be done
  4170. BOOL fRelease; //indicates whether a node should
  4171. // be asked to release the name
  4172. BOOL fInformWins; //indicates whether the remote WINS
  4173. //has to be apprised of the clash
  4174. //result. Can be TRUE only if both
  4175. //fChallenge and fRelease are TRUE
  4176. time_t ltime; //stores time since Jan 1, 1970
  4177. STATUS RetStat = WINS_SUCCESS;
  4178. NMSCHL_CMD_TYP_E CmdTyp_e; //type of command specified to
  4179. //NmsChl
  4180. //DBG_PERFMON_VAR
  4181. DBGENTER("NmsNmhReplRegInd\n");
  4182. fUpdate = FALSE;
  4183. /*
  4184. * initialize the row info. data structure with the data to insert into
  4185. * the row. The data passed is
  4186. * Name, NameLen, address, group/unique status,
  4187. * timestamp, version number
  4188. */
  4189. RowInfo.pName = pName;
  4190. RowInfo.NameLen = NameLen;
  4191. RowInfo.pNodeAdd = pNodeAdd;
  4192. RowInfo.NodeTyp = (BYTE)((Flag & NMSDB_BIT_NODE_TYP)
  4193. >> NMSDB_SHIFT_NODE_TYP);
  4194. //Node type (B, P or M node)
  4195. RowInfo.EntTyp = NMSDB_UNIQUE_ENTRY; // this is a unique
  4196. //registration
  4197. (void)time(&ltime); //time does not return any error code
  4198. RowInfo.EntryState_e = NMSDB_ENTRY_STATE_M(Flag);
  4199. RowInfo.OwnerId = OwnerId;
  4200. RowInfo.VersNo = VersNo;
  4201. RowInfo.fUpdVersNo = TRUE;
  4202. RowInfo.fUpdTimeStamp= TRUE;
  4203. RowInfo.fStatic = NMSDB_IS_ENTRY_STATIC_M(Flag);
  4204. RowInfo.fLocal = FALSE;
  4205. RowInfo.fAdmin = FALSE;
  4206. // RowInfo.CommitGrBit = 0;
  4207. DBGPRINT4(DET, "NmsNmhReplRegInd: Name (%s);16th char (%X);State (%d); Entry is (%s)\n", RowInfo.pName, *(RowInfo.pName+15),RowInfo.EntryState_e, RowInfo.fStatic ? "STATIC" : "DYNAMIC");
  4208. DBGPRINT2(DET,"Vers. No. is (%d %d)\n", VersNo.HighPart, VersNo.LowPart);
  4209. /*
  4210. * Enter Critical Section
  4211. */
  4212. PERF("Try to get rid of this or atleast minimise its impact")
  4213. EnterCriticalSection(&NmsNmhNamRegCrtSec);
  4214. //DBG_START_PERF_MONITORING
  4215. try
  4216. {
  4217. if ( NMSDB_ENTRY_TOMB_M(Flag) ) {
  4218. RowInfo.TimeStamp = ltime + WinsCnf.TombstoneTimeout;
  4219. }
  4220. else if (OwnerId == NMSDB_LOCAL_OWNER_ID)
  4221. {
  4222. RowInfo.TimeStamp = ltime + WinsCnf.RefreshInterval;
  4223. }
  4224. else
  4225. {
  4226. RowInfo.TimeStamp = ltime + WinsCnf.VerifyInterval;
  4227. }
  4228. /*
  4229. * Insert record in the directory
  4230. */
  4231. RetStat = NmsDbInsertRowInd(
  4232. &RowInfo,
  4233. &StatusInfo
  4234. );
  4235. if (RetStat == WINS_SUCCESS)
  4236. {
  4237. /*
  4238. * If there is a conflict, do the appropriate processing
  4239. */
  4240. if (StatusInfo.StatCode == NMSDB_CONFLICT)
  4241. {
  4242. DBGPRINT0(FLOW, "NmsNmhReplRegInd: Name Conflict\n");
  4243. ClashAtReplUniqueR(
  4244. &RowInfo,
  4245. &StatusInfo,
  4246. &fUpdate,
  4247. &fUpdVersNo,
  4248. &fChallenge,
  4249. &fRelease,
  4250. &fInformWins
  4251. );
  4252. //
  4253. // if we need to challenge a node or release a name
  4254. // hand over the request to the name challenge manager
  4255. //
  4256. if ((fChallenge) || (fRelease))
  4257. {
  4258. DBGPRINT0(FLOW,
  4259. "NmsNmh: Handing name registration to challenge manager\n");
  4260. /*
  4261. * Ask the Name Challenge component to take it from
  4262. * here
  4263. */
  4264. if (fChallenge)
  4265. {
  4266. if (fRelease)
  4267. {
  4268. if (!fInformWins)
  4269. {
  4270. //
  4271. // Set this since we use it when we do the release.
  4272. //
  4273. RowInfo.NodeAdds.NoOfMems = 1;
  4274. RowInfo.NodeAdds.Mem[0].OwnerId = OwnerId;
  4275. RowInfo.NodeAdds.Mem[0].TimeStamp = RowInfo.TimeStamp;
  4276. RowInfo.NodeAdds.Mem[0].Add = *pNodeAdd;
  4277. //
  4278. // Clash with active/multihomed
  4279. //
  4280. CmdTyp_e = NMSCHL_E_CHL_N_REL;
  4281. }
  4282. else
  4283. {
  4284. //
  4285. // We will never enter this code.
  4286. //
  4287. ASSERT(0);
  4288. CmdTyp_e = NMSCHL_E_CHL_N_REL_N_INF;
  4289. }
  4290. }
  4291. else
  4292. {
  4293. CmdTyp_e = NMSCHL_E_CHL;
  4294. }
  4295. }
  4296. else
  4297. {
  4298. if (fRelease)
  4299. {
  4300. if (!fInformWins)
  4301. {
  4302. CmdTyp_e = NMSCHL_E_REL;
  4303. }
  4304. else
  4305. {
  4306. //
  4307. // We will never enter this code.
  4308. //
  4309. ASSERT(0);
  4310. CmdTyp_e = NMSCHL_E_REL_N_INF;
  4311. }
  4312. }
  4313. }
  4314. NmsChlHdlNamReg(
  4315. CmdTyp_e,
  4316. WINS_E_RPLPULL,
  4317. NULL,
  4318. NULL,
  4319. 0,
  4320. 0,
  4321. &RowInfo,
  4322. &StatusInfo,
  4323. pAddOfRemWins
  4324. );
  4325. }
  4326. else // it is not a request for the name challenge manager
  4327. {
  4328. //
  4329. // If version number needs to be updated, do so
  4330. if (fUpdVersNo)
  4331. {
  4332. RowInfo.VersNo = NmsNmhMyMaxVersNo;
  4333. RowInfo.fUpdTimeStamp = FALSE;
  4334. RetStat = NmsDbUpdateVersNo(
  4335. TRUE,
  4336. &RowInfo,
  4337. &StatusInfo
  4338. );
  4339. DBGPRINT1(FLOW,
  4340. "NmsNmhReplRegInd: Version Number changed to (%d)\n",
  4341. NmsNmhMyMaxVersNo);
  4342. }
  4343. else
  4344. {
  4345. if (fUpdate)
  4346. {
  4347. //
  4348. // The row needs to be updated
  4349. //
  4350. RetStat = NmsDbUpdateRow(
  4351. &RowInfo,
  4352. &StatusInfo
  4353. );
  4354. }
  4355. else //no update need be done
  4356. {
  4357. StatusInfo.StatCode = NMSDB_SUCCESS;
  4358. DBGPRINT0(FLOW,
  4359. "Repl Registration (unique entry) not needed for this Conflict\n");
  4360. }
  4361. }
  4362. FUTURES("Use WINS status codes. Get rid of NMSDB status codes -- Maybe")
  4363. if (
  4364. (RetStat != WINS_SUCCESS) ||
  4365. (StatusInfo.StatCode != NMSDB_SUCCESS)
  4366. )
  4367. {
  4368. RetStat = WINS_FAILURE;
  4369. DBGPRINT5(ERR, "NmsNmhReplUniqueR: Could not update Db with replica %s[%x] of Owner Id (%d) and Vers. No (%d %d)\n", RowInfo.pName, *(RowInfo.pName + 15), RowInfo.OwnerId, RowInfo.VersNo.HighPart, RowInfo.VersNo.LowPart);
  4370. }
  4371. else //we succeeded in inserting the row
  4372. {
  4373. DBGPRINT0(FLOW, "NmsNmhReplRegInd: Updated Db\n");
  4374. if (fUpdVersNo)
  4375. {
  4376. NMSNMH_INC_VERS_COUNTER_M(
  4377. NmsNmhMyMaxVersNo,
  4378. NmsNmhMyMaxVersNo
  4379. );
  4380. //
  4381. // Send a Push Notification if required
  4382. //
  4383. DBGIF(fWinsCnfRplEnabled)
  4384. RPL_PUSH_NTF_M(RPL_PUSH_NO_PROP, NULL, NULL, NULL);
  4385. }
  4386. }
  4387. }
  4388. }
  4389. #ifdef WINSDBG
  4390. else //no conflict means success
  4391. {
  4392. DBGPRINT0(FLOW,
  4393. "NmsNmhReplRegInd:Replica Registration Done. No conflict\n");
  4394. }
  4395. #endif
  4396. } // end of if (RetStat == WINS_SUCCESS)
  4397. #ifdef WINSDBG
  4398. else
  4399. {
  4400. DBGPRINT0(ERR, "NmsNmhReplRegInd: Could not register replica\n");
  4401. }
  4402. #endif
  4403. } // end of try block
  4404. except (EXCEPTION_EXECUTE_HANDLER) {
  4405. DWORD ExcCode = GetExceptionCode();
  4406. DBGPRINTEXC("NmsNmhReplRegInd");
  4407. DBGPRINT4(EXC, "NmsNmhNamReplRegInd. Name is (%s), Version No (%d %d); Owner Id (%d)\n", RowInfo.pName, RowInfo.VersNo.HighPart,
  4408. RowInfo.VersNo.LowPart, RowInfo.OwnerId);
  4409. WinsEvtLogDetEvt(FALSE, WINS_EVT_RPL_REG_UNIQUE_ERR,
  4410. NULL, __LINE__, "sdddd", RowInfo.pName,
  4411. ExcCode,
  4412. pAddOfRemWins != NULL ? pAddOfRemWins->Add.IPAdd : 0,
  4413. RowInfo.VersNo.LowPart, RowInfo.VersNo.HighPart);
  4414. if (WINS_EXC_BAD_RECORD == ExcCode && fUpdate) {
  4415. // The row needs to be updated
  4416. DBGPRINT4(EXC, "NmsNmhNamReplRegInd. Bad Record will overwitten by Name is (%s), Version No (%d %d); Owner Id (%d)\n", RowInfo.pName, RowInfo.VersNo.HighPart,
  4417. RowInfo.VersNo.LowPart, RowInfo.OwnerId);
  4418. RetStat = NmsDbUpdateRow(&RowInfo,&StatusInfo);
  4419. if ( WINS_SUCCESS == RetStat && NMSDB_SUCCESS == StatusInfo.StatCode ) {
  4420. NMSNMH_INC_VERS_COUNTER_M(NmsNmhMyMaxVersNo,NmsNmhMyMaxVersNo);
  4421. // Send a Push Notification if required
  4422. DBGIF(fWinsCnfRplEnabled)
  4423. RPL_PUSH_NTF_M(RPL_PUSH_NO_PROP, NULL, NULL, NULL);
  4424. } else {
  4425. // dont let bad record stop replication.
  4426. RetStat = WINS_SUCCESS;
  4427. }
  4428. } else {
  4429. RetStat = WINS_FAILURE;
  4430. }
  4431. }
  4432. LeaveCriticalSection(&NmsNmhNamRegCrtSec);
  4433. //DBG_PRINT_PERF_DATA
  4434. return(RetStat);
  4435. } //NmsNmhReplRegInd()
  4436. STATUS
  4437. NmsNmhReplGrpMems(
  4438. IN LPBYTE pName,
  4439. IN DWORD NameLen,
  4440. IN BYTE EntTyp,
  4441. IN PNMSDB_NODE_ADDS_T pGrpMem,
  4442. IN DWORD Flag, //change to take Flag byte
  4443. IN DWORD OwnerId,
  4444. IN VERS_NO_T VersNo,
  4445. IN PCOMM_ADD_T pAddOfRemWins
  4446. )
  4447. /*++
  4448. Routine Description:
  4449. This function is called to register a replica of a group
  4450. Arguments:
  4451. pName - Name of replica to register
  4452. NameLen - Length of the name
  4453. EntTyp - Type of replica (Normal group or special group)
  4454. pGrpMem - Address of array of group members
  4455. Flag - Flag word of replica record
  4456. OwnerId - Owner Id
  4457. VersNo - Version No.
  4458. Externals Used:
  4459. NmsNmhNamRegCrtSec
  4460. Return Value:
  4461. Success status codes -- WINS_SUCCESS
  4462. Error status codes -- WINS_FAILURE
  4463. Error Handling:
  4464. Called by:
  4465. PullEntries() in rplpull.c
  4466. Side Effects:
  4467. Comments:
  4468. None
  4469. --*/
  4470. {
  4471. DWORD i;
  4472. NMSDB_ROW_INFO_T RowInfo;
  4473. time_t ltime;
  4474. NMSDB_STAT_INFO_T StatusInfo;
  4475. STATUS RetStat = WINS_SUCCESS;
  4476. BOOL fUpdate; //indicates whether conflicting entry
  4477. //needs to be overwritten
  4478. BOOL fUpdVersNo; //indicates whether version number
  4479. //needs to be incremented
  4480. BOOL fAddMem; //indicates whether a member needs to
  4481. //be added
  4482. BOOL fRelease; //indicates whether a node should
  4483. // be asked to release the name
  4484. BOOL fChallenge; //indicates whether a node should
  4485. // be challenged (will be set to TRUE
  4486. // only for the multihomed scenario)
  4487. BOOL fUpdTimeStamp; //indicates whether the time stamp
  4488. // of the entry should be changed
  4489. BOOL fInformWins;
  4490. NMSCHL_CMD_TYP_E CmdTyp_e; //type of command specified to NmsChl
  4491. //DBG_PERFMON_VAR
  4492. DBGENTER("NmsNmhReplGrpMems\n");
  4493. fUpdate = FALSE;
  4494. /*
  4495. * initialize the row info. data structure with the data to insert into
  4496. * the row. The data passed is
  4497. * Name, NameLen, IP address, group/unique status,
  4498. * timestamp, version number
  4499. */
  4500. RowInfo.pName = pName;
  4501. RowInfo.NameLen = NameLen;
  4502. RowInfo.NodeAdds.NoOfMems = pGrpMem->NoOfMems;
  4503. PERF("Since this function will be called multiple times, it would be better")
  4504. PERF("to call time() in the caller (i.e. PullEntries)")
  4505. (void)time(&ltime); //time() does not return any error code
  4506. EnterCriticalSection(&NmsNmhNamRegCrtSec);
  4507. if ( NMSDB_ENTRY_TOMB_M(Flag) ) {
  4508. ltime += WinsCnf.TombstoneTimeout;
  4509. }
  4510. else if (OwnerId == NMSDB_LOCAL_OWNER_ID)
  4511. {
  4512. ltime += WinsCnf.RefreshInterval;
  4513. }
  4514. else
  4515. {
  4516. ltime += WinsCnf.VerifyInterval;
  4517. }
  4518. LeaveCriticalSection(&NmsNmhNamRegCrtSec);
  4519. if (EntTyp != NMSDB_NORM_GRP_ENTRY)
  4520. {
  4521. if (EntTyp == NMSDB_MULTIHOMED_ENTRY)
  4522. {
  4523. //
  4524. // For multihomed nodes
  4525. //
  4526. RowInfo.NodeTyp = (BYTE)((Flag & NMSDB_BIT_NODE_TYP)
  4527. >> NMSDB_SHIFT_NODE_TYP);
  4528. }
  4529. else
  4530. {
  4531. RowInfo.NodeTyp = 0;
  4532. }
  4533. //
  4534. // It is a special group entry or a multihomed entry
  4535. //
  4536. for(i=0; i<pGrpMem->NoOfMems; i++)
  4537. {
  4538. RowInfo.NodeAdds.Mem[i].Add = pGrpMem->Mem[i].Add;
  4539. RowInfo.NodeAdds.Mem[i].OwnerId = pGrpMem->Mem[i].OwnerId;
  4540. RowInfo.NodeAdds.Mem[i].TimeStamp = ltime;
  4541. #if 0
  4542. NOTE("Currently, the timestamp of the record or those of its members is not")
  4543. NOTE("replicated. There is no need for this. In the future, if a WINS server")
  4544. NOTE("starts looking at the timestamps of non-owned members of a special group")
  4545. NOTE("or a multihomed entry, we would need to replicate this")
  4546. RowInfo.NodeAdds.Mem[i].TimeStamp =
  4547. pGrpMem->Mem[i].TimeStamp;
  4548. #endif
  4549. }
  4550. RowInfo.pNodeAdd = NULL;
  4551. }
  4552. else // replica is a normal group
  4553. {
  4554. RowInfo.pNodeAdd = &pGrpMem->Mem[0].Add;
  4555. RowInfo.NodeAdds.Mem[0].Add = pGrpMem->Mem[0].Add;
  4556. RowInfo.NodeAdds.Mem[0].OwnerId = pGrpMem->Mem[0].OwnerId;
  4557. RowInfo.NodeAdds.Mem[0].TimeStamp = ltime;
  4558. RowInfo.NodeTyp = 0;
  4559. }
  4560. RowInfo.EntTyp = EntTyp;
  4561. RowInfo.OwnerId = (BYTE)OwnerId; // this is a replica
  4562. RowInfo.VersNo = VersNo;
  4563. RowInfo.TimeStamp = ltime;
  4564. RowInfo.EntryState_e = NMSDB_ENTRY_STATE_M(Flag);
  4565. RowInfo.fUpdVersNo = TRUE;
  4566. RowInfo.fUpdTimeStamp= TRUE;
  4567. RowInfo.fStatic = NMSDB_IS_ENTRY_STATIC_M(Flag);
  4568. RowInfo.fAdmin = FALSE;
  4569. RowInfo.fLocal = FALSE;
  4570. // RowInfo.CommitGrBit = 0;
  4571. DBGPRINT5(DET, "NmsNmhReplGrpMems: Name (%s);16th char (%X);State (%d); Static flag (%d); Entry is a %s\n", RowInfo.pName, *(RowInfo.pName+15), RowInfo.EntryState_e, RowInfo.fStatic,
  4572. (EntTyp == NMSDB_NORM_GRP_ENTRY ? "NORMAL GROUP" : (EntTyp == NMSDB_SPEC_GRP_ENTRY) ? "SPECIAL GROUP" : "MULTIHOMED"));
  4573. DBGPRINT2(DET, "Vers. No. is (%d %d)\n", VersNo.HighPart, VersNo.LowPart);
  4574. /*
  4575. * Enter Critical Section
  4576. */
  4577. PERF("Try to get rid of this or atleast minimise its impact")
  4578. EnterCriticalSection(&NmsNmhNamRegCrtSec);
  4579. //DBG_START_PERF_MONITORING
  4580. try {
  4581. RetStat = NmsDbInsertRowGrp(
  4582. &RowInfo,
  4583. &StatusInfo
  4584. );
  4585. if (RetStat == WINS_SUCCESS)
  4586. {
  4587. /*
  4588. * If there is a conflict, do the appropriate processing
  4589. */
  4590. if (StatusInfo.StatCode == NMSDB_CONFLICT)
  4591. {
  4592. DBGPRINT0(FLOW, "NmsNmhReplGrpMems: Name Conflict\n");
  4593. ClashAtReplGrpR(
  4594. &RowInfo,
  4595. &StatusInfo,
  4596. &fAddMem,
  4597. &fUpdate,
  4598. &fUpdVersNo,
  4599. &fRelease,
  4600. &fChallenge,
  4601. &fUpdTimeStamp,
  4602. &fInformWins
  4603. );
  4604. PERF("Might want to examine which cases happen most often and then rearrange")
  4605. PERF("this so that the most often expected cases come first in the following")
  4606. PERF("if tests")
  4607. //
  4608. // if fRelease or fChallenge (will be set only for
  4609. // multihomed case) is TRUE, we don't look at any other
  4610. // attributes
  4611. //
  4612. if (fRelease)
  4613. {
  4614. DBGPRINT0(FLOW,
  4615. "NmsNmhReplGrpMems: Handing name registration to challenge manager\n");
  4616. if (fChallenge)
  4617. {
  4618. /*
  4619. *Ask the Name Challenge comp to take it from
  4620. *here. fInformWins will not ever by TRUE as
  4621. * it stands currently 10/15/98 (has been
  4622. * the case since the beginning).
  4623. */
  4624. CmdTyp_e = (fInformWins ?
  4625. NMSCHL_E_CHL_N_REL_N_INF :
  4626. NMSCHL_E_CHL_N_REL);
  4627. }
  4628. else
  4629. {
  4630. CmdTyp_e = NMSCHL_E_REL;
  4631. }
  4632. NmsChlHdlNamReg(
  4633. CmdTyp_e,
  4634. WINS_E_RPLPULL,
  4635. NULL,
  4636. NULL,
  4637. 0,
  4638. 0,
  4639. &RowInfo,
  4640. &StatusInfo,
  4641. pAddOfRemWins
  4642. );
  4643. }
  4644. else // we need to handle this in this thread only
  4645. {
  4646. //
  4647. // If one or more members have to be added to the
  4648. // list already there (RowInfo.NodeAdds will have
  4649. // these new members)
  4650. //
  4651. if (fAddMem)
  4652. {
  4653. //
  4654. // The owner stays the same
  4655. //
  4656. //RowInfo.OwnerId = StatusInfo.OwnerId;
  4657. //
  4658. // If vers number needs to be updated, do so
  4659. //
  4660. // Note: This should never happen if the
  4661. // record in the db is not owned by this
  4662. // WINS
  4663. //
  4664. if (fUpdVersNo)
  4665. {
  4666. //
  4667. // The owner stays the same. We will
  4668. // never update the version number
  4669. // unless it is owned by the local WINS
  4670. //
  4671. RowInfo.OwnerId = NMSDB_LOCAL_OWNER_ID;
  4672. RowInfo.VersNo = NmsNmhMyMaxVersNo;
  4673. ASSERT(StatusInfo.OwnerId ==
  4674. NMSDB_LOCAL_OWNER_ID);
  4675. }
  4676. //
  4677. // If fUpdVersNo is not set, it means that
  4678. // the record is owned by another WINS. Because
  4679. // we are adding a member, we should change
  4680. // both the owner id and the version number
  4681. // to that of the current record. In other
  4682. // words, do an update. This will ensure that
  4683. // partners of this WINS will see the changed
  4684. // member list.
  4685. //
  4686. #if 0
  4687. else
  4688. {
  4689. RowInfo.fUpdVersNo = FALSE;
  4690. }
  4691. #endif
  4692. RetStat = NmsDbUpdateRow (
  4693. &RowInfo,
  4694. &StatusInfo
  4695. );
  4696. }
  4697. else // no member needs to be added
  4698. {
  4699. //
  4700. // If vers number needs to be updated, do so
  4701. //
  4702. if (fUpdVersNo)
  4703. {
  4704. RowInfo.VersNo = NmsNmhMyMaxVersNo;
  4705. //
  4706. // we use the attribute fUpdTimeStamp
  4707. // only if fUpdVersNo is TRUE (and
  4708. // fAddMem == FALSE)
  4709. //
  4710. RowInfo.fUpdTimeStamp = fUpdTimeStamp;
  4711. RetStat = NmsDbUpdateVersNo(
  4712. TRUE,
  4713. &RowInfo,
  4714. &StatusInfo
  4715. );
  4716. }
  4717. else
  4718. {
  4719. //
  4720. // If the entire record needs to be
  4721. // updated do so.
  4722. //
  4723. if (fUpdate)
  4724. {
  4725. RetStat = NmsDbUpdateRow(
  4726. &RowInfo,
  4727. &StatusInfo
  4728. );
  4729. DBGPRINT0(FLOW,
  4730. "NmsNmhReplGrpMems: Updated Db\n");
  4731. }
  4732. else
  4733. {
  4734. StatusInfo.StatCode = NMSDB_SUCCESS;
  4735. DBGPRINT0(FLOW,
  4736. "Repl Registration (group) not needed for this conflict\n");
  4737. }
  4738. } // vers no. not to be incremented
  4739. } // no member needs to be added
  4740. FUTURES("Use WINS status codes. Get rid of NMSDB status codes - Maybe")
  4741. //we succeeded in inserting the row
  4742. if (
  4743. (RetStat != WINS_SUCCESS) ||
  4744. (StatusInfo.StatCode != NMSDB_SUCCESS)
  4745. )
  4746. {
  4747. RetStat = WINS_FAILURE;
  4748. DBGPRINT5(ERR, "NmsNmhReplGrpR: Could not update Db with replica %s[%x] of Owner Id (%d) and Vers. No (%d %d)\n", RowInfo.pName, *(RowInfo.pName + 15), RowInfo.OwnerId, RowInfo.VersNo.HighPart, RowInfo.VersNo.LowPart);
  4749. }
  4750. else
  4751. {
  4752. if (fUpdVersNo)
  4753. {
  4754. NMSNMH_INC_VERS_COUNTER_M(
  4755. NmsNmhMyMaxVersNo,
  4756. NmsNmhMyMaxVersNo
  4757. );
  4758. DBGIF(fWinsCnfRplEnabled)
  4759. RPL_PUSH_NTF_M(RPL_PUSH_NO_PROP, NULL, NULL,
  4760. NULL);
  4761. }
  4762. }
  4763. } // need to handle it in this thread only
  4764. }
  4765. else //no conflict means success
  4766. {
  4767. DBGPRINT0(FLOW,
  4768. "Replica Registration Done. No conflict\n");
  4769. }
  4770. } // end of if (RetStat == WINS_SUCCESS)
  4771. #ifdef WINSDBG
  4772. else
  4773. {
  4774. DBGPRINT0(ERR,
  4775. "NmsNmhReplGrpMems: Could not register replica\n");
  4776. }
  4777. #endif
  4778. } // end of try block
  4779. except (EXCEPTION_EXECUTE_HANDLER) {
  4780. BYTE Tmp[20];
  4781. DWORD ExcCode = GetExceptionCode();
  4782. DBGPRINT1(EXC, "NmsNmhReplGrpMems: Got exception (%d)\n",
  4783. ExcCode);
  4784. WinsEvtLogDetEvt(FALSE, WINS_EVT_RPL_REG_GRP_MEM_ERR,
  4785. NULL, __LINE__, "sdsdd", RowInfo.pName,
  4786. ExcCode,
  4787. pAddOfRemWins != NULL ? _itoa(pAddOfRemWins->Add.IPAdd, Tmp, 10) : "SEE AN EARLIER LOG",
  4788. RowInfo.VersNo.LowPart, RowInfo.VersNo.HighPart);
  4789. if (WINS_EXC_BAD_RECORD == ExcCode && fUpdate) {
  4790. // The row needs to be updated
  4791. DBGPRINT4(EXC, "NmsNmhNamReplGrpMems. Bad Record will overwitten by Name is (%s), Version No (%d %d); Owner Id (%d)\n", RowInfo.pName, RowInfo.VersNo.HighPart,
  4792. RowInfo.VersNo.LowPart, RowInfo.OwnerId);
  4793. RetStat = NmsDbUpdateRow(&RowInfo,&StatusInfo);
  4794. if ( WINS_SUCCESS == RetStat && NMSDB_SUCCESS == StatusInfo.StatCode ) {
  4795. NMSNMH_INC_VERS_COUNTER_M(NmsNmhMyMaxVersNo,NmsNmhMyMaxVersNo);
  4796. // Send a Push Notification if required
  4797. DBGIF(fWinsCnfRplEnabled)
  4798. RPL_PUSH_NTF_M(RPL_PUSH_NO_PROP, NULL, NULL, NULL);
  4799. } else {
  4800. // dont let bad record stop replication.
  4801. RetStat = WINS_SUCCESS;
  4802. }
  4803. } else {
  4804. RetStat = WINS_FAILURE;
  4805. }
  4806. RetStat = WINS_FAILURE;
  4807. }
  4808. LeaveCriticalSection(&NmsNmhNamRegCrtSec);
  4809. //DBG_PRINT_PERF_DATA
  4810. DBGLEAVE("NmsNmhReplGrpMems\n");
  4811. return(RetStat);
  4812. } //NmsNmhReplGrpMems()
  4813. BOOL
  4814. UnionGrps(
  4815. PNMSDB_ROW_INFO_T pEntryToReg,
  4816. PNMSDB_ROW_INFO_T pEntryInCnf
  4817. )
  4818. /*++
  4819. Routine Description:
  4820. This function is called to create a union of special groups
  4821. Arguments:
  4822. pEntryToReg - Entry to register
  4823. pEntryInCnf - Entry In conflict
  4824. Externals Used:
  4825. None
  4826. Return Value:
  4827. TRUE if the union is a superset
  4828. FALSE otherwise
  4829. Error Handling:
  4830. Called by:
  4831. ClashAtReplGrpR
  4832. Side Effects:
  4833. Comments:
  4834. None
  4835. --*/
  4836. {
  4837. DWORD no;
  4838. DWORD i, n;
  4839. BOOL fFound;
  4840. BOOL fToRemove;
  4841. BOOL fUnion = FALSE;
  4842. PNMSDB_GRP_MEM_ENTRY_T pCnfMems;
  4843. PNMSDB_GRP_MEM_ENTRY_T pRegMems;
  4844. PNMSDB_ADD_STATE_T pOwnAddTbl = pNmsDbOwnAddTbl;
  4845. BOOL fMemToReplaceFound;
  4846. DWORD IdOfMemToReplace;
  4847. DWORD EntryInCnfMemsBeforeUnion;
  4848. DWORD EntryToRegMemsBeforeUnion;
  4849. DBGENTER("UnionGrps\n");
  4850. DBGPRINT2(DET, "UnionGrps: No Of Mems To register = (%d)\nNo Of Mems in Conflicting record = (%d)\n",
  4851. pEntryToReg->NodeAdds.NoOfMems,
  4852. pEntryInCnf->NodeAdds.NoOfMems
  4853. );
  4854. //
  4855. // Remember the number of members in the conflicting record before
  4856. // performing the union. After the union, if the list grows, we make the
  4857. // local wins owner of this record NMSDB_LOCAL_OWNER_ID. This causes
  4858. // the verid to go up and hence will update the member list of this record
  4859. // in our replication partner dbs.
  4860. //
  4861. EntryInCnfMemsBeforeUnion = pEntryInCnf->NodeAdds.NoOfMems;
  4862. EntryToRegMemsBeforeUnion = pEntryToReg->NodeAdds.NoOfMems;
  4863. //
  4864. // First, remove all members from the conflicting record that
  4865. // are owned by the WINS whose replica we pulled but are not
  4866. // in the list of the remote WINS sever owned members of the replica
  4867. //
  4868. pCnfMems = pEntryInCnf->NodeAdds.Mem;
  4869. for (i=0; i < pEntryInCnf->NodeAdds.NoOfMems; )
  4870. {
  4871. if (pCnfMems->OwnerId == pEntryToReg->OwnerId)
  4872. {
  4873. pRegMems = pEntryToReg->NodeAdds.Mem;
  4874. fToRemove = TRUE;
  4875. for (no=0; no < pEntryToReg->NodeAdds.NoOfMems; no++, pRegMems++)
  4876. {
  4877. if (pCnfMems->OwnerId != pRegMems->OwnerId)
  4878. {
  4879. //
  4880. // OwnerId is different from that of the replica,
  4881. // go to the next member in the list
  4882. //
  4883. continue;
  4884. }
  4885. else //owner id same as that of replica member
  4886. {
  4887. if (pCnfMems->Add.Add.IPAdd != pRegMems->Add.Add.IPAdd)
  4888. {
  4889. //
  4890. // IP add. different, continue on so that
  4891. // we compare with the next member in
  4892. // the replica
  4893. //
  4894. continue;
  4895. }
  4896. else //ip addresses are same
  4897. {
  4898. fToRemove = FALSE;
  4899. break;
  4900. }
  4901. }
  4902. } // end of for
  4903. if (fToRemove)
  4904. {
  4905. PNMSDB_GRP_MEM_ENTRY_T pMem;
  4906. DBGPRINT4(FLOW, "UnionGrps: REMOVING conflicting member no = (%d) of (%s) with owner id. = (%d) and address (%x)\n", i, pEntryToReg->pName, pCnfMems->OwnerId, pCnfMems->Add.Add.IPAdd);
  4907. pMem = pCnfMems;
  4908. for (n = i; n < (pEntryInCnf->NodeAdds.NoOfMems - 1); n++)
  4909. {
  4910. *pMem = *(pMem + 1);
  4911. pMem++;
  4912. }
  4913. pEntryInCnf->NodeAdds.NoOfMems--;
  4914. if (!fUnion)
  4915. {
  4916. fUnion = TRUE;
  4917. }
  4918. continue;
  4919. }
  4920. }
  4921. i++;
  4922. pCnfMems++;
  4923. } // end of for (loop over conflicting members)
  4924. //
  4925. // For each member in the record to register, do the following..
  4926. //
  4927. pRegMems = pEntryToReg->NodeAdds.Mem;
  4928. for(i=0; i < pEntryToReg->NodeAdds.NoOfMems; pRegMems++, i++)
  4929. {
  4930. fFound = FALSE;
  4931. DBGPRINT3(DET, "UnionGrps: Member no (%d) of record to register has IP address = (%d) and owner id. = (%d)\n", i, pRegMems->Add.Add.IPAdd,
  4932. pRegMems->OwnerId
  4933. );
  4934. //
  4935. // Check against all members of the record in conflict
  4936. //
  4937. pCnfMems = pEntryInCnf->NodeAdds.Mem;
  4938. fMemToReplaceFound = FALSE;
  4939. for(no=0; no < pEntryInCnf->NodeAdds.NoOfMems; no++, pCnfMems++)
  4940. {
  4941. DBGPRINT3(DET, "UnionGrps: Comparing with member (%d) of conflicting record. Member address is (%d) and owner id is (%d)\n",
  4942. no, pCnfMems->Add.Add.IPAdd, pCnfMems->OwnerId);
  4943. //
  4944. // If the address is the same and the owner Id is the
  4945. // same, we break out of the loop in order to check
  4946. // the next member of the record to register's list
  4947. //
  4948. if (
  4949. pCnfMems->Add.Add.IPAdd ==
  4950. pRegMems->Add.Add.IPAdd
  4951. )
  4952. {
  4953. if ( pCnfMems->OwnerId == pRegMems->OwnerId )
  4954. {
  4955. DBGPRINT3(DET, "UnionGrps: IP address = (%d) with owner id. of (%d) is already there in conflicting group (%s)\n",
  4956. pRegMems->Add.Add.IPAdd,
  4957. pRegMems->OwnerId,
  4958. pEntryToReg->Name
  4959. );
  4960. //
  4961. // set fFound to TRUE so that this
  4962. // member is not added to StoreMems
  4963. // later on in this for loop.
  4964. //
  4965. fFound = TRUE;
  4966. }
  4967. else //same IP address, but different owners
  4968. {
  4969. DBGPRINT4(DET, "UnionGrps: IP address = (%d) (with owner id. of (%d)) is already there in conflicting group (%s) but is owned by (%d) \n",
  4970. pRegMems->Add.Add.IPAdd,
  4971. pRegMems->OwnerId,
  4972. pEntryToReg->Name,
  4973. pCnfMems->OwnerId,
  4974. );
  4975. fFound = TRUE;
  4976. //
  4977. // if the timestamp is MAXULONG, then
  4978. // we should not replace the owner id.
  4979. //Currently MAXULONG is there only for
  4980. //static SG members.
  4981. //
  4982. if (pCnfMems->TimeStamp != MAXLONG_PTR)
  4983. {
  4984. //
  4985. // Replace the owner id of the member
  4986. // in the conflicting record with that
  4987. // of the member in the record to reg
  4988. //
  4989. pCnfMems->OwnerId = pRegMems->OwnerId;
  4990. //
  4991. // Set fUnion to TRUE so that the
  4992. // caller of this function increments
  4993. // the version count (only if the
  4994. // conflicting record is owned; In such
  4995. // a case, we want to propagate the
  4996. // record)
  4997. //
  4998. fUnion = TRUE;
  4999. }
  5000. }
  5001. //
  5002. // break out of the for loop;
  5003. // We are done with this member of the
  5004. // record to register
  5005. //
  5006. break;
  5007. }
  5008. else
  5009. {
  5010. //
  5011. // Addresses don't match. If the member in the
  5012. // conflicting record is not owned by the local
  5013. // WINS it might be a candidate for replacement
  5014. // if we don't find a member with a matching
  5015. // address. NOTE: a member with a timestamp of
  5016. // MAXULONG is not to be replaced.
  5017. // Currently, only a static SG member can have
  5018. // a MAXULONG value
  5019. //
  5020. if ((pCnfMems->OwnerId != NMSDB_LOCAL_OWNER_ID)
  5021. &&
  5022. (pCnfMems->TimeStamp != MAXLONG_PTR))
  5023. {
  5024. if (
  5025. !fMemToReplaceFound
  5026. &&
  5027. ((pOwnAddTbl + pCnfMems->OwnerId)->MemberPrec
  5028. <
  5029. (pOwnAddTbl + pRegMems->OwnerId)->MemberPrec)
  5030. )
  5031. {
  5032. fMemToReplaceFound = TRUE;
  5033. IdOfMemToReplace = no;
  5034. }
  5035. }
  5036. }
  5037. } // for (..) for looping over all mem. of conflicting record
  5038. //
  5039. // If we did not find the member in conflicting record
  5040. // we insert it into StoreMems if there are vacant slots
  5041. // at the end
  5042. //
  5043. if(!fFound)
  5044. {
  5045. if (pEntryInCnf->NodeAdds.NoOfMems < NMSDB_MAX_MEMS_IN_GRP)
  5046. {
  5047. //
  5048. // add the member of the record to register to
  5049. // StoreMems
  5050. //
  5051. pEntryInCnf->NodeAdds.Mem[
  5052. pEntryInCnf->NodeAdds.NoOfMems++] = *pRegMems;
  5053. fUnion = TRUE;
  5054. }
  5055. else
  5056. {
  5057. //
  5058. // if there is atleast one remote member of lower
  5059. // precedence value, replace it
  5060. //
  5061. if (fMemToReplaceFound)
  5062. {
  5063. pEntryInCnf->NodeAdds.Mem[IdOfMemToReplace] =
  5064. *pRegMems;
  5065. fUnion = TRUE;
  5066. }
  5067. //
  5068. // check the next member in the pulled in replica
  5069. //
  5070. }
  5071. }
  5072. } // end of for loop
  5073. //
  5074. // if the conflicting member list was changed,
  5075. // Copy all information in pEntryInCnf->NodeAdds to
  5076. // pEntryToReg->NodeAdds
  5077. //
  5078. if (fUnion)
  5079. {
  5080. pRegMems = pEntryToReg->NodeAdds.Mem;
  5081. pCnfMems = pEntryInCnf->NodeAdds.Mem;
  5082. for (
  5083. i=0;
  5084. i < pEntryInCnf->NodeAdds.NoOfMems;
  5085. i++, pRegMems++, pCnfMems++
  5086. )
  5087. {
  5088. *pRegMems = *pCnfMems;
  5089. }
  5090. pEntryToReg->NodeAdds.NoOfMems = pEntryInCnf->NodeAdds.NoOfMems;
  5091. }
  5092. // if the new list is bigger, make the local wins the owner of this record.
  5093. if ( pEntryInCnf->NodeAdds.NoOfMems > EntryInCnfMemsBeforeUnion &&
  5094. pEntryInCnf->NodeAdds.NoOfMems > EntryToRegMemsBeforeUnion )
  5095. {
  5096. if ( pEntryInCnf->OwnerId != NMSDB_LOCAL_OWNER_ID ) {
  5097. // change the timestamp to verifyinterval so that this record does not get
  5098. // scavenged.
  5099. time((time_t*)&(pEntryToReg->TimeStamp));
  5100. pEntryToReg->TimeStamp += WinsCnf.VerifyInterval;
  5101. pEntryInCnf->OwnerId = NMSDB_LOCAL_OWNER_ID;
  5102. DBGPRINT3(DET, "UnionGrps: Conflicting mem# %d, registering record mem %d, new list# %d - ownership changed\n",
  5103. EntryInCnfMemsBeforeUnion, EntryToRegMemsBeforeUnion, pEntryInCnf->NodeAdds.NoOfMems);
  5104. }
  5105. }
  5106. DBGPRINT1(FLOW,
  5107. "UnionGrps: Union %s\n", (fUnion ? "DONE" : "NOT DONE"));
  5108. DBGLEAVE("UnionGrps\n");
  5109. return(fUnion);
  5110. } //UnionGrps
  5111. VOID
  5112. NmsNmhUpdVersNo(
  5113. IN LPBYTE pName,
  5114. IN DWORD NameLen,
  5115. OUT LPBYTE pRcode,
  5116. IN PCOMM_ADD_T pWinsAdd
  5117. )
  5118. /*++
  5119. Routine Description:
  5120. This function is called to update the version number of a record
  5121. Arguments:
  5122. pName - Name to be registered
  5123. NameLen - Length of Name
  5124. pRcode - result of the operation
  5125. WinsId - Id of WINS that initiated this operation
  5126. (not used currently)
  5127. Externals Used:
  5128. NmsNmhNamRegCrtSec
  5129. Return Value:
  5130. None
  5131. Error Handling:
  5132. Called by:
  5133. HandleUpdVersNoReq in rplpush.c
  5134. Side Effects:
  5135. Comments:
  5136. NOTE: This function is supposed to be called only by the PUSH
  5137. thread. It should *NOT* be called by the PULL thread. This
  5138. is because of the inherent assumption made by this function
  5139. regarding the type of index to set at the exit point of the function
  5140. --*/
  5141. {
  5142. NMSDB_ROW_INFO_T RowInfo; // contains row info
  5143. NMSDB_STAT_INFO_T StatusInfo; /* error status and associated
  5144. * info returned by the NmsDb func
  5145. */
  5146. // time_t ltime; //stores time since Jan 1, 1970
  5147. DBGENTER("NmsNmhUpdVersNo\n");
  5148. /*
  5149. * initialize the row info. data structure with the data to insert into
  5150. * the row. The data passed is
  5151. * Name, NameLen, address, group/unique status,
  5152. * timestamp, version number
  5153. */
  5154. RowInfo.pName = pName;
  5155. RowInfo.NameLen = NameLen;
  5156. //(void)time(&ltime); //time does not return any error code
  5157. //RowInfo.TimeStamp = ltime; // put current time here
  5158. RowInfo.fUpdVersNo = TRUE;
  5159. RowInfo.fUpdTimeStamp = FALSE;
  5160. RowInfo.fAdmin = FALSE; //does not really have to be set
  5161. //
  5162. // Set the current index to the name column
  5163. //
  5164. NmsDbSetCurrentIndex(
  5165. NMSDB_E_NAM_ADD_TBL_NM,
  5166. NMSDB_NAM_ADD_CLUST_INDEX_NAME
  5167. );
  5168. /*
  5169. * Enter Critical Section
  5170. */
  5171. EnterCriticalSection(&NmsNmhNamRegCrtSec);
  5172. /*
  5173. Store version number
  5174. */
  5175. RowInfo.VersNo = NmsNmhMyMaxVersNo;
  5176. try {
  5177. NmsDbUpdateVersNo(
  5178. FALSE,
  5179. &RowInfo,
  5180. &StatusInfo
  5181. );
  5182. FUTURES("Use WINS status codes. Get rid of NMSDB status codes - maybe")
  5183. if (StatusInfo.StatCode != NMSDB_SUCCESS)
  5184. {
  5185. *pRcode = NMSMSGF_E_SRV_ERR;
  5186. }
  5187. else
  5188. {
  5189. DBGPRINT0(FLOW, "NmsNmhUpdVersNo:Vers. No incremented \n");
  5190. NMSNMH_INC_VERS_COUNTER_M(
  5191. NmsNmhMyMaxVersNo,
  5192. NmsNmhMyMaxVersNo
  5193. );
  5194. *pRcode = NMSMSGF_E_SUCCESS;
  5195. DBGIF(fWinsCnfRplEnabled)
  5196. RPL_PUSH_NTF_M(RPL_PUSH_NO_PROP, NULL, pWinsAdd, NULL);
  5197. }
  5198. }
  5199. except (EXCEPTION_EXECUTE_HANDLER) {
  5200. DBGPRINTEXC("NmsNmhUpdVersNo");
  5201. WINSEVT_LOG_D_M(GetExceptionCode(),WINS_EVT_UPD_VERS_NO_ERR);
  5202. }
  5203. LeaveCriticalSection(&NmsNmhNamRegCrtSec);
  5204. //
  5205. // Set the current index to the owner-version # columns
  5206. //
  5207. NmsDbSetCurrentIndex(
  5208. NMSDB_E_NAM_ADD_TBL_NM,
  5209. NMSDB_NAM_ADD_PRIM_INDEX_NAME
  5210. );
  5211. return;
  5212. } //NmsNmhUpdVersNo()
  5213. /*
  5214. Clash scenarios:
  5215. Clash of a active unique replica with a normal group, any state: Keep the normal group. Group may be a T because the router
  5216. is down.
  5217. */