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.

1670 lines
45 KiB

  1. /*++
  2. Copyright (c) 1997-2001 Microsoft Corporation
  3. Module Name:
  4. dynreg.c
  5. Abstract:
  6. Domain Name System (DNS) API
  7. Dynamic registration implementation
  8. Author:
  9. Ram Viswanathan (ramv) March 27 1997
  10. Revision History:
  11. --*/
  12. #include "local.h"
  13. #define ENABLE_DEBUG_LOGGING 0
  14. #include "logit.h"
  15. HANDLE hQuitEvent = NULL;
  16. HANDLE hSem = NULL;
  17. HANDLE handle[2] = { NULL, NULL} ;
  18. HANDLE hConsumerThread = NULL;
  19. BOOL g_fStopNotify = FALSE;
  20. PDYNDNSQUEUE g_pdnsQueue = NULL;
  21. PDYNDNSQUEUE g_pTimedOutQueue = NULL;
  22. DWORD g_dwQCount = 0;
  23. DWORD g_MainQueueCount = 0;
  24. #define MAX_QLEN 0xFFFF
  25. #define MAX_RETRIES 0x3
  26. #define DNS_MAX_DHCP_SERVER_REGISTRATION_QUEUE_SIZE 250 // Arbitrary?
  27. //
  28. // Credentials for updates
  29. //
  30. PSEC_WINNT_AUTH_IDENTITY_W g_pIdentityCreds = NULL;
  31. //CredHandle g_CredHandle;
  32. HANDLE g_UpdateCredContext = NULL;
  33. //
  34. // Queue allocations in dnslib heap
  35. //
  36. #define QUEUE_ALLOC_HEAP(Size) Dns_Alloc(Size)
  37. #define QUEUE_ALLOC_HEAP_ZERO(Size) Dns_AllocZero(Size)
  38. #define QUEUE_FREE_HEAP(pMem) Dns_Free(pMem)
  39. //
  40. // local helper functions
  41. //
  42. DNS_STATUS
  43. DynDnsRegisterEntries(
  44. VOID
  45. );
  46. DNS_STATUS
  47. DynDnsAddForward(
  48. IN OUT REGISTER_HOST_ENTRY HostAddr,
  49. IN LPWSTR pszName,
  50. IN DWORD dwTTL,
  51. IN PIP_ARRAY DnsServerList
  52. )
  53. {
  54. DNS_STATUS status = 0;
  55. DNS_RECORD record;
  56. DYNREG_F1( "Inside function DynDnsAddForward" );
  57. RtlZeroMemory( &record, sizeof(DNS_RECORD) );
  58. record.pName = (PCHAR)pszName;
  59. record.wType = DNS_TYPE_A;
  60. record.dwTtl = dwTTL;
  61. record.wDataLength = sizeof(record.Data.A);
  62. record.Data.A.IpAddress = HostAddr.Addr.ipAddr;
  63. DYNREG_F1( "DynDnsAddForward - Calling DnsReplaceRecordSet_W for A record:" );
  64. DYNREG_F2( " Name: %S", record.pName );
  65. DYNREG_F2( " Address: 0x%x", record.Data.A.IpAddress );
  66. status = DnsReplaceRecordSetW(
  67. & record,
  68. DNS_UPDATE_CACHE_SECURITY_CONTEXT,
  69. NULL, // no security context
  70. (PIP4_ARRAY) DnsServerList,
  71. NULL // reserved
  72. );
  73. DYNREG_F2( "DynDnsAddForward - DnsReplaceRecordSet returned status: 0%x", status );
  74. return( status );
  75. }
  76. DNS_STATUS
  77. DynDnsDeleteForwards(
  78. IN PDNS_RECORD pDnsList,
  79. IN IP_ADDRESS ipAddr,
  80. IN PIP_ARRAY DnsServerList
  81. )
  82. {
  83. DNS_STATUS status = 0;
  84. PDNS_RECORD prr;
  85. DNS_RECORD record;
  86. DYNREG_F1( "Inside function DynDnsDeleteForwards" );
  87. //
  88. // the list pointed to by pDnsList is a set of PTR records.
  89. //
  90. RtlZeroMemory( &record, sizeof(DNS_RECORD) );
  91. prr = pDnsList;
  92. for ( prr = pDnsList;
  93. prr;
  94. prr = prr->pNext )
  95. {
  96. if ( prr->wType != DNS_TYPE_PTR )
  97. {
  98. //
  99. // should not happen
  100. //
  101. continue;
  102. }
  103. //
  104. // As far as the DHCP server is concerned, when timeout happens
  105. // or when client releases an address, It can update the
  106. // address lookup to clean up turds left over by say, a roaming
  107. // laptop
  108. //
  109. record.pName = prr->Data.Ptr.pNameHost;
  110. record.wType = DNS_TYPE_A;
  111. record.wDataLength = sizeof(DNS_A_DATA);
  112. record.Data.A.IpAddress = ipAddr ;
  113. //
  114. // make the appropriate call and return the first failed error
  115. //
  116. DYNREG_F1( "DynDnsDeleteForwards - Calling ModifyRecords(Remove) for A record:" );
  117. DYNREG_F2( " Name: %S", record.pName );
  118. DYNREG_F2( " Address: 0x%x", record.Data.A.IpAddress );
  119. status = DnsModifyRecordsInSet_W(
  120. NULL, // no add records
  121. & record, // delete record
  122. DNS_UPDATE_CACHE_SECURITY_CONTEXT,
  123. NULL, // no security context
  124. (PIP4_ARRAY) DnsServerList, // DNS servers
  125. NULL // reserved
  126. );
  127. if ( status != ERROR_SUCCESS )
  128. {
  129. //
  130. // DCR_QUESTION: do we really want to stop on failure?
  131. break;
  132. }
  133. DYNREG_F2( "DynDnsDeleteForwards - ModifyRecords(Remove) returned status: 0%x", status );
  134. }
  135. return( status );
  136. }
  137. DNS_STATUS
  138. DynDnsAddEntry(
  139. REGISTER_HOST_ENTRY HostAddr,
  140. LPWSTR pszName,
  141. DWORD dwRegisteredTTL,
  142. BOOL fDoForward,
  143. PDWORD pdwFwdErrCode,
  144. PIP_ARRAY DnsServerList
  145. )
  146. {
  147. DNS_STATUS status = 0;
  148. DWORD returnCode = 0;
  149. DNS_RECORD record;
  150. WCHAR reverseNameBuf[DNS_MAX_REVERSE_NAME_BUFFER_LENGTH];
  151. DWORD cch;
  152. DYNREG_F1( "Inside function DynDnsAddEntry" );
  153. *pdwFwdErrCode = 0;
  154. if ( !(HostAddr.dwOptions & REGISTER_HOST_PTR) )
  155. {
  156. status = ERROR_INVALID_PARAMETER;
  157. goto Exit;
  158. }
  159. //
  160. // create reverse lookup name for IP address
  161. //
  162. Dns_Ip4AddressToReverseName_W(
  163. reverseNameBuf,
  164. HostAddr.Addr.ipAddr );
  165. if ( fDoForward )
  166. {
  167. DYNREG_F1( "DynDnsAddEntry - Calling DynDnsAddForward" );
  168. //
  169. // we simply make a best case effort to do the forward add
  170. // if it fails, we simply ignore
  171. //
  172. returnCode = DynDnsAddForward(
  173. HostAddr,
  174. pszName,
  175. dwRegisteredTTL,
  176. DnsServerList );
  177. DYNREG_F2( "DynDnsAddEntry - DynDnsAddForward returned: 0%x",
  178. returnCode );
  179. *pdwFwdErrCode = returnCode;
  180. }
  181. RtlZeroMemory( &record, sizeof(DNS_RECORD) );
  182. record.pName = (PDNS_NAME) reverseNameBuf;
  183. record.dwTtl = dwRegisteredTTL;
  184. record.wType = DNS_TYPE_PTR;
  185. record.Data.Ptr.pNameHost = (PDNS_NAME)pszName;
  186. record.wDataLength = sizeof(record.Data.Ptr.pNameHost);
  187. DYNREG_F1( "DynDnsAddEntry - Calling DnsAddRecords_W for PTR record:" );
  188. DYNREG_F2( " Name: %S", record.pName );
  189. DYNREG_F2( " Ptr: %S", record.Data.Ptr.pNameHost );
  190. status = DnsModifyRecordsInSet_W(
  191. & record, // add record
  192. NULL, // no delete records
  193. DNS_UPDATE_CACHE_SECURITY_CONTEXT,
  194. NULL, // no context handle
  195. (PIP4_ARRAY) DnsServerList, // DNS servers
  196. NULL // reserved
  197. );
  198. DYNREG_F2( "DynDnsAddEntry - DnsAddRecords_W returned status: 0%x", status );
  199. Exit:
  200. return( status );
  201. }
  202. DNS_STATUS
  203. DynDnsDeleteEntry(
  204. REGISTER_HOST_ENTRY HostAddr,
  205. LPWSTR pszName,
  206. BOOL fDoForward,
  207. PDWORD pdwFwdErrCode,
  208. PIP_ARRAY DnsServerList
  209. )
  210. {
  211. //
  212. // Brief Synopsis of functionality:
  213. // On DoForward try deleting the forward mapping. Ignore failure
  214. // Then try deleting the PTR record. If that fails
  215. // because server is down, try again, if it fails because the
  216. // operation was refused, then dont retry
  217. //
  218. DWORD status = 0;
  219. DWORD returnCode = 0;
  220. DNS_RECORD recordPtr;
  221. DNS_RECORD recordA;
  222. WCHAR reverseNameBuf[DNS_MAX_REVERSE_NAME_BUFFER_LENGTH] ;
  223. INT i;
  224. INT cch;
  225. PDNS_RECORD precord = NULL;
  226. DYNREG_F1( "Inside function DynDnsDeleteEntry" );
  227. *pdwFwdErrCode = 0;
  228. //
  229. // build reverse lookup name for IP
  230. //
  231. Dns_Ip4AddressToReverseName_W(
  232. reverseNameBuf,
  233. HostAddr.Addr.ipAddr);
  234. if ( fDoForward )
  235. {
  236. if ( pszName && *pszName )
  237. {
  238. //
  239. // we delete a specific forward. not all forwards as we do
  240. // when we do a query
  241. //
  242. RtlZeroMemory( &recordA, sizeof(DNS_RECORD) );
  243. recordA.pName = (PDNS_NAME) pszName;
  244. recordA.wType = DNS_TYPE_A;
  245. recordA.wDataLength = sizeof(DNS_A_DATA);
  246. recordA.Data.A.IpAddress = HostAddr.Addr.ipAddr;
  247. DYNREG_F1( "DynDnsDeleteEntry - Calling ModifyRecords(Remove) for A record:" );
  248. DYNREG_F2( " Name: %S", recordA.pName );
  249. DYNREG_F2( " Address: 0x%x", recordA.Data.A.IpAddress );
  250. //
  251. // make the appropriate call
  252. //
  253. returnCode = DnsModifyRecordsInSet_W(
  254. NULL, // no add records
  255. &recordA, // delete record
  256. DNS_UPDATE_CACHE_SECURITY_CONTEXT,
  257. NULL, // no security context
  258. (PIP4_ARRAY) DnsServerList, // DNS servers
  259. NULL // reserved
  260. );
  261. DYNREG_F2( "DynDnsDeleteEntry - ModifyRecords(Remove) returned status: 0%x", returnCode );
  262. *pdwFwdErrCode = returnCode;
  263. }
  264. else
  265. {
  266. DYNREG_F1( "DynDnsDeleteEntry - Name not specified, going to query for PTR" );
  267. //
  268. //name not specified
  269. //
  270. status = DnsQuery_W(
  271. reverseNameBuf,
  272. DNS_TYPE_PTR,
  273. DNS_QUERY_BYPASS_CACHE,
  274. DnsServerList,
  275. &precord,
  276. NULL );
  277. DYNREG_F2( "DynDnsDeleteEntry - DnsQuery_W returned status: 0%x", status );
  278. switch ( status )
  279. {
  280. case DNS_ERROR_RCODE_NO_ERROR:
  281. DYNREG_F1( "DynDnsDeleteEntry - Calling DynDnsDeleteForwards" );
  282. returnCode = DynDnsDeleteForwards(
  283. precord,
  284. HostAddr.Addr.ipAddr,
  285. DnsServerList );
  286. DYNREG_F2( "DynDnsDeleteEntry - DynDnsDeleteForwards returned status: 0%x", returnCode );
  287. *pdwFwdErrCode = returnCode;
  288. #if 0
  289. switch ( returnCode )
  290. {
  291. case DNS_ERROR_RCODE_NO_ERROR:
  292. //
  293. // we succeeded, break out
  294. //
  295. break;
  296. case DNS_ERROR_RCODE_REFUSED:
  297. //
  298. // nothing can be done
  299. //
  300. break;
  301. case DNS_ERROR_RCODE_SERVER_FAILURE:
  302. case DNS_ERROR_TRY_AGAIN_LATER:
  303. case ERROR_TIMEOUT:
  304. //
  305. // need to retry this again
  306. //
  307. // goto Exit; // if uncommented will force retry
  308. break;
  309. case DNS_ERROR_RCODE_NOT_IMPLEMENTED:
  310. default:
  311. //
  312. // query itself failed. Nothing can be done
  313. //
  314. break;
  315. }
  316. #endif
  317. break;
  318. default:
  319. //
  320. // caller takes care of each situation in turn
  321. // PTR record cannot be queried for and hence
  322. // cant be deleted
  323. //
  324. goto Exit;
  325. }
  326. }
  327. }
  328. //
  329. // delete PTR Record
  330. //
  331. if ( pszName && *pszName )
  332. {
  333. //
  334. // name is known
  335. //
  336. RtlZeroMemory( &recordPtr, sizeof(DNS_RECORD) );
  337. recordPtr.pName = (PDNS_NAME) reverseNameBuf;
  338. recordPtr.wType = DNS_TYPE_PTR;
  339. recordPtr.wDataLength = sizeof(DNS_PTR_DATA);
  340. recordPtr.Data.Ptr.pNameHost = (PDNS_NAME) pszName;
  341. DYNREG_F1( "DynDnsDeleteEntry - Calling ModifyRecords(Remove) for PTR record:" );
  342. DYNREG_F2( " Name: %S", recordPtr.pName );
  343. DYNREG_F2( " PTR : 0%x", recordPtr.Data.Ptr.pNameHost );
  344. status = DnsModifyRecordsInSet_W(
  345. NULL, // no add records
  346. &recordPtr, // delete record
  347. DNS_UPDATE_CACHE_SECURITY_CONTEXT,
  348. NULL, // no security context
  349. (PIP4_ARRAY) DnsServerList, // DNS servers
  350. NULL // reserved
  351. );
  352. DYNREG_F2( "DynDnsDeleteEntry - ModifyRecords(Remove) returned status: 0%x", status );
  353. }
  354. else
  355. {
  356. DYNREG_F1( "DynDnsDeleteEntry - Calling ModifyRecords(Remove) for PTR record:" );
  357. if ( fDoForward && precord )
  358. {
  359. //
  360. // remove record from the earlier query that you made
  361. //
  362. status = DnsModifyRecordsInSet_W(
  363. NULL, // no add records
  364. precord, // delete record from query
  365. DNS_UPDATE_CACHE_SECURITY_CONTEXT,
  366. NULL, // no security context
  367. (PIP4_ARRAY) DnsServerList,
  368. NULL // reserved
  369. );
  370. DYNREG_F2( "DynDnsDeleteEntry - ModifyRecords(Remove) returned status: 0%x", status );
  371. }
  372. else
  373. {
  374. //
  375. // name is NOT known
  376. //
  377. // remove ALL records of PTR type
  378. // - zero datalength indicates type delete
  379. //
  380. RtlZeroMemory( &recordPtr, sizeof(DNS_RECORD) );
  381. recordPtr.pName = (PDNS_NAME) reverseNameBuf;
  382. recordPtr.wType = DNS_TYPE_PTR;
  383. recordPtr.Data.Ptr.pNameHost = (PDNS_NAME) NULL;
  384. DYNREG_F1( "DynDnsDeleteEntry - Calling ModifyRecords(Remove) for ANY PTR records:" );
  385. DYNREG_F2( " Name: %S", recordPtr.pName );
  386. DYNREG_F2( " PTR : 0%x", recordPtr.Data.Ptr.pNameHost );
  387. status = DnsModifyRecordsInSet_W(
  388. NULL, // no add records
  389. &recordPtr, // delete record
  390. DNS_UPDATE_CACHE_SECURITY_CONTEXT,
  391. NULL, // no security context
  392. (PIP4_ARRAY) DnsServerList,
  393. NULL // reserved
  394. );
  395. DYNREG_F2( "DynDnsDeleteEntry - ModifyRecords(Remove) returned status: 0%x", status );
  396. }
  397. }
  398. Exit:
  399. if ( precord )
  400. {
  401. // DCR: need to fix this in Win2K
  402. //
  403. //QUEUE_FREE_HEAP( precord );
  404. DnsRecordListFree(
  405. precord,
  406. DnsFreeRecordListDeep );
  407. }
  408. return( status );
  409. }
  410. DNS_STATUS
  411. DynDnsRegisterEntries(
  412. VOID
  413. )
  414. /*
  415. DynDnsRegisterEntries()
  416. This is the thread that dequeues the appropriate parameters
  417. from the main queue and starts acting upon it. This is where
  418. the bulk of the work gets done. Note that this function
  419. gets called in an endless loop
  420. Briefly, this is what the function does.
  421. a) Find PTR corresponding to the Host Addr passed in.
  422. b) If this is the same as the Address name passed in, then leave as is,
  423. Otherwise delete and add new PTR record.
  424. c) Follow forward and delete if possible from the forward's
  425. dns server.
  426. d) If DoForward then do what the client would've done in an NT5.0 case,
  427. i.e. Try to write a new forward lookup.
  428. Arguments:
  429. No arguments
  430. Return Value:
  431. is 0 if Success. and (DWORD)-1 if failure.
  432. */
  433. {
  434. /*
  435. cases to be considered here.
  436. DYNDNS_ADD_ENTRY:
  437. First query for the lookup
  438. For each of the PTR records that come back, you need to check
  439. against the one you are asked to register. If there is a match,
  440. exit with success. If not add this entry for the PTR
  441. if downlevel, then we need to add this entry to forward A record
  442. as well.
  443. DYNDNS_DELETE_ENTRY
  444. Delete the entry that corresponds to the pair that you have specified
  445. here. If it does not exist then do nothing about it.
  446. If downlevel here, then go to the A record correspond to this and
  447. delete the forward entry as well.
  448. */
  449. DWORD status, dwWaitResult;
  450. PQELEMENT pQElement = NULL;
  451. LPWSTR pszName = NULL;
  452. BOOL fDoForward;
  453. PQELEMENT pBackDependency = NULL;
  454. REGISTER_HOST_ENTRY HostAddr ;
  455. DWORD dwOperation;
  456. DWORD dwCurrTime;
  457. DWORD dwTTL;
  458. DWORD dwWaitTime = INFINITE;
  459. DWORD dwFwdAddErrCode = 0;
  460. DHCP_CALLBACK_FN pfnDhcpCallBack = NULL;
  461. PVOID pvData = NULL;
  462. DYNREG_F1( "Inside function DynDnsRegisterEntries" );
  463. //
  464. // call back function
  465. //
  466. //
  467. // check to see if there is any item in the timed out queue
  468. // that has the timer gone out and so you can start processing
  469. // that element right away
  470. //
  471. dwCurrTime = Dns_GetCurrentTimeInSeconds();
  472. if ( g_pTimedOutQueue &&
  473. g_pTimedOutQueue->pHead &&
  474. (dwCurrTime > g_pTimedOutQueue->pHead->dwRetryTime) )
  475. {
  476. //
  477. // dequeue an element from the timed out queue and process it
  478. //
  479. DYNREG_F1( "DynDnsRegisterEntries - Dequeue element from timed out list" );
  480. pQElement = Dequeue( g_pTimedOutQueue );
  481. if ( !pQElement )
  482. {
  483. status = ERROR_SUCCESS;
  484. goto Exit;
  485. }
  486. pfnDhcpCallBack = pQElement->pfnDhcpCallBack;
  487. pvData = pQElement->pvData;
  488. //
  489. // now determine if we have processed this element way too many
  490. // times
  491. //
  492. if ( pQElement->dwRetryCount >= MAX_RETRIES )
  493. {
  494. DYNREG_F1( "DynDnsRegisterEntries - Element has failed too many times, calling DHCP callback function" );
  495. if (pQElement->fDoForwardOnly)
  496. {
  497. if ( pfnDhcpCallBack )
  498. (*pfnDhcpCallBack)(DNSDHCP_FWD_FAILED, pvData);
  499. }
  500. else
  501. {
  502. if ( pfnDhcpCallBack )
  503. (*pfnDhcpCallBack)(DNSDHCP_FAILURE, pvData);
  504. }
  505. if ( pQElement->pszName )
  506. QUEUE_FREE_HEAP( pQElement->pszName );
  507. QUEUE_FREE_HEAP( pQElement );
  508. status = ERROR_SUCCESS;
  509. goto Exit;
  510. }
  511. }
  512. else
  513. {
  514. DWORD dwRetryTime = GetEarliestRetryTime (g_pTimedOutQueue);
  515. DYNREG_F1( "DynDnsRegisterEntries - No element in timed out queue." );
  516. DYNREG_F1( " Going to wait for next element." );
  517. dwWaitTime = dwRetryTime != (DWORD)-1 ?
  518. (dwRetryTime > dwCurrTime? (dwRetryTime - dwCurrTime) *1000: 0)
  519. : INFINITE;
  520. dwWaitResult = WaitForMultipleObjects ( 2,
  521. handle,
  522. FALSE,
  523. dwWaitTime );
  524. switch ( dwWaitResult )
  525. {
  526. case WAIT_OBJECT_0:
  527. //
  528. // quit event, return and let caller take care
  529. //
  530. return(0);
  531. case WAIT_OBJECT_0 + 1 :
  532. //
  533. // dequeue an element from the main queue and process
  534. //
  535. pQElement = Dequeue(g_pdnsQueue);
  536. if (!pQElement)
  537. {
  538. //
  539. // should not happen, assert failure and return error
  540. //
  541. status = NO_ERROR; // Note: This actually does happen
  542. // because when Ram adds a new
  543. // entry, he may put it in the
  544. // timed out queue instead of the
  545. // g_pdnsQueue when there is a related
  546. // item pending a retry time. Assert
  547. // removed and error code changed to
  548. // to success by GlennC - 3/6/98.
  549. goto Exit;
  550. }
  551. EnterCriticalSection(&g_QueueCS);
  552. g_MainQueueCount--;
  553. LeaveCriticalSection(&g_QueueCS);
  554. break;
  555. case WAIT_TIMEOUT:
  556. //
  557. // Let us exit the function this time around. We will catch the
  558. // timed out element the next time around
  559. //
  560. return ERROR_SUCCESS;
  561. }
  562. }
  563. //
  564. // safe to make a call since you are not dependent on anyone
  565. //
  566. DYNREG_F1( "DynDnsRegisterEntries - Got an element to process!" );
  567. pszName = pQElement->pszName;
  568. fDoForward = pQElement->fDoForward;
  569. HostAddr = pQElement->HostAddr;
  570. dwOperation = pQElement->dwOperation;
  571. dwTTL = pQElement->dwTTL;
  572. pfnDhcpCallBack = pQElement->pfnDhcpCallBack;
  573. pvData = pQElement->pvData;
  574. if ( dwOperation == DYNDNS_ADD_ENTRY )
  575. {
  576. //
  577. // make the appropriate API call to add an entry
  578. //
  579. if (pQElement->fDoForwardOnly )
  580. {
  581. DYNREG_F1( "DynDnsRegisterEntries - Calling DynDnsAddForward" );
  582. status = DynDnsAddForward ( HostAddr,
  583. pszName,
  584. dwTTL,
  585. pQElement->DnsServerList );
  586. DYNREG_F2( "DynDnsRegisterEntries - DynDnsAddForward returned status: 0%x", status );
  587. }
  588. else
  589. {
  590. DYNREG_F1( "DynDnsRegisterEntries - Calling DynDnsAddEntry" );
  591. status = DynDnsAddEntry( HostAddr,
  592. pszName,
  593. dwTTL,
  594. fDoForward,
  595. &dwFwdAddErrCode,
  596. pQElement->DnsServerList );
  597. DYNREG_F2( "DynDnsRegisterEntries - DynDnsAddEntry returned status: 0%x", status );
  598. }
  599. }
  600. else
  601. {
  602. //
  603. // make the appropriate call to delete here
  604. //
  605. if ( pQElement->fDoForwardOnly )
  606. {
  607. DNS_RECORD record;
  608. RtlZeroMemory( &record, sizeof(DNS_RECORD) );
  609. record.pName = (PCHAR)pszName;
  610. record.wType = DNS_TYPE_A;
  611. record.wDataLength = sizeof(DNS_A_DATA);
  612. record.Data.A.IpAddress = HostAddr.Addr.ipAddr ;
  613. status = DNS_ERROR_RCODE_NO_ERROR;
  614. DYNREG_F1( "DynDnsRegisterEntries - Calling ModifyRecords(Remove)" );
  615. dwFwdAddErrCode = DnsModifyRecordsInSet_W(
  616. NULL, // no add records
  617. & record, // delete record
  618. DNS_UPDATE_CACHE_SECURITY_CONTEXT,
  619. NULL, // no security context
  620. (PIP4_ARRAY) pQElement->DnsServerList,
  621. NULL // reserved
  622. );
  623. DYNREG_F2( "DynDnsRegisterEntries - ModifyRecords(Remove) returned status: 0%x", dwFwdAddErrCode );
  624. }
  625. else
  626. {
  627. DYNREG_F1( "DynDnsRegisterEntries - Calling DynDnsDeleteEntry" );
  628. status = DynDnsDeleteEntry( HostAddr,
  629. pszName,
  630. fDoForward,
  631. &dwFwdAddErrCode,
  632. pQElement->DnsServerList );
  633. DYNREG_F2( "DynDnsRegisterEntries - DynDnsDeleteEntry returned status: 0%x", status );
  634. }
  635. }
  636. if (status == DNS_ERROR_RCODE_NO_ERROR &&
  637. dwFwdAddErrCode == DNS_ERROR_RCODE_NO_ERROR )
  638. {
  639. if ( pfnDhcpCallBack )
  640. (*pfnDhcpCallBack) (DNSDHCP_SUCCESS, pvData);
  641. if ( pQElement )
  642. {
  643. if ( pQElement->pszName )
  644. QUEUE_FREE_HEAP( pQElement->pszName );
  645. QUEUE_FREE_HEAP( pQElement );
  646. }
  647. }
  648. else if ( status == DNS_ERROR_RCODE_NO_ERROR &&
  649. dwFwdAddErrCode != DNS_ERROR_RCODE_NO_ERROR )
  650. {
  651. //
  652. // adding reverse succeeded but adding forward failed
  653. //
  654. DWORD dwCurrTime = Dns_GetCurrentTimeInSeconds();
  655. pQElement->fDoForwardOnly = TRUE;
  656. if ( pQElement->dwRetryCount >= MAX_RETRIES )
  657. {
  658. //
  659. // clean up pQElement and stop retrying
  660. //
  661. if ( pfnDhcpCallBack )
  662. (*pfnDhcpCallBack)(DNSDHCP_FWD_FAILED, pvData);
  663. if ( pQElement->pszName )
  664. QUEUE_FREE_HEAP( pQElement->pszName );
  665. QUEUE_FREE_HEAP( pQElement );
  666. status = ERROR_SUCCESS;
  667. goto Exit;
  668. }
  669. //
  670. // we may need to retry this guy later
  671. //
  672. switch ( dwFwdAddErrCode )
  673. {
  674. case DNS_ERROR_RCODE_SERVER_FAILURE:
  675. status = AddToTimedOutQueue(
  676. pQElement,
  677. g_pTimedOutQueue,
  678. dwCurrTime + RETRY_TIME_SERVER_FAILURE );
  679. break;
  680. case DNS_ERROR_TRY_AGAIN_LATER:
  681. status = AddToTimedOutQueue(
  682. pQElement,
  683. g_pTimedOutQueue,
  684. dwCurrTime + RETRY_TIME_TRY_AGAIN_LATER );
  685. break;
  686. case ERROR_TIMEOUT:
  687. status = AddToTimedOutQueue(
  688. pQElement,
  689. g_pTimedOutQueue,
  690. dwCurrTime + RETRY_TIME_TIMEOUT );
  691. break;
  692. default:
  693. //
  694. // different kind of error on attempting to add forward.
  695. // like connection refused etc.
  696. // call the callback to indicate that you failed on
  697. // forward only
  698. if ( pQElement )
  699. {
  700. if ( pQElement->pszName )
  701. QUEUE_FREE_HEAP( pQElement->pszName );
  702. QUEUE_FREE_HEAP( pQElement );
  703. }
  704. if ( pfnDhcpCallBack )
  705. (*pfnDhcpCallBack)(DNSDHCP_FWD_FAILED, pvData);
  706. }
  707. }
  708. else if ( status != DNS_ERROR_RCODE_NO_ERROR &&
  709. dwFwdAddErrCode == DNS_ERROR_RCODE_NO_ERROR )
  710. {
  711. //
  712. // adding forward succeeded but adding reverse failed
  713. //
  714. DWORD dwCurrTime = Dns_GetCurrentTimeInSeconds();
  715. pQElement->fDoForwardOnly = FALSE;
  716. pQElement->fDoForward = FALSE;
  717. if ( pQElement->dwRetryCount >= MAX_RETRIES )
  718. {
  719. //
  720. // clean up pQElement and stop retrying
  721. //
  722. if ( pfnDhcpCallBack )
  723. (*pfnDhcpCallBack)(DNSDHCP_FAILURE, pvData);
  724. if ( pQElement->pszName )
  725. QUEUE_FREE_HEAP( pQElement->pszName );
  726. QUEUE_FREE_HEAP( pQElement );
  727. status = ERROR_SUCCESS;
  728. goto Exit;
  729. }
  730. //
  731. // we may need to retry this guy later
  732. //
  733. switch ( status )
  734. {
  735. case DNS_ERROR_RCODE_SERVER_FAILURE:
  736. status = AddToTimedOutQueue(
  737. pQElement,
  738. g_pTimedOutQueue,
  739. dwCurrTime + RETRY_TIME_SERVER_FAILURE );
  740. break;
  741. case DNS_ERROR_TRY_AGAIN_LATER:
  742. status = AddToTimedOutQueue(
  743. pQElement,
  744. g_pTimedOutQueue,
  745. dwCurrTime + RETRY_TIME_TRY_AGAIN_LATER );
  746. break;
  747. case ERROR_TIMEOUT:
  748. status = AddToTimedOutQueue(
  749. pQElement,
  750. g_pTimedOutQueue,
  751. dwCurrTime + RETRY_TIME_TIMEOUT );
  752. break;
  753. default:
  754. //
  755. // different kind of error on attempting to add forward.
  756. // like connection refused etc.
  757. // call the callback to indicate that you at least succeeded
  758. // with the forward registration
  759. if ( pQElement )
  760. {
  761. if ( pQElement->pszName )
  762. QUEUE_FREE_HEAP( pQElement->pszName );
  763. QUEUE_FREE_HEAP( pQElement );
  764. }
  765. if ( pfnDhcpCallBack )
  766. (*pfnDhcpCallBack)(DNSDHCP_FAILURE, pvData);
  767. }
  768. }
  769. else if (status == DNS_ERROR_RCODE_SERVER_FAILURE ||
  770. status == DNS_ERROR_TRY_AGAIN_LATER ||
  771. status == ERROR_TIMEOUT )
  772. {
  773. //
  774. // we need to retry this guy later
  775. //
  776. DWORD dwCurrTime = Dns_GetCurrentTimeInSeconds();
  777. switch (status)
  778. {
  779. case DNS_ERROR_RCODE_SERVER_FAILURE:
  780. status = AddToTimedOutQueue(
  781. pQElement,
  782. g_pTimedOutQueue,
  783. dwCurrTime + RETRY_TIME_SERVER_FAILURE );
  784. break;
  785. case DNS_ERROR_TRY_AGAIN_LATER:
  786. status = AddToTimedOutQueue(
  787. pQElement,
  788. g_pTimedOutQueue,
  789. dwCurrTime + RETRY_TIME_TRY_AGAIN_LATER );
  790. break;
  791. case ERROR_TIMEOUT:
  792. status = AddToTimedOutQueue(
  793. pQElement,
  794. g_pTimedOutQueue,
  795. dwCurrTime + RETRY_TIME_TIMEOUT );
  796. break;
  797. }
  798. }
  799. else
  800. {
  801. //
  802. // a different kind of error, really nothing can be done
  803. // free memory and get the hell out
  804. // call the callback to say that registration failed
  805. //
  806. if ( pQElement )
  807. {
  808. if ( pQElement->pszName )
  809. QUEUE_FREE_HEAP( pQElement->pszName );
  810. QUEUE_FREE_HEAP( pQElement );
  811. }
  812. if ( pfnDhcpCallBack )
  813. (*pfnDhcpCallBack)(DNSDHCP_FAILURE, pvData);
  814. }
  815. Exit:
  816. return( status);
  817. }
  818. //
  819. // Main registration thread
  820. //
  821. VOID
  822. DynDnsConsumerThread(
  823. VOID
  824. )
  825. {
  826. DWORD dwRetval;
  827. DYNREG_F1( "Inside function DynDnsConsumerThread" );
  828. while ( ! g_fStopNotify )
  829. {
  830. dwRetval = DynDnsRegisterEntries();
  831. if ( !dwRetval )
  832. {
  833. //
  834. // Ram note: get Munil/Ramesh to implement call back function
  835. //
  836. }
  837. }
  838. //
  839. // you have been asked to exit
  840. //
  841. FreeQueue( g_pdnsQueue );
  842. g_pdnsQueue = NULL;
  843. EnterCriticalSection(&g_QueueCS);
  844. g_MainQueueCount = 0;
  845. LeaveCriticalSection(&g_QueueCS);
  846. FreeQueue( g_pTimedOutQueue );
  847. g_pTimedOutQueue = NULL;
  848. ExitThread(0); // This sets the handle in the waitforsingleobject for
  849. //
  850. // the termination function
  851. //
  852. }
  853. //
  854. // Init\Cleanup routines
  855. //
  856. VOID
  857. CommonDynRegCleanup(
  858. VOID
  859. )
  860. /*++
  861. Routine Description:
  862. Common cleanup between failed init and terminate.
  863. Function exists just to kill off common code.
  864. Arguments:
  865. None.
  866. Return Value:
  867. None.
  868. --*/
  869. {
  870. //
  871. // common cleanup
  872. // - semaphore
  873. // - event
  874. // - security credential info
  875. if ( hSem )
  876. {
  877. CloseHandle( hSem );
  878. hSem = NULL;
  879. }
  880. if ( hQuitEvent )
  881. {
  882. CloseHandle( hQuitEvent );
  883. hQuitEvent = NULL;
  884. }
  885. if ( g_pIdentityCreds )
  886. {
  887. Dns_FreeAuthIdentityCredentials( g_pIdentityCreds );
  888. g_pIdentityCreds = NULL;
  889. }
  890. if ( g_UpdateCredContext )
  891. {
  892. DnsReleaseContextHandle( g_UpdateCredContext );
  893. g_UpdateCredContext = NULL;
  894. }
  895. }
  896. DNS_STATUS
  897. WINAPI
  898. DnsDhcpSrvRegisterInitialize(
  899. IN PDNS_CREDENTIALS pCredentials
  900. )
  901. /*++
  902. Routine Description:
  903. Initialize DHCP server DNS registration.
  904. Arguments:
  905. pCredentials -- credentials to do registrations under (if any)
  906. Return Value:
  907. DNS or Win32 error code.
  908. --*/
  909. {
  910. INT i;
  911. DWORD threadId;
  912. DNS_STATUS status;
  913. //
  914. // init globals
  915. // - also init debug logging
  916. //
  917. DYNREG_INIT();
  918. DNS_ASSERT(!hQuitEvent && !hSem);
  919. g_fStopNotify = FALSE;
  920. if ( !( hQuitEvent = CreateEvent( NULL, TRUE, FALSE, NULL ) ) )
  921. {
  922. status = GetLastError();
  923. goto Exit;
  924. }
  925. if ( ! ( hSem = CreateSemaphore( NULL, 0, MAX_QLEN, NULL ) ) )
  926. {
  927. status = GetLastError();
  928. goto Exit;
  929. }
  930. handle[0]= hQuitEvent;
  931. handle[1]= hSem;
  932. Dns_InitializeSecondsTimer();
  933. status = InitializeQueues( &g_pdnsQueue, &g_pTimedOutQueue );
  934. if ( status != NO_ERROR )
  935. {
  936. g_pdnsQueue = NULL;
  937. g_pTimedOutQueue = NULL;
  938. goto Exit;
  939. }
  940. EnterCriticalSection(&g_QueueCS);
  941. g_MainQueueCount = 0;
  942. LeaveCriticalSection(&g_QueueCS);
  943. //
  944. // have creds?
  945. // - create global credentials
  946. // - acquire a valid SSPI handle using these creds
  947. //
  948. // DCR: global cred handle not MT safe
  949. // here we are in the DHCP server process and don't have
  950. // any reason to use another update context; but if
  951. // shared with some other service this breaks
  952. //
  953. // fix should be to have separate
  954. // - creds
  955. // - cred handle
  956. // that is kept here (not cached) and pushed down
  957. // on each update call
  958. //
  959. if ( pCredentials )
  960. {
  961. DNS_ASSERT( g_pIdentityCreds == NULL );
  962. g_pIdentityCreds = Dns_AllocateCredentials(
  963. pCredentials->pUserName,
  964. pCredentials->pDomain,
  965. pCredentials->pPassword );
  966. if ( !g_pIdentityCreds )
  967. {
  968. status = DNS_ERROR_NO_MEMORY;
  969. goto Exit;
  970. }
  971. // DCR: this won't work if creds will expire
  972. // but it seems like they autorefresh
  973. status = Dns_StartSecurity(
  974. FALSE // not process attach
  975. );
  976. if ( status != NO_ERROR )
  977. {
  978. status = ERROR_CANNOT_IMPERSONATE;
  979. goto Exit;
  980. }
  981. status = Dns_RefreshSSpiCredentialsHandle(
  982. FALSE, // client
  983. (PCHAR) g_pIdentityCreds // creds
  984. );
  985. if ( status != NO_ERROR )
  986. {
  987. status = ERROR_CANNOT_IMPERSONATE;
  988. goto Exit;
  989. }
  990. #if 0
  991. DNS_ASSERT( g_UpdateCredContext == NULL );
  992. status = DnsAcquireContextHandle_W(
  993. 0, // flags
  994. g_pIdentityCreds, // creds
  995. & g_UpdateCredContext // set handle
  996. );
  997. if ( status != NO_ERROR )
  998. {
  999. goto Exit;
  1000. }
  1001. #endif
  1002. }
  1003. //
  1004. // fire up registration thread
  1005. // - pass creds as start param
  1006. // - if thread start fails, free creds
  1007. //
  1008. hConsumerThread = CreateThread(
  1009. NULL,
  1010. 0,
  1011. (LPTHREAD_START_ROUTINE)DynDnsConsumerThread,
  1012. NULL,
  1013. 0,
  1014. &threadId );
  1015. if ( hConsumerThread == NULL )
  1016. {
  1017. status = GetLastError();
  1018. goto Exit;
  1019. }
  1020. Exit:
  1021. //
  1022. // if failed, clean up globals
  1023. //
  1024. if ( status != NO_ERROR &&
  1025. status != ERROR_CANNOT_IMPERSONATE )
  1026. {
  1027. if ( g_pdnsQueue )
  1028. {
  1029. FreeQueue( g_pdnsQueue );
  1030. g_pdnsQueue = NULL;
  1031. }
  1032. if ( g_pTimedOutQueue )
  1033. {
  1034. FreeQueue(g_pTimedOutQueue);
  1035. g_pTimedOutQueue = NULL;
  1036. }
  1037. EnterCriticalSection(&g_QueueCS);
  1038. g_MainQueueCount = 0;
  1039. LeaveCriticalSection(&g_QueueCS);
  1040. // global cleanup
  1041. // - shared between failure case here and term function
  1042. CommonDynRegCleanup();
  1043. }
  1044. return status;
  1045. }
  1046. DNS_STATUS
  1047. WINAPI
  1048. DnsDhcpSrvRegisterInit(
  1049. VOID
  1050. )
  1051. /*++
  1052. Routine Description:
  1053. Backward compatibility stub to above function.
  1054. Arguments:
  1055. None.
  1056. Return Value:
  1057. DNS or Win32 error code.
  1058. --*/
  1059. {
  1060. return DnsDhcpSrvRegisterInitialize( NULL );
  1061. }
  1062. DNS_STATUS
  1063. WINAPI
  1064. DnsDhcpSrvRegisterTerm(
  1065. VOID
  1066. )
  1067. /*++
  1068. Routine Description:
  1069. Initialization routine each process should call exactly on exit after
  1070. using DnsDhcpSrvRegisterHostAddrs. This will signal to us that if our
  1071. thread is still trying to talk to a server, we'll stop trying.
  1072. Arguments:
  1073. None.
  1074. Return Value:
  1075. DNS or Win32 error code.
  1076. --*/
  1077. {
  1078. BOOL fRet;
  1079. DWORD dwRetval = ERROR_SUCCESS;
  1080. DWORD dwWaitResult;
  1081. DYNREG_F1( "Inside function DnsDhcpSrvRegisterTerm" );
  1082. //
  1083. // Need to notify Consumer Thread that he is getting thrown
  1084. // out and clean up after him. Send an event after him
  1085. //
  1086. g_fStopNotify = TRUE;
  1087. fRet = SetEvent( hQuitEvent );
  1088. dwWaitResult = WaitForSingleObject( hConsumerThread, INFINITE );
  1089. switch (dwWaitResult)
  1090. {
  1091. case WAIT_OBJECT_0:
  1092. //
  1093. // client thread terminated
  1094. //
  1095. CloseHandle(hConsumerThread);
  1096. hConsumerThread = NULL;
  1097. break;
  1098. case WAIT_TIMEOUT:
  1099. if ( hConsumerThread )
  1100. {
  1101. //
  1102. // Why hasn't this thread stopped?
  1103. //
  1104. DYNREG_F1( "DNSAPI: DHCP Server DNS registration thread won't stop!" );
  1105. DNS_ASSERT( FALSE );
  1106. }
  1107. }
  1108. //
  1109. // cleanup globals
  1110. // - event
  1111. // - semaphore
  1112. // - update security cred info
  1113. //
  1114. CommonDynRegCleanup();
  1115. //
  1116. // Blow away any cached security context handles
  1117. //
  1118. // DCR: security context dump is not multi-service safe
  1119. // should have this cleanup just the context's associated
  1120. // with DHCP server service;
  1121. // either need some key or use cred handle
  1122. //
  1123. Dns_TimeoutSecurityContextList( TRUE );
  1124. return dwRetval;
  1125. }
  1126. DNS_STATUS
  1127. WINAPI
  1128. DnsDhcpSrvRegisterHostName(
  1129. IN REGISTER_HOST_ENTRY HostAddr,
  1130. IN PWSTR pwsName,
  1131. IN DWORD dwTTL,
  1132. IN DWORD dwFlags, // An entry you want to blow away
  1133. IN DHCP_CALLBACK_FN pfnDhcpCallBack,
  1134. IN PVOID pvData,
  1135. IN PIP_ADDRESS pipDnsServerList,
  1136. IN DWORD dwDnsServerCount
  1137. )
  1138. /*++
  1139. DnsDhcpSrvRegisterHostName()
  1140. The main DHCP registration thread calls this function each time a
  1141. registration needs to be done.
  1142. Brief Synopsis of the working of this function
  1143. This function creates a queue object of the type given in queue.c
  1144. and enqueues the appropriate object after grabbing hold of the
  1145. critical section.
  1146. Arguments:
  1147. HostAddr --- The Host Addr you wish to register
  1148. pszName --- The Host Name to be associated with the address
  1149. dwTTL --- Time to Live.
  1150. dwOperation -- The following flags are valid
  1151. DYNDNS_DELETE_ENTRY -- Delete the entry being referred to.
  1152. DYNDNS_ADD_ENTRY -- Register the new entry.
  1153. DYNDNS_REG_FORWARD -- Register the forward as well
  1154. Return Value:
  1155. is 0 if Success. and (DWORD)-1 if failure.
  1156. --*/
  1157. {
  1158. PQELEMENT pQElement = NULL;
  1159. DWORD status = ERROR_SUCCESS;
  1160. BOOL fSem = FALSE;
  1161. BOOL fRegForward = dwFlags & DYNDNS_REG_FORWARD ? TRUE: FALSE ;
  1162. DYNREG_F1( "Inside function DnsDhcpSrvRegisterHostName_W" );
  1163. // RAMNOTE: parameter checking on queuing
  1164. if ( g_fStopNotify ||
  1165. ! g_pTimedOutQueue ||
  1166. ! g_pdnsQueue )
  1167. {
  1168. DYNREG_F1( "g_fStopNotify || ! g_pTimedOutQueue || ! g_pdnsQueue" );
  1169. DYNREG_F1( "DnsDhcpSrvRegisterHostName_W - Returning ERROR_INVALID_PARAMETER" );
  1170. return ERROR_INVALID_PARAMETER;
  1171. }
  1172. if ( !(dwFlags & DYNDNS_DELETE_ENTRY) && ( !pwsName || !*pwsName ) )
  1173. {
  1174. DYNREG_F1( "!(dwFlags & DYNDNS_DELETE_ENTRY) && ( !pwsName || !*pwsName )" );
  1175. DYNREG_F1( "DnsDhcpSrvRegisterHostName_W - Returning ERROR_INVALID_PARAMETER" );
  1176. //
  1177. // Null parameter for name can be specified only when operation
  1178. // is to do a delete
  1179. //
  1180. return ERROR_INVALID_PARAMETER;
  1181. }
  1182. if ( ! (dwFlags & DYNDNS_ADD_ENTRY || dwFlags & DYNDNS_DELETE_ENTRY ) )
  1183. {
  1184. DYNREG_F1( "! (dwFlags & DYNDNS_ADD_ENTRY || dwFlags & DYNDNS_DELETE_ENTRY )" );
  1185. DYNREG_F1( "DnsDhcpSrvRegisterHostName_W - Returning ERROR_INVALID_PARAMETER" );
  1186. return ERROR_INVALID_PARAMETER;
  1187. }
  1188. if ( (dwFlags & DYNDNS_DELETE_ENTRY) && (dwFlags & DYNDNS_ADD_ENTRY) )
  1189. {
  1190. DYNREG_F1( "(dwFlags & DYNDNS_DELETE_ENTRY) && (dwFlags & DYNDNS_ADD_ENTRY)" );
  1191. DYNREG_F1( "DnsDhcpSrvRegisterHostName_W - Returning ERROR_INVALID_PARAMETER" );
  1192. //
  1193. // you cant ask me to both add and delete an entry
  1194. //
  1195. return ERROR_INVALID_PARAMETER;
  1196. }
  1197. if ( ! (HostAddr.dwOptions & REGISTER_HOST_PTR) )
  1198. {
  1199. DYNREG_F1( "! (HostAddr.dwOptions & REGISTER_HOST_PTR)" );
  1200. DYNREG_F1( "DnsDhcpSrvRegisterHostName_W - Returning ERROR_INVALID_PARAMETER" );
  1201. return ERROR_INVALID_PARAMETER;
  1202. }
  1203. if ( g_MainQueueCount > DNS_MAX_DHCP_SERVER_REGISTRATION_QUEUE_SIZE )
  1204. {
  1205. return DNS_ERROR_TRY_AGAIN_LATER;
  1206. }
  1207. //
  1208. // create a queue element.
  1209. //
  1210. pQElement = (PQELEMENT) QUEUE_ALLOC_HEAP_ZERO(sizeof(QELEMENT) );
  1211. if ( !pQElement )
  1212. {
  1213. DYNREG_F1( "DnsDhcpSrvRegisterHostName_W - Failed to create element!" );
  1214. status = DNS_ERROR_NO_MEMORY;
  1215. goto Exit;
  1216. }
  1217. memcpy(&(pQElement->HostAddr), &HostAddr, sizeof(REGISTER_HOST_ENTRY));
  1218. pQElement->pszName = NULL;
  1219. if ( pwsName )
  1220. {
  1221. pQElement->pszName = (LPWSTR) QUEUE_ALLOC_HEAP_ZERO(wcslen(pwsName)*2+ 2 );
  1222. if ( !pQElement->pszName )
  1223. {
  1224. DYNREG_F1( "DnsDhcpSrvRegisterHostName_W - Failed to allocate name buffer!" );
  1225. status = DNS_ERROR_NO_MEMORY;
  1226. goto Exit;
  1227. }
  1228. wcscpy(pQElement->pszName, pwsName);
  1229. }
  1230. if ( dwDnsServerCount )
  1231. {
  1232. pQElement->DnsServerList = Dns_BuildIpArray( dwDnsServerCount,
  1233. pipDnsServerList );
  1234. if ( !pQElement->DnsServerList )
  1235. {
  1236. status = DNS_ERROR_NO_MEMORY;
  1237. goto Exit;
  1238. }
  1239. }
  1240. pQElement->dwTTL = dwTTL;
  1241. pQElement->fDoForward = fRegForward;
  1242. //
  1243. // callback function
  1244. //
  1245. pQElement->pfnDhcpCallBack = pfnDhcpCallBack;
  1246. pQElement->pvData = pvData; // parameter to callback function
  1247. if (dwFlags & DYNDNS_ADD_ENTRY)
  1248. pQElement->dwOperation = DYNDNS_ADD_ENTRY;
  1249. else
  1250. pQElement->dwOperation = DYNDNS_DELETE_ENTRY;
  1251. //
  1252. // Set all the other fields to NULLs
  1253. //
  1254. pQElement->dwRetryTime = 0;
  1255. pQElement->pFLink = NULL;
  1256. pQElement->pBLink = NULL;
  1257. pQElement ->fDoForwardOnly = FALSE;
  1258. //
  1259. // put this element in the queue
  1260. //
  1261. DYNREG_F1( "DnsDhcpSrvRegisterHostName_W - Put queue element in list" );
  1262. status = Enqueue ( pQElement, g_pdnsQueue, g_pTimedOutQueue);
  1263. //
  1264. // FYI: Count of main queue elements is incremented inside Enqueue()
  1265. //
  1266. if (status)
  1267. {
  1268. DYNREG_F1( "DnsDhcpSrvRegisterHostName_W - Failed to queue element in list!" );
  1269. goto Exit;
  1270. }
  1271. //
  1272. // Signal the semaphore the consumer may be waiting on
  1273. //
  1274. fSem = ReleaseSemaphore( hSem,
  1275. 1,
  1276. &g_dwQCount );
  1277. if ( !fSem )
  1278. {
  1279. DNS_ASSERT( fSem ); // assert and say that something weird happened
  1280. }
  1281. return(status);
  1282. Exit:
  1283. if ( status )
  1284. {
  1285. //
  1286. // something failed. Free all alloc'd memory
  1287. //
  1288. if ( pQElement )
  1289. {
  1290. if ( pQElement->pszName )
  1291. QUEUE_FREE_HEAP( pQElement->pszName );
  1292. QUEUE_FREE_HEAP( pQElement );
  1293. }
  1294. }
  1295. return( status );
  1296. }
  1297. //
  1298. // End dynreg.c
  1299. //