Question: PERL Script analysis Step 1 . Analyze/examine the scripts ethers2dhcp.pl and Makefile.txt Contents of ethers2dhcp.pl :~ $ cat ethers2dhcp.pl #!/usr/bin/perl # ethers2dhcp.pl invoked in Makefile

PERL Script analysis

Step 1. Analyze/examine the scripts ethers2dhcp.pl and Makefile.txt

Contents of ethers2dhcp.pl

:~ $ cat ethers2dhcp.pl

#!/usr/bin/perl # ethers2dhcp.pl invoked in Makefile as something like # cat /config/dns/cs.global/zone.158.121.* | ./ethers2dhcp.pl > hosts_auto # # Combine info from the ethers file and from the dns into dhcp host # declarations on stdout. Hosts that are in ethers and do not have a # static IP allocated in the dns will be enabled for dynamic IPs out # of the pool; their host declaration will not have a fixed-address # declaration. Hosts in ethers that have static IPs allocated will # have a fixed-address declaration. Hosts not in ethers cannot get # anything from our diced. # # Since we write each fixed-address as a Fully Qualified Domain Name, # we don't care at all about keeping track of the IPs in the zones. # This implies that if DNS is broken then servers cannot boot; it # also implies that the DHCP server should be a DNS server as well. # ## Input side # Zone file "Resource Records" that we care about look like these: # ;name ttl addr-class type resource_record_data # 1 IN PTR pix0.cs.umb.edu. # ; cs is currently the box "blade73". # 2 IN PTR cs.umb.edu. # 3 IN PTR mx1.cs.umb.edu. # # A trailing dot on a domain name is like leading slash on a pathname. # Note well that the fqdn is the last field on the right; that makes # reverse zone files way easier to parse than the forward ones. # # Lines in /etc/ethers look like this: # 00:03:ba:24:78:6f blade68.cs.umb.edu # # Entries in hosts_manual are host declarations, as is our output. # ## Output side # dhcpd.conf file format for that same info should look like this: # host blade68.cs.umb.edu { # hardware ethernet 00:03:ba:24:78:6f; # fixed-address blade68.cs.umb.edu; # }

^L ################## MAIN ###################### my %ethers_by_fqdns, %fixed_addresses, %hosts_manual; # All key on FQDNs. $ethers_file = "/config/etc/ethers"; # UMB Rdist master file location $hosts_manual="hosts_manual"; # For stop list -- exceptional hosts with # declarations written manually. $orphans_file = "orphans"; # Orphan fqdn's whose MAC we don't know. &load_hosts_manual; # Load hash of manual clients keyed by fqdn. &load_ethers_by_fqdns; # Load hash of ethernet addrs keyed by fqdn. &load_fixed_addresses; # Input reverse zone file(s) on stdin, # load hash of flags keyed by fqdn. &do_host_declarations; # Process and Output dhcp declarations. &do_orphans; # As a side effect, note "orphans". exit; ############### SUBROUTINES ################## sub load_hosts_manual { # Load global hash %hosts_manual from, usually, ./hosts_manual. my $fqdn; open(MANUAL,"<$hosts_manual") || die("Cannot open $hosts_manual"); while (){ next unless ( /^\s*host\s+/ ); # Focus on active host declarations. chop(); #($fqdn = $_) =~ s/.*fqdn\s+//; # Strip leading keyword. ($fqdn = $_) =~ s///; # Strip that leading keyword. $fqdn =~ s/\s+.*//; # Strip trailing bracket. #print STDERR "Adding $fqdn to stop list. "; $hosts_manual{$fqdn}=1; } close(MANUAL); return; }

