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

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