summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephen Hemminger <stephen.hemminger@vyatta.com>2008-04-03 17:22:01 -0700
committerStephen Hemminger <stephen.hemminger@vyatta.com>2008-04-03 17:22:01 -0700
commitcac51df000d90b9723abde545450fde66d1d7865 (patch)
tree37a3dc23c048f40ccca03f788ead2c9877d377be
parent9158b59fd7cdd018a5c9b1e36c097b0436fd02a4 (diff)
downloadvyatta-cfg-cac51df000d90b9723abde545450fde66d1d7865.tar.gz
vyatta-cfg-cac51df000d90b9723abde545450fde66d1d7865.zip
handle multiple address deletion when link is down
More robust fix for Bug 2802. Handle case of multiple addresses and lines in the linkstatus file. Add locking to try and prevent multiple update.
-rwxr-xr-xscripts/vyatta-interfaces.pl52
1 files changed, 41 insertions, 11 deletions
diff --git a/scripts/vyatta-interfaces.pl b/scripts/vyatta-interfaces.pl
index 01ddd5e..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;
@@ -333,10 +336,14 @@ sub if_nametoindex {
my $ifindex = <$sysfs>;
close($sysfs) or die "read sysfs error\n";
chomp $ifindex;
- print "$intf = $ifindex\n";
+
return $ifindex;
}
+sub htonl {
+ return unpack('L',pack('N',shift));
+}
+
sub delete_eth_addrs {
my ($addr, $intf) = @_;
@@ -347,25 +354,48 @@ 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 (is_ip_configured($intf, $addr)) {
# Link is up, so just delete address
# Zebra is watching for netlink events and will handle it
- 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";
+ exec 'ip', 'addr', 'del', $addr, 'dev', $intf
+ or die "Could not exec ip?";
}
+
# Destroy watchlink's internal status so it doesn't erronously
# restore the address when link is restored
- my $status = '/var/linkstatus/' . if_nametoindex($intf);
- unlink($status) or die "can't remove $status";
+ my $statusfile = '/var/linkstatus/' . if_nametoindex($intf);
+
+ # 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
+
+ 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;
}