| 1 | #!/usr/bin/perl |
|---|
| 2 | |
|---|
| 3 | use strict; |
|---|
| 4 | use IO::File; |
|---|
| 5 | use IO::Pipe; |
|---|
| 6 | use Getopt::Long; |
|---|
| 7 | |
|---|
| 8 | # Commands to use below. These all seem to be in the same place on FreeBSD and |
|---|
| 9 | # Lunix |
|---|
| 10 | my $TMCC = "/usr/local/etc/emulab/tmcc"; |
|---|
| 11 | my $FINDIF = "/usr/local/etc/emulab/findif"; |
|---|
| 12 | my $IFCONFIG = "/sbin/ifconfig"; |
|---|
| 13 | my $ROUTE = "/sbin/route"; |
|---|
| 14 | |
|---|
| 15 | my $tmcc = new IO::Pipe || die "Can't create tmcc pipe: $!\n"; # To parse tmcc |
|---|
| 16 | my $interface; # Interface with external address |
|---|
| 17 | my $ip; # IP address of external interface |
|---|
| 18 | my $mac; # MAC address |
|---|
| 19 | my $netmask; # Netmask |
|---|
| 20 | my $router; # Router for the internet |
|---|
| 21 | my $routedest; # Add host route to this address (if given) |
|---|
| 22 | my $recordfile; # Record interfaces |
|---|
| 23 | |
|---|
| 24 | # Linux and FreeBSD use slightly different route syntax, so get the OS |
|---|
| 25 | my $os = `uname`; |
|---|
| 26 | chomp $os; |
|---|
| 27 | |
|---|
| 28 | # Option parsing, --destination sets $routedest |
|---|
| 29 | GetOptions('destination=s' => \$routedest, "record=s" => \$recordfile); |
|---|
| 30 | |
|---|
| 31 | # Parse out the info about tunnelips |
|---|
| 32 | $tmcc->reader("$TMCC tunnelip"); |
|---|
| 33 | while (<$tmcc>) { |
|---|
| 34 | chomp; |
|---|
| 35 | /TUNNELIP=([\d\.]*)/ && do { $ip = $1; }; |
|---|
| 36 | /TUNNELMASK=([\d\.]*)/ && do { $netmask = $1; }; |
|---|
| 37 | /TUNNELMAC=([[:xdigit:]]*)/ && do { $mac = $1; }; |
|---|
| 38 | /TUNNELROUTER=([\d\.]*)/ && do { $router = $1; }; |
|---|
| 39 | } |
|---|
| 40 | $tmcc->close(); |
|---|
| 41 | |
|---|
| 42 | die "No MAC information for tunnel.\n" unless $mac; |
|---|
| 43 | |
|---|
| 44 | # Use the emulab findif command to get the right interface to configure |
|---|
| 45 | $interface = `$FINDIF $mac`; |
|---|
| 46 | chomp $interface; |
|---|
| 47 | die "Can't get interface for mac address $mac: $?" if $? || !$interface; |
|---|
| 48 | |
|---|
| 49 | # Do the ifconfig |
|---|
| 50 | my @ifconfig = ($IFCONFIG, $interface, $ip); |
|---|
| 51 | push(@ifconfig, 'netmask', $netmask) if $netmask; |
|---|
| 52 | |
|---|
| 53 | system(@ifconfig); |
|---|
| 54 | die join(" ", @ifconfig) . " failed: $!\n" if $?; |
|---|
| 55 | |
|---|
| 56 | # Add the host route, if needed |
|---|
| 57 | if ($router) { |
|---|
| 58 | if ($routedest ) { |
|---|
| 59 | my @cmd; |
|---|
| 60 | |
|---|
| 61 | if ( $os =~ /^Linux/ ) { |
|---|
| 62 | @cmd = ($ROUTE, 'add', $routedest, 'gw', $router); |
|---|
| 63 | } |
|---|
| 64 | elsif ( $os =~ /^FreeBSD/ ) { |
|---|
| 65 | @cmd = ($ROUTE, 'add', $routedest, $router); |
|---|
| 66 | } |
|---|
| 67 | else { |
|---|
| 68 | die "Unknown OS: $os\n"; |
|---|
| 69 | } |
|---|
| 70 | system(@cmd); |
|---|
| 71 | die join(" ", @cmd) . " failed: $?\n" if $?; |
|---|
| 72 | } |
|---|
| 73 | } |
|---|
| 74 | else { warn "Destination but no router\n" if $routedest; } |
|---|
| 75 | if ($recordfile) { |
|---|
| 76 | $netmask = "255.255.255.0" unless $netmask; |
|---|
| 77 | my $rf = new IO::File(">>$recordfile") || |
|---|
| 78 | die "Can't open $recordfile:$!\n"; |
|---|
| 79 | print $rf "$ip:$interface:$mac:$netmask\n"; |
|---|
| 80 | $rf->close(); |
|---|
| 81 | } |
|---|
| 82 | exit(0); |
|---|