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.

4796 lines
102 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. rdns.cxx
  5. Abstract:
  6. Reverse DNS service
  7. Author:
  8. Philippe Choquier (phillich) 5-june-1996
  9. --*/
  10. // only need async if not every HTTP req ends up calling DNS resolution
  11. // if async then potentially 100s of HTTP requests
  12. // so should be sync.
  13. // Bind(addr) @ session start
  14. // Init(BLOB) / CheckAccess( callbakc ) / Terminate()
  15. // callback : yes or no, post empty completion status
  16. #define dllexp __declspec( dllexport )
  17. #include <nt.h>
  18. #include <ntrtl.h>
  19. #include <nturtl.h>
  20. #include <windows.h>
  21. #include <winsock2.h>
  22. #include <time.h>
  23. #include <stdio.h>
  24. #include <malloc.h>
  25. #include <windns.h>
  26. #include <iis64.h>
  27. #include <dbgutil.h>
  28. #include <rdns.hxx>
  29. #include <issched.hxx>
  30. #include <inetsvcs.h>
  31. #define DN_LEN 64
  32. #define RDNS_REG_KEY "SYSTEM\\CurrentControlSet\\Services\\InetInfo\\Parameters"
  33. #define RDNS_REG_MAX_THREAD "DnsMaxThread"
  34. #define RDNS_REG_CACHE_SIZE "DnsCacheSizeInK"
  35. #define RDNS_REG_TTL "DnsTTLInSeconds"
  36. #define RDNS_REG_MAX_THREAD_DEF 0
  37. #define RDNS_REG_CACHE_SIZE_DEF 256
  38. // in seconds
  39. #define RDNS_REG_TTL_DEF (20*60)
  40. #define RDNS_SCAVENGER_GRANULARITY (2*60)
  41. #define XBF_EXTEND 64
  42. #define RDNS_HASH_SIZE 1021
  43. #define ENTRYPTR( a, b ) (a+b-1)
  44. #define LOCALHOST_ADDRESS 0x0100007F // 127.0.0.1
  45. //
  46. // Local classes
  47. //
  48. class RDnsCacheEntry {
  49. public:
  50. BOOL Init( UINT i );
  51. void Reset();
  52. //
  53. UINT RemoveFromPrio( RDnsCacheEntry* );
  54. UINT RemoveFromHash( RDnsCacheEntry* );
  55. void InsertInPrioBefore( RDnsCacheEntry*, UINT );
  56. void InsertInHashBefore( RDnsCacheEntry*, UINT );
  57. UINT GetNextHash() { return m_pHashNext; }
  58. UINT GetNextPrio() { return m_pPrioNext; }
  59. BOOL MatchAddr(struct sockaddr *, time_t tNow );
  60. BOOL MatchName(LPSTR pszName, time_t tNow );
  61. BOOL CopyName(LPSTR pszResult, DWORD dwResMaxLen)
  62. {
  63. UINT l = strlen(m_achName) + 1;
  64. if ( dwResMaxLen >= l )
  65. {
  66. memcpy( pszResult, m_achName, l );
  67. return TRUE;
  68. }
  69. return FALSE;
  70. }
  71. BOOL CopyAddr( sockaddr* p )
  72. {
  73. memcpy( p, &m_addr, sizeof(m_addr) ); return TRUE;
  74. }
  75. DWORD GetHash() { return m_h; }
  76. void SetFree() { m_fIsFree = TRUE; }
  77. BOOL Store(struct sockaddr *pAddr, DWORD h, time_t Expire, LPSTR pszName );
  78. BOOL Expired( time_t tNow ) { return !m_fIsFree && m_Expire <= tNow; }
  79. BOOL IsIp2Dns() { return m_fIsIp2Dns; }
  80. VOID SetIsIp2Dns( BOOL f ) { m_fIsIp2Dns = f; }
  81. private:
  82. struct sockaddr m_addr;
  83. CHAR m_achName[DN_LEN];
  84. UINT m_pHashNext;
  85. UINT m_pHashPrev;
  86. UINT m_pPrioNext;
  87. UINT m_pPrioPrev;
  88. UINT m_iIndex;
  89. DWORD m_h;
  90. BOOL m_fIsFree;
  91. time_t m_Expire;
  92. BOOL m_fIsIp2Dns;
  93. } ;
  94. class RDnsDict {
  95. public:
  96. BOOL Init()
  97. {
  98. m_cAlloc = 0;
  99. m_cSize = 0;
  100. INITIALIZE_CRITICAL_SECTION( &m_csLock );
  101. if ( m_FreeList = Append() )
  102. {
  103. ENTRYPTR(m_pV,m_FreeList)->Init( m_FreeList );
  104. }
  105. if ( m_PrioList = Append() )
  106. {
  107. ENTRYPTR(m_pV,m_PrioList)->Init( m_PrioList );
  108. }
  109. return TRUE;
  110. }
  111. void Terminate()
  112. {
  113. if (m_cAlloc )
  114. {
  115. LocalFree( m_pV );
  116. }
  117. DeleteCriticalSection( &m_csLock );
  118. }
  119. void Lock() { EnterCriticalSection( &m_csLock ); }
  120. void Unlock() { LeaveCriticalSection( &m_csLock ); }
  121. // Append an entry
  122. UINT NewEntry( struct sockaddr *pAddr, DWORD h, time_t Expire, LPSTR pszName );
  123. UINT NewDns2IpEntry( struct sockaddr *pAddr, DWORD h, time_t Expire, LPSTR pszName );
  124. DWORD ComputeHash( struct sockaddr* pAddr );
  125. DWORD ComputeHash( LPSTR pszName );
  126. BOOL Search( struct sockaddr* pAddr, DWORD h, LPSTR pszResult, DWORD dwResMaxLen );
  127. BOOL SearchByName( struct sockaddr* pAddr, DWORD h, LPSTR pszName );
  128. UINT GetFreeEntry();
  129. UINT Append();
  130. void FreeEntry( UINT i);
  131. void Scavenger();
  132. private:
  133. UINT m_cAlloc; // allocated memory
  134. UINT m_cSize; // used memory
  135. CRITICAL_SECTION m_csLock;
  136. RDnsCacheEntry* m_pV;
  137. UINT m_PrioList;
  138. UINT m_FreeList;
  139. UINT m_pHash[RDNS_HASH_SIZE];
  140. UINT m_pDns2IpHash[RDNS_HASH_SIZE];
  141. } ;
  142. //
  143. // Local functions
  144. //
  145. VOID
  146. AddrCheckDnsCallBack(
  147. DNSARG p,
  148. BOOL fSt,
  149. LPSTR pDns
  150. );
  151. VOID
  152. AddrCheckDnsCallBack2(
  153. DNSARG p,
  154. BOOL fSt,
  155. LPSTR pDns
  156. );
  157. VOID
  158. AddrCheckDnsCallBack3(
  159. DNSARG p,
  160. BOOL fSt,
  161. LPSTR pDns
  162. );
  163. VOID
  164. ResolveDnsCallBack(
  165. DNSARG p,
  166. BOOL fSt,
  167. LPSTR pDns
  168. );
  169. //
  170. // globals
  171. //
  172. DWORD g_cCacheSize = RDNS_REG_CACHE_SIZE_DEF * 1024;
  173. DWORD g_cTTL = RDNS_REG_TTL_DEF;
  174. HANDLE g_hThreadsTerminated = NULL;
  175. HANDLE g_hDnsPort = NULL;
  176. UINT g_cThreads;
  177. UINT g_cMaxThreadLimit = RDNS_REG_MAX_THREAD_DEF;
  178. long g_cAvailableThreads;
  179. RDnsDict g_RDns;
  180. CSidCache * g_pscPen = NULL;
  181. DWORD g_dwScavengerWorkItem = NULL;
  182. BOOL g_fEnableRdns = TRUE;
  183. DNSFUNCDESC g_Dns2Ip = { RDNS_REQUEST_TYPE_DNS2IP, ::AddrCheckDnsCallBack2 };
  184. DNSFUNCDESC g_Ip2Dns = { RDNS_REQUEST_TYPE_IP2DNS, ::AddrCheckDnsCallBack};
  185. DNSFUNCDESC g_ResolveDns = { RDNS_REQUEST_TYPE_IP2DNS, ::ResolveDnsCallBack};
  186. DNSFUNCDESC g_ResolveDns2Ip = { RDNS_REQUEST_TYPE_DNS2IP, ::AddrCheckDnsCallBack3 };
  187. BYTE NULL_IP_ADDR[]="\x00\x00\x00\x00";
  188. //
  189. //
  190. //
  191. BOOL
  192. PenAddToCache(
  193. PSID pS,
  194. DWORD dwTTL
  195. )
  196. /*++
  197. Routine Description:
  198. Add to Pwd Exp Notification cache
  199. Arguments:
  200. pS - ptr to SID to add to cache
  201. Return Value:
  202. TRUE if successful, FALSE otherwise
  203. --*/
  204. {
  205. DBG_ASSERT(g_fEnableRdns);
  206. return g_pscPen->AddToCache( pS, dwTTL );
  207. }
  208. BOOL
  209. PenIsInCache(
  210. PSID pS
  211. )
  212. /*++
  213. Routine Description:
  214. Check if SID in Pwd Exp Notification cache
  215. Arguments:
  216. pS - ptr to SID to check
  217. Return Value:
  218. TRUE if SID in cache, FALSE otherwise
  219. --*/
  220. {
  221. DBG_ASSERT(g_fEnableRdns);
  222. return g_pscPen->IsInCache( pS );
  223. }
  224. BOOL
  225. PenCheckPresentAndResetTtl(
  226. PSID pS,
  227. DWORD dwTtl
  228. )
  229. /*++
  230. Routine Description:
  231. Check if SID in Pwd Exp Notification cache
  232. and update TTL
  233. Arguments:
  234. pS - ptr to SID to check
  235. dwTtl - new TTL value
  236. Return Value:
  237. TRUE if SID in cache, FALSE otherwise
  238. --*/
  239. {
  240. DBG_ASSERT(g_fEnableRdns);
  241. return g_pscPen->CheckPresentAndResetTtl( pS, dwTtl );
  242. }
  243. //
  244. //
  245. //
  246. BOOL
  247. RDnsCacheEntry::Init(
  248. UINT i
  249. )
  250. /*++
  251. Routine Description:
  252. Initialize a cache entry
  253. Arguments:
  254. i - index (1-based) of this entry in the dict array
  255. Return Value:
  256. TRUE if successful, FALSE otherwise
  257. --*/
  258. {
  259. DBG_ASSERT(g_fEnableRdns);
  260. m_iIndex = i;
  261. Reset();
  262. return TRUE;
  263. }
  264. void
  265. RDnsCacheEntry::Reset(
  266. VOID
  267. )
  268. /*++
  269. Routine Description:
  270. Reset a cache entry
  271. Arguments:
  272. None
  273. Return Value:
  274. Nothing
  275. --*/
  276. {
  277. DBG_ASSERT(g_fEnableRdns);
  278. m_pHashNext = NULL; // non-circular list
  279. m_pHashPrev = NULL;
  280. m_pPrioNext = m_iIndex; // circular list
  281. m_pPrioPrev = m_iIndex;
  282. m_fIsFree = TRUE;
  283. }
  284. BOOL
  285. RDnsCacheEntry::MatchAddr(
  286. struct sockaddr * pAddr,
  287. time_t tNow
  288. )
  289. /*++
  290. Routine Description:
  291. Check if entry match specified address and not expired
  292. Arguments:
  293. pAddr - ptr to address
  294. tNow - current time
  295. Return Value:
  296. TRUE if match and not expired, FALSE otherwise
  297. --*/
  298. {
  299. int l;
  300. LPBYTE p1;
  301. LPBYTE p2;
  302. DBG_ASSERT(g_fEnableRdns);
  303. switch ( pAddr->sa_family )
  304. {
  305. case AF_INET:
  306. l = SIZEOF_IP_ADDRESS;
  307. p1 = (LPBYTE)(&((PSOCKADDR_IN)pAddr)->sin_addr);
  308. p2 = (LPBYTE)(&((PSOCKADDR_IN)&m_addr)->sin_addr);
  309. break;
  310. #if 0
  311. case AF_IPX:
  312. l = 6;
  313. p1 = (LPBYTE)(((PSOCKADDR)pAddr)->sa_data);
  314. p2 = (LPBYTE)(((PSOCKADDR)&m_addr)->sa_data);
  315. break;
  316. #endif
  317. default:
  318. return FALSE;
  319. }
  320. return !memcmp( p1, p2, l ) && m_Expire > tNow;
  321. }
  322. BOOL
  323. RDnsCacheEntry::MatchName(
  324. LPSTR pszName,
  325. time_t tNow
  326. )
  327. /*++
  328. Routine Description:
  329. Check if entry match specified DNS name and not expired
  330. Arguments:
  331. pszName - ptr to DNS name
  332. tNow - current time
  333. Return Value:
  334. TRUE if match and not expired, FALSE otherwise
  335. --*/
  336. {
  337. DBG_ASSERT(g_fEnableRdns);
  338. return !strcmp( pszName, m_achName ) && m_Expire > tNow;
  339. }
  340. BOOL
  341. RDnsCacheEntry::Store(
  342. struct sockaddr *pAddr,
  343. DWORD h,
  344. time_t Expire,
  345. LPSTR pszName
  346. )
  347. /*++
  348. Routine Description:
  349. Store a address<>name pair with expiration time
  350. Arguments:
  351. pAddr - ptr to address
  352. h - hash value of this address
  353. Expire - expiration time
  354. pszName - DNS name
  355. Return Value:
  356. TRUE if successful, FALSE otherwise
  357. --*/
  358. {
  359. int l;
  360. DBG_ASSERT(g_fEnableRdns);
  361. memcpy( &m_addr, pAddr, sizeof(m_addr) );
  362. if ( (l=strlen(pszName)+1) <= sizeof(m_achName) )
  363. {
  364. memcpy( m_achName, pszName, l );
  365. }
  366. else
  367. {
  368. return FALSE;
  369. }
  370. m_h = h;
  371. m_fIsFree = FALSE;
  372. m_Expire = Expire;
  373. return TRUE;
  374. }
  375. UINT
  376. RDnsCacheEntry::RemoveFromPrio(
  377. RDnsCacheEntry* pE
  378. )
  379. /*++
  380. Routine Description:
  381. Remove from priority list
  382. Arguments:
  383. pE - ptr to base of array
  384. Return Value:
  385. next index in the priority list
  386. --*/
  387. {
  388. DBG_ASSERT(g_fEnableRdns);
  389. if ( m_pPrioPrev )
  390. {
  391. ENTRYPTR(pE,m_pPrioPrev)->m_pPrioNext = m_pPrioNext;
  392. }
  393. if ( m_pPrioNext )
  394. {
  395. ENTRYPTR(pE,m_pPrioNext)->m_pPrioPrev = m_pPrioPrev;
  396. }
  397. return m_pPrioNext;
  398. }
  399. void
  400. RDnsCacheEntry::InsertInPrioBefore(
  401. RDnsCacheEntry* pE,
  402. UINT i
  403. )
  404. /*++
  405. Routine Description:
  406. Insert in priority list after specified index
  407. Arguments:
  408. pE - ptr to base of array
  409. i - index of element to insert before
  410. Return Value:
  411. Nothing
  412. --*/
  413. {
  414. m_pPrioPrev = NULL;
  415. DBG_ASSERT(g_fEnableRdns);
  416. if ( i )
  417. {
  418. UINT iPrev = ENTRYPTR(pE,i)->m_pPrioPrev;
  419. ENTRYPTR(pE,i)->m_pPrioPrev = m_iIndex;
  420. if ( iPrev )
  421. {
  422. ENTRYPTR(pE,iPrev)->m_pPrioNext = m_iIndex;
  423. m_pPrioPrev = iPrev;
  424. }
  425. }
  426. m_pPrioNext = i;
  427. }
  428. UINT
  429. RDnsCacheEntry::RemoveFromHash(
  430. RDnsCacheEntry* pE
  431. )
  432. /*++
  433. Routine Description:
  434. Remove from hash list
  435. Arguments:
  436. pE - ptr to base of array
  437. Return Value:
  438. next index in the hash list
  439. --*/
  440. {
  441. DBG_ASSERT(g_fEnableRdns);
  442. if ( m_pHashPrev )
  443. {
  444. ENTRYPTR(pE,m_pHashPrev)->m_pHashNext = m_pHashNext;
  445. }
  446. if ( m_pHashNext )
  447. {
  448. ENTRYPTR(pE,m_pHashNext)->m_pHashPrev = m_pHashPrev;
  449. }
  450. return m_pHashNext;
  451. }
  452. void
  453. RDnsCacheEntry::InsertInHashBefore(
  454. RDnsCacheEntry* pE,
  455. UINT i
  456. )
  457. /*++
  458. Routine Description:
  459. Insert in hash list after specified index
  460. Arguments:
  461. pE - ptr to base of array
  462. i - index of element to insert before
  463. Return Value:
  464. Nothing
  465. --*/
  466. {
  467. m_pHashPrev = NULL;
  468. DBG_ASSERT(g_fEnableRdns);
  469. if ( i )
  470. {
  471. UINT iPrev = ENTRYPTR(pE,i)->m_pHashPrev;
  472. ENTRYPTR(pE,i)->m_pHashPrev = m_iIndex;
  473. if ( iPrev )
  474. {
  475. ENTRYPTR(pE,iPrev)->m_pHashNext = m_iIndex;
  476. m_pHashPrev = iPrev;
  477. }
  478. }
  479. m_pHashNext = i;
  480. }
  481. UINT
  482. RDnsDict::NewEntry(
  483. struct sockaddr *pAddr,
  484. DWORD h,
  485. time_t Expire,
  486. LPSTR pszName
  487. )
  488. /*++
  489. Routine Description:
  490. Store a address<>name pair with expiration time
  491. Arguments:
  492. pAddr - ptr to address
  493. h - hash value of this address
  494. Expire - expiration time
  495. pszName - DNS name
  496. Return Value:
  497. index (1-based) of new entry, NULL if error
  498. --*/
  499. {
  500. DBG_ASSERT(g_fEnableRdns);
  501. Lock();
  502. UINT i = GetFreeEntry();
  503. if ( i )
  504. {
  505. RDnsCacheEntry *p = ENTRYPTR(m_pV,i);
  506. if ( !p->Store( pAddr, h, Expire, pszName ) )
  507. {
  508. // put back on free list
  509. p->InsertInPrioBefore( m_pV, m_FreeList );
  510. i = NULL;
  511. }
  512. else
  513. {
  514. p->InsertInPrioBefore( m_pV, m_PrioList );
  515. p->InsertInHashBefore( m_pV, m_pHash[h] );
  516. m_pHash[h] = i;
  517. }
  518. p->SetIsIp2Dns( TRUE );
  519. }
  520. Unlock();
  521. return i;
  522. }
  523. UINT
  524. RDnsDict::NewDns2IpEntry(
  525. struct sockaddr *pAddr,
  526. DWORD h,
  527. time_t Expire,
  528. LPSTR pszName
  529. )
  530. /*++
  531. Routine Description:
  532. Store a address<>name pair with expiration time
  533. Arguments:
  534. pAddr - ptr to address
  535. h - hash value of DNS name
  536. Expire - expiration time
  537. pszName - DNS name
  538. Return Value:
  539. index (1-based) of new entry, NULL if error
  540. --*/
  541. {
  542. DBG_ASSERT(g_fEnableRdns);
  543. Lock();
  544. UINT i = GetFreeEntry();
  545. if ( i )
  546. {
  547. RDnsCacheEntry *p = ENTRYPTR(m_pV,i);
  548. if ( !p->Store( pAddr, h, Expire, pszName ) )
  549. {
  550. // put back on free list
  551. p->InsertInPrioBefore( m_pV, m_FreeList );
  552. i = NULL;
  553. }
  554. else
  555. {
  556. p->InsertInPrioBefore( m_pV, m_PrioList );
  557. p->InsertInHashBefore( m_pV, m_pDns2IpHash[h] );
  558. m_pDns2IpHash[h] = i;
  559. }
  560. p->SetIsIp2Dns( FALSE );
  561. }
  562. Unlock();
  563. return i;
  564. }
  565. DWORD
  566. RDnsDict::ComputeHash(
  567. struct sockaddr* pAddr
  568. )
  569. /*++
  570. Routine Description:
  571. Compute hash code of address
  572. Arguments:
  573. pAddr - ptr to address
  574. Return Value:
  575. Hash code <0...RDNS_HASH_SIZE>
  576. --*/
  577. {
  578. UINT x;
  579. UINT l;
  580. DWORD h = 0;
  581. LPBYTE p;
  582. DBG_ASSERT(g_fEnableRdns);
  583. switch ( pAddr->sa_family )
  584. {
  585. case AF_INET:
  586. l = SIZEOF_IP_ADDRESS;
  587. p = (LPBYTE)(&((PSOCKADDR_IN)pAddr)->sin_addr);
  588. break;
  589. #if 0
  590. case AF_IPX:
  591. l = 6;
  592. p = (LPBYTE)pAddr->sa_data;
  593. break;
  594. #endif
  595. default:
  596. l = 8;
  597. p = (LPBYTE)pAddr->sa_data;
  598. break;
  599. }
  600. for ( x = 0 ; x < l ; ++x )
  601. {
  602. h = ((h<<5)|(h>>27)) ^ p[x];
  603. }
  604. return h % RDNS_HASH_SIZE;
  605. }
  606. DWORD
  607. RDnsDict::ComputeHash(
  608. LPSTR pszName
  609. )
  610. /*++
  611. Routine Description:
  612. Compute hash code of name
  613. Arguments:
  614. pszName - DNS name
  615. Return Value:
  616. Hash code <0...RDNS_HASH_SIZE>
  617. --*/
  618. {
  619. UINT x;
  620. UINT l;
  621. DWORD h = 0;
  622. LPBYTE p;
  623. DBG_ASSERT(g_fEnableRdns);
  624. l = strlen( pszName );
  625. p = (LPBYTE)pszName;
  626. for ( x = 0 ; x < l ; ++x )
  627. {
  628. h = ((h<<5)|(h>>27)) ^ p[x];
  629. }
  630. return h % RDNS_HASH_SIZE;
  631. }
  632. BOOL
  633. RDnsDict::Search(
  634. struct sockaddr* pAddr,
  635. DWORD h,
  636. LPSTR pszResult,
  637. DWORD dwResMaxLen
  638. )
  639. /*++
  640. Routine Description:
  641. Search for address in cache
  642. Arguments:
  643. pAddr - ptr to address
  644. h - hash code for address
  645. pszResult - ptr to array updated with name if found
  646. dwResMaxLen - size of pszResult array
  647. Return Value:
  648. TRUE if found and stored in pszResult, otherwise FALSE
  649. --*/
  650. {
  651. UINT i = m_pHash[h];
  652. RDnsCacheEntry *p;
  653. BOOL fSt = FALSE;
  654. time_t tNow = time(NULL);
  655. DBG_ASSERT(g_fEnableRdns);
  656. Lock();
  657. while ( i )
  658. {
  659. p = ENTRYPTR(m_pV,i);
  660. if ( p->MatchAddr( pAddr, tNow ) )
  661. {
  662. fSt = p->CopyName( pszResult, dwResMaxLen );
  663. // update position in LRU list
  664. p->RemoveFromPrio( m_pV );
  665. p->InsertInPrioBefore( m_pV, m_PrioList );
  666. break;
  667. }
  668. i = p->GetNextHash();
  669. }
  670. Unlock();
  671. return fSt;
  672. }
  673. BOOL
  674. RDnsDict::SearchByName(
  675. struct sockaddr* pAddr,
  676. DWORD h,
  677. LPSTR pszName
  678. )
  679. /*++
  680. Routine Description:
  681. Search for name in cache
  682. Arguments:
  683. pAddr - ptr to address
  684. h - hash code for address
  685. pszName - name to search for
  686. Return Value:
  687. TRUE if found and stored in pAddr, otherwise FALSE
  688. --*/
  689. {
  690. UINT i = m_pDns2IpHash[h];
  691. RDnsCacheEntry *p;
  692. BOOL fSt = FALSE;
  693. time_t tNow = time(NULL);
  694. DBG_ASSERT(g_fEnableRdns);
  695. Lock();
  696. while ( i )
  697. {
  698. p = ENTRYPTR(m_pV,i);
  699. if ( p->MatchName( pszName, tNow ) )
  700. {
  701. fSt = p->CopyAddr( pAddr );
  702. // update position in LRU list
  703. p->RemoveFromPrio( m_pV );
  704. p->InsertInPrioBefore( m_pV, m_PrioList );
  705. break;
  706. }
  707. i = p->GetNextHash();
  708. }
  709. Unlock();
  710. return fSt;
  711. }
  712. UINT
  713. RDnsDict::GetFreeEntry(
  714. VOID
  715. )
  716. /*++
  717. Routine Description:
  718. Get a free entry in cache array
  719. Arguments:
  720. None
  721. Return Value:
  722. index ( 1-based ) of free element to use
  723. --*/
  724. {
  725. UINT i;
  726. UINT iN;
  727. RDnsCacheEntry *p;
  728. DBG_ASSERT(g_fEnableRdns);
  729. if ( m_PrioList == NULL || m_FreeList == NULL )
  730. {
  731. return NULL;
  732. }
  733. i = ENTRYPTR(m_pV,m_FreeList)->GetNextPrio();
  734. if ( i != m_FreeList )
  735. {
  736. ENTRYPTR(m_pV,i)->RemoveFromPrio( m_pV );
  737. ENTRYPTR(m_pV,i)->Reset();
  738. }
  739. else
  740. {
  741. if ( i = Append() )
  742. {
  743. ENTRYPTR(m_pV,i)->Init( i );
  744. }
  745. else
  746. {
  747. // get from LRU
  748. i = ENTRYPTR(m_pV,m_PrioList)->GetNextPrio();
  749. if ( i != m_PrioList )
  750. {
  751. // remove from hash list
  752. p = ENTRYPTR(m_pV,i);
  753. p->RemoveFromPrio( m_pV );
  754. iN = p->RemoveFromHash(m_pV);
  755. // if hash entry pointed to this element, update hash entry
  756. if ( p->IsIp2Dns() )
  757. {
  758. if ( m_pHash[p->GetHash()] == i )
  759. {
  760. m_pHash[p->GetHash()] = iN;
  761. }
  762. }
  763. else
  764. {
  765. if ( m_pDns2IpHash[p->GetHash()] == i )
  766. {
  767. m_pDns2IpHash[p->GetHash()] = iN;
  768. }
  769. }
  770. p->Reset();
  771. }
  772. else
  773. {
  774. return NULL;
  775. }
  776. }
  777. }
  778. return i;
  779. }
  780. UINT
  781. RDnsDict::Append(
  782. VOID
  783. )
  784. /*++
  785. Routine Description:
  786. Append an entry to the cache array
  787. Arguments:
  788. None
  789. Return Value:
  790. index ( 1-based ) of new element
  791. --*/
  792. {
  793. DBG_ASSERT(g_fEnableRdns);
  794. if ( m_cSize + 1 > m_cAlloc )
  795. {
  796. int cNew = (( m_cSize + 1 + XBF_EXTEND )/XBF_EXTEND)*XBF_EXTEND;
  797. if ( cNew*sizeof(RDnsCacheEntry) > g_cCacheSize )
  798. {
  799. return NULL;
  800. }
  801. LPBYTE pN = (LPBYTE)LocalAlloc( LMEM_FIXED, cNew*sizeof(RDnsCacheEntry) );
  802. if ( pN == NULL )
  803. {
  804. return NULL;
  805. }
  806. if ( m_cSize )
  807. {
  808. memcpy( pN, m_pV, m_cSize*sizeof(RDnsCacheEntry) );
  809. }
  810. if ( m_cAlloc )
  811. {
  812. LocalFree( m_pV );
  813. }
  814. m_pV = (RDnsCacheEntry*)pN;
  815. m_cAlloc = cNew;
  816. }
  817. return ++m_cSize;
  818. }
  819. void
  820. RDnsDict::FreeEntry(
  821. UINT i
  822. )
  823. /*++
  824. Routine Description:
  825. Free an element in the cache array, put it on free list
  826. Arguments:
  827. index ( 1-based ) of element to be freed
  828. Return Value:
  829. Nothing
  830. --*/
  831. {
  832. DBG_ASSERT(g_fEnableRdns);
  833. UINT iN;
  834. RDnsCacheEntry *p = ENTRYPTR(m_pV,i);
  835. iN = p->RemoveFromHash(m_pV);
  836. // if hash entry pointed to this element, update hash entry
  837. if ( p->IsIp2Dns() )
  838. {
  839. if ( m_pHash[p->GetHash()] == i )
  840. {
  841. m_pHash[p->GetHash()] = iN;
  842. }
  843. }
  844. else
  845. {
  846. if ( m_pDns2IpHash[p->GetHash()] == i )
  847. {
  848. m_pDns2IpHash[p->GetHash()] = iN;
  849. }
  850. }
  851. p->SetFree();
  852. p->RemoveFromPrio( m_pV );
  853. p->InsertInPrioBefore( m_pV, m_FreeList );
  854. }
  855. void
  856. RDnsDict::Scavenger(
  857. VOID
  858. )
  859. /*++
  860. Routine Description:
  861. Scavenger code to delete expired entries in the cache array
  862. Arguments:
  863. None
  864. Return Value:
  865. Nothing
  866. --*/
  867. {
  868. DBG_ASSERT(g_fEnableRdns);
  869. Lock();
  870. RDnsCacheEntry *p = m_pV;
  871. UINT i;
  872. time_t tNow = time(NULL);
  873. for ( i = 0 ; i < m_cSize ; ++i, ++p )
  874. {
  875. if ( p->Expired( tNow ) )
  876. {
  877. FreeEntry( i + 1 );
  878. }
  879. }
  880. Unlock();
  881. }
  882. VOID
  883. WINAPI
  884. RDnsScavenger(
  885. LPVOID
  886. )
  887. /*++
  888. Routine Description:
  889. Scavenger function for RDns & Pen
  890. Arguments:
  891. LPVOID - not used
  892. Return Value:
  893. Nothing
  894. --*/
  895. {
  896. DBG_ASSERT(g_fEnableRdns);
  897. g_RDns.Scavenger();
  898. if ( g_pscPen != NULL )
  899. {
  900. g_pscPen->Scavenger();
  901. }
  902. }
  903. BOOL
  904. InitRDns(
  905. VOID
  906. )
  907. /*++
  908. Routine Description:
  909. Init the Reverse DNS API
  910. Arguments:
  911. None
  912. Return Value:
  913. TRUE if success, otherwise FALSE
  914. --*/
  915. {
  916. #if DBG
  917. //
  918. // check that RDNS_HASH_SIZE is prime
  919. //
  920. UINT x = 2;
  921. UINT x2;
  922. for ( x = 2 ; (x2=x*x) <= RDNS_HASH_SIZE; ++x )
  923. {
  924. if ( (RDNS_HASH_SIZE/x)*x == RDNS_HASH_SIZE )
  925. {
  926. ASSERT( FALSE );
  927. }
  928. }
  929. #endif
  930. HKEY hKey;
  931. // get cache size, max # threads
  932. if ( RegOpenKey( HKEY_LOCAL_MACHINE, RDNS_REG_KEY, &hKey )
  933. == ERROR_SUCCESS )
  934. {
  935. DWORD dwType;
  936. DWORD dwValue;
  937. DWORD dwSize = sizeof(dwValue);
  938. if ( RegQueryValueEx( hKey,
  939. RDNS_REG_MAX_THREAD,
  940. NULL,
  941. &dwType,
  942. (LPBYTE)&dwValue,
  943. &dwSize ) == ERROR_SUCCESS
  944. && dwType == REG_DWORD )
  945. {
  946. g_cMaxThreadLimit = dwValue;
  947. }
  948. else
  949. {
  950. g_cMaxThreadLimit = RDNS_REG_MAX_THREAD_DEF;
  951. }
  952. dwSize = sizeof(dwValue);
  953. if ( RegQueryValueEx( hKey,
  954. RDNS_REG_CACHE_SIZE,
  955. NULL,
  956. &dwType,
  957. (LPBYTE)&dwValue,
  958. &dwSize ) == ERROR_SUCCESS
  959. && dwType == REG_DWORD )
  960. {
  961. g_cCacheSize = dwValue * 1024;
  962. }
  963. else
  964. {
  965. g_cCacheSize = RDNS_REG_CACHE_SIZE_DEF * 1024;
  966. }
  967. dwSize = sizeof(dwValue);
  968. if ( RegQueryValueEx( hKey,
  969. RDNS_REG_TTL,
  970. NULL,
  971. &dwType,
  972. (LPBYTE)&dwValue,
  973. &dwSize ) == ERROR_SUCCESS
  974. && dwType == REG_DWORD )
  975. {
  976. g_cTTL = dwValue;
  977. }
  978. else
  979. {
  980. g_cTTL = RDNS_REG_TTL_DEF;
  981. }
  982. RegCloseKey( hKey );
  983. }
  984. if ( g_RDns.Init() == FALSE )
  985. {
  986. return FALSE;
  987. }
  988. g_pscPen = new CSidCache;
  989. if ( g_pscPen == NULL )
  990. {
  991. return FALSE;
  992. }
  993. g_pscPen->Init();
  994. g_cAvailableThreads = 0;
  995. g_cThreads = 0;
  996. g_hDnsPort = CreateIoCompletionPort( INVALID_HANDLE_VALUE,
  997. NULL,
  998. NULL,
  999. g_cMaxThreadLimit );
  1000. g_hThreadsTerminated = IIS_CREATE_EVENT(
  1001. "g_hThreadsTerminated",
  1002. &g_hThreadsTerminated,
  1003. TRUE,
  1004. FALSE
  1005. );
  1006. if ( g_hDnsPort == NULL || g_hThreadsTerminated == NULL )
  1007. {
  1008. CloseHandle( g_hDnsPort );
  1009. CloseHandle( g_hThreadsTerminated );
  1010. g_hDnsPort = NULL;
  1011. g_hThreadsTerminated = NULL;
  1012. return FALSE;
  1013. }
  1014. g_dwScavengerWorkItem = ScheduleWorkItem( RDnsScavenger,
  1015. NULL,
  1016. 1000 * RDNS_SCAVENGER_GRANULARITY,
  1017. TRUE );
  1018. return TRUE;
  1019. }
  1020. void
  1021. TerminateRDns(
  1022. VOID
  1023. )
  1024. /*++
  1025. Routine Description:
  1026. Terminate the Reverse DNS API
  1027. Arguments:
  1028. None
  1029. Return Value:
  1030. Nothing
  1031. --*/
  1032. {
  1033. UINT x;
  1034. if ( !g_fEnableRdns ) {
  1035. return;
  1036. }
  1037. //
  1038. // post queued to everybody
  1039. // all threads will dec global count of thread, when 0 set event
  1040. // close port
  1041. if ( g_cThreads )
  1042. {
  1043. for ( x = 0 ; x < g_cThreads ; ++x )
  1044. {
  1045. PostQueuedCompletionStatus( g_hDnsPort, NULL, NULL, NULL );
  1046. }
  1047. WaitForSingleObject( g_hThreadsTerminated, 5 * 1000 );
  1048. }
  1049. CloseHandle( g_hDnsPort );
  1050. CloseHandle( g_hThreadsTerminated );
  1051. g_hDnsPort = NULL;
  1052. g_hThreadsTerminated = NULL;
  1053. if ( g_dwScavengerWorkItem != NULL )
  1054. {
  1055. RemoveWorkItem( g_dwScavengerWorkItem );
  1056. g_dwScavengerWorkItem = NULL;
  1057. }
  1058. g_RDns.Terminate();
  1059. if ( g_pscPen != NULL )
  1060. {
  1061. g_pscPen->Terminate();
  1062. delete g_pscPen;
  1063. g_pscPen = NULL;
  1064. }
  1065. }
  1066. DWORD WINAPI
  1067. AsyncThread(
  1068. LPVOID
  1069. )
  1070. /*++
  1071. Routine Description:
  1072. Thread handling reverse DNS request
  1073. Arguments:
  1074. LPVOID - not used
  1075. Return Value:
  1076. Thread exit status
  1077. --*/
  1078. {
  1079. DWORD dwSize;
  1080. ULONG_PTR dwKey;
  1081. PVOID * ppInfo;
  1082. DNSARG pArg;
  1083. struct sockaddr *pAddr;
  1084. struct sockaddr EmptyAddr;
  1085. LPSTR pName;
  1086. CHAR achName[DN_LEN];
  1087. DWORD h;
  1088. BOOL fSt;
  1089. struct hostent* pH;
  1090. DBG_ASSERT(g_fEnableRdns);
  1091. while ( GetQueuedCompletionStatus( g_hDnsPort,
  1092. &dwSize,
  1093. &dwKey,
  1094. (LPOVERLAPPED*)&ppInfo,
  1095. (DWORD)-1 ) )
  1096. {
  1097. InterlockedDecrement( &g_cAvailableThreads );
  1098. //
  1099. // if pInfo is NULL it is close request
  1100. //
  1101. if ( NULL == ppInfo)
  1102. {
  1103. if ( InterlockedDecrement( (PLONG)&g_cThreads ) == 0)
  1104. {
  1105. SetEvent( g_hThreadsTerminated );
  1106. }
  1107. break;
  1108. }
  1109. pAddr = (struct sockaddr *)ppInfo[0];
  1110. pArg = ppInfo[1];
  1111. switch ( ((PDNSFUNCDESC)dwKey)->dwRequestType )
  1112. {
  1113. case RDNS_REQUEST_TYPE_IP2DNS:
  1114. h = g_RDns.ComputeHash( pAddr );
  1115. fSt = FALSE;
  1116. if ( pH = gethostbyaddr( (char*)(&((PSOCKADDR_IN)pAddr)->sin_addr),
  1117. SIZEOF_IP_ADDRESS,
  1118. PF_INET ) )
  1119. {
  1120. g_RDns.NewEntry( pAddr, h, time(NULL)+g_cTTL, pH->h_name );
  1121. fSt = TRUE;
  1122. }
  1123. else
  1124. {
  1125. //
  1126. // Create entry with empty name as result of negative search
  1127. //
  1128. g_RDns.NewEntry( pAddr, h, time(NULL)+g_cTTL, "" );
  1129. }
  1130. (((PDNSFUNCDESC)dwKey)->pFunc)(pArg, fSt, pH ? pH->h_name : NULL );
  1131. break;
  1132. case RDNS_REQUEST_TYPE_DNS2IP:
  1133. pName = (LPSTR)pAddr;
  1134. h = g_RDns.ComputeHash( pName );
  1135. fSt = FALSE;
  1136. if ( pH = gethostbyname( pName ) )
  1137. {
  1138. memcpy( &((sockaddr_in*)&EmptyAddr)->sin_addr, pH->h_addr, SIZEOF_IP_ADDRESS );
  1139. EmptyAddr.sa_family = AF_INET;
  1140. fSt = TRUE;
  1141. }
  1142. else
  1143. {
  1144. //
  1145. // Create entry with null addr as result of negative search
  1146. //
  1147. memset( &EmptyAddr, '\0', sizeof(EmptyAddr) );
  1148. }
  1149. g_RDns.NewDns2IpEntry( &EmptyAddr, h, time(NULL)+g_cTTL, pName );
  1150. (((PDNSFUNCDESC)dwKey)->pFunc)(pArg, fSt, (LPSTR)&EmptyAddr );
  1151. break;
  1152. }
  1153. InterlockedIncrement( &g_cAvailableThreads );
  1154. pAddr = NULL;
  1155. pArg = NULL;
  1156. free(ppInfo);
  1157. }
  1158. return 0;
  1159. }
  1160. //AtqPostCompletionStatus(
  1161. // IN PATQ_CONTEXT patqContext, from QueryClientConn()->QueryAtqContext()
  1162. // IN DWORD BytesTransferred will be 0
  1163. // )
  1164. BOOL
  1165. AsyncHostByAddr(
  1166. PDNSFUNCDESC pFunc, // will store DNS name, post dummy completion status
  1167. // if NULL ( or g_cMaxThreadLimit==0 ) then sync request
  1168. DNSARG pArg, // ptr to be passed to FUNC
  1169. struct sockaddr *pHostAddr,
  1170. BOOL *pfSync, // updated with TRUE if sync call
  1171. LPSTR pName,
  1172. DWORD dwMaxNameLen
  1173. )
  1174. /*++
  1175. Routine Description:
  1176. Reverse DNS query
  1177. Arguments:
  1178. pFunc - ptr to function to be called for asynchronous result
  1179. pArg - argument to be supplied while calling pFunc
  1180. pHostAddr - address to reverse resolve
  1181. pfSync - updated with TRUE if synchronous result ( i.e. pName updated
  1182. with result if function returns TRUE )
  1183. pName - to be updated with DNS name if synchronous result
  1184. dwMaxNameLen - size of supplied pName buffer
  1185. Return Value:
  1186. TRUE if success, otherwise FALSE
  1187. --*/
  1188. {
  1189. BOOL fRet = TRUE;
  1190. DWORD h;
  1191. DBG_ASSERT(g_fEnableRdns);
  1192. h = g_RDns.ComputeHash( pHostAddr );
  1193. if ( g_RDns.Search( pHostAddr, h, pName, dwMaxNameLen ) )
  1194. {
  1195. *pfSync = TRUE;
  1196. return TRUE;
  1197. }
  1198. if ( pFunc == NULL || g_cMaxThreadLimit == 0 )
  1199. {
  1200. struct hostent* pH;
  1201. if ( pHostAddr->sa_family == AF_INET &&
  1202. (pH = gethostbyaddr( (char*)(&((PSOCKADDR_IN)pHostAddr)->sin_addr),
  1203. SIZEOF_IP_ADDRESS,
  1204. PF_INET )) )
  1205. {
  1206. UINT l = strlen( pH->h_name ) + 1;
  1207. if ( l <= dwMaxNameLen )
  1208. {
  1209. memcpy( pName, pH->h_name, l );
  1210. fRet = TRUE;
  1211. }
  1212. else
  1213. {
  1214. *pName = '\0';
  1215. fRet = FALSE;
  1216. }
  1217. }
  1218. else
  1219. {
  1220. //
  1221. // Create entry with empty name as result of negative search
  1222. //
  1223. *pName = '\0';
  1224. fRet = FALSE;
  1225. }
  1226. g_RDns.NewEntry( pHostAddr,
  1227. h,
  1228. time(NULL)+g_cTTL,
  1229. pName );
  1230. *pfSync = TRUE;
  1231. return fRet;
  1232. }
  1233. *pfSync = FALSE;
  1234. return FireUpNewThread( pFunc, pArg, (LPVOID)pHostAddr );
  1235. }
  1236. BOOL
  1237. AsyncAddrByHost(
  1238. PDNSFUNCDESC pFunc, // will store DNS name, post dummy completion status
  1239. // if NULL ( or g_cMaxThreadLimit==0 ) then sync request
  1240. DNSARG pArg, // ptr to be passed to FUNC
  1241. struct sockaddr *pHostAddr,
  1242. BOOL *pfSync, // updated with TRUE if sync call
  1243. LPSTR pszName
  1244. )
  1245. /*++
  1246. Routine Description:
  1247. DNS query
  1248. Arguments:
  1249. pFunc - ptr to function to be called for asynchronous result
  1250. pArg - argument to be supplied while calling pFunc
  1251. pHostAddr - to be updated with address
  1252. pfSync - updated with TRUE if synchronous result ( i.e. pName updated
  1253. with result if function returns TRUE )
  1254. pName - to be updated with DNS name if synchronous result
  1255. Return Value:
  1256. TRUE if success, otherwise FALSE
  1257. --*/
  1258. {
  1259. BOOL fRet = TRUE;
  1260. DWORD h;
  1261. DBG_ASSERT(g_fEnableRdns);
  1262. h = g_RDns.ComputeHash( pszName );
  1263. if ( g_RDns.SearchByName( pHostAddr, h, pszName ) )
  1264. {
  1265. *pfSync = TRUE;
  1266. return TRUE;
  1267. }
  1268. if ( pFunc == NULL || g_cMaxThreadLimit == 0 )
  1269. {
  1270. struct hostent* pH;
  1271. if ( pH = gethostbyname( pszName ) )
  1272. {
  1273. memcpy( &((sockaddr_in*)pHostAddr)->sin_addr, pH->h_addr, pH->h_length );
  1274. pHostAddr->sa_family = AF_INET;
  1275. fRet = TRUE;
  1276. }
  1277. else
  1278. {
  1279. //
  1280. // Create entry with empty name as result of negative search
  1281. //
  1282. memset( pHostAddr, '\0', sizeof(struct sockaddr) );
  1283. fRet = FALSE;
  1284. }
  1285. g_RDns.NewDns2IpEntry( pHostAddr,
  1286. h,
  1287. time(NULL)+g_cTTL,
  1288. pszName );
  1289. *pfSync = TRUE;
  1290. return fRet;
  1291. }
  1292. *pfSync = FALSE;
  1293. return FireUpNewThread( pFunc, pArg, (LPVOID)pszName );
  1294. }
  1295. BOOL
  1296. FireUpNewThread(
  1297. PDNSFUNCDESC pFunc,
  1298. DNSARG pArg,
  1299. LPVOID pOvr
  1300. )
  1301. {
  1302. //
  1303. // If no threads are available, kick a new one off up to the limit
  1304. //
  1305. if ( (g_cAvailableThreads == 0) &&
  1306. (g_cThreads < g_cMaxThreadLimit) )
  1307. {
  1308. HANDLE hThread;
  1309. DWORD dwThreadID;
  1310. InterlockedIncrement( (PLONG)&g_cThreads );
  1311. hThread = CreateThread( NULL,
  1312. 0,
  1313. (LPTHREAD_START_ROUTINE)AsyncThread,
  1314. NULL,
  1315. 0,
  1316. &dwThreadID );
  1317. if ( hThread )
  1318. {
  1319. CloseHandle( hThread ); // Free system resources
  1320. InterlockedIncrement( &g_cAvailableThreads );
  1321. }
  1322. else
  1323. {
  1324. //
  1325. // We fail if there are no threads running
  1326. //
  1327. if ( InterlockedDecrement( (PLONG)&g_cThreads ) == 0)
  1328. {
  1329. return FALSE;
  1330. }
  1331. }
  1332. }
  1333. PVOID * ppInfo = (PVOID *) malloc(2*sizeof(PVOID));
  1334. if (NULL != ppInfo)
  1335. {
  1336. ppInfo[0] = pOvr;
  1337. ppInfo[1] = pArg;
  1338. }
  1339. BOOL fRet = PostQueuedCompletionStatus( g_hDnsPort,
  1340. 0,
  1341. (ULONG_PTR)pFunc,
  1342. (LPOVERLAPPED)ppInfo
  1343. );
  1344. if( !fRet )
  1345. {
  1346. free( ppInfo );
  1347. }
  1348. return fRet;
  1349. }
  1350. #if DBG
  1351. typedef struct _TEST_RDNS
  1352. {
  1353. LPSTR pIA;
  1354. char achName[32];
  1355. struct sockaddr sa;
  1356. } TEST_RDNS;
  1357. TEST_RDNS TR[]={
  1358. { "157.55.83.72", "PHILLICH3" },
  1359. { "157.55.91.17", "JOHNL0" },
  1360. { "157.55.84.160", "JOHNSONA" },
  1361. { "157.55.87.80", "MICHTH1" },
  1362. { "157.55.86.54", "MICHTH2" },
  1363. } ;
  1364. LONG cPending = 0;
  1365. void CheckAddr( TEST_RDNS*p, LPSTR a)
  1366. {
  1367. // char achErr[80];
  1368. // wsprintf( achErr, "Arg=%d, bool=%d, addr=%s\n", a, f, p );
  1369. // OutputDebugString( achErr );
  1370. int l = strlen( p->achName );
  1371. if ( _memicmp( p->achName, a, l ) )
  1372. {
  1373. ASSERT( FALSE );
  1374. }
  1375. }
  1376. void pFunc( DNSARG a, BOOL f, LPSTR p)
  1377. {
  1378. if ( f )
  1379. {
  1380. CheckAddr( (TEST_RDNS*)a, p );
  1381. }
  1382. else
  1383. {
  1384. char achErr[80];
  1385. wsprintf( achErr, "Failed gethostbyaddr=%s\n", ((TEST_RDNS*)a)->pIA );
  1386. OutputDebugString( achErr );
  1387. }
  1388. InterlockedDecrement( &cPending );
  1389. }
  1390. DNSFUNCDESC g_TestFunc = { RDNS_REQUEST_TYPE_IP2DNS, pFunc };
  1391. void TestRDns()
  1392. {
  1393. static struct sockaddr sa;
  1394. BOOL fS;
  1395. UINT x;
  1396. UINT y;
  1397. CHAR achName[64];
  1398. UINT a,b,c,d;
  1399. for ( x = y = 0 ; x < 1000 ; ++x )
  1400. {
  1401. TEST_RDNS *p = TR+y;
  1402. sscanf( p->pIA, "%u.%u.%u.%u", &a, &b, &c, &d );
  1403. ((PSOCKADDR_IN)&p->sa)->sin_addr.s_net = (u_char)a;
  1404. ((PSOCKADDR_IN)&p->sa)->sin_addr.s_host = (u_char)b;
  1405. ((PSOCKADDR_IN)&p->sa)->sin_addr.s_lh = (u_char)c;
  1406. ((PSOCKADDR_IN)&p->sa)->sin_addr.s_impno = (u_char)d;
  1407. p->sa.sa_family = AF_INET;
  1408. if ( AsyncHostByAddr(
  1409. (PDNSFUNCDESC)&g_TestFunc,
  1410. (DNSARG)p,
  1411. &p->sa,
  1412. &fS,
  1413. achName,
  1414. sizeof(achName)
  1415. ) )
  1416. {
  1417. if ( fS )
  1418. {
  1419. CheckAddr( p, achName );
  1420. }
  1421. else
  1422. {
  1423. InterlockedIncrement( &cPending );
  1424. Sleep( 500 );
  1425. }
  1426. }
  1427. else
  1428. {
  1429. ASSERT( FALSE );
  1430. }
  1431. if ( ++y == sizeof(TR)/sizeof(TEST_RDNS) )
  1432. {
  1433. y = 0;
  1434. }
  1435. }
  1436. for ( ;; )
  1437. {
  1438. if ( cPending == 0 )
  1439. {
  1440. break;
  1441. }
  1442. Sleep( 1000 );
  1443. }
  1444. OutputDebugString( "Done" );
  1445. }
  1446. #endif
  1447. LPVOID
  1448. BsearchEx (
  1449. LPVOID key,
  1450. LPVOID base,
  1451. size_t num,
  1452. size_t width,
  1453. CMPFUNC compare,
  1454. LPVOID param
  1455. )
  1456. /*++
  1457. Routine Description:
  1458. Binary search with additional parameter to be passed
  1459. to compare routine
  1460. Arguments:
  1461. key - ptr to key
  1462. base - ptr to base of array
  1463. num - number of elements in array
  1464. width - size of array element
  1465. compare - compare routine, called with ptr to 2 elements and param
  1466. param - additional parameter presented to the compare routine
  1467. Return Value:
  1468. ptr to element in array if key found, else NULL
  1469. --*/
  1470. {
  1471. char *lo = (char *)base;
  1472. char *hi = (char *)base + (num - 1) * width;
  1473. char *mid;
  1474. unsigned int half;
  1475. int result;
  1476. while (lo <= hi)
  1477. if (half = num / 2)
  1478. {
  1479. mid = lo + (num & 1 ? half : (half - 1)) * width;
  1480. if (!(result = (*compare)(key,mid,param)))
  1481. return(mid);
  1482. else if (result < 0)
  1483. {
  1484. hi = mid - width;
  1485. num = num & 1 ? half : half-1;
  1486. }
  1487. else {
  1488. lo = mid + width;
  1489. num = half;
  1490. }
  1491. }
  1492. else if (num)
  1493. return((*compare)(key,lo,param) ? NULL : lo);
  1494. else
  1495. break;
  1496. return(NULL);
  1497. }
  1498. BOOL
  1499. ADDRESS_CHECK::BindCheckList(
  1500. LPBYTE p,
  1501. DWORD c
  1502. )
  1503. /*++
  1504. Routine Description:
  1505. Bind a check list ( presented as a BLOB ) to an
  1506. ADDRESS_CHECK object
  1507. Arguments:
  1508. p - ptr to BLOB
  1509. c - size of BLOB
  1510. Return Value:
  1511. TRUE if successful, FALSE otherwise
  1512. --*/
  1513. {
  1514. PADDRESS_CHECK_LIST pList;
  1515. UINT l;
  1516. if ( p == NULL )
  1517. {
  1518. if ( m_Storage.Init() && m_Storage.Resize( sizeof(ADDRESS_CHECK_LIST)
  1519. + sizeof(ADDRESS_HEADER) * 2
  1520. + sizeof(NAME_HEADER) * 2 ) )
  1521. {
  1522. DWORD i;
  1523. pList = (PADDRESS_CHECK_LIST)m_Storage.GetAlloc();
  1524. // BugFix: 47982 Whistler
  1525. // Prefix bug pList not being valid.
  1526. // EBK 5/5/2000
  1527. if (pList)
  1528. {
  1529. pList->iDenyAddr = i = MAKEREF( sizeof(ADDRESS_CHECK_LIST) );
  1530. i += sizeof(ADDRESS_HEADER);
  1531. pList->iGrantAddr = i;
  1532. i += sizeof(ADDRESS_HEADER);
  1533. pList->iDenyName = i;
  1534. i += sizeof(NAME_HEADER);
  1535. pList->iGrantName = i;
  1536. i += sizeof(NAME_HEADER);
  1537. pList->cRefSize = MAKEOFFSET(i);
  1538. pList->dwFlags = RDNS_FLAG_DODNS2IPCHECK;
  1539. return TRUE;
  1540. }
  1541. }
  1542. return FALSE;
  1543. }
  1544. else
  1545. {
  1546. return m_Storage.Init( p, c );
  1547. }
  1548. }
  1549. BOOL
  1550. ADDRESS_CHECK::SetFlag(
  1551. DWORD dwFlag,
  1552. BOOL fEnable
  1553. )
  1554. /*++
  1555. Routine Description:
  1556. Set flag in address check object
  1557. Arguments:
  1558. dwFlag - flag to enable/disable
  1559. fEnable - TRUE to enable, else FALSE
  1560. Return Value:
  1561. TRUE if successful, FALSE otherwise
  1562. --*/
  1563. {
  1564. LPBYTE pStore = m_Storage.GetAlloc();
  1565. PADDRESS_CHECK_LIST pList;
  1566. if ( pStore )
  1567. {
  1568. pList = (PADDRESS_CHECK_LIST)pStore;
  1569. if ( fEnable )
  1570. {
  1571. pList->dwFlags |= dwFlag;
  1572. }
  1573. else
  1574. {
  1575. pList->dwFlags &= ~dwFlag;
  1576. }
  1577. return TRUE;
  1578. }
  1579. return FALSE;
  1580. }
  1581. DWORD
  1582. ADDRESS_CHECK::GetFlags(
  1583. )
  1584. /*++
  1585. Routine Description:
  1586. Get flags in address check object
  1587. Arguments:
  1588. None
  1589. Return Value:
  1590. Flags if object exists, otherwise 0
  1591. --*/
  1592. {
  1593. LPBYTE pStore = m_Storage.GetAlloc();
  1594. PADDRESS_CHECK_LIST pList;
  1595. if ( pStore )
  1596. {
  1597. pList = (PADDRESS_CHECK_LIST)pStore;
  1598. return pList->dwFlags;
  1599. }
  1600. return 0;
  1601. }
  1602. BOOL
  1603. ADDRESS_CHECK::LocateAddr(
  1604. BOOL fGrant,
  1605. DWORD iIndex,
  1606. PADDRESS_HEADER* ppHd,
  1607. PADDRESS_LIST_ENTRY* pHeader,
  1608. LPDWORD piIndexInHeader
  1609. )
  1610. /*++
  1611. Routine Description:
  1612. Locate an address in the specified list, returns ptr
  1613. to header & element in address list
  1614. Arguments:
  1615. fGrant - TRUE to locate in grant list, FALSE for deny list
  1616. iIndex - index in list (0-based )
  1617. ppHd - updated with ptr to address header
  1618. pHeader - updated with ptr to address list entry
  1619. piIndexInHeader - updated with index in array addressed by
  1620. pHeader->iFirstAddress
  1621. Return Value:
  1622. TRUE if iIndex valid in array defined by fGrant, FALSE otherwise
  1623. --*/
  1624. {
  1625. LPBYTE pStore = m_Storage.GetAlloc();
  1626. PADDRESS_CHECK_LIST pList;
  1627. PADDRESS_HEADER pHd;
  1628. UINT iL;
  1629. if ( pStore )
  1630. {
  1631. pList = (PADDRESS_CHECK_LIST)pStore;
  1632. *ppHd = pHd = (PADDRESS_HEADER)MAKEPTR( pStore, fGrant ? pList->iGrantAddr : pList->iDenyAddr);
  1633. for ( iL = 0 ; iL < pHd->cEntries ; ++iL )
  1634. {
  1635. // adjust index by 1: 1st entry is mask
  1636. if ( iIndex < (pHd->Entries[iL].cAddresses-1) )
  1637. {
  1638. *pHeader = pHd->Entries+iL;
  1639. *piIndexInHeader = iIndex+1;
  1640. return TRUE;
  1641. }
  1642. iIndex -= (pHd->Entries[iL].cAddresses-1);
  1643. }
  1644. }
  1645. return FALSE;
  1646. }
  1647. BOOL
  1648. ADDRESS_CHECK::GetAddr(
  1649. BOOL fGrant,
  1650. DWORD iIndex,
  1651. LPDWORD pdwFamily,
  1652. LPBYTE* pMask,
  1653. LPBYTE* pAddr
  1654. )
  1655. /*++
  1656. Routine Description:
  1657. Get an address entry
  1658. Arguments:
  1659. fGrant - TRUE to locate in grant list, FALSE for deny list
  1660. iIndex - index in list (0-based )
  1661. pdwFamily - updated with address family ( as in sockaddr.sa_type )
  1662. pMask - updated with ptr to mask
  1663. pAddr - updated with ptr to address
  1664. Return Value:
  1665. TRUE if iIndex valid in array defined by fGrant, FALSE otherwise
  1666. --*/
  1667. {
  1668. PADDRESS_LIST_ENTRY pHeader;
  1669. PADDRESS_HEADER pHd;
  1670. DWORD iIndexInHeader;
  1671. LPBYTE pStore = m_Storage.GetAlloc();
  1672. if ( LocateAddr( fGrant, iIndex, &pHd, &pHeader, &iIndexInHeader ) )
  1673. {
  1674. UINT cS = GetAddrSize( pHeader->iFamily );
  1675. *pdwFamily = pHeader->iFamily;
  1676. pStore = MAKEPTR(pStore, pHeader->iFirstAddress);
  1677. *pMask = pStore;
  1678. *pAddr = pStore+iIndexInHeader*cS;
  1679. return TRUE;
  1680. }
  1681. return FALSE;
  1682. }
  1683. BOOL
  1684. ADDRESS_CHECK::DeleteAddr(
  1685. BOOL fGrant,
  1686. DWORD iIndex
  1687. )
  1688. /*++
  1689. Routine Description:
  1690. Delete an address entry
  1691. Arguments:
  1692. fGrant - TRUE to locate in grant list, FALSE for deny list
  1693. iIndex - index in list (0-based )
  1694. Return Value:
  1695. TRUE if iIndex valid in array defined by fGrant, FALSE otherwise
  1696. --*/
  1697. {
  1698. PADDRESS_LIST_ENTRY pHeader;
  1699. PADDRESS_HEADER pHd;
  1700. DWORD iIndexInHeader;
  1701. LPBYTE pStore = m_Storage.GetAlloc();
  1702. if ( LocateAddr( fGrant, iIndex, &pHd, &pHeader, &iIndexInHeader ) )
  1703. {
  1704. UINT cS = GetAddrSize( pHeader->iFamily );
  1705. UINT iS = MAKEOFFSET(pHeader->iFirstAddress)+iIndexInHeader*cS;
  1706. LPBYTE pAddr = MAKEPTR(pStore, iS);
  1707. memmove( pAddr,
  1708. pAddr + cS,
  1709. m_Storage.GetUsed() - iS - cS );
  1710. m_Storage.AdjustUsed( -(int)cS );
  1711. --pHeader->cAddresses;
  1712. AdjustRefs( pStore, MAKEOFFSET(pHeader->iFirstAddress)+1, -(int)cS );
  1713. --pHd->cAddresses;
  1714. return TRUE;
  1715. }
  1716. return FALSE;
  1717. }
  1718. int __cdecl
  1719. AddrCmp(
  1720. LPVOID pA,
  1721. LPVOID pB,
  1722. LPVOID pP
  1723. )
  1724. /*++
  1725. Routine Description:
  1726. Compare 2 address entries.
  1727. uses mask as defined by PADDRCMPDESC pP
  1728. Arguments:
  1729. pA - ptr to 1st address entry ( as byte array )
  1730. pB - ptr to 2nd address entry ( as byte array )
  1731. pP - ptr yo ADDRCMDDESC
  1732. Return Value:
  1733. -1 if *pA < *pB, 0 if *pA == *pB, 1 if *pA > *pB
  1734. --*/
  1735. {
  1736. PADDRCMPDESC pacd = (PADDRCMPDESC)pP;
  1737. int l;
  1738. UINT a;
  1739. UINT b;
  1740. if ( pacd->cFullBytes || pacd->LastByte )
  1741. {
  1742. if ( (l = memcmp( pA, pB, pacd->cFullBytes )) )
  1743. {
  1744. return l;
  1745. }
  1746. if ( pacd->LastByte )
  1747. {
  1748. a = ((LPBYTE)pA)[pacd->cFullBytes] & pacd->LastByte;
  1749. b = ((LPBYTE)pB)[pacd->cFullBytes] & pacd->LastByte;
  1750. return a < b ? -1 : ( a==b ? 0 : 1 );
  1751. }
  1752. return 0;
  1753. }
  1754. else
  1755. {
  1756. // bit cmp from pMask
  1757. LPBYTE pM = pacd->pMask;
  1758. LPBYTE pMM = pM + pacd->cSizeAddress;
  1759. for ( ; pM < pMM ; ++pM )
  1760. {
  1761. a = *((LPBYTE)pA) & *pM;
  1762. b = *((LPBYTE)pB) & *pM;
  1763. if ( a<b )
  1764. {
  1765. return -1;
  1766. }
  1767. else if ( a > b )
  1768. {
  1769. return 1;
  1770. }
  1771. pA = (LPVOID)(((LPBYTE)pA) + 1);
  1772. pB = (LPVOID)(((LPBYTE)pB) + 1);
  1773. }
  1774. return 0;
  1775. }
  1776. }
  1777. int __cdecl
  1778. NameCmp(
  1779. LPVOID pA,
  1780. LPVOID pB,
  1781. LPVOID pP
  1782. )
  1783. /*++
  1784. Routine Description:
  1785. Compare 2 name entries.
  1786. Entry is either defined as a ptr to ASCII ( if equal to NAMECMPDESC.pName )
  1787. or as ptr to DWORD offset in LPSTR array based as NAMECMPDESC.pBase
  1788. Arguments:
  1789. pA - ptr to 1st name entry
  1790. pB - ptr to 2nd name entry
  1791. pP - ptr yo NAMECMDDESC
  1792. Return Value:
  1793. -1 if *pA < *pB, 0 if *pA == *pB, 1 if *pA > *pB
  1794. --*/
  1795. {
  1796. int l;
  1797. UINT a;
  1798. UINT b;
  1799. PNAMECMPDESC pncd = (PNAMECMPDESC)pP;
  1800. LPVOID pName = pncd->pName;
  1801. LPBYTE pBase = pncd->pBase;
  1802. if ( pA != pName )
  1803. {
  1804. pA = MAKEPTR( pBase, *(DWORD*)pA );
  1805. }
  1806. if ( pB != pName )
  1807. {
  1808. pB = MAKEPTR( pBase, *(DWORD*)pB );
  1809. }
  1810. return _stricmp( (const char*)pA, (const char*)pB );
  1811. }
  1812. BOOL
  1813. ADDRESS_CHECK::AddAddr(
  1814. BOOL fGrant,
  1815. DWORD dwFamily,
  1816. LPBYTE pMask,
  1817. LPBYTE pAddr
  1818. )
  1819. /*++
  1820. Routine Description:
  1821. Add an address entry
  1822. Arguments:
  1823. fGrant - TRUE to locate in grant list, FALSE for deny list
  1824. dwFamily - address family, as in sockaddr.sa_type
  1825. pMask - ptr to mask
  1826. pAddr - ptr to address
  1827. Return Value:
  1828. TRUE if success, otherwise FALSE
  1829. --*/
  1830. {
  1831. LPBYTE pStore = m_Storage.GetAlloc();
  1832. PADDRESS_CHECK_LIST pList;
  1833. PADDRESS_HEADER pHd;
  1834. UINT iL;
  1835. UINT cS = GetAddrSize( dwFamily );
  1836. LPBYTE pA;
  1837. ADDRCMPDESC acd;
  1838. LPBYTE pS;
  1839. PADDRESS_LIST_ENTRY pE;
  1840. MakeAcd( &acd, pMask, cS );
  1841. if ( pStore )
  1842. {
  1843. pList = (PADDRESS_CHECK_LIST)pStore;
  1844. pHd = (PADDRESS_HEADER)MAKEPTR( pStore, fGrant ? pList->iGrantAddr : pList->iDenyAddr);
  1845. for ( iL = 0 ; iL < pHd->cEntries ; ++iL )
  1846. {
  1847. if ( pHd->Entries[iL].iFamily == dwFamily )
  1848. {
  1849. pS = MAKEPTR(pStore, pHd->Entries[iL].iFirstAddress );
  1850. int cm;
  1851. if ( !(cm = memcmp( pMask, pS, cS )) )
  1852. {
  1853. // found matching family, mask
  1854. // find where to insert
  1855. DWORD i;
  1856. for ( i= 1, cm = 1 ; i < pHd->Entries[iL].cAddresses ; ++i )
  1857. {
  1858. if ( !(cm = AddrCmp( pAddr, pS+cS*i, &acd )) )
  1859. {
  1860. // already exist
  1861. return FALSE;
  1862. }
  1863. else if ( cm < 0 )
  1864. {
  1865. // insert @ i
  1866. insert_addr:
  1867. UINT s = m_Storage.GetUsed();
  1868. if ( m_Storage.Resize( cS ) )
  1869. {
  1870. int l;
  1871. pStore = m_Storage.GetAlloc();
  1872. pList = (PADDRESS_CHECK_LIST)pStore;
  1873. pHd = (PADDRESS_HEADER)MAKEPTR( pStore, fGrant ? pList->iGrantAddr : pList->iDenyAddr);
  1874. pS = MAKEPTR(pStore, l=MAKEOFFSET(pHd->Entries[iL].iFirstAddress+i*cS) );
  1875. memmove( pS+cS, pS, s-l );
  1876. memcpy( pS, pAddr, cS );
  1877. AdjustRefs( pStore, pHd->Entries[iL].iFirstAddress+1, cS );
  1878. ++pHd->Entries[iL].cAddresses;
  1879. ++pHd->cAddresses;
  1880. return TRUE;
  1881. }
  1882. return FALSE;
  1883. }
  1884. }
  1885. goto insert_addr;
  1886. }
  1887. else if ( cm < 0 )
  1888. {
  1889. insert_at_current_pos:
  1890. // must insert new Entry @ iL
  1891. int i = m_Storage.GetUsed()+sizeof(ADDRESS_LIST_ENTRY);
  1892. UINT cWasUsed = m_Storage.GetUsed();
  1893. if ( m_Storage.Resize( sizeof(ADDRESS_LIST_ENTRY)+cS*2 ) )
  1894. {
  1895. // refresh pointers
  1896. pStore = m_Storage.GetAlloc();
  1897. pList = (PADDRESS_CHECK_LIST)pStore;
  1898. pList->cRefSize += sizeof(ADDRESS_LIST_ENTRY);
  1899. pHd = (PADDRESS_HEADER)MAKEPTR( pStore, fGrant ? pList->iGrantAddr : pList->iDenyAddr);
  1900. pE = pHd->Entries + iL;
  1901. // SELFREFINDEX where to insert
  1902. UINT iS = DIFF((LPBYTE)(pHd->Entries+iL)-pStore);
  1903. // make room for entry
  1904. memmove( pE+1,
  1905. pE,
  1906. cWasUsed-iS );
  1907. AdjustRefs( pStore, DIFF((LPBYTE)pHd->Entries-pStore), sizeof(ADDRESS_LIST_ENTRY) );
  1908. // fill entry
  1909. pE->iFamily = dwFamily;
  1910. pE->cAddresses = 2;
  1911. pE->iFirstAddress = MAKEREF( i );
  1912. pE->cFullBytes = acd.cFullBytes;
  1913. pE->LastByte = acd.LastByte;
  1914. // copy mask & addr
  1915. pA = MAKEPTR( pStore, i );
  1916. memcpy( pA, pMask, cS );
  1917. memcpy( pA+cS, pAddr, cS );
  1918. ++pHd->cEntries;
  1919. ++pHd->cAddresses;
  1920. return TRUE;
  1921. }
  1922. break;
  1923. }
  1924. }
  1925. else if ( pHd->Entries[iL].iFamily > dwFamily )
  1926. {
  1927. goto insert_at_current_pos;
  1928. }
  1929. }
  1930. goto insert_at_current_pos;
  1931. }
  1932. return FALSE;
  1933. }
  1934. inline
  1935. DWORD
  1936. ADDRESS_CHECK::GetNbAddr(
  1937. BOOL fGrant
  1938. )
  1939. /*++
  1940. Routine Description:
  1941. Get number of entries in list
  1942. Arguments:
  1943. fGrant - TRUE to locate in grant list, FALSE for deny list
  1944. Return Value:
  1945. Number of entries in list
  1946. --*/
  1947. {
  1948. LPBYTE pStore = m_Storage.GetAlloc();
  1949. PADDRESS_CHECK_LIST pList;
  1950. PADDRESS_HEADER pHd;
  1951. if ( pStore )
  1952. {
  1953. pList = (PADDRESS_CHECK_LIST)pStore;
  1954. pHd = (PADDRESS_HEADER)MAKEPTR( pStore, fGrant ? pList->iGrantAddr : pList->iDenyAddr);
  1955. return pHd->cAddresses;
  1956. }
  1957. return 0;
  1958. }
  1959. VOID
  1960. ADDRESS_CHECK::MakeAcd(
  1961. PADDRCMPDESC pacd,
  1962. LPBYTE pMask,
  1963. UINT cLen
  1964. )
  1965. /*++
  1966. Routine Description:
  1967. Build a ADDRCMPDESC struct based on ptr to mask and address length
  1968. Arguments:
  1969. pacd - ptr to ADDRCMPDESC to build
  1970. pMask - ptr to mask
  1971. cLen - address length
  1972. Return Value:
  1973. Nothing
  1974. --*/
  1975. {
  1976. pacd->pMask = pMask;
  1977. pacd->cFullBytes = 0;
  1978. pacd->LastByte = 0;
  1979. pacd->cSizeAddress = cLen;
  1980. while ( pacd->cFullBytes < cLen &&
  1981. pMask[pacd->cFullBytes] == 0xff )
  1982. {
  1983. ++pacd->cFullBytes;
  1984. }
  1985. if ( pacd->cFullBytes < cLen )
  1986. {
  1987. UINT i;
  1988. pacd->LastByte = pMask[pacd->cFullBytes];
  1989. for ( i = pacd->cFullBytes+1 ; i < cLen ; ++i )
  1990. {
  1991. if ( pMask[i] != 0 )
  1992. {
  1993. // non-standard mask
  1994. pacd->cFullBytes = 0;
  1995. pacd->LastByte = 0;
  1996. break;
  1997. }
  1998. }
  1999. }
  2000. }
  2001. BOOL
  2002. ADDRESS_CHECK::IsMatchAddr(
  2003. BOOL fGrant,
  2004. DWORD dwFamily,
  2005. LPBYTE pAddr
  2006. )
  2007. /*++
  2008. Routine Description:
  2009. Check if address in list
  2010. Arguments:
  2011. fGrant - TRUE to locate in grant list, FALSE for deny list
  2012. dwFamily - address family, as in sockaddr.sa_type
  2013. pAddr - ptr to address
  2014. Return Value:
  2015. TRUE if address is in specified list, otherwise FALSE
  2016. --*/
  2017. {
  2018. LPBYTE pStore = m_Storage.GetAlloc();
  2019. PADDRESS_CHECK_LIST pList;
  2020. PADDRESS_HEADER pHd;
  2021. UINT iL;
  2022. UINT cS = GetAddrSize( dwFamily );
  2023. if ( pStore )
  2024. {
  2025. pList = (PADDRESS_CHECK_LIST)pStore;
  2026. pHd = (PADDRESS_HEADER)MAKEPTR( pStore, fGrant ? pList->iGrantAddr : pList->iDenyAddr);
  2027. for ( iL = 0 ; iL < pHd->cEntries ; ++iL )
  2028. {
  2029. if ( dwFamily == pHd->Entries[iL].iFamily )
  2030. {
  2031. ADDRCMPDESC acd;
  2032. LPBYTE pA = MAKEPTR( pStore, pHd->Entries[iL].iFirstAddress );
  2033. acd.cSizeAddress = cS;
  2034. acd.pMask = pA;
  2035. acd.cFullBytes = pHd->Entries[iL].cFullBytes;
  2036. acd.LastByte = pHd->Entries[iL].LastByte;
  2037. if ( BsearchEx( pAddr, pA+cS, pHd->Entries[iL].cAddresses - 1, cS, (CMPFUNC)AddrCmp, &acd ) )
  2038. {
  2039. return TRUE;
  2040. }
  2041. }
  2042. else if ( dwFamily > pHd->Entries[iL].iFamily )
  2043. {
  2044. break;
  2045. }
  2046. }
  2047. }
  2048. return FALSE;
  2049. }
  2050. VOID
  2051. ADDRESS_CHECK::AdjustRefs(
  2052. LPBYTE pStore,
  2053. DWORD dwCut,
  2054. DWORD dwAdj
  2055. )
  2056. /*++
  2057. Routine Description:
  2058. Adjust references in ADDRESS_CHECK by offset dwAdj for references
  2059. above or equal to dwCut
  2060. Arguments:
  2061. pStore - ptr to address check binary object
  2062. dwCut - references above or equal to this parameter are to be adjusted
  2063. by dwAdj
  2064. dwAdj - offset to add to reference above or equal to dwCut
  2065. Return Value:
  2066. Nothing
  2067. --*/
  2068. {
  2069. LPBYTE pL = pStore + ((PADDRESS_CHECK_LIST)pStore)->cRefSize;
  2070. dwCut = MAKEREF( dwCut );
  2071. for ( ; pStore < pL ; pStore += sizeof(DWORD) )
  2072. {
  2073. if ( *((LPDWORD)pStore) >= dwCut )
  2074. {
  2075. *((LPDWORD)pStore) += dwAdj;
  2076. }
  2077. }
  2078. }
  2079. UINT
  2080. ADDRESS_CHECK::GetAddrSize(
  2081. DWORD dwF
  2082. )
  2083. /*++
  2084. Routine Description:
  2085. Returns address size in byte based on family ( sockaddr.sa_type )
  2086. Arguments:
  2087. dwF - address family ( as in sockaddr.sa_type )
  2088. Return Value:
  2089. Address length, in byte. 0 for unknown address families
  2090. --*/
  2091. {
  2092. DWORD dwS;
  2093. switch ( dwF )
  2094. {
  2095. case AF_INET:
  2096. dwS = SIZEOF_IP_ADDRESS;
  2097. break;
  2098. default:
  2099. dwS = 0;
  2100. break;
  2101. }
  2102. return dwS;
  2103. }
  2104. BOOL
  2105. ADDRESS_CHECK::DeleteAllAddr(
  2106. BOOL fGrant
  2107. )
  2108. /*++
  2109. Routine Description:
  2110. Delete all address entries in specified list
  2111. Arguments:
  2112. fGrant - TRUE to locate in grant list, FALSE for deny list
  2113. Return Value:
  2114. TRUE if success, otherwise FALSE
  2115. --*/
  2116. {
  2117. while ( DeleteAddr( fGrant, 0 ) )
  2118. {
  2119. }
  2120. return TRUE;
  2121. }
  2122. BOOL
  2123. XAR::Resize(
  2124. DWORD dwDelta
  2125. )
  2126. /*++
  2127. Routine Description:
  2128. Resize storage by dwDelta.
  2129. This can modify storage ptr, so ptr based on value returned by GetAlloc()
  2130. are invalidated by calling this.
  2131. Arguments:
  2132. dwDelta - delta to add ( substract if (int)dwDelta < 0 )
  2133. to storage
  2134. Return Value:
  2135. TRUE if success, otherwise FALSE
  2136. --*/
  2137. {
  2138. if ( (int)dwDelta > 0 )
  2139. {
  2140. if ( (m_cUsed + dwDelta > m_cAlloc) )
  2141. {
  2142. UINT cNew = ((m_cUsed+dwDelta+XAR_GRAIN)/XAR_GRAIN)*XAR_GRAIN;
  2143. LPBYTE p = (LPBYTE)LocalAlloc( LMEM_FIXED|LMEM_ZEROINIT, cNew );
  2144. if ( p )
  2145. {
  2146. memcpy( p, m_pAlloc, m_cUsed );
  2147. if ( m_fDidAlloc )
  2148. {
  2149. LocalFree( m_pAlloc );
  2150. }
  2151. m_pAlloc = p;
  2152. m_cAlloc = cNew;
  2153. m_fDidAlloc = TRUE;
  2154. }
  2155. else
  2156. {
  2157. return FALSE;
  2158. }
  2159. }
  2160. }
  2161. m_cUsed += dwDelta;
  2162. return TRUE;
  2163. }
  2164. AC_RESULT
  2165. ADDRESS_CHECK::CheckAddress(
  2166. struct sockaddr* pAddr
  2167. )
  2168. /*++
  2169. Routine Description:
  2170. Check if address is in grant or deny list
  2171. Arguments:
  2172. pAddr - ptr to address
  2173. Return Value:
  2174. TRUE if address is granted access, otherwise FALSE
  2175. --*/
  2176. {
  2177. LPBYTE p;
  2178. if ( !pAddr || !g_fEnableRdns )
  2179. {
  2180. goto ex;
  2181. }
  2182. // if deny list non empty, check not in list
  2183. switch ( pAddr->sa_family )
  2184. {
  2185. case AF_INET:
  2186. p = (LPBYTE)(&((PSOCKADDR_IN)pAddr)->sin_addr);
  2187. break;
  2188. case AF_IPX:
  2189. goto ex;
  2190. //p = (LPBYTE)(((PSOCKADDR)pAddr)->sa_data);
  2191. //break;
  2192. }
  2193. if ( GetNbAddr( FALSE ) )
  2194. {
  2195. if ( IsMatchAddr( FALSE, pAddr->sa_family, p ) )
  2196. {
  2197. return AC_IN_DENY_LIST;
  2198. }
  2199. return AC_NOT_IN_DENY_LIST;
  2200. }
  2201. // if grant list non empty, check in list
  2202. if ( GetNbAddr( TRUE ) )
  2203. {
  2204. if ( IsMatchAddr( TRUE, pAddr->sa_family, p ) )
  2205. {
  2206. return AC_IN_GRANT_LIST;
  2207. }
  2208. return AC_NOT_IN_GRANT_LIST;
  2209. }
  2210. ex:
  2211. return AC_NO_LIST;
  2212. }
  2213. VOID
  2214. AddrCheckDnsCallBack(
  2215. DNSARG p,
  2216. BOOL fSt,
  2217. LPSTR pDns
  2218. )
  2219. /*++
  2220. Routine Description:
  2221. Callback routine from reverse DNS resolver.
  2222. Shell for real function in ADDRESS_CHECK
  2223. Arguments:
  2224. p - ptr to ADDRESS_CHECK
  2225. fSt - TRUE if reverse DNS resolver success, otherwise FALSE
  2226. pDns - DNS name if fSt is TRUE
  2227. Return Value:
  2228. Nothing
  2229. --*/
  2230. {
  2231. ((ADDRESS_CHECK*)p)->AddrCheckDnsCallBack( fSt, pDns );
  2232. }
  2233. VOID
  2234. AddrCheckDnsCallBack2(
  2235. DNSARG p,
  2236. BOOL fSt,
  2237. LPSTR pDns
  2238. )
  2239. /*++
  2240. Routine Description:
  2241. Callback routine from reverse DNS2 resolver.
  2242. Shell for real function in ADDRESS_CHECK
  2243. Arguments:
  2244. p - ptr to ADDRESS_CHECK
  2245. fSt - TRUE if reverse DNS resolver success, otherwise FALSE
  2246. pDns - DNS name if fSt is TRUE
  2247. Return Value:
  2248. Nothing
  2249. --*/
  2250. {
  2251. ((ADDRESS_CHECK*)p)->AddrCheckDnsCallBack2( fSt, (struct sockaddr *)pDns );
  2252. }
  2253. VOID
  2254. AddrCheckDnsCallBack3(
  2255. DNSARG p,
  2256. BOOL fSt,
  2257. LPSTR pDns
  2258. )
  2259. /*++
  2260. Routine Description:
  2261. Callback routine from reverse DNS3 resolver.
  2262. Shell for real function in ADDRESS_CHECK
  2263. Arguments:
  2264. p - ptr to ADDRESS_CHECK
  2265. fSt - TRUE if reverse DNS resolver success, otherwise FALSE
  2266. pDns - DNS name if fSt is TRUE
  2267. Return Value:
  2268. Nothing
  2269. --*/
  2270. {
  2271. ((ADDRESS_CHECK*)p)->AddrCheckDnsCallBack3( fSt, (struct sockaddr *)pDns );
  2272. }
  2273. VOID
  2274. ResolveDnsCallBack(
  2275. DNSARG p,
  2276. BOOL fSt,
  2277. LPSTR pDns
  2278. )
  2279. /*++
  2280. Routine Description:
  2281. Callback routine from reverse DNS resolver.
  2282. Shell for real function in ADDRESS_CHECK
  2283. Arguments:
  2284. p - ptr to ADDRESS_CHECK
  2285. fSt - TRUE if reverse DNS resolver success, otherwise FALSE
  2286. pDns - DNS name if fSt is TRUE
  2287. Return Value:
  2288. Nothing
  2289. --*/
  2290. {
  2291. ((ADDRESS_CHECK*)p)->ResolveDnsCallBack( fSt, pDns );
  2292. }
  2293. VOID
  2294. ADDRESS_CHECK::AddrCheckDnsCallBack(
  2295. BOOL fSt,
  2296. LPSTR pDns
  2297. )
  2298. /*++
  2299. Routine Description:
  2300. Callback routine from reverse DNS resolver
  2301. Arguments:
  2302. fSt - TRUE if reverse DNS resolver success, otherwise FALSE
  2303. pDns - DNS name if fSt is TRUE
  2304. Return Value:
  2305. Nothing
  2306. --*/
  2307. {
  2308. m_fDnsResolved = TRUE;
  2309. if ( fSt )
  2310. {
  2311. strncpy( m_pszDnsName, pDns, DNS_MAX_NAME_LENGTH );
  2312. m_pszDnsName[ DNS_MAX_NAME_LENGTH ] = '\0';
  2313. if ( !m_Storage.GetAlloc() ||
  2314. (((PADDRESS_CHECK_LIST)m_Storage.GetAlloc())->dwFlags & RDNS_FLAG_DODNS2IPCHECK) )
  2315. {
  2316. if ( !m_fIpResolved )
  2317. {
  2318. BOOL fSync;
  2319. BOOL St;
  2320. // get IP addr
  2321. St = AsyncAddrByHost(
  2322. (PDNSFUNCDESC)&g_Dns2Ip,
  2323. (DNSARG)this,
  2324. &m_ResolvedAddr,
  2325. &fSync,
  2326. m_pszDnsName );
  2327. if ( St )
  2328. {
  2329. if ( !fSync )
  2330. {
  2331. return;
  2332. }
  2333. fSt = (!memcmp( (LPBYTE)(&((PSOCKADDR_IN)&m_ResolvedAddr)->sin_addr),
  2334. (LPBYTE)(&((PSOCKADDR_IN)m_pAddr)->sin_addr),
  2335. SIZEOF_IP_ADDRESS ) ||
  2336. (((PSOCKADDR_IN)m_pAddr)->sin_addr.s_addr == LOCALHOST_ADDRESS)) &&
  2337. CheckName( pDns );
  2338. }
  2339. else
  2340. {
  2341. m_dwErrorResolving = ERROR_INVALID_PARAMETER;
  2342. fSt = FALSE;
  2343. }
  2344. m_fIpResolved = TRUE;
  2345. }
  2346. }
  2347. else
  2348. {
  2349. fSt = CheckName( pDns );
  2350. }
  2351. }
  2352. else
  2353. {
  2354. m_dwErrorResolving = ERROR_INVALID_PARAMETER;
  2355. }
  2356. (m_HttpReqCallback)( m_HttpReqParam, fSt );
  2357. }
  2358. VOID
  2359. ADDRESS_CHECK::AddrCheckDnsCallBack2(
  2360. BOOL fSt,
  2361. struct sockaddr*pAddr
  2362. )
  2363. /*++
  2364. Routine Description:
  2365. Callback routine from reverse DNS2 resolver
  2366. Arguments:
  2367. fSt - TRUE if reverse DNS resolver success, otherwise FALSE
  2368. pAddr - address if fSt is TRUE
  2369. Return Value:
  2370. Nothing
  2371. --*/
  2372. {
  2373. m_fIpResolved = TRUE;
  2374. memcpy( &m_ResolvedAddr, pAddr, sizeof(struct sockaddr*) );
  2375. if ( fSt )
  2376. {
  2377. fSt = (!memcmp( (LPBYTE)(&((PSOCKADDR_IN)pAddr)->sin_addr),
  2378. (LPBYTE)(&((PSOCKADDR_IN)m_pAddr)->sin_addr),
  2379. SIZEOF_IP_ADDRESS ) ||
  2380. (((PSOCKADDR_IN)m_pAddr)->sin_addr.s_addr == LOCALHOST_ADDRESS)) &&
  2381. CheckName( m_pszDnsName );
  2382. }
  2383. else
  2384. {
  2385. m_dwErrorResolving = ERROR_INVALID_PARAMETER;
  2386. }
  2387. (m_HttpReqCallback)( m_HttpReqParam, fSt );
  2388. }
  2389. VOID
  2390. ADDRESS_CHECK::AddrCheckDnsCallBack3(
  2391. BOOL fSt,
  2392. struct sockaddr*pAddr
  2393. )
  2394. /*++
  2395. Routine Description:
  2396. Callback routine from reverse DNS3 resolver
  2397. Arguments:
  2398. fSt - TRUE if reverse DNS resolver success, otherwise FALSE
  2399. pAddr - address if fSt is TRUE
  2400. Return Value:
  2401. Nothing
  2402. --*/
  2403. {
  2404. m_fIpResolved = TRUE;
  2405. memcpy( &m_ResolvedAddr, pAddr, sizeof(struct sockaddr*) );
  2406. if ( fSt )
  2407. {
  2408. fSt = !memcmp( (LPBYTE)(&((PSOCKADDR_IN)pAddr)->sin_addr),
  2409. (LPBYTE)(&((PSOCKADDR_IN)m_pAddr)->sin_addr),
  2410. SIZEOF_IP_ADDRESS ) ||
  2411. (((PSOCKADDR_IN)m_pAddr)->sin_addr.s_addr == LOCALHOST_ADDRESS);
  2412. if ( !fSt )
  2413. {
  2414. m_pszDnsName[ 0 ] = '\0';
  2415. }
  2416. }
  2417. (m_HttpReqCallbackEx)( m_HttpReqParam, fSt, m_pszDnsName );
  2418. }
  2419. VOID
  2420. ADDRESS_CHECK::ResolveDnsCallBack(
  2421. BOOL fSt,
  2422. LPSTR pDns
  2423. )
  2424. /*++
  2425. Routine Description:
  2426. Callback routine from reverse DNS resolver
  2427. Arguments:
  2428. fSt - TRUE if reverse DNS resolver success, otherwise FALSE
  2429. pDns - DNS name if fSt is TRUE
  2430. Return Value:
  2431. Nothing
  2432. --*/
  2433. {
  2434. m_fDnsResolved = TRUE;
  2435. if ( fSt )
  2436. {
  2437. strncpy( m_pszDnsName, pDns, DNS_MAX_NAME_LENGTH );
  2438. m_pszDnsName[ DNS_MAX_NAME_LENGTH ] = '\0';
  2439. if ( !m_Storage.GetAlloc() ||
  2440. (((PADDRESS_CHECK_LIST)m_Storage.GetAlloc())->dwFlags & RDNS_FLAG_DODNS2IPCHECK) )
  2441. {
  2442. if ( !m_fIpResolved )
  2443. {
  2444. BOOL fSync;
  2445. BOOL St;
  2446. // get IP addr
  2447. St = AsyncAddrByHost(
  2448. (PDNSFUNCDESC)&g_ResolveDns2Ip,
  2449. (DNSARG)this,
  2450. &m_ResolvedAddr,
  2451. &fSync,
  2452. m_pszDnsName );
  2453. if ( St )
  2454. {
  2455. if ( !fSync )
  2456. {
  2457. return;
  2458. }
  2459. fSt = (!memcmp( (LPBYTE)(&((PSOCKADDR_IN)&m_ResolvedAddr)->sin_addr),
  2460. (LPBYTE)(&((PSOCKADDR_IN)m_pAddr)->sin_addr),
  2461. SIZEOF_IP_ADDRESS ) ||
  2462. (((PSOCKADDR_IN)m_pAddr)->sin_addr.s_addr == LOCALHOST_ADDRESS)) &&
  2463. CheckName( pDns );
  2464. }
  2465. else
  2466. {
  2467. fSt = FALSE;
  2468. }
  2469. m_fIpResolved = TRUE;
  2470. }
  2471. }
  2472. }
  2473. (m_HttpReqCallbackEx)( m_HttpReqParam, fSt, pDns );
  2474. }
  2475. AC_RESULT
  2476. ADDRESS_CHECK::CheckAccess(
  2477. LPBOOL pfSync,
  2478. ADDRCHECKFUNC pFunc,
  2479. ADDRCHECKARG pArg
  2480. )
  2481. /*++
  2482. Routine Description:
  2483. Check that bound address has access to bound check list
  2484. validation can be either synchronous or asynchronous, caller
  2485. must handle both cases.
  2486. If async, caller must be prepared to handle completion notification
  2487. at any time after calling this function.
  2488. Arguments:
  2489. pfSync - updated with TRUE if validation was synchronous
  2490. ( i.e. if return value reflect validation status )
  2491. pFunc - ptr to callback routine use if asynchronous validation
  2492. pArg - argument used when calling pFunc
  2493. Return Value:
  2494. If sync, TRUE if bound address validated, otherwise FALSE
  2495. If async, TRUE if request successfully queued, otherwise FALSE
  2496. --*/
  2497. {
  2498. BOOL St;
  2499. AC_RESULT fSt = CheckAddress( m_pAddr );
  2500. if ( fSt == AC_IN_DENY_LIST || fSt == AC_IN_GRANT_LIST )
  2501. {
  2502. *pfSync = TRUE;
  2503. return fSt;
  2504. }
  2505. if ( !GetNbName( TRUE ) && !GetNbName(FALSE) )
  2506. {
  2507. *pfSync = TRUE;
  2508. return fSt;
  2509. }
  2510. if ( !m_fDnsResolved )
  2511. {
  2512. if ( m_pszDnsName == NULL )
  2513. {
  2514. m_pszDnsName = (CHAR*) LocalAlloc( LPTR, DNS_MAX_NAME_LENGTH + 1 );
  2515. if ( m_pszDnsName == NULL )
  2516. {
  2517. *pfSync = TRUE;
  2518. return AC_NOT_CHECKED;
  2519. }
  2520. }
  2521. m_HttpReqCallback = pFunc;
  2522. m_HttpReqParam = pArg;
  2523. // get DNS name
  2524. St = AsyncHostByAddr(
  2525. (PDNSFUNCDESC)&g_Ip2Dns,
  2526. (DNSARG)this,
  2527. m_pAddr,
  2528. pfSync,
  2529. m_pszDnsName,
  2530. DNS_MAX_NAME_LENGTH
  2531. );
  2532. if ( !St || !*pfSync )
  2533. {
  2534. return AC_NOT_CHECKED;
  2535. }
  2536. m_fDnsResolved = TRUE;
  2537. }
  2538. else
  2539. {
  2540. *pfSync = TRUE;
  2541. }
  2542. if ( !m_Storage.GetAlloc() ||
  2543. (((PADDRESS_CHECK_LIST)m_Storage.GetAlloc())->dwFlags & RDNS_FLAG_DODNS2IPCHECK) )
  2544. {
  2545. if ( !m_fIpResolved )
  2546. {
  2547. // get IP addr
  2548. St = AsyncAddrByHost(
  2549. (PDNSFUNCDESC)&g_Dns2Ip,
  2550. (DNSARG)this,
  2551. &m_ResolvedAddr,
  2552. pfSync,
  2553. m_pszDnsName );
  2554. if ( !St || !*pfSync )
  2555. {
  2556. return AC_NOT_CHECKED;
  2557. }
  2558. m_fIpResolved = TRUE;
  2559. }
  2560. if ( memcmp( (LPBYTE)(&((PSOCKADDR_IN)&m_ResolvedAddr)->sin_addr),
  2561. (LPBYTE)(&((PSOCKADDR_IN)m_pAddr)->sin_addr),
  2562. SIZEOF_IP_ADDRESS ) &&
  2563. (((PSOCKADDR_IN)m_pAddr)->sin_addr.s_addr != LOCALHOST_ADDRESS))
  2564. {
  2565. return AC_IN_DENY_LIST;
  2566. }
  2567. }
  2568. return CheckName( m_pszDnsName );
  2569. }
  2570. AC_RESULT
  2571. ADDRESS_CHECK::CheckIpAccess(
  2572. LPBOOL pfNeedDns
  2573. )
  2574. /*++
  2575. Routine Description:
  2576. Check that bound address has access to bound IP check list
  2577. Arguments:
  2578. pfNeedDns - updated with TRUE if DNS access check necessary
  2579. Return Value:
  2580. returns AC_RESULT
  2581. --*/
  2582. {
  2583. AC_RESULT ac = CheckAddress( m_pAddr );
  2584. if ( ac != AC_IN_DENY_LIST && ac != AC_IN_GRANT_LIST )
  2585. {
  2586. *pfNeedDns = (GetNbName( TRUE ) || GetNbName(FALSE));
  2587. }
  2588. else
  2589. {
  2590. *pfNeedDns = FALSE;
  2591. }
  2592. return ac;
  2593. }
  2594. #if 0
  2595. AC_RESULT
  2596. ADDRESS_CHECK::CheckDnsAccess(
  2597. LPBOOL pfGranted,
  2598. LPBOOL pfIsList
  2599. )
  2600. /*++
  2601. Routine Description:
  2602. Check that bound DNS name has access to bound DNS check list
  2603. Arguments:
  2604. pfGranted - updated with TRUE if access granted, otherwise FALSE
  2605. pfIsList- updated with TRUE if address found in deny/grant list
  2606. Return Value:
  2607. return TRUE if no error, otherwise FALSE
  2608. --*/
  2609. {
  2610. return CheckName( m_pszDnsName );
  2611. }
  2612. #endif
  2613. LPSTR
  2614. ADDRESS_CHECK::InitReverse(
  2615. LPSTR pR,
  2616. LPSTR pTarget,
  2617. LPBOOL pfAlloc
  2618. )
  2619. /*++
  2620. Routine Description:
  2621. Build a reversed DNS representation of supplied DNS name
  2622. Arguments:
  2623. pR - DNS name to reverse
  2624. pTarget - ptr to buffer to be used for reverse representation,
  2625. assumed to be SIZE_FAST_REVERSE_DNS byte wide
  2626. pfAlloc - updated with TRUE if memory allocation was necessary
  2627. to hold result. To be presented to TerminateReverse()
  2628. Return Value:
  2629. buffer holding reversed representation of DNS name, to be presented
  2630. to TerminateReverse()
  2631. --*/
  2632. {
  2633. UINT l = strlen( pR );
  2634. LPSTR p = pTarget;
  2635. if ( l > SIZE_FAST_REVERSE_DNS )
  2636. {
  2637. if ( (p = (LPSTR)LocalAlloc( LMEM_FIXED, l ))==NULL )
  2638. {
  2639. // BugFix: 47980, 47981, 47989 Whistler
  2640. // Prefix bug pfAlloc not being set.
  2641. // EBK 5/5/2000
  2642. *pfAlloc = FALSE;
  2643. return p;
  2644. }
  2645. *pfAlloc = TRUE;
  2646. }
  2647. else
  2648. {
  2649. *pfAlloc = FALSE;
  2650. }
  2651. // reverse pR to p
  2652. LPSTR pD;
  2653. UINT cS;
  2654. LPSTR pT = p + l;
  2655. *pT = '\0';
  2656. if ( *pR )
  2657. {
  2658. for ( ;; )
  2659. {
  2660. if ( pD = (LPSTR)memchr( pR, '.', l ) )
  2661. {
  2662. cS = DIFF(pD - pR);
  2663. }
  2664. else
  2665. {
  2666. cS = l;
  2667. }
  2668. memcpy( pT - cS, pR, cS );
  2669. if ( pR[cS++] )
  2670. {
  2671. pR += cS;
  2672. pT -= cS;
  2673. *pT = '.';
  2674. l -= cS;
  2675. }
  2676. else
  2677. {
  2678. break;
  2679. }
  2680. }
  2681. }
  2682. return p;
  2683. }
  2684. VOID
  2685. ADDRESS_CHECK::TerminateReverse(
  2686. LPSTR pAlloc,
  2687. BOOL fAlloc
  2688. )
  2689. /*++
  2690. Routine Description:
  2691. Free resources used by InitReverse
  2692. Arguments:
  2693. pAlloc - buffer holding result of InitReverse()
  2694. fAlloc - flag updated by InitReverse()
  2695. Return Value:
  2696. Nothing
  2697. --*/
  2698. {
  2699. if ( fAlloc )
  2700. {
  2701. LocalFree( pAlloc );
  2702. }
  2703. }
  2704. BOOL
  2705. ADDRESS_CHECK::CheckReversedName(
  2706. LPSTR pName
  2707. )
  2708. /*++
  2709. Routine Description:
  2710. Check if DNS name ( reversed format ) is in grant or deny list
  2711. Arguments:
  2712. pName - DNS name
  2713. Return Value:
  2714. TRUE if name is granted access, otherwise FALSE
  2715. --*/
  2716. {
  2717. CHAR achReversed[SIZE_FAST_REVERSE_DNS];
  2718. // BugFix: 117800, 117809, 117818, Whistler
  2719. // Prefix bug fAlloc not being set.
  2720. // Prefix did not like the fix to just make
  2721. // sure it was set in InitReverse, so now I
  2722. // am initializing it prior to the call. It's
  2723. // overkill, but should make prefix happy.
  2724. // EBK 5/15/2000
  2725. BOOL fAlloc = FALSE;
  2726. LPSTR pReversed;
  2727. BOOL fSt;
  2728. if ( pReversed = InitReverse( pName, achReversed, &fAlloc ) )
  2729. {
  2730. fSt = CheckReversedName( pReversed );
  2731. }
  2732. else
  2733. {
  2734. fSt = FALSE;
  2735. }
  2736. TerminateReverse( pReversed, fAlloc );
  2737. return fSt;
  2738. }
  2739. AC_RESULT
  2740. ADDRESS_CHECK::CheckName(
  2741. LPSTR pName
  2742. )
  2743. /*++
  2744. Routine Description:
  2745. Check if DNS name is in grant or deny list
  2746. Arguments:
  2747. pName - DNS name
  2748. Return Value:
  2749. TRUE if name is granted access, otherwise FALSE
  2750. --*/
  2751. {
  2752. // if name is empty, it cannot be checked
  2753. if (pName[0] == '\0')
  2754. {
  2755. return AC_NOT_CHECKED;
  2756. }
  2757. // if deny list non empty, check not in list
  2758. if ( GetNbName( FALSE ) )
  2759. {
  2760. if ( IsMatchName( FALSE, pName ) )
  2761. {
  2762. return AC_IN_DENY_LIST;
  2763. }
  2764. return AC_NOT_IN_DENY_LIST;
  2765. }
  2766. // if grant list non empty, check in list
  2767. if ( GetNbName( TRUE ) )
  2768. {
  2769. if ( IsMatchName( TRUE, pName ) )
  2770. {
  2771. return AC_IN_GRANT_LIST;
  2772. }
  2773. return AC_NOT_IN_GRANT_LIST;
  2774. }
  2775. return AC_NO_LIST;
  2776. }
  2777. UINT
  2778. ADDRESS_CHECK::GetNbComponent(
  2779. LPSTR pName
  2780. )
  2781. /*++
  2782. Routine Description:
  2783. Returns number of components in DNS name
  2784. Arguments:
  2785. pName - DNS name
  2786. Return Value:
  2787. Number of components.
  2788. --*/
  2789. {
  2790. LPSTR pDot = pName;
  2791. UINT cComp;
  2792. for ( cComp = 1 ; pDot = strchr( pDot, '.') ; ++cComp )
  2793. {
  2794. ++pDot;
  2795. }
  2796. return cComp;
  2797. }
  2798. BOOL
  2799. ADDRESS_CHECK::AddReversedName(
  2800. BOOL fGrant,
  2801. LPSTR pName
  2802. )
  2803. /*++
  2804. Routine Description:
  2805. Add a name entry, reversing its DNS components
  2806. Arguments:
  2807. fGrant - TRUE to locate in grant list, FALSE for deny list
  2808. pName - ptr to DNS name
  2809. Return Value:
  2810. TRUE if success, otherwise FALSE
  2811. --*/
  2812. {
  2813. CHAR achReversed[SIZE_FAST_REVERSE_DNS];
  2814. // BugFix: 117800, 117809, 117818, Whistler
  2815. // Prefix bug fAlloc not being set.
  2816. // Prefix did not like the fix to just make
  2817. // sure it was set in InitReverse, so now I
  2818. // am initializing it prior to the call. It's
  2819. // overkill, but should make prefix happy.
  2820. // EBK 5/15/2000
  2821. BOOL fAlloc = FALSE;
  2822. LPSTR pReversed;
  2823. BOOL fSt;
  2824. if ( pReversed = InitReverse( pName, achReversed, &fAlloc ) )
  2825. {
  2826. fSt = AddName( fGrant, pReversed );
  2827. }
  2828. else
  2829. {
  2830. fSt = FALSE;
  2831. }
  2832. TerminateReverse( pReversed, fAlloc );
  2833. return fSt;
  2834. }
  2835. BOOL
  2836. ADDRESS_CHECK::AddName(
  2837. BOOL fGrant,
  2838. LPSTR pName,
  2839. DWORD dwFlags
  2840. )
  2841. /*++
  2842. Routine Description:
  2843. Add a name entry
  2844. Arguments:
  2845. fGrant - TRUE to locate in grant list, FALSE for deny list
  2846. pName - ptr to DNS name
  2847. dwFlags - flags
  2848. Return Value:
  2849. TRUE if success, otherwise FALSE
  2850. --*/
  2851. {
  2852. LPBYTE pStore = m_Storage.GetAlloc();
  2853. PADDRESS_CHECK_LIST pList;
  2854. PNAME_HEADER pHd;
  2855. UINT iL;
  2856. UINT cS = GetNbComponent( pName ) | ( dwFlags & DNSLIST_FLAG_NOSUBDOMAIN );
  2857. UINT cN = strlen( pName ) + 1;
  2858. LPBYTE pA;
  2859. LPBYTE pS;
  2860. PNAME_LIST_ENTRY pE;
  2861. UINT iS;
  2862. int cm;
  2863. if ( pStore )
  2864. {
  2865. pList = (PADDRESS_CHECK_LIST)pStore;
  2866. pHd = (PNAME_HEADER)MAKEPTR( pStore, fGrant ? pList->iGrantName : pList->iDenyName);
  2867. pE = (PNAME_LIST_ENTRY)((LPBYTE)pHd + sizeof(NAME_HEADER));
  2868. for ( iL = 0 ; iL < pHd->cEntries ; ++iL )
  2869. {
  2870. if ( pE->cComponents == cS )
  2871. {
  2872. // found matching family, mask
  2873. // find where to insert
  2874. DWORD i;
  2875. for ( i= 0 ; i < pE->cNames ; ++i )
  2876. {
  2877. pS = MAKEPTR(pStore, pE->iName[i] );
  2878. if ( !(cm = _stricmp( pName, (LPSTR)pS )) )
  2879. {
  2880. // already exist
  2881. return FALSE;
  2882. }
  2883. else if ( cm < 0 )
  2884. {
  2885. // insert @ i
  2886. insert_name:
  2887. UINT s = m_Storage.GetUsed();
  2888. iS = DIFF((LPBYTE)pE - pStore);
  2889. if ( m_Storage.Resize( sizeof(SELFREFINDEX)+cN ) )
  2890. {
  2891. int l;
  2892. // refresh ptrs
  2893. pStore = m_Storage.GetAlloc();
  2894. pList = (PADDRESS_CHECK_LIST)pStore;
  2895. pHd = (PNAME_HEADER)MAKEPTR( pStore, fGrant ? pList->iGrantName : pList->iDenyName);
  2896. pE = (PNAME_LIST_ENTRY)(pStore+iS);
  2897. pS = MAKEPTR(pStore, l=DIFF((LPBYTE)(pE->iName+i)-pStore) );
  2898. memmove( pS+sizeof(SELFREFINDEX), pS, s-l );
  2899. pList->cRefSize += sizeof(SELFREFINDEX);
  2900. AdjustRefs( pStore, l, sizeof(SELFREFINDEX) );
  2901. s+=sizeof(SELFREFINDEX);
  2902. pE->iName[i] = MAKEREF(s);
  2903. memcpy( MAKEPTR(pStore,s), pName, cN );
  2904. ++pE->cNames;
  2905. ++pHd->cNames;
  2906. return TRUE;
  2907. }
  2908. return FALSE;
  2909. }
  2910. }
  2911. goto insert_name;
  2912. }
  2913. else if ( cS < pE->cComponents )
  2914. {
  2915. insert_at_current_pos:
  2916. // must insert new Entry @ pE
  2917. int i = m_Storage.GetUsed()+sizeof(NAME_LIST_ENTRY)+sizeof(SELFREFINDEX);
  2918. UINT iS = DIFF((LPBYTE)pE - pStore);
  2919. UINT cWasUsed = m_Storage.GetUsed();
  2920. if ( m_Storage.Resize( sizeof(NAME_LIST_ENTRY)+sizeof(SELFREFINDEX)+cN ) )
  2921. {
  2922. // refresh ptrs
  2923. pStore = m_Storage.GetAlloc();
  2924. pList = (PADDRESS_CHECK_LIST)pStore;
  2925. pHd = (PNAME_HEADER)MAKEPTR( pStore, fGrant ? pList->iGrantName : pList->iDenyName);
  2926. pE = (PNAME_LIST_ENTRY)(pStore +iS);
  2927. pList->cRefSize += sizeof(NAME_LIST_ENTRY)+sizeof(SELFREFINDEX);
  2928. // make room for entry
  2929. memmove( (LPBYTE)(pE+1) + sizeof(SELFREFINDEX),
  2930. pE,
  2931. cWasUsed - iS );
  2932. AdjustRefs( pStore, iS, sizeof(NAME_LIST_ENTRY)+sizeof(SELFREFINDEX) );
  2933. pE->cComponents = cS;
  2934. pE->cNames = 1;
  2935. pE->iName[0] = MAKEREF( i );
  2936. // copy name
  2937. pA = MAKEPTR( pStore, i );
  2938. memcpy( pA, pName, cN );
  2939. ++pHd->cEntries;
  2940. ++pHd->cNames;
  2941. return TRUE;
  2942. }
  2943. break;
  2944. }
  2945. pE = (PNAME_LIST_ENTRY)((LPBYTE)pE + sizeof(NAME_LIST_ENTRY) + pE->cNames * sizeof(SELFREFINDEX));
  2946. }
  2947. goto insert_at_current_pos;
  2948. }
  2949. return FALSE;
  2950. }
  2951. BOOL
  2952. ADDRESS_CHECK::DeleteName(
  2953. BOOL fGrant,
  2954. DWORD iIndex
  2955. )
  2956. /*++
  2957. Routine Description:
  2958. Delete a DNS name entry
  2959. Arguments:
  2960. fGrant - TRUE to locate in grant list, FALSE for deny list
  2961. iIndex - index in list (0-based )
  2962. Return Value:
  2963. TRUE if iIndex valid in array defined by fGrant, FALSE otherwise
  2964. --*/
  2965. {
  2966. PNAME_LIST_ENTRY pE;
  2967. PNAME_HEADER pHd;
  2968. DWORD iIndexInHeader;
  2969. LPBYTE pStore = m_Storage.GetAlloc();
  2970. if ( LocateName( fGrant, iIndex, &pHd, &pE, &iIndexInHeader ) )
  2971. {
  2972. UINT iS = MAKEOFFSET( pE->iName[iIndexInHeader] );
  2973. LPBYTE pAddr = MAKEPTR(pStore, iS);
  2974. UINT cS = strlen( (LPSTR)pAddr ) + 1;
  2975. memmove( pAddr,
  2976. pAddr + cS,
  2977. m_Storage.GetUsed() - iS - cS );
  2978. AdjustRefs( pStore, iS, -(int)cS );
  2979. m_Storage.AdjustUsed( -(int)cS );
  2980. iS = DIFF((LPBYTE)(pE->iName+iIndexInHeader) - pStore);
  2981. memmove( pE->iName+iIndexInHeader,
  2982. pE->iName+iIndexInHeader+1,
  2983. m_Storage.GetUsed() - iS - sizeof(SELFREFINDEX) );
  2984. ((PADDRESS_CHECK_LIST)pStore)->cRefSize -= sizeof(SELFREFINDEX);
  2985. AdjustRefs( pStore, DIFF((LPBYTE)pE - pStore), (DWORD)-(int)sizeof(SELFREFINDEX) );
  2986. m_Storage.AdjustUsed( -(int)sizeof(SELFREFINDEX) );
  2987. --pE->cNames;
  2988. --pHd->cNames;
  2989. return TRUE;
  2990. }
  2991. return FALSE;
  2992. }
  2993. BOOL
  2994. ADDRESS_CHECK::GetReversedName(
  2995. BOOL fGrant,
  2996. DWORD iIndex,
  2997. LPSTR pName,
  2998. LPDWORD pdwSize
  2999. )
  3000. /*++
  3001. Routine Description:
  3002. Get DNS name in specified list
  3003. Arguments:
  3004. fGrant - TRUE to locate in grant list, FALSE for deny list
  3005. iIndex - index (0-based) in specified list
  3006. pName - ptr to buffer to be used to hold result
  3007. pdwSize - in: specify buffer max length. out: result size
  3008. ( including '\0' delimiter )
  3009. Return Value:
  3010. TRUE if iIndex valid in specified list and buffer wide enough
  3011. to hold result, FALSE otherwise ( can be ERROR_NOT_ENOUGH_MEMORY,
  3012. ERROR_INVALID_PARAMETER )
  3013. --*/
  3014. {
  3015. CHAR achReversed[SIZE_FAST_REVERSE_DNS];
  3016. // BugFix: 117800, 117809, 117818, Whistler
  3017. // Prefix bug fAlloc not being set.
  3018. // Prefix did not like the fix to just make
  3019. // sure it was set in InitReverse, so now I
  3020. // am initializing it prior to the call. It's
  3021. // overkill, but should make prefix happy.
  3022. // EBK 5/15/2000
  3023. BOOL fAlloc = FALSE;
  3024. LPSTR pReversed;
  3025. BOOL fSt = FALSE;
  3026. LPSTR pRName;
  3027. if ( GetName( fGrant, iIndex, &pRName ) )
  3028. {
  3029. if ( pReversed = InitReverse( pRName, achReversed, &fAlloc ) )
  3030. {
  3031. UINT l = strlen( pReversed ) + 1;
  3032. if ( l <= *pdwSize )
  3033. {
  3034. memcpy( pName, pReversed, l );
  3035. fSt = TRUE;
  3036. }
  3037. else
  3038. {
  3039. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  3040. }
  3041. *pdwSize = l;
  3042. }
  3043. else
  3044. {
  3045. SetLastError( 0 );
  3046. *pdwSize = 0;
  3047. }
  3048. TerminateReverse( pReversed, fAlloc );
  3049. }
  3050. else
  3051. {
  3052. SetLastError( ERROR_INVALID_PARAMETER );
  3053. *pdwSize = 0;
  3054. }
  3055. return fSt;
  3056. }
  3057. BOOL
  3058. ADDRESS_CHECK::GetName(
  3059. BOOL fGrant,
  3060. DWORD iIndex,
  3061. LPSTR* ppName,
  3062. LPDWORD pdwFlags
  3063. )
  3064. /*++
  3065. Routine Description:
  3066. Get DNS name in specified list
  3067. Arguments:
  3068. fGrant - TRUE to locate in grant list, FALSE for deny list
  3069. iIndex - index (0-based) in specified list
  3070. ppName - updated with ptr to DNS name
  3071. pdwFlags - updated with DNS flags, can be NULL
  3072. Return Value:
  3073. TRUE if iIndex valid in specified list, otherwise FALSE
  3074. --*/
  3075. {
  3076. PNAME_LIST_ENTRY pHeader;
  3077. PNAME_HEADER pHd;
  3078. DWORD iIndexInHeader;
  3079. LPBYTE pStore = m_Storage.GetAlloc();
  3080. if ( LocateName( fGrant, iIndex, &pHd, &pHeader, &iIndexInHeader ) )
  3081. {
  3082. *ppName = (LPSTR)MAKEPTR(pStore, pHeader->iName[iIndexInHeader] );
  3083. if ( pdwFlags )
  3084. {
  3085. *pdwFlags = pHeader->cComponents & DNSLIST_FLAGS;
  3086. }
  3087. return TRUE;
  3088. }
  3089. return FALSE;
  3090. }
  3091. DWORD
  3092. ADDRESS_CHECK::GetNbName(
  3093. BOOL fGrant
  3094. )
  3095. /*++
  3096. Routine Description:
  3097. Get number of entries in list
  3098. Arguments:
  3099. fGrant - TRUE to locate in grant list, FALSE for deny list
  3100. Return Value:
  3101. Number of entries in list
  3102. --*/
  3103. {
  3104. LPBYTE pStore = m_Storage.GetAlloc();
  3105. PADDRESS_CHECK_LIST pList;
  3106. PNAME_HEADER pHd;
  3107. if ( pStore )
  3108. {
  3109. pList = (PADDRESS_CHECK_LIST)pStore;
  3110. pHd = (PNAME_HEADER)MAKEPTR( pStore, fGrant ? pList->iGrantName : pList->iDenyName);
  3111. return pHd->cNames;
  3112. }
  3113. return 0;
  3114. }
  3115. BOOL
  3116. ADDRESS_CHECK::LocateName(
  3117. BOOL fGrant,
  3118. DWORD iIndex,
  3119. PNAME_HEADER* ppHd,
  3120. PNAME_LIST_ENTRY* pHeader,
  3121. LPDWORD piIndexInHeader
  3122. )
  3123. /*++
  3124. Routine Description:
  3125. Locate a name in the specified list, returns ptr
  3126. to header & element in address list
  3127. Arguments:
  3128. fGrant - TRUE to locate in grant list, FALSE for deny list
  3129. iIndex - index in list ( 0-based )
  3130. ppHd - updated with ptr to name header
  3131. pHeader - updated with ptr to name list entry
  3132. piIndexInHeader - updated with index in array pHeader->iName
  3133. Return Value:
  3134. TRUE if iIndex valid in array defined by fGrant, FALSE otherwise
  3135. --*/
  3136. {
  3137. LPBYTE pStore = m_Storage.GetAlloc();
  3138. PADDRESS_CHECK_LIST pList;
  3139. PNAME_HEADER pHd;
  3140. PNAME_LIST_ENTRY pE;
  3141. UINT iL;
  3142. if ( pStore )
  3143. {
  3144. pList = (PADDRESS_CHECK_LIST)pStore;
  3145. *ppHd = pHd = (PNAME_HEADER)MAKEPTR( pStore, fGrant ? pList->iGrantName : pList->iDenyName);
  3146. pE = (PNAME_LIST_ENTRY)((LPBYTE)pHd + sizeof(NAME_HEADER));
  3147. for ( iL = 0 ; iL < pHd->cEntries ; ++iL )
  3148. {
  3149. if ( iIndex < pE->cNames )
  3150. {
  3151. *pHeader = pE;
  3152. *piIndexInHeader = iIndex;
  3153. return TRUE;
  3154. }
  3155. iIndex -= pE->cNames;
  3156. pE = (PNAME_LIST_ENTRY)((LPBYTE)pE + sizeof(NAME_LIST_ENTRY) + pE->cNames * sizeof(SELFREFINDEX));
  3157. }
  3158. }
  3159. return FALSE;
  3160. }
  3161. BOOL
  3162. ADDRESS_CHECK::DeleteAllName(
  3163. BOOL fGrant
  3164. )
  3165. /*++
  3166. Routine Description:
  3167. Delete all DNS name entries
  3168. Arguments:
  3169. fGrant - TRUE to delete in grant list, FALSE for deny list
  3170. Return Value:
  3171. TRUE if success, FALSE otherwise
  3172. --*/
  3173. {
  3174. while ( DeleteName( fGrant, 0 ) )
  3175. {
  3176. }
  3177. return TRUE;
  3178. }
  3179. BOOL
  3180. ADDRESS_CHECK::IsMatchName(
  3181. BOOL fGrant,
  3182. LPSTR pName
  3183. )
  3184. /*++
  3185. Routine Description:
  3186. Check if name in list
  3187. Arguments:
  3188. fGrant - TRUE to locate in grant list, FALSE for deny list
  3189. pName - ptr to DNS name
  3190. Return Value:
  3191. TRUE if name is in specified list, otherwise FALSE
  3192. --*/
  3193. {
  3194. LPBYTE pStore = m_Storage.GetAlloc();
  3195. PADDRESS_CHECK_LIST pList;
  3196. PNAME_HEADER pHd;
  3197. PNAME_LIST_ENTRY pE;
  3198. UINT iL;
  3199. UINT cS;
  3200. NAMECMPDESC ncd;
  3201. DWORD cbNameLength;
  3202. BOOL fTryAgain = FALSE;
  3203. CHAR achName[ DNS_MAX_NAME_LENGTH + 1 ];
  3204. ncd.pBase = pStore;
  3205. if ( pStore )
  3206. {
  3207. strncpy( achName, pName, DNS_MAX_NAME_LENGTH );
  3208. achName[ DNS_MAX_NAME_LENGTH ] = '\0';
  3209. cbNameLength = strlen( achName );
  3210. pName = achName;
  3211. // BugFix: 47983 Whistler
  3212. // Prefix bug pName not being valid.
  3213. // EBK 5/5/2000
  3214. DBG_ASSERT(cbNameLength >= 1);
  3215. if ( pName && pName[ cbNameLength - 1 ] == '.' )
  3216. {
  3217. // This is an FQDN (i.e. it has a period at the end).
  3218. // We need to be more careful with our handling of it, since we want
  3219. // to match against checks which didn't specify the trailing period.
  3220. fTryAgain = TRUE;
  3221. // Temporarily remove the trailing period
  3222. pName[ cbNameLength - 1 ] = '\0';
  3223. }
  3224. TryAgain:
  3225. /* INTRINSA suppress = uninitialized */
  3226. cS = GetNbComponent( pName );
  3227. pList = (PADDRESS_CHECK_LIST)pStore;
  3228. pHd = (PNAME_HEADER)MAKEPTR( pStore, fGrant ? pList->iGrantName : pList->iDenyName);
  3229. pE = (PNAME_LIST_ENTRY)((LPBYTE)pHd + sizeof(NAME_HEADER));
  3230. for ( iL = 0 ; iL < pHd->cEntries ; ++iL )
  3231. {
  3232. UINT cASComp = pE->cComponents & ~DNSLIST_FLAGS;
  3233. if ( cS == cASComp ||
  3234. ((cS > cASComp) && !(pE->cComponents & DNSLIST_FLAG_NOSUBDOMAIN)) )
  3235. {
  3236. LPSTR p = pName;
  3237. BOOL fSt;
  3238. if ( cS > cASComp )
  3239. {
  3240. int i = cS - cASComp;
  3241. for ( ; i-- ; )
  3242. {
  3243. if ( p = strchr( p, '.' ) )
  3244. {
  3245. ++p;
  3246. }
  3247. }
  3248. }
  3249. ncd.pName = (LPVOID)p;
  3250. fSt = BsearchEx( p,
  3251. pE->iName,
  3252. pE->cNames,
  3253. sizeof(SELFREFINDEX),
  3254. (CMPFUNC)NameCmp,
  3255. &ncd ) != NULL;
  3256. if ( fSt )
  3257. {
  3258. return TRUE;
  3259. }
  3260. }
  3261. pE = (PNAME_LIST_ENTRY)((LPBYTE)pE + sizeof(NAME_LIST_ENTRY) + pE->cNames * sizeof(SELFREFINDEX));
  3262. }
  3263. if ( fTryAgain )
  3264. {
  3265. fTryAgain = FALSE;
  3266. pName[ cbNameLength - 1 ] = '.';
  3267. goto TryAgain;
  3268. }
  3269. }
  3270. return FALSE;
  3271. }
  3272. #if 0 // inlined now
  3273. BOOL
  3274. ADDRESS_CHECK::BindAddr(
  3275. struct sockaddr* pAddr
  3276. )
  3277. /*++
  3278. Routine Description:
  3279. Bind an address to an ADDRESS_CHECK object
  3280. Arguments:
  3281. pAddr - ptr to address
  3282. Return Value:
  3283. TRUE if sucess, FALSE otherwise
  3284. --*/
  3285. {
  3286. m_pAddr = pAddr;
  3287. m_fDnsResolved = FALSE;
  3288. m_fIpResolved = FALSE;
  3289. m_dwErrorResolving = 0;
  3290. return TRUE;
  3291. }
  3292. VOID
  3293. ADDRESS_CHECK::UnbindAddr(
  3294. VOID
  3295. )
  3296. /*++
  3297. Routine Description:
  3298. Unbind an address to an ADDRESS_CHECK object
  3299. Arguments:
  3300. None
  3301. Return Value:
  3302. Nothing
  3303. --*/
  3304. {
  3305. m_pAddr = NULL;
  3306. m_fDnsResolved = FALSE;
  3307. }
  3308. # endif // 0
  3309. BOOL
  3310. ADDRESS_CHECK::QueryDnsName(
  3311. LPBOOL pfSync,
  3312. ADDRCHECKFUNCEX pFunc,
  3313. ADDRCHECKARG pArg,
  3314. LPSTR * ppName
  3315. )
  3316. /*++
  3317. Routine Description:
  3318. Reverse resolve bound address to DNS name
  3319. Arguments:
  3320. pfSync - updated with TRUE if validation was synchronous
  3321. ( i.e. if return value reflect validation status )
  3322. pFunc - ptr to callback routine use if asynchronous validation
  3323. pArg - argument used when calling pFunc
  3324. Return Value:
  3325. If sync, TRUE if bound address validated, otherwise FALSE
  3326. If async, TRUE if request successfully queued, otherwise FALSE
  3327. --*/
  3328. {
  3329. BOOL fSt;
  3330. if ( !m_pAddr )
  3331. {
  3332. return FALSE;
  3333. }
  3334. if ( !m_fDnsResolved )
  3335. {
  3336. if ( m_pszDnsName == NULL )
  3337. {
  3338. m_pszDnsName = (CHAR*) LocalAlloc( LPTR, DNS_MAX_NAME_LENGTH + 1 );
  3339. if ( m_pszDnsName == NULL )
  3340. {
  3341. return FALSE;
  3342. }
  3343. }
  3344. m_HttpReqCallbackEx = pFunc;
  3345. m_HttpReqParam = pArg;
  3346. // get DNS name
  3347. fSt = AsyncHostByAddr(
  3348. (PDNSFUNCDESC)(pFunc ? &g_ResolveDns : NULL),
  3349. (DNSARG)this,
  3350. m_pAddr,
  3351. pfSync,
  3352. m_pszDnsName,
  3353. DNS_MAX_NAME_LENGTH
  3354. );
  3355. if ( !fSt || !*pfSync )
  3356. {
  3357. return fSt;
  3358. }
  3359. m_fDnsResolved = TRUE;
  3360. if ( m_pszDnsName[ 0 ] == '\0' )
  3361. {
  3362. m_dwErrorResolving = ERROR_INVALID_PARAMETER;
  3363. return FALSE;
  3364. }
  3365. }
  3366. else
  3367. {
  3368. *pfSync = TRUE;
  3369. }
  3370. if ( !m_Storage.GetAlloc() ||
  3371. (((PADDRESS_CHECK_LIST)m_Storage.GetAlloc())->dwFlags & RDNS_FLAG_DODNS2IPCHECK) )
  3372. {
  3373. if ( !m_fIpResolved )
  3374. {
  3375. m_HttpReqCallbackEx = pFunc;
  3376. m_HttpReqParam = pArg;
  3377. // get IP addr
  3378. fSt = AsyncAddrByHost(
  3379. (PDNSFUNCDESC)(pFunc ? &g_ResolveDns2Ip : NULL),
  3380. (DNSARG)this,
  3381. &m_ResolvedAddr,
  3382. pfSync,
  3383. m_pszDnsName );
  3384. if ( !fSt || !*pfSync )
  3385. {
  3386. return fSt;
  3387. }
  3388. m_fIpResolved = TRUE;
  3389. if ( !memcmp( (LPBYTE)(&((PSOCKADDR_IN)&m_ResolvedAddr)->sin_addr),
  3390. (LPBYTE)NULL_IP_ADDR,
  3391. SIZEOF_IP_ADDRESS ) )
  3392. {
  3393. m_dwErrorResolving = ERROR_INVALID_PARAMETER;
  3394. return FALSE;
  3395. }
  3396. }
  3397. if ( memcmp( (LPBYTE)(&((PSOCKADDR_IN)&m_ResolvedAddr)->sin_addr),
  3398. (LPBYTE)(&((PSOCKADDR_IN)m_pAddr)->sin_addr),
  3399. SIZEOF_IP_ADDRESS ) &&
  3400. (((PSOCKADDR_IN)m_pAddr)->sin_addr.s_addr != LOCALHOST_ADDRESS ) )
  3401. {
  3402. m_pszDnsName[ 0 ] = '\0';
  3403. return FALSE;
  3404. }
  3405. }
  3406. *ppName = m_pszDnsName;
  3407. return TRUE;
  3408. }
  3409. BOOL
  3410. CSidCache::Init(
  3411. VOID
  3412. )
  3413. /*++
  3414. Routine Description:
  3415. Initialize SID cache object
  3416. Arguments:
  3417. None
  3418. Return Value:
  3419. TRUE if success, FALSE otherwise
  3420. --*/
  3421. {
  3422. INITIALIZE_CRITICAL_SECTION( &csLock );
  3423. return TRUE;
  3424. }
  3425. VOID
  3426. CSidCache::Terminate(
  3427. VOID
  3428. )
  3429. /*++
  3430. Routine Description:
  3431. Terminate SID cache object
  3432. Arguments:
  3433. None
  3434. Return Value:
  3435. Nothing
  3436. --*/
  3437. {
  3438. DeleteCriticalSection( &csLock );
  3439. }
  3440. BOOL
  3441. CSidCache::AddToCache(
  3442. PSID pSid,
  3443. DWORD dwTTL
  3444. )
  3445. /*++
  3446. Routine Description:
  3447. Add SID entry to cache
  3448. Arguments:
  3449. pSid - SID to add to cache
  3450. dwTTL - Time to Live ( in seconds ) in cache
  3451. Return Value:
  3452. TRUE if success, FALSE otherwise
  3453. --*/
  3454. {
  3455. BOOL fSt = TRUE;
  3456. EnterCriticalSection( &csLock );
  3457. if ( !IsInCache( pSid ) )
  3458. {
  3459. DWORD dwL = GetLengthSid( pSid );
  3460. DWORD dwWas = xaStore.GetUsed();
  3461. if ( xaStore.Resize( sizeof(SID_CACHE_ENTRY) + dwL ) )
  3462. {
  3463. PSID_CACHE_ENTRY pB = (PSID_CACHE_ENTRY)(xaStore.GetAlloc()
  3464. + dwWas );
  3465. pB->tExpire = (DWORD)(time(NULL) + dwTTL);
  3466. pB->dwSidLen = dwL;
  3467. memcpy( pB->Sid, pSid, dwL );
  3468. }
  3469. else
  3470. {
  3471. fSt = FALSE;
  3472. }
  3473. }
  3474. LeaveCriticalSection( &csLock );
  3475. return fSt;
  3476. }
  3477. BOOL
  3478. CSidCache::IsInCache(
  3479. PSID pSid
  3480. )
  3481. /*++
  3482. Routine Description:
  3483. Check if SID present and in cache
  3484. Arguments:
  3485. pSid - SID to add to cache
  3486. Return Value:
  3487. TRUE if found, FALSE otherwise
  3488. --*/
  3489. {
  3490. return CheckPresentAndResetTtl( pSid, 0xffffffff );
  3491. }
  3492. BOOL
  3493. CSidCache::CheckPresentAndResetTtl(
  3494. PSID pSid,
  3495. DWORD dwTtl
  3496. )
  3497. /*++
  3498. Routine Description:
  3499. Check if SID present and in cache and if found
  3500. update its TTL
  3501. Arguments:
  3502. pSid - SID to add to cache
  3503. dwTTL - Time to Live ( in seconds ) in cache
  3504. Return Value:
  3505. TRUE if found, FALSE otherwise
  3506. --*/
  3507. {
  3508. // walk through xaStore,
  3509. BOOL fSt = FALSE;
  3510. EnterCriticalSection( &csLock );
  3511. PSID_CACHE_ENTRY pB = (PSID_CACHE_ENTRY)(xaStore.GetAlloc() );
  3512. PSID_CACHE_ENTRY pM = (PSID_CACHE_ENTRY)(xaStore.GetAlloc()
  3513. + xaStore.GetUsed());
  3514. if ( pB )
  3515. {
  3516. while ( pB < pM )
  3517. {
  3518. if ( EqualSid( (PSID)(pB->Sid), pSid ) )
  3519. {
  3520. if ( dwTtl != 0xffffffff )
  3521. {
  3522. pB->tExpire = (DWORD)(time(NULL) + dwTtl);
  3523. }
  3524. fSt = TRUE;
  3525. break;
  3526. }
  3527. pB = (PSID_CACHE_ENTRY)( (LPBYTE)pB + pB->dwSidLen + sizeof(SID_CACHE_ENTRY) );
  3528. }
  3529. }
  3530. LeaveCriticalSection( &csLock );
  3531. return fSt;
  3532. }
  3533. BOOL
  3534. CSidCache::Scavenger(
  3535. VOID
  3536. )
  3537. /*++
  3538. Routine Description:
  3539. Remove expired entries from cache based on TTL
  3540. Arguments:
  3541. None
  3542. Return Value:
  3543. TRUE if no error, FALSE otherwise
  3544. --*/
  3545. {
  3546. // walk through xaStore,
  3547. BOOL fSt = TRUE;
  3548. EnterCriticalSection( &csLock );
  3549. PSID_CACHE_ENTRY pB = (PSID_CACHE_ENTRY)(xaStore.GetAlloc() );
  3550. PSID_CACHE_ENTRY pM = (PSID_CACHE_ENTRY)(xaStore.GetAlloc()
  3551. + xaStore.GetUsed());
  3552. DWORD tNow = (DWORD)(time(NULL));
  3553. DWORD dwAdj = 0;
  3554. if ( pB )
  3555. {
  3556. while ( pB < pM )
  3557. {
  3558. DWORD dwL = pB->dwSidLen+sizeof(SID_CACHE_ENTRY);
  3559. if ( pB->tExpire <= tNow )
  3560. {
  3561. dwAdj += dwL;
  3562. }
  3563. else if ( dwAdj )
  3564. {
  3565. memmove( (LPBYTE)pB-dwAdj,
  3566. pB,
  3567. dwL );
  3568. }
  3569. pB = (PSID_CACHE_ENTRY)( (LPBYTE)pB + dwL );
  3570. }
  3571. xaStore.AdjustUsed( -(int)dwAdj );
  3572. }
  3573. LeaveCriticalSection( &csLock );
  3574. return fSt;
  3575. }
  3576. #if DBG
  3577. VOID
  3578. ADDRESS_CHECK::DumpAddr(
  3579. BOOL fGrant
  3580. )
  3581. {
  3582. UINT i = GetNbAddr( fGrant );
  3583. UINT x;
  3584. for ( x = 0 ; x < i ; ++x )
  3585. {
  3586. LPBYTE pM;
  3587. LPBYTE pA;
  3588. DWORD dwF;
  3589. GetAddr( fGrant, x, &dwF, &pM, &pA );
  3590. CHAR achE[80];
  3591. wsprintf( achE, "%d.%d.%d.%d %d.%d.%d.%d\r\n",
  3592. pM[0], pM[1], pM[2], pM[3],
  3593. pA[0], pA[1], pA[2], pA[3] );
  3594. OutputDebugString( achE );
  3595. }
  3596. }
  3597. VOID
  3598. ADDRESS_CHECK::DumpName(
  3599. BOOL fGrant
  3600. )
  3601. {
  3602. UINT i = GetNbName( fGrant );
  3603. UINT x;
  3604. for ( x = 0 ; x < i ; ++x )
  3605. {
  3606. //CHAR achN[80];
  3607. //DWORD dwN = sizeof(achN);
  3608. LPSTR pN;
  3609. GetName( fGrant, x, &pN ); //achN, &dwN );
  3610. OutputDebugString( pN );
  3611. OutputDebugString( "\r\n" );
  3612. }
  3613. }
  3614. VOID
  3615. ADDRESS_CHECK::DumpAddrAndName(
  3616. VOID
  3617. )
  3618. {
  3619. OutputDebugString( "Addr granted:\r\n" );
  3620. DumpAddr( TRUE );
  3621. OutputDebugString( "Addr denied:\r\n" );
  3622. DumpAddr( FALSE );
  3623. OutputDebugString( "Name granted:\r\n" );
  3624. DumpName( TRUE );
  3625. OutputDebugString( "Name denied:\r\n" );
  3626. DumpName( FALSE );
  3627. }
  3628. void CaBack( ADDRCHECKARG pArg, BOOL f )
  3629. {
  3630. CHAR achE[80];
  3631. wsprintf( achE, "pArg=%08x, BOOL = %d\r\n", pArg, f );
  3632. OutputDebugString( achE );
  3633. }
  3634. VOID TestAPI()
  3635. {
  3636. ADDRESS_CHECK *pac=new ADDRESS_CHECK;
  3637. pac->BindCheckList();
  3638. pac->AddAddr( TRUE, AF_INET, (LPBYTE)"\xff\xff\x0\x0", (LPBYTE)"\x55\x66\x77\x88" );
  3639. pac->AddAddr( TRUE, AF_INET, (LPBYTE)"\xff\xff\x0\x0", (LPBYTE)"\x44\x66\x77\x88" );
  3640. pac->AddAddr( TRUE, AF_INET, (LPBYTE)"\xff\xff\x0\x0", (LPBYTE)"\x55\x77\x77\x88" );
  3641. pac->AddAddr( TRUE, AF_INET, (LPBYTE)"\xff\xff\x0\x0", (LPBYTE)"\x55\x66\x77\x88" ); // should fail
  3642. pac->AddAddr( TRUE, AF_INET, (LPBYTE)"\xff\x00\x0\x0", (LPBYTE)"\x55\x66\x77\x88" );
  3643. pac->AddAddr( TRUE, AF_INET, (LPBYTE)"\xff\xff\xff\x0",(LPBYTE)"\x55\x66\x77\x88" );
  3644. UINT i = pac->GetNbAddr( TRUE );
  3645. UINT x;
  3646. for ( x = 0 ; x < i ; ++x )
  3647. {
  3648. LPBYTE pM;
  3649. LPBYTE pA;
  3650. DWORD dwF;
  3651. pac->GetAddr( TRUE, x, &dwF, &pM, &pA );
  3652. }
  3653. pac->DeleteAddr( TRUE, 1 );
  3654. pac->DeleteAddr( TRUE, 1 );
  3655. pac->DeleteAddr( TRUE, 1 );
  3656. pac->DeleteAddr( TRUE, 1 );
  3657. pac->DeleteAddr( TRUE, 1 ); // should fail
  3658. pac->DeleteAddr( TRUE, 0 );
  3659. pac->DeleteAddr( TRUE, 0 ); // should fail
  3660. // names
  3661. pac->AddName( TRUE, "msft.com" );
  3662. pac->AddName( TRUE, "msft.com" ); // should fail
  3663. pac->AddName( TRUE, "fr" );
  3664. pac->AddName( TRUE, "www.sunw.com" );
  3665. pac->AddName( TRUE, "ftp.sunw.com" );
  3666. pac->AddName( TRUE, "aapl.com" );
  3667. i = pac->GetNbName( TRUE );
  3668. x;
  3669. for ( x = 0 ; x < i ; ++x )
  3670. {
  3671. //CHAR achN[80];
  3672. //DWORD dwN = sizeof(achN);
  3673. LPSTR pN;
  3674. pac->GetName( TRUE, x, &pN ); //achN, &dwN );
  3675. }
  3676. pac->CheckName( "msft.com" );
  3677. sockaddr* psa = new sockaddr;
  3678. BOOL fInList;
  3679. psa->sa_family = AF_INET;
  3680. memcpy( (&((PSOCKADDR_IN)psa)->sin_addr), "\x44\x66\xaa\xbb", SIZEOF_IP_ADDRESS );
  3681. pac->CheckAddress( psa );
  3682. BOOL fSync;
  3683. psa->sa_family = AF_INET;
  3684. memcpy( (&((PSOCKADDR_IN)psa)->sin_addr), "\x9d\x37\x53\x48", SIZEOF_IP_ADDRESS ); // PHILLICH3
  3685. pac->BindAddr( psa );
  3686. pac->CheckAccess( &fSync, (ADDRCHECKFUNC)CaBack, (ADDRCHECKARG)NULL );
  3687. // pac->DeleteName( TRUE, 1 );
  3688. // pac->DeleteName( TRUE, 1 );
  3689. // pac->DeleteName( TRUE, 1 );
  3690. // pac->DeleteName( TRUE, 1 );
  3691. // pac->DeleteName( TRUE, 1 ); // should fail
  3692. // pac->DeleteName( TRUE, 0 );
  3693. // pac->DeleteName( TRUE, 0 ); // should fail
  3694. }
  3695. #endif