#!/usr/bin/perl

use strict;
use IO::File;
use IO::Pipe;

my $IFCONFIG = "/sbin/ifconfig";
my $ZEBRA= "/usr/lib/quagga/zebra";
my $OSPFD= "/usr/lib/quagga/ospfd";

my $ospffn = "/usr/local/federation/etc/ospfd.conf";
my $zebrafn = "/usr/local/federation/etc/zebra.conf";
my @live_ones;
my @bits_in_quad;
my %ainfo;

sub quad_to_int {
    my($ip) = @_;
    my @q = split(/\./, $ip);
    return ($q[0] << 24) + ($q[1] << 16) +  ($q[2] << 8) + $q[3];
}

sub int_to_quad {
    my($i) = @_;
    return sprintf("%d.%d.%d.%d", ($i >> 24) & 0xff, ($i>>16) & 0xff, 
	($i >>8) & 0xff, $i & 0xff);
}

sub nbits {
    my($b) = @_;
    return 0 if $b == 0;
    my $r = 1;
    for (my $i = 1 ; $i < $b; $i++) {
	$r <<= 1;
	$r += 1;
    }
    for (my $i = $b;  $i< 32; $i ++) {
	$r <<= 1;
	$r &= 0xfffffffe;
    }
    return $r;
}

sub netslash {
    my($ip, $slash) = @_;
    return int_to_quad(quad_to_int($ip) & nbits($slash));
}

for (my $i =0; $i < 256; $i++) {
    $bits_in_quad[$i] = 0;
}
my $m = 0xff;
for (my $i = 8; $i > 0; $i--) {
    $bits_in_quad[$m] = $i;
    $m <<= 1;
    $m &= 0xfe;
}


if ( !-x $OSPFD) {
    if (-x "/usr/bin/apt-get" ) {
	system("/usr/bin/apt-get", "-y", "install", "quagga");
    }
    elsif (-x "/usr/bin/yum") {
	system("/usr/bin/yum", "-y", "install", "quagga");
    }
}

chomp (my $cif = `/usr/local/etc/emulab/control_interface`);
chomp (my $hostname = `hostname`);
$hostname =~ s/\..*//;

my $ifp = new IO::Pipe();
$ifp->reader("$IFCONFIG");
my $current = undef;
while (<$ifp>) {
    /^(\S+)/ && do {
	my $ifname = $1;
	if ($ifname ne $cif && $ifname !~ "^lo" ) {
	    push(@live_ones, $ifname);
	    $current = $ifname;
	}
	else { $current = undef; }
	print "$ifname $current\n";
    };
    /inet addr:\s*(\S+)\s*\S*\s*mask:\s*(\S+)/i && do {
	next unless $current;
	print "$current $1 $2\n";
	my $slash = 0;
	foreach my $quad (split(/\./, $2)) {
	    if ($bits_in_quad[$quad] != 0 ) { $slash += $bits_in_quad[$quad];}
	    else { last;}
	}
	$ainfo{$current} = [ $1, $slash ];
	print $current, " ", @{$ainfo{$current}}, "\n";
    }
}
$ifp->close();

my $f = new IO::File(">$zebrafn") || die "Can't open $zebrafn: $!\n";
print $f "hostname $hostname\n";
foreach my $i (@live_ones) {
    print $f "interface $i\n";
}
$f->close();
my $f = new IO::File(">$ospffn") || die "Can't open $ospffn: $!\n";
print $f "hostname $hostname\n";
print $f "router ospf\n";
foreach my $i (@live_ones) {
    print $f " network ";
    print $f netslash($ainfo{$i}->[0], $ainfo{$i}->[1]),"/",$ainfo{$i}->[1]," area 0.0.0.2\n";
}
$f->close();
foreach my $fn ($zebrafn, $ospffn) {
    system("chmod 644 $fn");
}
$f = new IO::File(">/proc/sys/net/ipv4/ip_forward") || 
    die "Can't open sys forwarding file:$!\n";
print $f "1\n";
$f->close();
system("$ZEBRA -d -f $zebrafn");
system("$OSPFD -d -f $ospffn");