^L sub load_ethers_by_fqdns { my $lineno, $baddata, $re, $ether, $fqdn; my %fqdns_by_ethers; # This will help us spot duplicate MAC addrs. # Only used in this subroutine. # Load global hash %ethers_by_fqdns from, usually, /etc/ethers. open(ETHERS,"<$ethers_file") || die("Cannot open $ethers_file"); $lineno = $baddata = 0; while (){ $lineno++; # A tight test for a clean line. Haven't really needed i. $re = "[0-9a-f]{1,2}"; # One or two hex digits. if ( ! /^$re:$re:$re:$re:$re:$re\s+[a-z0-9-_\.]+/i ) { print STDERR " BAD line $lineno: $_"; $baddata = 1; # flag the error next; } chop; ($ether, $fqdn) = split('\s+',$_,2); # As we read them in, check for duplicate MAC addrs. if (exists $fqdns_by_ethers{$ether}) { print STDERR " ERROR: "; print STDERR " Duplicate MAC address at line $lineno in $ethers_file. "; print STDERR " Hosts $fqdns_by_ethers{$ether} and $fqdn"; print STDERR " have the same MAC. "; $baddata = 1; # flag the error } # Also check for duplicate hostnames, which may be dup lines. if (exists $ethers_by_fqdns{$fqdn}) { print STDERR " ERROR: "; print STDERR " Duplicate hostname at line $lineno in $ethers_file. "; print STDERR " Host $fqdn is listed more than once. "; $baddata = 1; # flag the error } $ethers_by_fqdns{$fqdn} = $ether; $fqdns_by_ethers{$ether} = $fqdn; } close(ETHERS); if ( $baddata ) { #die(" BAD line(s) found in $ethers_file. Quitting."); die(" BAD data found in $ethers_file. Quitting"); } return; } ^L

sub load_fixed_addresses { # Read in the reverse zone file(s) on stdin and load a hash # of IPs keyed by fqdn. By our definition, hosts that are # reverse mapped have fixed addresses. # # We used to not care about the host IPs, but now that we have # two routers it matters; hosts on certain networks get a router # declaration to override the default. Keeping the full IP in # the hash makes that possible. # # The quick and dirty way of 'knowing' the network part of the # IP is to rely on our local convention of embedding the pathname # of the zone file in a leading comment. For example # ; /config/dns/cs.global/zone.158.121.107 installed in /etc/domain # from which we can get "158.121.107". # The pathname is duplicated in the RCS header, so ditch that. my $fqdn, $network, $hostpart; while (<>){ # Pick off magic comments before dropping all other comments. if ( /^\s*;/ && m#/zone\.\d{1,3}\.# && ! /,v/ ) { chop(); ($network = $_) =~ s/.*zone\.//; # Strip leading junk. $network =~ s/\s.*//; # Strip trailing junk. #print(STDERR "Saw network $network "); } next if ( /^\s*;/ ); # Skip comments. next unless ( /\s+PTR\s+/ ); # Focus on PTR RR's. chop(); ($hostpart = $_) =~ s/\s.*$//; # Crack off the first field. ($fqdn = $_) =~ s/\.\s*$//; # Strip trailing dot and ws. $fqdn =~ s/.*\s//; # Crack off last field. $fixed_addresses{$fqdn} = "$network.$hostpart"; #print(STDERR "fixed_addresses{$fqdn} = $fixed_addresses{$fqdn} "); } } sub do_host_declarations { # We loop over the known ethernet addresses and put out a dhcp # host declaration for each, unless host is in the stop list of # hosts_manual. If the fqdn has a fixed address, # then we make such a declaration within the host declaration; # otherwise say nothing and the host will be enabled to get an # address from the server's pool. # # This is the spot to special-case router declarations per-network. my $fqdn; foreach $fqdn (sort keys %ethers_by_fqdns) { next if (exists $hosts_manual{$fqdn}); print "host $fqdn { "; print " hardware ethernet $ethers_by_fqdns{$fqdn}; "; if (exists $fixed_addresses{$fqdn}) { #print STDERR "exists \$fixed_addresses{$fqdn} "; print " fixed-address $fqdn; "; if ($fixed_addresses{$fqdn} =~ /158\.121\.107\./ ) { #print " option routers 192.168.107.254; "; print " option routers pix1.cs.umb.edu; "; } } if ($fqdn =~ /math\.umb\.edu$/) { # IFF FQDN has math in it, then override default domain. print " option domain-name \"math.umb.edu\"; "; } elsif ($fqdn =~ /win\.cs\.umb\.edu$/) { # IFF FQDN has win in it, then override default domain. print " option domain-name \"win.cs.umb.edu\"; "; # IFF FQDN has win in it, then tell it to use AD for DNS. # FRAGILE! # sf09 IN CNAME sf09.win.cs.umb.edu. # sf09.win IN A 158.121.105.10 # xs.win IN A 158.121.104.64 #option domain-name-servers blade30.cs.umb.edu, blade41.cs.umb.edu; #option domain-name-servers 192.168.105.40, 192.168.105.51; # 20090730 Using hardwired IPs for robustness against win server down. #print " option domain-name-servers 192.168.105.10, 192.168.104.64; "; } print "} "; } }

^L sub do_orphans { # We loop over the known fqdn's and print those for which we # don't know the MAC address. This is not necessary to the # task of building a dhcpd.conf, but for informing sysadmins # of the set difference. # FQDN's are printed to the $orphans_file. my $fqdn; open(ORPHANS,">$orphans_file") || die("Cannot open $orphans_file"); foreach $fqdn (sort keys %fixed_addresses) { if (! exists $ethers_by_fqdns{$fqdn}) { print ORPHANS "$fqdn "; } } }

Contentes of Makefile.txt

# /config/DHCP/Makefile manually maintained locally # # Build the dhcpd.conf file(s) needed by our server(s). # The set of known ethernet addresses changes often, as # does the set of hosts that are to get fixed addresses. # # Note that $@ is the name of the target file. # # ./orphans is a file written as a side effect for my # own purposes as admin. It is a list of FQDNs for which # we have allocated an IP but don't know a MAC address. # The ethers file should be updated; ping each host and, # for the ones that succeed, run arp to see their MAC. # In production, be silent about the work. #.SILENT: BUILT_FILES= \ dhcpd.conf.sf01 \ dhcpd.conf.ns1 \ dhcpd.conf.ns2 \ dhcpd.conf.ns3 \ hosts_auto orphans ETHERS = /config/etc/ethers ZONES = /config/dns/cs.global/zone.158.121.* HOSTS_MANUAL = hosts_manual PROG = ./ethers2dhcp.pl HOSTS_AUTO = hosts_auto ORPHANS = orphans # PROG uses ETHERS, ZONES and HOSTS_MANUAL to build # hosts_auto and orphans files. all: $(BUILT_FILES) clean: rm -f $(BUILT_FILES) dhcpd.conf.sf01: Makefile dhcpd.sf01 $(HOSTS_MANUAL) $(HOSTS_AUTO) cat dhcpd.sf01 $(HOSTS_MANUAL) $(HOSTS_AUTO) > $@ dhcpd.conf.ns1: Makefile dhcpd.ns1 $(HOSTS_MANUAL) $(HOSTS_AUTO) cat dhcpd.ns1 $(HOSTS_MANUAL) $(HOSTS_AUTO) > $@ dhcpd.conf.ns2: Makefile dhcpd.ns2 $(HOSTS_MANUAL) $(HOSTS_AUTO) cat dhcpd.ns2 $(HOSTS_MANUAL) $(HOSTS_AUTO) > $@ dhcpd.conf.ns3: Makefile dhcpd.ns3 $(HOSTS_MANUAL) $(HOSTS_AUTO) cat dhcpd.ns3 $(HOSTS_MANUAL) $(HOSTS_AUTO) > $@ # Orphans file is created as a side effect. $(ORPHANS): $(HOSTS_AUTO) $(HOSTS_AUTO): Makefile $(PROG) $(ZONES) $(ETHERS) $(HOSTS_MANUAL) cat $(ZONES) | $(PROG) > $@ ## A better cut at filling in the ethers file with MACs of orphans. orphans_found: orphans ./check_orphans.pl < orphans > orphans_found ## Some scratch work about filling in /etc/ethers as well as we can. ARP_FILES = /home/rickm/ethers.d/2* ethers.seen: Makefile arp_filter.pl $(ARP_FILES) cat $(ARP_FILES) | arp_filter.pl | sort -u > $@ /tmp/ethers_known_vs_seen: /config/etc/ethers ethers.seen comm -3 /config/etc/ethers ethers.seen > $@ # Expect, or hope, that there are no MACs unique to ethers.seen. # Such lines will start with a TAB, and represent hosts that # are using a mapped IP and are not in our ethers file. # ## Here is a Bourne shell script to ping all our IPs. ## It is coded as the case 'survey' in /home/rickm/bin/pingem. ## Immediately after running this script, run ## arp -a > /home/rickm/ethers.d/`date +%Y%m%d` ## # #!/bin/sh # HOSTMAX=254 # for network in \ # 192.168.104 \ # 192.168.105 \ # 192.168.106 \ # 192.168.107 # do # hostnum=1 # while ( test "$hostnum" -lt "$HOSTMAX" ) # do # #echo "Would ping $network.$hostnum" # ping $network.$hostnum 1 # hostnum=`expr "$hostnum" + 1` # done # done ## comm(1) man page: # # The following options are supported: # # -1 Suppress the output column of lines unique to file1. # # -2 Suppress the output column of lines unique to file2. # # -3 Suppress the output column of lines duplicated in # file1 and file2. 

STEP 2. In a text file script_analysis.txt, write a description of

what the files do... ...and how they do it

Be sure to pay attention to rickm's comments but do not just paraphrase them.

Step by Step Solution

There are 3 Steps involved in it

1 Expert Approved Answer
Step: 1 Unlock blur-text-image
Question Has Been Solved by an Expert!

Get step-by-step solutions from verified subject matter experts

Step: 2 Unlock
Step: 3 Unlock

Students Have Also Explored These Related Databases Questions!