summaryrefslogtreecommitdiff
path: root/scripts/vyatta-interfaces.pl
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/vyatta-interfaces.pl')
-rwxr-xr-xscripts/vyatta-interfaces.pl85
1 files changed, 56 insertions, 29 deletions
diff --git a/scripts/vyatta-interfaces.pl b/scripts/vyatta-interfaces.pl
index c60288a..28b1c14 100755
--- a/scripts/vyatta-interfaces.pl
+++ b/scripts/vyatta-interfaces.pl
@@ -33,9 +33,12 @@
use lib "/opt/vyatta/share/perl5/";
use VyattaConfig;
use VyattaMisc;
+
use Getopt::Long;
use POSIX;
use NetAddr::IP;
+use Tie::File;
+use Fcntl qw (:flock);
use strict;
use warnings;
@@ -325,6 +328,22 @@ sub update_eth_addrs {
exit 1;
}
+sub if_nametoindex {
+ my ($intf) = @_;
+
+ open my $sysfs, "<", "/sys/class/net/$intf/ifindex"
+ || die "Unknown interface $intf";
+ my $ifindex = <$sysfs>;
+ close($sysfs) or die "read sysfs error\n";
+ chomp $ifindex;
+
+ return $ifindex;
+}
+
+sub htonl {
+ return unpack('L',pack('N',shift));
+}
+
sub delete_eth_addrs {
my ($addr, $intf) = @_;
@@ -335,41 +354,49 @@ sub delete_eth_addrs {
exit 0;
}
my $version = is_ip_v4_or_v6($addr);
+ if ($version == 6) {
+ exec 'ip', '-6', 'addr', 'del', $addr, 'dev', $intf
+ or die "Could not exec ip?";
+ }
+
+ ($version == 4) or die "Bad ip version";
- # If interface has address than delete it
if (is_ip_configured($intf, $addr)) {
- if ($version == 4) {
- exec 'ip', 'addr', 'del', $addr, 'dev', $intf;
- } elsif ($version == 6) {
- exec 'ip', '-6', 'addr', 'del', $addr, 'dev', $intf;
- } else {
- die "Bad ip version";
- }
- die "Can't exec ip";
+ # Link is up, so just delete address
+ # Zebra is watching for netlink events and will handle it
+ exec 'ip', 'addr', 'del', $addr, 'dev', $intf
+ or die "Could not exec ip?";
}
+
- # Interface address might have been removed by quagga link going down
- # so tell quagga no to restore it on link-detect
- my $vtysh;
- if ( -x '/usr/bin/vyatta-vtysh' ) {
- $vtysh = '/usr/bin/vyatta-vtysh';
- } else {
- $vtysh = '/usr/bin/vtysh';
- }
+ # Destroy watchlink's internal status so it doesn't erronously
+ # restore the address when link is restored
+ my $statusfile = '/var/linkstatus/' . if_nametoindex($intf);
- my @cmd = ();
- if ($version == 4) {
- @cmd = ('vtysh', '-c',
- "configure terminal; interface $intf; no ip address $intf" );
- } elsif ($version == 6) {
- @cmd = ('vtysh', '-c',
- "configure terminal; interface $intf; no ip6 address $intf" );
- } else {
- die "Bad ip version";
- }
- exec $vtysh, @cmd;
+ # Use tie to treat file as array
+ my $tie = tie my @status, 'Tie::File', $statusfile
+ or die "can't open $statusfile";
+
+ $tie->flock(LOCK_EX); # Block out watchlink
+ $tie = undef; # Drop reference so untie will work
- die "Can't exec vtysh";
+ my $ip = NetAddr::IP->new($addr);
+ my $recno = 0;
+ foreach my $line (@status) {
+ chomp $line;
+
+ # The format of watchlink file is host byte order (IPV6??)
+ my ($ifindex, $raddr, $bcast, $prefix) = split (/,/, $line);
+ my $laddr = htonl($raddr);
+ my $this = NetAddr::IP->new("$laddr/$prefix");
+ if ($ip eq $this) {
+ splice @status, $recno, 1; # delete the line
+ } else {
+ $recno++;
+ }
+ }
+ untie @status;
+ exit 0;
}
sub update_mac {