diff options
author | Stephen Hemminger <stephen.hemminger@vyatta.com> | 2008-03-11 16:37:58 -0700 |
---|---|---|
committer | Stephen Hemminger <stephen.hemminger@vyatta.com> | 2008-03-11 16:37:58 -0700 |
commit | 2fd9d914de23cd6fabc08e3e4be4a588f2b2803d (patch) | |
tree | a4ddf89a5134f460213279001a46ee523b566aec /scripts | |
parent | a650defe75b160a78aec3e1837cfa1e5a994ff3a (diff) | |
download | vyatta-cfg-2fd9d914de23cd6fabc08e3e4be4a588f2b2803d.tar.gz vyatta-cfg-2fd9d914de23cd6fabc08e3e4be4a588f2b2803d.zip |
more robust handling of set mac address
Bugfix: 2826
Enforce restrictions on address (must be valid ethernet address),
and only bring interface down/up if already up.
Diffstat (limited to 'scripts')
-rwxr-xr-x | scripts/vyatta-interfaces.pl | 47 |
1 files changed, 45 insertions, 2 deletions
diff --git a/scripts/vyatta-interfaces.pl b/scripts/vyatta-interfaces.pl index 1cad719..e3afe68 100755 --- a/scripts/vyatta-interfaces.pl +++ b/scripts/vyatta-interfaces.pl @@ -34,7 +34,7 @@ use lib "/opt/vyatta/share/perl5/"; use VyattaConfig; use VyattaMisc; use Getopt::Long; - +use POSIX; use NetAddr::IP; use strict; @@ -45,18 +45,22 @@ my $dhcp_conf = '/etc/dhcp3/dhclient.conf'; my $dhcp_pid = '/var/run/dhclient.pid'; my $dhcp_leases = '/var/lib/dhcp3/dhclient.leases'; +my ($eth_update, $eth_delete, $addr, $restart_dhclient, $dev, $mac, $mac_update); -my ($eth_update, $eth_delete, $addr, $restart_dhclient, $dev); GetOptions("eth-addr-update=s" => \$eth_update, "eth-addr-delete=s" => \$eth_delete, "valid-addr=s" => \$addr, "restart-dhclient!" => \$restart_dhclient, "dev=s" => \$dev, + "valid-mac=s" => \$mac, + "set-mac=s" => \$mac_update, ); if (defined $eth_update) { update_eth_addrs($eth_update, $dev); } if (defined $eth_delete) { delete_eth_addrs($eth_delete, $dev); } if (defined $addr) { is_valid_addr($addr, $dev); } +if (defined $mac) { is_valid_mac($mac, $dev); } +if (defined $mac_update) { update_mac($mac_update, $dev); } if (defined $restart_dhclient) { dhcp_restart_daemon(); } sub is_ip_configured { @@ -342,6 +346,45 @@ sub delete_eth_addrs { } } +sub update_mac { + my ($mac, $intf) = @_; + + open my $fh, "<", "/sys/class/net/$intf/flags" + or die "Error: $intf is not a network device\n"; + + my $flags = <$fh>; + chomp $flags; + close $fh or die "Error: can't read state\n"; + + if (POSIX::strtoul($flags) & 1) { + # NB: Perl 5 system return value is bass-ackwards + system "sudo ip link set $intf down" + and die "Could not set $intf down ($!)\n"; + system "sudo ip link set $intf address $mac" + and die "Could not set $intf address ($!)\n"; + system "sudo ip link set $intf up" + and die "Could not set $intf up ($!)\n"; + } else { + exec "sudo ip link set $intf address $mac"; + } + exit 0; +} + +sub is_valid_mac { + my ($mac, $intf) = @_; + my @octets = split /:/, $mac; + + ($#octets == 5) or die "Error: wrong number of octets: $#octets\n"; + + (($octets[0] & 1) == 0) or die "Error: $mac is a multicast address\n"; + + my $sum = 0; + $sum += strtoul('0x' . $_) foreach @octets; + ( $sum != 0 ) or die "Error: zero is not a valid address\n"; + + exit 0; +} + sub is_valid_addr { my ($addr_net, $intf) = @_; |