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.

518 lines
14 KiB

  1. #+---------------------------------------------------------------------------
  2. #
  3. # Microsoft Windows
  4. # Copyright (C) Microsoft Corporation, 1998.
  5. #
  6. # File: C H K A F . P L
  7. #
  8. # Contents: Perl script to check the networking portion of
  9. # an answerfile.
  10. #
  11. # Notes:
  12. #
  13. # Author: kumarp 21-August-98
  14. #
  15. #----------------------------------------------------------------------------
  16. #----------------------------------------------------------------------------
  17. # Known issues:
  18. # - None at present
  19. #
  20. # Future enhancements:
  21. # - check if the value assigned to all known keys are valid. this can
  22. # be done by having a hash having {<key> => <regex-to-check>} pairs
  23. # for each key to check.
  24. # e.g. { 'DHCP' => 'yes|no' }
  25. # - check syntax of entries in the [NetBindings] section.
  26. # - check for empty values that will cause winnt32 to croak
  27. # e.g. key=
  28. #----------------------------------------------------------------------------
  29. #use strict;
  30. #----------------------------------------------------------------------------
  31. # Open the answerfile and read in all sections and their contents
  32. # into a hash so that further processing is easier
  33. #
  34. my %inf;
  35. my $CurrentSection="";
  36. my $CurrentFile=$ARGV[0];
  37. open(AFILE, "<$CurrentFile") || die "Cannot open $ARGV[0]: $!";
  38. while (<AFILE>)
  39. {
  40. next if (/^\s*;/);
  41. if (/^\s*\[([^\]]+)\]/)
  42. {
  43. $CurrentSection=$1;
  44. store_key($CurrentSection, "", "");
  45. }
  46. elsif (/\"?([a-zA-Z0-9_\.]+)\"?\s*=\s*([^\n]*)/)
  47. {
  48. my ($key, $value);
  49. my @value_items;
  50. if ($CurrentSection eq "")
  51. {
  52. die "Keys outside a section?";
  53. }
  54. $key = $1;
  55. @value_items = strip_quotes(split(/,/, $2));
  56. $value = join(",", @value_items);
  57. store_key($CurrentSection, $key, $value);
  58. }
  59. }
  60. close(AFILE);
  61. # ----------------------------------------------------------------------
  62. # Must have [Networking] section
  63. #
  64. if (! exists($inf{'Networking'}))
  65. {
  66. show_error('', '', "[Networking] section is missing!");
  67. }
  68. # ----------------------------------------------------------------------
  69. # Atleast one of the following sections needs to be present
  70. # [NetAdapters], [NetProtocols], [NetClients], [NetServices]
  71. #
  72. if (!(exists($inf{'NetAdapters'}) ||
  73. exists($inf{'NetProtocols'}) ||
  74. exists($inf{'NetClients'}) ||
  75. exists($inf{'NetServices'})) &&
  76. !exists($inf{'Networking'}{lc('InstallDefaultComponents')}))
  77. {
  78. show_error("", "", "None of the following sections are present, are you sure this is an answerfile ?\n--> [NetAdapters], [NetProtocols], [NetClients], [NetServices]");
  79. }
  80. # ----------------------------------------------------------------------
  81. # the following keywords are obsolete in an adapter params section
  82. #
  83. my @obsolete_keywords_adapter =
  84. ('detect');
  85. # ----------------------------------------------------------------------
  86. # - Must use InfId key in each adapter-params section
  87. # - '*' can be used if only one adapter is specified
  88. #
  89. my $adapter;
  90. foreach $adapter (keys %{$inf{'NetAdapters'}})
  91. {
  92. my $params_section;
  93. next if ($adapter eq "");
  94. $params_section = $inf{'NetAdapters'}{$adapter};
  95. if (!defined($inf{$params_section}{'infid'}))
  96. {
  97. show_error($params_section, "", "Adapter parameters section must have InfId");
  98. }
  99. else
  100. {
  101. if (($inf{$params_section}{'infid'} eq '*') &&
  102. (keys %{$inf{'NetAdapters'}} > 2))
  103. {
  104. show_error($params_section, 'InfId', "When you have more than one net cards, you cannot use '*' as value of InfId");
  105. }
  106. }
  107. check_for_obsolete_keys($params_section, \@obsolete_keywords_adapter);
  108. }
  109. # ----------------------------------------------------------------------
  110. # - adapter pointed to by SpecificTo key must exist in [NetAdapters] section
  111. # - all sections pointed to by AdapterSections must exist
  112. # - each section that has a SpecificTo key must be referenced by
  113. # AdapterSections key
  114. #
  115. my $section;
  116. foreach $section (keys %inf)
  117. {
  118. if (exists($inf{$section}{'specificto'}))
  119. {
  120. my $adapter;
  121. $adapter = $inf{$section}{'specificto'};
  122. if (!exists($inf{'NetAdapters'}{lc($adapter)}))
  123. {
  124. show_error($section, 'SpecificTo',
  125. "$adapter is not defined in section [NetAdapters]");
  126. }
  127. my $ref_found = 0;
  128. foreach $tsection (keys %inf)
  129. {
  130. if (exists($inf{$tsection}{'adaptersections'}))
  131. {
  132. my @adapter_sections =
  133. split(/,/, $inf{$tsection}{'adaptersections'});
  134. if (is_in_list($section, \@adapter_sections))
  135. {
  136. $ref_found = 1;
  137. last;
  138. }
  139. }
  140. }
  141. if (!$ref_found)
  142. {
  143. show_error($section, '', "this section seems to hold adapter specific parameters of '$adapter', but no protocol parameters section references it using 'AdapterSections' key");
  144. }
  145. }
  146. if (exists($inf{$section}{'adaptersections'}))
  147. {
  148. my $section_list;
  149. my $adapter_section;
  150. my @adapter_sections;
  151. $section_list = $inf{$section}{'adaptersections'};
  152. @adapter_sections = split(/,/, $section_list);
  153. foreach $adapter_section (@adapter_sections)
  154. {
  155. if (!exists($inf{$adapter_section}))
  156. {
  157. show_error($section, 'AdapterSections', "section $adapter_section does not exist");
  158. }
  159. }
  160. }
  161. }
  162. # ----------------------------------------------------------------------
  163. # - when specifying [NetBindings] section, atleast the following
  164. # sections must be specified:
  165. # --> [NetAdapters], [NetProtocols]
  166. #
  167. if (exists($inf{'NetBindings'}) &&
  168. !(exists($inf{'NetAdapters'}) && exists($inf{'NetProtocols'})))
  169. {
  170. show_error('NetBindings', '', "When using this section, you should also specify atleast the following sections: [NetAdapters], [NetProtocols]");
  171. }
  172. my @obsolete_keywords_non_adapter =
  173. ('infid');
  174. # ----------------------------------------------------------------------
  175. # - make sure all components specified in [Net*] sections are
  176. # known components. if not, either it is a new component or it is a typo.
  177. #
  178. my $known_components =
  179. {
  180. 'NetProtocols' => ['', 'MS_TCPIP', 'MS_NWIPX', 'MS_PPTP', 'MS_L2TP',
  181. 'MS_DLC', 'MS_AppleTalk', 'MS_NetBEUI', 'MS_NetMon',
  182. 'MS_ATMLANE', 'MS_AtmUni', 'MS_AtmArps', 'MS_GPC'],
  183. 'NetClients' => ['', 'MS_MSClient', 'MS_NWClient'],
  184. 'NetServices' => ['', 'MS_Server', 'MS_RasCli', 'MS_RasSrv', 'MS_RasRtr']
  185. };
  186. foreach $section (keys %$known_components)
  187. {
  188. my @components = keys %{$inf{$section}};
  189. if (@components)
  190. {
  191. my @known_component_list = @{$$known_components{$section}};
  192. foreach $component (@components)
  193. {
  194. if (!is_in_list($component, \@known_component_list))
  195. {
  196. show_error($section, $component, "'$component' is not known to be valid component in section [$section]");
  197. }
  198. }
  199. }
  200. }
  201. # ----------------------------------------------------------------------
  202. # - make sure that global & adapter-specific parameters are not
  203. # specified in the wrong section
  204. # - warn about any parameters that are not known to be valid for a component
  205. #
  206. my $params =
  207. {
  208. 'MS_TCPIP' =>
  209. {
  210. 'global' => ['DNS', 'DNSSuffixSearchOrder',
  211. 'UseDomainNameDevolution', 'EnableSecurity',
  212. 'ScopeID', 'EnableLMHosts',
  213. # find out if the following are still valid
  214. 'EnableIpForwarding'],
  215. 'adapter' => ['DNSServerSearchOrder',
  216. 'WINS', 'WinsServerList',
  217. 'NetBiosOption', 'DhcpClassId', 'DNSDomain',
  218. 'DHCP', 'IPAddress', 'SubnetMask',
  219. 'DefaultGateway'],
  220. },
  221. 'MS_NWIPX' =>
  222. {
  223. 'global' => ['VirtualNetworkNumber', 'DedicatedRouter',
  224. 'EnableWANRouter',
  225. # find out if the following are still valid
  226. 'RipRoute'],
  227. 'adapter' => ['PktType', 'NetworkNumber',
  228. # find out if the following are still valid
  229. 'MaxPktSize', 'BindSap', 'EnableFuncaddr',
  230. 'SourceRouteDef', 'SourceRouteMcast', 'SourceRouting'],
  231. },
  232. 'MS_PPTP' =>
  233. {
  234. 'global' => ['NumberLineDevices'],
  235. 'adapter' => [],
  236. },
  237. 'MS_AppleTalk' =>
  238. {
  239. 'global' => ['DefaultPort', 'DesiredZone', 'EnableRouter'],
  240. 'adapter' => ['SeedingNetwork', 'ZoneList', 'DefaultZone',
  241. 'NetworkRangeLowerEnd', 'NetworkRangeUpperEnd'],
  242. },
  243. 'MS_MSClient' =>
  244. {
  245. 'global' => ['BrowseDomains', 'NameServiceNetworkAddress',
  246. 'NameServiceProtocol', 'RPCSupportForBanyan',
  247. 'Browser.Parameters', 'NetLogon.Parameters',
  248. 'LanaPath', 'LanaCode',
  249. # find out if the following are still valid
  250. 'DefaultSecurityProvider'],
  251. 'adapter' => [],
  252. },
  253. 'MS_NWClient' =>
  254. {
  255. 'global' => ['PreferredServer', 'DefaultTree',
  256. 'DefaultContext', 'LogonScript',
  257. 'NWCWorkstation.Parameters'],
  258. 'adapter' => [],
  259. },
  260. 'MS_Server' =>
  261. {
  262. 'global' => ['Optimization', 'BroadcastsToLanman2Clients',
  263. 'LanmanServer.Parameters', 'LanmanServer.Shares',
  264. 'LanmanServer.AutotunedParameters'],
  265. 'adapter' => [],
  266. },
  267. 'MS_RAS' =>
  268. {
  269. 'global' => ['ForceEncryptedPassword', 'ForceEncryptedData',
  270. 'Multilink', 'DialinProtocols',
  271. 'NetBEUIClientAccess', 'TcpIpClientAccess',
  272. 'UseDHCP', 'IpPoolStart', 'IpPoolMask',
  273. 'ClientCanRequestIPAddress', 'IPXClientAccess',
  274. 'AutomaticNetworkNumbers', 'NetworkNumberFrom',
  275. 'AssignSameNetworkNumber',
  276. 'ClientsCanRequestIpxNodeNumber'],
  277. 'adapter' => [],
  278. },
  279. };
  280. my @afile_keywords =
  281. ('', 'AdapterSections', 'SpecificTo');
  282. my $component;
  283. foreach $component (keys %$params)
  284. {
  285. my ($global_params, $adapter_params);
  286. my @adapter_params_in_global_section;
  287. my @global_params_in_adapter_sections;
  288. my ($params_section, $adapter_section);
  289. my @adapter_sections;
  290. my @adapter_and_global_params;
  291. $global_params = $$params{$component}{'global'};
  292. $adapter_params = $$params{$component}{'adapter'};
  293. @adapter_and_global_params = (@$adapter_params, @$global_params);
  294. if ($params_section = get_params_section($component))
  295. {
  296. if (@adapter_params_in_global_section =
  297. grep { exists($inf{$params_section}{lc($_)}); } @$adapter_params)
  298. {
  299. show_error($params_section, '', "this section can only have global parameters of $component. The following adapter specific parameters are incorrectly listed in this section: " . join(", ", @adapter_params_in_global_section));
  300. }
  301. if (@adapter_sections = get_adapter_sections($component))
  302. {
  303. foreach $adapter_section (@adapter_sections)
  304. {
  305. check_for_unknown_keys($component, $adapter_section,
  306. \@adapter_and_global_params,
  307. \@obsolete_keywords_non_adapter);
  308. if (@global_params_in_adapter_sections =
  309. grep { exists($inf{$adapter_section}{lc($_)}) } @$global_params)
  310. {
  311. show_error($adapter_section, '', "this section can only have adapter specific parameters of $component. The following global parameters are incorrectly listed in this section: " . join(", ", @global_params_in_adapter_sections));
  312. }
  313. }
  314. }
  315. check_for_obsolete_keys($params_section, \@obsolete_keywords_non_adapter);
  316. check_for_unknown_keys($component, $params_section,
  317. \@adapter_and_global_params,
  318. \@obsolete_keywords_non_adapter);
  319. }
  320. }
  321. sub get_params_section
  322. {
  323. my @net_sections = ('NetProtocols', 'NetServices', 'NetClients');
  324. my $component = lc($_[0]);
  325. my ($params_section, $section, $tsection);
  326. foreach $section (@net_sections)
  327. {
  328. if (exists($inf{$section}{$component}))
  329. {
  330. $tsection = $inf{$section}{$component};
  331. if (exists($inf{$tsection}))
  332. {
  333. $params_section = $tsection;
  334. }
  335. last;
  336. }
  337. }
  338. return $params_section;
  339. }
  340. sub get_adapter_sections
  341. {
  342. my $component = lc($_[0]);
  343. my $params_section;
  344. my @adapter_sections;
  345. if ($params_section = get_params_section($component))
  346. {
  347. @adapter_sections =
  348. split(/,/, $inf{$params_section}{'adaptersections'});
  349. }
  350. return @adapter_sections;
  351. }
  352. sub check_for_unknown_keys
  353. {
  354. my $component = $_[0];
  355. my $params_section = $_[1];
  356. my @valid_keys = @{$_[2]};
  357. my @ignore_keys = @{$_[3]};
  358. my @all_valid_keys = (@afile_keywords, @valid_keys);
  359. my @keys_in_section;
  360. my @unknown_keys;
  361. @keys_in_section = keys(%{$inf{$params_section}});
  362. if (@unknown_keys =
  363. grep { !is_in_list($_, \@all_valid_keys) &&
  364. !is_in_list($_, \@ignore_keys) } @keys_in_section)
  365. {
  366. show_error($params_section, '', "has the following keys that are not valid for '$component': " . join(", ", @unknown_keys));
  367. }
  368. }
  369. sub check_for_obsolete_keys
  370. {
  371. my $obsolete_keyword;
  372. my $params_section = $_[0];
  373. my @obsolete_keywords = @{$_[1]};
  374. foreach $obsolete_keyword (@obsolete_keywords)
  375. {
  376. if (exists($inf{$params_section}{$obsolete_keyword}))
  377. {
  378. show_error($params_section, $obsolete_keyword, "this keyword is now obsolete");
  379. }
  380. }
  381. }
  382. # ----------------------------------------------------------------------
  383. # helper stuff
  384. #
  385. my %inf_line_num;
  386. sub store_key
  387. {
  388. # my $section = lc($_[0]);
  389. my $section = $_[0];
  390. my $key = lc($_[1]);
  391. my $value = $_[2];
  392. # print "$.: [$section].$key = $value\n";
  393. $inf{$section}{$key} = $value;
  394. $inf_line_num{$section}{$key} = $.;
  395. }
  396. sub show_error
  397. {
  398. my $section = $_[0];
  399. my $key = lc($_[1]);
  400. my $msg = $_[2];
  401. my $line_num;
  402. if (defined($line_num = $inf_line_num{$section}{$key}))
  403. {
  404. print "$CurrentFile($line_num) : [$section]",
  405. $key ne "" ? ".$key : " : " : ", "$msg\n";
  406. }
  407. else
  408. {
  409. print "$CurrentFile : $msg\n";
  410. }
  411. }
  412. sub is_in_list
  413. {
  414. my $item = lc($_[0]);
  415. my @item_list = @{$_[1]};
  416. my $t_item;
  417. foreach $t_item (@item_list)
  418. {
  419. if (lc($t_item) eq $item)
  420. {
  421. return 1;
  422. }
  423. }
  424. return 0;
  425. }
  426. sub strip_quotes
  427. {
  428. my ($item, $b, $e);
  429. foreach $item (@_)
  430. {
  431. $b = index($item, "\"");
  432. $e = rindex($item, "\"");
  433. if (($b >= 0) && ($b != $e))
  434. {
  435. $item = substr($item, $b+1, $e-$b-1);
  436. }
  437. }
  438. @_;
  439. }
  440. # ----------------------------------------------------------------------
  441. # misc debug helper stuff
  442. #
  443. sub pl
  444. {
  445. print "Items: ", join(", ", @_), "\n";
  446. };