Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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