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.

366 lines
9.1 KiB

  1. //++
  2. //
  3. // Copyright (C) Microsoft Corporation, 1987 - 1999
  4. //
  5. // Module Name:
  6. //
  7. // domutil.c
  8. //
  9. // Abstract:
  10. //
  11. // Test to ensure that a workstation has network (IP) connectivity to
  12. // the outside.
  13. //
  14. // Author:
  15. //
  16. // 15-Dec-1997 (cliffv)
  17. // Anilth - 4-20-1998
  18. //
  19. // Environment:
  20. //
  21. // User mode only.
  22. // Contains NT-specific code.
  23. //
  24. // Revision History:
  25. //
  26. // 1-June-1998 (denisemi) add DnsServerHasDCRecords to check DC dns records
  27. // registration
  28. //
  29. // 26-June-1998 (t-rajkup) add general tcp/ip , dhcp and routing,
  30. // winsock, ipx, wins and netbt information.
  31. //--
  32. //
  33. // Common include files.
  34. //
  35. #include "precomp.h"
  36. #include "domutil.h"
  37. #include "ipcfgtest.h"
  38. /*!--------------------------------------------------------------------------
  39. AddTestedDomain
  40. Add a domain to the list of domains to test.
  41. Arguments:
  42. pswzNetbiosDomainName - Name of the domain.
  43. If pswzDnsDomainName is NULL, this can be either a netbios or dns domain name.
  44. If pswzDnsDomainName is not NULL, this must be the netbios name of the domain.
  45. pwszDnsDomainName - Another name of the domain.
  46. If specified, this must be the DNS name of the domain.
  47. PrimaryDomain - True if this is the primary domain
  48. Return Value:
  49. Returns pointer to structure describing the domain
  50. NULL: Memory allocation failure.
  51. Author: KennT
  52. ---------------------------------------------------------------------------*/
  53. PTESTED_DOMAIN
  54. AddTestedDomain(
  55. IN NETDIAG_PARAMS *pParams,
  56. IN NETDIAG_RESULT *pResults,
  57. IN LPWSTR pswzNetbiosDomainName,
  58. IN LPWSTR pswzDnsDomainName,
  59. IN BOOL bPrimaryDomain
  60. )
  61. {
  62. PTESTED_DOMAIN pTestedDomain = NULL;
  63. PLIST_ENTRY pListEntry;
  64. BOOL fIsNetbios;
  65. BOOL fIsDns;
  66. //
  67. // Determine if the passed in parameters are Netbios or DNS names
  68. //
  69. if ( pswzDnsDomainName == NULL ) {
  70. fIsDns = NetpDcValidDnsDomain( pswzNetbiosDomainName );
  71. fIsNetbios = NetpIsDomainNameValid( pswzNetbiosDomainName );
  72. // Don't allow a single name to be both netbios and dns.
  73. if ( fIsDns && fIsNetbios ) {
  74. //
  75. // If there is a period in the name,
  76. // it is a DNS name, otherwise
  77. // it is a Netbios Name
  78. //
  79. if ( wcschr( pswzNetbiosDomainName, L'.' ) != NULL ) {
  80. fIsNetbios = FALSE;
  81. } else {
  82. fIsDns = FALSE;
  83. }
  84. }
  85. if ( !fIsNetbios && !fIsDns ) {
  86. DebugMessage2("'%ws' is not a valid domain name\n\n", pswzNetbiosDomainName );
  87. return NULL;
  88. }
  89. if ( fIsDns ) {
  90. pswzDnsDomainName = pswzNetbiosDomainName;
  91. }
  92. if ( !fIsNetbios ) {
  93. pswzNetbiosDomainName = NULL;
  94. }
  95. } else {
  96. fIsNetbios = NetpIsDomainNameValid( pswzNetbiosDomainName );
  97. if ( !fIsNetbios ) {
  98. DebugMessage2("'%ws' is not a valid Netbios domain name\n\n", pswzNetbiosDomainName );
  99. return NULL;
  100. }
  101. fIsDns = NetpDcValidDnsDomain( pswzDnsDomainName );
  102. if ( !fIsDns ) {
  103. DebugMessage2("'%ws' is not a valid DNS domain name\n\n", pswzDnsDomainName );
  104. return NULL;
  105. }
  106. }
  107. //
  108. // Check if the domain is already defined.
  109. //
  110. for ( pListEntry = pResults->Global.listTestedDomains.Flink ;
  111. pListEntry != &pResults->Global.listTestedDomains ;
  112. pListEntry = pListEntry->Flink )
  113. {
  114. //
  115. // If the entry is found,
  116. // use it.
  117. //
  118. pTestedDomain = CONTAINING_RECORD( pListEntry, TESTED_DOMAIN, Next );
  119. if ( pswzNetbiosDomainName != NULL &&
  120. pTestedDomain->NetbiosDomainName != NULL &&
  121. _wcsicmp( pTestedDomain->NetbiosDomainName, pswzNetbiosDomainName ) == 0 ) {
  122. //
  123. // The netbios domain name matched.
  124. // So the DNS name must match if it exists.
  125. //
  126. if ( pswzDnsDomainName != NULL &&
  127. pTestedDomain->DnsDomainName != NULL ) {
  128. if ( !NlEqualDnsName( pTestedDomain->DnsDomainName, pswzDnsDomainName ) ) {
  129. DebugMessage3("'%ws' and '%ws' DNS domain names different\n\n", pTestedDomain->DnsDomainName, pswzDnsDomainName );
  130. return NULL;
  131. }
  132. }
  133. break;
  134. }
  135. if ( pswzDnsDomainName != NULL &&
  136. pTestedDomain->DnsDomainName != NULL &&
  137. NlEqualDnsName( pTestedDomain->DnsDomainName, pswzDnsDomainName ) ) {
  138. break;
  139. }
  140. pTestedDomain = NULL;
  141. }
  142. //
  143. // Allocate a structure to describe the domain.
  144. //
  145. if ( pTestedDomain == NULL )
  146. {
  147. pTestedDomain = Malloc( sizeof(TESTED_DOMAIN) );
  148. if ( pTestedDomain == NULL )
  149. {
  150. PrintMessage(pParams, IDS_GLOBAL_OutOfMemory);
  151. return NULL;
  152. }
  153. ZeroMemory( pTestedDomain, sizeof(TESTED_DOMAIN) );
  154. InitializeListHead( &pTestedDomain->TestedDcs );
  155. InsertTailList( &pResults->Global.listTestedDomains, &pTestedDomain->Next );
  156. }
  157. //
  158. // Update the domain name.
  159. //
  160. if ( pTestedDomain->DnsDomainName == NULL && pswzDnsDomainName != NULL ) {
  161. pTestedDomain->DnsDomainName = NetpAllocWStrFromWStr( pswzDnsDomainName );
  162. if ( pTestedDomain->DnsDomainName == NULL ) {
  163. PrintMessage( pParams, IDS_GLOBAL_OutOfMemory);
  164. return NULL;
  165. }
  166. }
  167. if ( pTestedDomain->NetbiosDomainName == NULL && pswzNetbiosDomainName != NULL ) {
  168. pTestedDomain->NetbiosDomainName = NetpAllocWStrFromWStr( pswzNetbiosDomainName );
  169. if ( pTestedDomain->NetbiosDomainName == NULL ) {
  170. PrintMessage( pParams, IDS_GLOBAL_OutOfMemory);
  171. return NULL;
  172. }
  173. }
  174. //
  175. // Fill in other fields.
  176. //
  177. if ( bPrimaryDomain ) {
  178. pTestedDomain->fPrimaryDomain = TRUE;
  179. }
  180. if ( pTestedDomain->fPrimaryDomain ) {
  181. pTestedDomain->QueryableDomainName = NULL;
  182. } else {
  183. //
  184. // The queryable domain name is the DNS domain name (if known)
  185. if ( pTestedDomain->DnsDomainName != NULL ) {
  186. pTestedDomain->QueryableDomainName = pTestedDomain->DnsDomainName;
  187. } else {
  188. pTestedDomain->QueryableDomainName = pTestedDomain->NetbiosDomainName;
  189. }
  190. }
  191. // The printable domain name is the Netbios domain name (if known)
  192. if (pTestedDomain->NetbiosDomainName != NULL ) {
  193. pTestedDomain->PrintableDomainName = pTestedDomain->NetbiosDomainName;
  194. } else {
  195. pTestedDomain->PrintableDomainName = pTestedDomain->DnsDomainName;
  196. }
  197. return pTestedDomain;
  198. }
  199. BOOL
  200. NetpDcValidDnsDomain(
  201. IN LPCWSTR DnsDomainName
  202. )
  203. /*++
  204. Routine Description:
  205. Returns whether the specified string is a valid DNS Domain name.
  206. Arguments:
  207. DnsDomainName - DNS domain name to validate.
  208. Return Value:
  209. TRUE - The specified name is syntactically a DNS Domain name.
  210. FALSE - The specified name in not syntactically a DNS Domain name.
  211. --*/
  212. {
  213. DNS_STATUS DnsStatus;
  214. DnsStatus = DnsValidateDnsName_W( DnsDomainName );
  215. if ( DnsStatus == ERROR_SUCCESS ||
  216. DnsStatus == DNS_ERROR_NON_RFC_NAME ) {
  217. return TRUE;
  218. }
  219. return FALSE;
  220. }
  221. BOOL
  222. NlEqualDnsName(
  223. IN LPCWSTR Name1,
  224. IN LPCWSTR Name2
  225. )
  226. /*++
  227. Routine Description:
  228. This routine compares two DNS names for equality.
  229. Case is ignored. A single trailing . is ignored.
  230. Null is compared equal to a zero length string.
  231. Arguments:
  232. Name1 - First DNS name to compare
  233. Name2 - Second DNS name to compare
  234. Return Value:
  235. TRUE: DNS names are equal.
  236. --*/
  237. {
  238. if ( Name1 == NULL ) {
  239. return (Name2 == NULL);
  240. } else if ( Name2 == NULL ) {
  241. return FALSE;
  242. }
  243. return DnsNameCompare_W( (LPWSTR) Name1, (LPWSTR) Name2 );
  244. }
  245. // from net\netlib\names.c
  246. BOOL
  247. NetpIsDomainNameValid(
  248. IN LPWSTR DomainName
  249. )
  250. /*++
  251. Routine Description:
  252. NetpIsDomainNameValid checks for "domain" format.
  253. The name is only checked syntactically; no attempt is made to determine
  254. whether or not a domain with that name actually exists.
  255. Arguments:
  256. DomainName - Supplies an alleged Domain name.
  257. Return Value:
  258. BOOL - TRUE if name is syntactically valid, FALSE otherwise.
  259. --*/
  260. {
  261. NET_API_STATUS ApiStatus = NO_ERROR;
  262. WCHAR CanonBuf[DNLEN+1];
  263. if (DomainName == (LPWSTR) NULL) {
  264. return (FALSE);
  265. }
  266. if ( (*DomainName) == (TCHAR)'\0' ) {
  267. return (FALSE);
  268. }
  269. ApiStatus = NetpNameCanonicalize(
  270. NULL, // no server name
  271. DomainName, // name to validate
  272. CanonBuf, // output buffer
  273. (DNLEN+1) * sizeof(WCHAR), // output buffer size
  274. NAMETYPE_DOMAIN, // type
  275. 0 ); // flags: none
  276. return (ApiStatus == NO_ERROR);
  277. } // NetpIsDomainNameValid