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 | my $forceip; # User overriddedn IP |
---|
24 | my $forcemask; # User overriddedn netmask |
---|
25 | |
---|
26 | # Linux and FreeBSD use slightly different route syntax, so get the OS |
---|
27 | my $os = `uname`; |
---|
28 | chomp $os; |
---|
29 | |
---|
30 | # Option parsing, --destination sets $routedest |
---|
31 | GetOptions('destination=s' => \$routedest, "record=s" => \$recordfile, |
---|
32 | 'forceip=s' => \$forceip, 'forcemask=s' => \$forcemask); |
---|
33 | |
---|
34 | # Parse out the info about tunnelips |
---|
35 | $tmcc->reader("$TMCC tunnelip"); |
---|
36 | while (<$tmcc>) { |
---|
37 | chomp; |
---|
38 | /TUNNELIP=([\d\.]*)/ && do { $ip = $1; }; |
---|
39 | /TUNNELMASK=([\d\.]*)/ && do { $netmask = $1; }; |
---|
40 | /TUNNELMAC=([[:xdigit:]]*)/ && do { $mac = $1; }; |
---|
41 | /TUNNELROUTER=([\d\.]*)/ && do { $router = $1; }; |
---|
42 | } |
---|
43 | $tmcc->close(); |
---|
44 | |
---|
45 | die "No MAC information for tunnel.\n" unless $mac; |
---|
46 | |
---|
47 | # Let the user override the IP and mask if they know what they are doing. |
---|
48 | $ip = $forceip if $forceip; |
---|
49 | $netmask = $forcemask if $forcemask; |
---|
50 | |
---|
51 | # Use the emulab findif command to get the right interface to configure |
---|
52 | $interface = `$FINDIF $mac`; |
---|
53 | chomp $interface; |
---|
54 | die "Can't get interface for mac address $mac: $?" if $? || !$interface; |
---|
55 | |
---|
56 | # Do the ifconfig |
---|
57 | my @ifconfig = ($IFCONFIG, $interface, $ip); |
---|
58 | push(@ifconfig, 'netmask', $netmask) if $netmask; |
---|
59 | |
---|
60 | system(@ifconfig); |
---|
61 | die join(" ", @ifconfig) . " failed: $!\n" if $?; |
---|
62 | |
---|
63 | # Add the host route, if needed |
---|
64 | if ($router) { |
---|
65 | if ($routedest ) { |
---|
66 | my @cmd; |
---|
67 | |
---|
68 | if ( $os =~ /^Linux/ ) { |
---|
69 | @cmd = ($ROUTE, 'add', $routedest, 'gw', $router); |
---|
70 | } |
---|
71 | elsif ( $os =~ /^FreeBSD/ ) { |
---|
72 | @cmd = ($ROUTE, 'add', $routedest, $router); |
---|
73 | } |
---|
74 | else { |
---|
75 | die "Unknown OS: $os\n"; |
---|
76 | } |
---|
77 | system(@cmd); |
---|
78 | die join(" ", @cmd) . " failed: $?\n" if $?; |
---|
79 | } |
---|
80 | } |
---|
81 | else { warn "Destination but no router\n" if $routedest; } |
---|
82 | if ($recordfile) { |
---|
83 | $netmask = "255.255.255.0" unless $netmask; |
---|
84 | my $rf = new IO::File(">>$recordfile") || |
---|
85 | die "Can't open $recordfile:$!\n"; |
---|
86 | print $rf "$ip:$interface:$mac:$netmask\n"; |
---|
87 | $rf->close(); |
---|
88 | } |
---|
89 | exit(0); |
---|