#!/usr/bin/perl use strict; use warnings; use POSIX; my $logger = "/usr/bin/logger"; my $resolv = "/etc/resolv.conf"; my $rclocal = "/etc/rc.local"; my $install_dir = "/usr/local/sbin"; my $name = "dns_kludge"; my $prgname = "$install_dir/$name"; my $P1 = '#!/usr/bin/perl use strict; use warnings; use subs qw (fatal_err logmsg); my %DNS_static = ('; my $P2 = '); my $logger = "/usr/bin/logger"; my $resolv = "/etc/resolv.conf"; my $sleeps = 0; my $max_sleep = 10; # ------------------------------------------------------------------------ sub logmsg { my ($msg) = @_; $msg =~ s/\s+$//; system "$logger $0: $msg\n"; } # ------------------------------------------------------------------------ sub fatal_err { logmsg "FATAL: $_[0]"; die $_[0]; } # ------------------------------------------------------------------------ logmsg "commenced"; while (1) { my @dns; my @head; my @tail; my %DNS = %DNS_static; $sleeps++; $sleeps = $max_sleep / 2 if ($sleeps > $max_sleep); sleep $sleeps * 60; open RESOLV,$resolv || fatal_err "Cannot open $resolv"; while () { if (/^nameserver (\S+)/) { my $dns = $1; push @dns,$_; delete $DNS{$dns} if ($DNS{$dns}); } else { if (@dns) { push @tail,$_; } else { push @head,$_; } } } if ( keys %DNS ) { logmsg "Over-writing $resolv"; open RESOLV,">$resolv" || fatal_err "Cannot open: $resolv"; foreach (@head) {print RESOLV} foreach my $dns (sort{$DNS{$a}<=>$DNS{$b}} keys %DNS){ print RESOLV "nameserver $dns\n"; } foreach (@dns) {print RESOLV} foreach (@tail) {print RESOLV} close RESOLV; $sleeps = 0; } }'; my $reply; my @dns; die "\nERROR: MUST specify either 'install' or 'uninstall' as an argument\n\n" unless (@ARGV); if ( $ARGV[0] eq "install" ) { # install unless ( -e $resolv && -w $resolv ) { die "ERROR: $resolv is missing or not writeable!\n"; } unless ( -e $rclocal && -w $rclocal ) { die "ERROR: $rclocal is missing or not writeable!\n"; } unless ( -d $install_dir) { mkdir $install_dir || die "Cannot create $install_dir - $!"; die "Cannot find folder: $install_dir" unless (-d $install_dir); print "INFO: Created folder $install_dir\n"; } unless ( -x $logger ) { print STDERR "ERROR: cannot find $logger\n"; die "Do you need to install util-linux?\n"; } print "\nEnter DNS servers, one at a time, as IP addr (Press Enter When Done):\n"; while () { my $reply = $_; $reply =~ s/\s+$//; $reply =~ s/^\s+//; last unless ($reply); unless ($reply =~ /^\d+\.\d+\.\d+\.\d+$/) { print "ERROR: $reply does not seem to be an IP address\n"; next; } my $ping = `ping -c1 $reply 2>&1`; if ($?) { print "WARNING: Cannot ping $reply!\n"; } push @dns,$reply; } die "\nERROR: Must specify at least one DNS server\n\n" unless (@dns); open PRG,">$prgname" || die "Cannot open $prgname for output - $!"; print PRG "$P1\n"; my $i = 1; foreach my $dns (@dns) { printf PRG "\t\"%s\" => %d,\n",$dns,$i++; } print PRG "$P2\n"; close PRG; chmod 0755,"$prgname"; open RCLOCAL,"$rclocal" || die "Cannot open: $rclocal - $!"; open NEW,">$rclocal.new" || die "Cannot open: $rclocal.new - $!"; my $exit = 0; while () { if ( /^exit/ && $exit == 0) { $exit++; print NEW "nohup $prgname &\n"; } print NEW; } print NEW "nohup $prgname &\n" unless ($exit); close NEW; close RCLOCAL; rename $rclocal,sprintf("%s.bak.%s",$rclocal,POSIX::strftime( "%y%m%d%H%M", localtime)); rename "$rclocal.new",$rclocal; chmod 0755,"$rclocal"; print "\nInstalled -- Reboot to activate\n\n"; } elsif ( $ARGV[0] eq "uninstall" ) { # uninstall unlink $prgname || die "Cannot unlink $prgname - $!"; open RCLOCAL,"$rclocal" || die "Cannot open: $rclocal - $!"; open NEW,">$rclocal.new" || die "Cannot open: $rclocal.new - $!"; while () { next if (index ($_,"nohup $prgname") == 0 ); print NEW; } close NEW; close RCLOCAL; rename $rclocal,sprintf("%s.bak.%s",$rclocal,POSIX::strftime( "%y%m%d%H%M", localtime)); rename "$rclocal.new",$rclocal; chmod 0755,"$rclocal"; print "\nUninstalled -- Reboot to remove\n\n"; } else { die "\nERROR: MUST specify either 'install' or 'uninstall'\n\n"; }