diff options
author | Stephen Hemminger <stephen.hemminger@vyatta.com> | 2008-04-03 17:22:01 -0700 |
---|---|---|
committer | Stephen Hemminger <stephen.hemminger@vyatta.com> | 2008-04-03 17:22:01 -0700 |
commit | cac51df000d90b9723abde545450fde66d1d7865 (patch) | |
tree | 37a3dc23c048f40ccca03f788ead2c9877d377be | |
parent | 9158b59fd7cdd018a5c9b1e36c097b0436fd02a4 (diff) | |
download | vyatta-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-x | scripts/vyatta-interfaces.pl | 52 |
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; } |