Wednesday, November 28, 2007

Internet FailOver script for FreeBSD written in Perl

I wrote Perl script to automatically detect internet uplink failure and switch over to backup internet link. When primary link is up again script will switch it back. Script must be run in crontab as often as you wish.

#!/usr/bin/perl
use Net::Frame::Device;
use Net::Ping;

$uplink1_interface="sis0";
$uplink2_interface="sis1";
$lan_interface="sis2";
$primary_gateway="10.0.3.1";
$secondary_gateway="10.10.1.1";

# print current date and time
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = gmtime(time);
$year=$year+1900;
print "GMT Time: $year-$mon-$mday $hour:$min:$sec\n";

my $device_uplink1 = Net::Frame::Device->new(dev => $uplink1_interface);
my $device_uplink2 = Net::Frame::Device->new(dev => $uplink2_interface);
my $device_lan = Net::Frame::Device->new(dev => $lan_interface);

print "Current default gateway:", $device_lan->gatewayIp, "\n";
print "Primary default gateway:", $primary_gateway, "\n";
print "Secondary gateway:", $secondary_gateway, "\n";

print "Checking primary internet uplink ...\n";
if (check_uplink($primary_gateway)) {
if ($device_lan->gatewayIp ne $primary_gateway) {
# set default route to $primary_gateway
`route delete default`;
`route add default $primary_gateway`;

# Change uplink interface to uplink1_interface
change_nat_interface($uplink1_interface);

# restart IPFW and NATD daemon
`/etc/rc.d/ipfw restart`;

print "Default gateway has been changed to $primary_gateway via interface $uplink1_interface\n";
} else {
print "Current default gateway is set to primary gateway and is ok\n";
}
} elsif (check_uplink($secondary_gateway)) {
if ($device_lan->gatewayIp ne $secondary_gateway) {
# set default route to $secondary_gateway
`route delete default`;
`route add default $secondary_gateway`;

# Change uplink interface to uplink2_interface
change_nat_interface($uplink2_interface);

# restart IPFW and NATD daemon
`/etc/rc.d/ipfw restart`;

print "Default gateway has been changed to $secondary_gateway via interface $uplink2_interface\n";
} else {
print "Current default gateway is set to secondary gateway and is ok\n";
}
} else {
print "Any uplink is up and working\n";
}

print "----\n";

######################################################
# Ping IP address and decide if it's reachable or not
# 1.parameter: IP
######################################################
sub check_uplink {
my ($ip) = @_;

my $p = Net::Ping->new("icmp");
my $ok = $p->ping($ip);
$p->close();

return $ok; # 0 - false; 1 - true
}

######################################################
# Change NATD interface file
# 1.parameter: network interface
######################################################
sub change_nat_interface {
my ($nat_if) = @_;

$filename="/tmp/natd_iface";
if (open(F, "> $filename")) {
print "change_nat_iface: writing $nat_if to $filename\n";
print F $nat_if;
close F;
} else {
print "change_nat_iface: Cannot write to $filename\n";
return 0;
}

return 1; # 0 - false; 1 - true
}

No comments: