Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

512 lines
16 KiB

  1. @rem = '
  2. @goto endofperl
  3. ';
  4. $USAGE = "
  5. Usage: $0 datafile
  6. topchk takes the output of \"ntfrsutl ds\" and summarizes the topology.
  7. ";
  8. die $USAGE unless @ARGV;
  9. printf("\n\n");
  10. $InFile = "";
  11. $replhours = 168; # No schedule means that DS replicates every hour.
  12. $hostsite = "unknown";
  13. $hostsrv = "unknown";
  14. $fromsite = "unknown";
  15. $fromsrv = "unknown";
  16. $schedule = "none";
  17. $enable = "unknown";
  18. $cxtion = "unknown";
  19. $cxtioncnt = 1;
  20. while (<>) {
  21. if ($InFile ne $ARGV) {
  22. $InFile = $ARGV;
  23. $modtime = (stat $InFile)[9];
  24. printf("Processing file %s Modify Time: %s\n\n", $InFile, scalar localtime($modtime));
  25. $infilelist = $infilelist . " " . $InFile;
  26. }
  27. chop;
  28. ($func, @a) = split(":");
  29. if (($func eq "") || ($func =~ m/^#/)) {next;}
  30. if ($func =~ m/ DNS Name/) {printf("%s\n\n", $_); next; }
  31. if ($func =~ m/SUBSCRIBER/) {
  32. if ($subscriber ne "") {
  33. printf("%-40s Root: %-25s Stage: %s\n", substr($subscriber,3), $rootdir, $stagedir);
  34. }
  35. $subscriber = $_;
  36. next;
  37. }
  38. if ($func =~ m/ Root/) {($junk1, $junk2, $rootdir) = split; next; }
  39. if ($func =~ m/ Stage/) {($junk1, $junk2, $stagedir) = split; next; }
  40. if ($func =~ m/SETTINGS/) {
  41. if ($subscriber ne "") {
  42. printf("%-40s Root: %-25s Stage: %s\n", substr($subscriber,3), $rootdir, $stagedir);
  43. $subscriber = "";
  44. }
  45. next;
  46. }
  47. if ($func =~ m/ Type/) {($junk1, $junk2, $settype) = split; next;}
  48. if ($func =~ m/^ MEMBER/) {
  49. #
  50. # New Member object. Check for no connection objects on previous member object.
  51. # If there was a previous connection obj found then print the record.
  52. #
  53. if ($cxtioncnt eq 0) {
  54. if ($settype == 2) {
  55. push @NoConnObj, sprintf("Member: %-36s host:%20s\\%-16s", $member, $hostsite, $hostsrv);
  56. } else {
  57. push @NoConnObj, sprintf("Member: %-36s host:%-25s", $member, $hostsrv);
  58. }
  59. $memberswithnocxtion++;
  60. }
  61. elsif ($cxtion ne "unknown") {
  62. &PrintRecord();
  63. }
  64. ($junk, $member) = split;
  65. $member = uc($member) if ($settype != 2);
  66. $hostsrv = "none";
  67. $cxtioncnt = 0;
  68. next;
  69. }
  70. if ($func =~ m/^ CXTION/) {
  71. if ($cxtion ne "unknown") {&PrintRecord();}
  72. ($junk, $cxtion) = split;
  73. $cxtioncnt++;
  74. $schedule = "none";
  75. next;
  76. }
  77. if ($func =~ m/^ Enabled/) {
  78. #printf("%s\n", $_);
  79. $enable = uc($a[0]);
  80. next;
  81. }
  82. if ($func =~ m/^ Computer Ref/) {
  83. if (m/[^:]+? :\s*\(null\)/x) {
  84. push @MembersWithNullCompRef, sprintf("Member: %-36s host:%20s\\%-16s", $member, $hostsite, $hostsrv);
  85. next;
  86. }
  87. }
  88. if (($settype == 2) && ($func =~ m/Server Ref/)) {
  89. #printf("%s\n", $_);
  90. # For SYSVOL
  91. #Server Ref : CN=NTDS Settings,CN=C0010000,CN=Servers,CN=0100Site,CN=Sites,CN=Configuratio...
  92. #Server Ref : (null)
  93. #Server Ref : CN=NTDS Settings,CN=NOTEBOOK,CN=Servers,CN=Standardname-des-ersten-Standorts...
  94. #Server Ref : CN=NTDS Settings,CN=ZEUS,CN=Servers,CN=Standardname-des-ersten-Standorts,CN=...
  95. if (m/\(null\)/i) {
  96. $cxtioncnt = 1; # to suppress no connection obj message.
  97. $nontdssettings++;
  98. push @NoDsSettings, $member;
  99. next;
  100. }
  101. ($hostsrv, $hostsite, $tail) = m/cn=ntds settings,cn=(.*),cn=servers,cn=(.*?)((,)|(\.\.\.))+?/i;
  102. if (($hostsrv eq '') || ($hostsite == "")) {
  103. }
  104. next;
  105. }
  106. if (($settype != 2) && (m/Cracked Name : 0000/)) {
  107. # For non-SYSVOL
  108. #Cracked Name : 00000002 CORP\CATL1FS01$
  109. ($j1, $j2, $j3, $j4, $hostsrv) = split;
  110. $CrackedName{$member} = uc($hostsrv);
  111. next;
  112. }
  113. if ($func =~ m/Partner Dn/) {
  114. #printf("%s\n", $_);
  115. if ($settype == 2) {
  116. #
  117. # SYSVOL Replica Set.
  118. # Partner Dn : cn=ntds settings,cn=c0int01,cn=servers,cn=credit1,cn=sites,cn=config
  119. # Partner Dn : cn=ntds settings,cn=zeus,cn=servers,cn=standardname-des-ersten-standorts,cn=...
  120. #
  121. ($fromsrv, $fromsite, $tail) = m/cn=ntds settings,cn=(.*),cn=servers,cn=(.*?)((,)|(\.\.\.))+?/i;
  122. $from = $fromsite . "\\" . $fromsrv;
  123. $host = $hostsite . "\\" . $hostsrv;
  124. } else {
  125. #
  126. # Partner Dn : cn={286f0e4d-bf95-4e31-81e2-f5a7f058e075},cn=cci-dfs|softdist,cn=cci-dfs,cn=...
  127. #
  128. ($fromsrv) = m/cn=(.*?),cn/i;
  129. $fromsite = "";
  130. $from = uc($fromsrv);
  131. $host = $hostsrv;
  132. }
  133. $fromlist{uc($from)}++;
  134. $fromlistname{uc($from)} .= " $host";
  135. $hostlist{uc($host)}++;
  136. $hostlistname{uc($host)} .= " $from";
  137. next;
  138. }
  139. if ($cxtion ne "unknown") {
  140. #
  141. # Day 2: 010000000000010000000000 This is monday.
  142. #
  143. # Count the number of non-zero hours
  144. #
  145. if (m/Day .\:/) {
  146. ($junk, $daynum, $scvector) = split;
  147. if ($daynum eq "1:" ) {$replhours = 0;}
  148. if ($daynum eq "2:" ) {$schedule = lc($scvector);} # save Monday's schedule.
  149. for ($i=0; $i < 24; $i++) {
  150. if (substr($scvector, $i, 1) ne "0") {$replhours++;}
  151. }
  152. if ($daynum eq "7:") { &PrintRecord(); } # Day 7: output record.
  153. }
  154. }
  155. if (($func =~ m/^ SET/) && ($setname eq "")) {
  156. $setname = $a[0];
  157. printf("\n\n%s\n\n", $_);
  158. next;
  159. }
  160. #
  161. # If start of a new Set. Print summary info on last one.
  162. #
  163. if ($func =~ m/^ SET/) {&PrintSummary();}
  164. }
  165. &PrintSummary();
  166. exit;
  167. sub PrintRecord {
  168. my $outstr;
  169. if ($settype == 2) {
  170. $outstr = sprintf("cxtion: %-36s host:%20s\\%-16s from:%20s\\%-16s RepHrs: %3d Sched: %-24s enabled: %5s\n",
  171. $cxtion, $hostsite, $hostsrv, $fromsite, $fromsrv, $replhours, $schedule, $enable);
  172. if ($replhours == 168) {
  173. push @Repl168Hrs, sprintf("Member: %-36s cxtion: %-36s host:%20s\\%-16s", $member, $cxtion, $hostsite, $hostsrv);
  174. }
  175. if ((uc($hostsite) eq uc($fromsite)) && (uc($hostsrv) eq uc($fromsrv))) {
  176. push @CxtionsToSelf, sprintf("Member: %-36s cxtion: %-36s host:%20s\\%-16s", $member, $cxtion, $hostsite, $hostsrv);
  177. }
  178. $outhash{$outstr} = $outstr;
  179. } else {
  180. #
  181. # For DFS replica sets, save the data until we have seen all the members
  182. # so we can then translate the FromServer connection attribute to the
  183. # cracked name of the member rather than use the friggen guid.
  184. #
  185. push @ConnDetail, {cxtion=>$cxtion, hostsrv=>$hostsrv,
  186. fromsrv=>uc($fromsrv), replhours=>$replhours,
  187. schedule=>$schedule, enable=>$enable,
  188. member=>uc($member) };
  189. }
  190. #
  191. # Track the number of connections with the same Monday schedule and the same per-week repl hours.
  192. #
  193. $monsched{$schedule}++;
  194. $hoursched{$replhours}++;
  195. if ($enable =~ m/FALSE/) {$disabledcxtion++;}
  196. $cxtion = "unknown";
  197. $fromsite = "unknown";
  198. $fromsrv = "unknown";
  199. $enable = "unknown";
  200. $replhours = 168;
  201. $schedule = "none";
  202. }
  203. sub PrintSummary {
  204. if ($cxtion ne "unknown") {
  205. #
  206. # print the last connection record.
  207. #
  208. &PrintRecord();
  209. }
  210. #
  211. # For DFS replica sets transform the from reference from the friggen guid
  212. # to the cracked name of the member.
  213. #
  214. if ($settype != 2) {
  215. foreach $conn (@ConnDetail) {
  216. if (exists $CrackedName{$conn->{fromsrv}}) {
  217. $conn->{fromsrv} = $CrackedName{$conn->{fromsrv}};
  218. }
  219. $outstr = sprintf("cxtion: %-36s host: %-25s from: %-25s RepHrs: %3d Sched: %-24s enabled: %5s\n",
  220. $conn->{cxtion}, $conn->{hostsrv}, $conn->{fromsrv},
  221. $conn->{replhours}, $conn->{schedule}, $conn->{enable} );
  222. $outhash{$outstr} = $outstr;
  223. if ($conn->{replhours} == 168) {
  224. push @Repl168Hrs, sprintf("Member: %-36s cxtion: %-36s host:%-25s from: %-25s",
  225. $conn->{member}, $conn->{cxtion}, $conn->{hostsrv}, $conn->{fromsrv} );
  226. }
  227. if ( uc($conn->{hostsrv}) eq uc($conn->{fromsrv}) ) {
  228. push @CxtionsToSelf, sprintf("Member: %-36s cxtion: %-36s host:%-25s",
  229. $conn->{member}, $conn->{cxtion}, $conn->{hostsrv} );
  230. }
  231. }
  232. foreach $param (sort keys(%fromlist)) {
  233. #
  234. # Transform the from list from the GUID index to a Cracked name
  235. # index for DFS replica sets.
  236. #
  237. if ($settype != 2) {
  238. $fromlist{$CrackedName{$param}} = $fromlist{$param};
  239. $fromlist{$param} = -1; # UNDEF doesn't seem to get rid of the key.
  240. }
  241. }
  242. }
  243. #
  244. # put out the summary info first.
  245. #
  246. # Servers referenced from cxtions (From List) but with no inbound connections.
  247. #
  248. foreach $param (sort keys(%fromlist)) {
  249. if ($hostlist{$param} == 0) {
  250. if ($settype == 2) {
  251. push @ServersWithOutboundButNoInbound, $param;
  252. } else {
  253. if ($fromlist{$param} >= 0) {
  254. push @ServersWithOutboundButNoInbound,
  255. sprintf("%-36s Member RDN: %s", $CrackedName{$param}, $param);
  256. }
  257. }
  258. }
  259. }
  260. #
  261. # Servers hosting cxtions (To List) but have no other connections referring to them.
  262. #
  263. foreach $param (sort keys(%hostlist)) {
  264. if ($fromlist{$param} == 0) {
  265. push @ServersWithInboundButNoOutbound, $param;
  266. }
  267. }
  268. if ((scalar @ServersWithOutboundButNoInbound) > 0) {
  269. printf("\n\n\n S E R V E R S M I S S I N G I N B O U N D C O N N E C T I O N S\n\n");
  270. print "The following FRS Member servers have outbound replication partners but no inbound \n",
  271. "connection objects. There could be serveral reasons for this:\n\n",
  272. " 1. There are no connection objects under the NTDS Settings object for this server. This is an error.\n",
  273. " 2. The ServerReference Attribute for this server is null. This is an error.\n",
  274. " 3. This server could be in a different domain so there will be no FRS member object for it.\n",
  275. " 4. The FRS member object may be missing. This is an error.\n\n";
  276. foreach $m (@ServersWithOutboundButNoInbound) {print "$m\n";}
  277. }
  278. if ((scalar @ServersWithInboundButNoOutbound) > 0) {
  279. printf("\n\n\n S E R V E R S M I S S I N G O U T B O U N D C O N N E C T I O N S\n\n");
  280. print "The following FRS Member servers have inbound replication partners but no outbound \n",
  281. "connection objects\n\n";
  282. foreach $m (@ServersWithInboundButNoOutbound) {print "$m\n";}
  283. }
  284. if (($settype == 2) && ($nontdssettings > 0)) {
  285. printf("\n\n\n M I S S I N G N T D S S E T T I N G S R E F E R E N C E S\n\n");
  286. printf("The following FRS Member objects have no Server Reference to an NTDS Settings Object\n\n");
  287. foreach $m (@NoDsSettings) {print "$m\n";}
  288. }
  289. if ((scalar @MembersWithNullCompRef) > 0) {
  290. printf("\n\n\n M E M B E R S M I S S I N G C O M P U T E R R E F E R E N C E\n\n");
  291. printf("The following FRS Member objects have no computer reference\n\n");
  292. foreach $m (@MembersWithNullCompRef) {print "$m\n";}
  293. }
  294. if ($memberswithnocxtion > 0) {
  295. printf("\n\n\n M E M B E R S M I S S I N G C O N N E C T I O N O B J E C T S\n\n");
  296. printf("The following FRS Member objects have no inbound connection Objects\n\n");
  297. foreach $m (@NoConnObj) {print "$m\n";}
  298. }
  299. if (scalar @CxtionsToSelf > 0) {
  300. printf("\n\n\n M E M B E R S W I T H S E L F - R E F E R E N C E C O N N E C T I O N O B J E C T S\n\n");
  301. printf("The following FRS Member objects have connection objects that refer back to themselves\n\n");
  302. foreach $m (@CxtionsToSelf) {print "$m\n";}
  303. }
  304. if (scalar @Repl168Hrs > 0) {
  305. printf("\n\n\n M E M B E R S W I T H 1 6 8 H O U R C O N N E C T I O N S\n\n");
  306. printf("The following FRS Member objects have connection objects with 168 hour replication schedules\n\n");
  307. foreach $m (@Repl168Hrs) {print "$m\n";}
  308. }
  309. printf("\n\n\n S U M M A R Y R E P O R T \n\n");
  310. if ($settype == 2) {
  311. printf("\nMember objects with no NTDS Settings reference: %5d\n", $nontdssettings);
  312. }
  313. printf("\nMember objects with no connection objects: %5d\n", $memberswithnocxtion);
  314. printf("\nConnection objects set to disabled: %5d\n", $disabledcxtion);
  315. printf("\n\nNumber connections with given Monday Schedule\n\n");
  316. foreach $param (sort keys(%monsched)) {
  317. printf("%-28s %5d\n", $param, $monsched{$param});
  318. }
  319. printf("\n\nNumber connections with per-week active replication hours\n\n");
  320. foreach $param (sort keys(%hoursched)) {
  321. printf("%-28s %5d\n", $hoursched{$param}, $param);
  322. }
  323. print "\f\n";
  324. #
  325. # Now output the details.
  326. #
  327. foreach $param (sort keys(%outhash)) {
  328. printf("%s", $outhash{$param});
  329. }
  330. printf("\n\n Servers referenced from cxtions (From List) \n\n");
  331. foreach $param (sort keys(%fromlist)) {
  332. #
  333. # skip the old guid based entries (for DFS replica sets) that have -1 for value.
  334. #
  335. if ($fromlist{$param} >= 0) {
  336. $fromlistname{$param} = join " ", sort split " ", $fromlistname{$param};
  337. printf("%-25s %3d %3d >> %s\n", $param, $fromlist{$param}, $hostlist{$param}, $fromlistname{$param});
  338. $mergelist{$param} = 1;
  339. }
  340. }
  341. printf("\n\n Servers hosting cxtions (To List) \n\n");
  342. foreach $param (sort keys(%hostlist)) {
  343. $hostlistname{$param} = join " ", sort split " ", $hostlistname{$param};
  344. printf("%-25s %3d %3d << %s\n", $param, $hostlist{$param}, $fromlist{$param}, $hostlistname{$param});
  345. $mergelist{$param} = 1;
  346. }
  347. printf("\n\n Server inbound/outbound partners \n\n");
  348. foreach $param (sort keys(%mergelist)) {
  349. printf("%-25s %3d << %s\n", $param, $hostlist{$param}, $hostlistname{$param});
  350. printf("%-25s %3d >> %s\n", $param, $fromlist{$param}, $fromlistname{$param});
  351. print "\n";
  352. }
  353. print "\f\n";
  354. #
  355. # Init for next replica set.
  356. #
  357. if ($func =~ m/^ SET/) {$setname = $a[0]; printf("\n\n%s\n\n", $_); }
  358. $replhours = 168; # No schedule means that DS replicates every hour.
  359. $hostsite = "unknown";
  360. $hostsrv = "unknown";
  361. $fromsite = "unknown";
  362. $fromsrv = "unknown";
  363. $schedule = "none";
  364. $enable = "unknown";
  365. $cxtion = "unknown";
  366. $cxtioncnt = 1;
  367. $nontdssettings = 0;
  368. $memberswithnocxtion = 0;
  369. $disabledcxtion = 0;
  370. $rootdir = "";
  371. $stagedir = "";
  372. undef %outhash;
  373. undef %monsched;
  374. undef %hoursched;
  375. undef %fromlist;
  376. undef %hostlist;
  377. undef @ServersWithOutboundButNoInbound;
  378. undef @ServersWithInboundButNoOutbound;
  379. undef @NoDsSettings;
  380. undef @MembersWithNullCompRef;
  381. undef @NoConnObj;
  382. undef @CxtionsToSelf;
  383. undef @Repl168Hrs;
  384. undef @ConnDetail;
  385. undef %CrackedName;
  386. undef %mergelist;
  387. undef %hostlistname;
  388. undef %fromlistname;
  389. }
  390. __END__
  391. :endofperl
  392. @perl %~dpn0.cmd %*