//+------------------------------------------------------------------------- // // // Copyright (C) 2002, Microsoft Corporation // // File: SiteInformation.cxx // // //-------------------------------------------------------------------------- #include #include #include #include #include #include #include #include #include #include "rpc.h" #include "rpcdce.h" #include #include #include #include #include #include // // Flags used in DsGetDcName() // struct _DFS_PREFIX_TABLE *_pSiteTable; DWORD DcFlags[] = { DS_DIRECTORY_SERVICE_REQUIRED | DS_IP_REQUIRED, DS_DIRECTORY_SERVICE_REQUIRED | DS_IP_REQUIRED | DS_FORCE_REDISCOVERY }; DfsString UseDcName; DFSSTATUS FindSiteInformation( PUNICODE_STRING pName, DfsString *pSite ) { NTSTATUS NtStatus; UNICODE_STRING Suffix; DfsString *pStoredSite; DFSSTATUS Status; if (_pSiteTable == NULL) { Status = ERROR_NOT_FOUND; return Status; } Status = ERROR_NOT_FOUND; NtStatus = DfsPrefixTableAcquireReadLock( _pSiteTable ); if (NtStatus == STATUS_SUCCESS) { NtStatus = DfsFindUnicodePrefixLocked( _pSiteTable, pName, &Suffix, (PVOID *)&pStoredSite, NULL ); DfsPrefixTableReleaseLock( _pSiteTable ); } if (NtStatus == STATUS_SUCCESS) { Status = pSite->CreateString(pStoredSite->GetString()); } DebugInformation((L"Find site %wZ, status %x\n", pName, Status)); return Status; } DFSSTATUS StoreSiteInformation( PUNICODE_STRING pName, DfsString *pSite ) { DfsString *pStoreSite; DFSSTATUS Status; NTSTATUS NtStatus = STATUS_SUCCESS; pStoreSite = new DfsString; if (pStoreSite == NULL) { return ERROR_NOT_ENOUGH_MEMORY; } Status = pStoreSite->CreateString(pSite->GetString()); if (Status != ERROR_SUCCESS) { return Status; } if (_pSiteTable == NULL) { NtStatus = DfsInitializePrefixTable( &_pSiteTable, FALSE, NULL ); } if (NtStatus == STATUS_SUCCESS) { NtStatus = DfsPrefixTableAcquireWriteLock( _pSiteTable); if (NtStatus == STATUS_SUCCESS) { NtStatus = DfsInsertInPrefixTableLocked( _pSiteTable, pName, (PVOID)(pStoreSite)); DfsPrefixTableReleaseLock(_pSiteTable); } } DebugInformation((L"Storing name %wZ, status %x\n", pName, NtStatus)); return RtlNtStatusToDosError(NtStatus); } DWORD GetSiteNameFromIpAddress(char * IpData, ULONG IpLength, USHORT IpFamily, LPWSTR **SiteNames) { DWORD Status = ERROR_INVALID_PARAMETER; PDOMAIN_CONTROLLER_INFO pDCInfo = NULL; PSOCKET_ADDRESS pSockAddr = NULL; PSOCKADDR_IN pSockAddrIn = NULL; struct hostent* pH = NULL; DWORD cRetry = 0; SOCKET_ADDRESS SockAddr; SOCKADDR_IN SockAddrIn; //setup the socket structures in order to call DsAddressToSiteNames pSockAddr = &SockAddr; pSockAddr->iSockaddrLength = sizeof(SOCKADDR_IN); pSockAddr->lpSockaddr = (LPSOCKADDR)&SockAddrIn; pSockAddrIn = &SockAddrIn; pSockAddrIn->sin_family = IpFamily; pSockAddrIn->sin_port = 0; RtlCopyMemory( &pSockAddrIn->sin_addr, IpData, (IpLength & 0xff)); // // Call DsGetDcName() with ever-increasing urgency, until either // we get a good DC or we just give up. // if (IsEmptyString(UseDcName.GetString()) == FALSE) { Status = DsAddressToSiteNames( UseDcName.GetString(), 1, pSockAddr, SiteNames); if (Status == ERROR_SUCCESS) { return Status; } } for (cRetry = 0; cRetry <= (sizeof(DcFlags) / sizeof(DcFlags[1])); cRetry++) { Status = DsGetDcName( NULL, // Computer to remote to NULL, // Domain - use local domain NULL, // Domain Guid NULL, // Site Guid DcFlags[cRetry], // Flags &pDCInfo); if (Status == ERROR_SUCCESS) { DebugInformation((L"Trying DC %ws with address %ws in domain %ws within forest %ws\n\n", pDCInfo->DomainControllerName, pDCInfo->DomainControllerAddress, pDCInfo->DomainName, pDCInfo->DnsForestName)); Status = DsAddressToSiteNames( pDCInfo->DomainControllerAddress, 1, pSockAddr, SiteNames); if(Status != ERROR_SUCCESS) { DebugInformation((L"DsAddressToSiteNames failed using DC %ws with error %d\n", pDCInfo->DomainControllerAddress, Status)); } if (Status == ERROR_SUCCESS) { UseDcName.CreateString(pDCInfo->DomainControllerAddress); goto Exit; } NetApiBufferFree( pDCInfo ); } else { DebugInformation((L"DsGetDcName failed with error %d\n", Status)); } } Exit: return Status; } DWORD GetSites(LPWSTR Target, DfsString *pSite ) { DWORD Status = 0; DWORD Loop = 0; struct hostent *hp = NULL; unsigned long InetAddr = 0; char * IpAddr = NULL; WSADATA wsadata; in_addr inAddrIpServer; NTSTATUS NtStatus = STATUS_SUCCESS; ANSI_STRING DestinationString; UNICODE_STRING ServerName; LPWSTR *pSiteNamesArray = NULL; Status = DfsRtlInitUnicodeStringEx(&ServerName, Target); if (Status != ERROR_SUCCESS) { return Status; } Status = FindSiteInformation( &ServerName, pSite); if (Status == ERROR_SUCCESS) { return Status; } Status = WSAStartup( MAKEWORD( 1, 1 ), &wsadata ); if (Status != ERROR_SUCCESS) { return Status; } DestinationString.Buffer = NULL; NtStatus = RtlUnicodeStringToAnsiString(&DestinationString, &ServerName, TRUE); if (NtStatus != STATUS_SUCCESS) { return RtlNtStatusToDosError(NtStatus); } // // This can be a bogus host name. So beware. // hp = gethostbyname (DestinationString.Buffer); if(hp != NULL) { for (Loop = 0; (hp->h_addr_list[Loop] != NULL); Loop++) { CopyMemory(&inAddrIpServer, hp->h_addr_list[Loop], sizeof(DWORD)); DebugInformation((L"Finding site for %wZ\n", &ServerName)); Status = GetSiteNameFromIpAddress( hp->h_addr_list[Loop], 4, AF_INET, &pSiteNamesArray ); } } else { Status = WSAGetLastError(); InetAddr = inet_addr( DestinationString.Buffer ); if((InetAddr == INADDR_NONE) || (InetAddr == 0)) { DebugInformation((L"gethostbyname for site for %wZ failed with error %d\n", &ServerName, Status)); } else { DebugInformation((L"Finding site for %wZ\n", &ServerName)); IpAddr = (char *) &InetAddr; Status = GetSiteNameFromIpAddress( IpAddr, 4, AF_INET, &pSiteNamesArray ); } } if (Status == ERROR_SUCCESS) { if ((pSiteNamesArray != NULL) && (pSiteNamesArray[0] != NULL)) { Status = pSite->CreateString(pSiteNamesArray[0]); } else { Status = pSite->CreateString(L"(No site association)"); } if (Status == ERROR_SUCCESS) { StoreSiteInformation( &ServerName, pSite); } } if (pSiteNamesArray != NULL) { NetApiBufferFree(pSiteNamesArray); } return Status; }