diff --git a/dhclient3 b/dhclient3
new file mode 100644
index 0000000000000000000000000000000000000000..a50f05ff35db699e0e04b14af549ab559b4d59c5
Binary files /dev/null and b/dhclient3 differ
diff --git a/vyatta-interfaces.pl b/vyatta-interfaces.pl
new file mode 100644
index 0000000000000000000000000000000000000000..981d733522042fe5f0880519b7eeb5e61fcce297
--- /dev/null
+++ b/vyatta-interfaces.pl
@@ -0,0 +1,652 @@
+#!/usr/bin/perl
+#
+# Module: vyatta-interfaces.pl
+# 
+# **** License ****
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# A copy of the GNU General Public License is available as
+# `/usr/share/common-licenses/GPL' in the Debian GNU/Linux distribution
+# or on the World Wide Web at `http://www.gnu.org/copyleft/gpl.html'.
+# You can also obtain it by writing to the Free Software Foundation,
+# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+# MA 02110-1301, USA.
+# 
+# This code was originally developed by Vyatta, Inc.
+# Portions created by Vyatta are Copyright (C) 2007 Vyatta, Inc.
+# All Rights Reserved.
+# 
+# Author: Stig Thormodsrud
+# Date: November 2007
+# Description: Script to assign addresses to interfaces.
+# 
+# **** End License ****
+#
+
+use lib "/opt/vyatta/share/perl5/";
+use Vyatta::Config;
+use Vyatta::Misc qw(generate_dhclient_intf_files
+		    getInterfaces getIP get_sysfs_value
+ 		    is_address_enabled is_dhcp_enabled is_ip_v4_or_v6);
+use Vyatta::File qw(touch);
+use Vyatta::Interface;
+
+use Getopt::Long;
+use POSIX;
+
+use strict;
+use warnings;
+
+my $dhcp_daemon = '/sbin/dhclient';
+my $ETHTOOL     = '/sbin/ethtool';
+
+my ($dev, $mac, $mac_update);
+my %skip_interface;
+my ($check_name, $show_names, $vif_name, $warn_name, $check_non_switched);
+my ($check_up, $dhcp_command, $allowed_speed, $restore_ipv6);
+my (@speed_duplex, @addr_commit, @check_speed);
+
+sub usage {
+    print <<EOF;
+Usage: $0 --dev=<interface> --check=<type>
+       $0 --dev=<interface> --warn
+       $0 --dev=<interface> --valid-mac=<aa:aa:aa:aa:aa:aa>
+       $0 --dev=<interface> --valid-addr-commit={addr1 addr2 ...}
+       $0 --dev=<interface> --speed-duplex=speed,duplex
+       $0 --dev=<interface> --check-speed=speed,duplex
+       $0 --dev=<interface> --allowed-speed
+       $0 --dev=<interface> --isup
+       $0 --dev=<interface> --restore-ipv6
+       $0 --dev=<interface> --check-non-switched
+       $0 --show=<type>
+EOF
+    exit 1;
+}
+
+GetOptions("valid-addr-commit=s{,}" => \@addr_commit,
+           "dev=s"             => \$dev,
+	   "valid-mac=s"       => \$mac,
+	   "set-mac=s"	       => \$mac_update,
+	   "dhcp=s"	       => \$dhcp_command,
+	   "check=s"	       => \$check_name,
+	   "show=s"	       => \$show_names,
+	   "skip=s"	       => sub { $skip_interface{$_[1]} = 1 },
+	   "vif=s"	       => \$vif_name,
+	   "warn"	       => \$warn_name,
+	   "isup"	       => \$check_up,
+	   "speed-duplex=s{2}" => \@speed_duplex,
+	   "check-speed=s{2}"  => \@check_speed,
+	   "allowed-speed"     => \$allowed_speed,
+	   "restore-ipv6"      => \$restore_ipv6,
+	   "check-non-switched"    => \$check_non_switched,
+) or usage();
+
+is_valid_addr_commit($dev, @addr_commit) if (@addr_commit);
+is_valid_mac($mac, $dev)		if ($mac);
+update_mac($mac_update, $dev)		if ($mac_update);
+dhcp($dhcp_command, $dev)	if ($dhcp_command);
+is_valid_name($check_name, $dev)	if ($check_name);
+exists_name($dev)			if ($warn_name);
+show_interfaces($show_names)		if ($show_names);
+is_up($dev)			        if ($check_up);
+set_speed_duplex($dev, @speed_duplex)   if (@speed_duplex);
+check_speed_duplex($dev, @check_speed)  if (@check_speed);
+allowed_speed($dev)			if ($allowed_speed);
+restore_ipv6_addr($dev)                 if ($restore_ipv6);
+check_non_switched($dev)                if ($check_non_switched);
+exit 0;
+
+sub is_ip_configured {
+    my ($intf, $ip) = @_;
+    my $found = grep { $_ eq $ip } Vyatta::Misc::getIP($intf);
+    return ($found > 0);
+}
+
+sub is_ipv4 {
+    return index($_[0],':') < 0;
+}
+
+sub is_up {
+    my $name = shift;
+    my $intf = new Vyatta::Interface($name);
+    
+    die "Unknown interface type for $name" unless $intf;
+    
+    exit 0 if ($intf->up());
+    exit 1;
+}
+
+sub dhcp_write_file {
+    my ($file, $data) = @_;
+
+    open(my $fh, '>', $file) || die "Couldn't open $file - $!";
+    print $fh $data;
+    close $fh;
+}
+
+sub dhcp_conf_header {
+    my $output;
+
+    my $date = `date`;
+    chomp $date;
+    $output  = "#\n# autogenerated by vyatta-interfaces.pl on $date\n#\n";
+    return $output;
+}
+
+sub get_hostname {
+    my $config = new Vyatta::Config;
+    $config->setLevel("system");
+    return $config->returnValue("host-name");
+}
+
+sub is_domain_name_set {
+    my $config = new Vyatta::Config;
+    $config->setLevel("system");
+    return $config->returnValue("domain-name");
+}
+
+sub get_mtu {
+    my $name = shift;
+    my $intf = new Vyatta::Interface($name);
+    return $intf->mtu();
+}
+
+sub replace_quot {
+    my $line = shift;
+    my $count = $line =~ s/\&quot;/\"/g;
+
+    if ( $count ne '' and $count % 2 ) {
+        print "Error: unbalanced quotes [$line]\n";
+        exit 1;
+    }
+    return $line;
+}
+
+sub get_client_options {
+    my $name = shift;
+    
+    my $config = new Vyatta::Config;
+    my $intf = new Vyatta::Interface($name);
+    my $path = $intf->path();
+    $config->setLevel("$path dhcp-options");    
+    my @options = $config->returnValues('client-option');
+    my $output = '';
+    foreach my $line (@options) {
+        my $decoded_line = replace_quot($line);
+        $output .= "\t$decoded_line\n";
+    }
+    return $output;
+}
+
+sub dhcp_update_config {
+    my ($conf_file, $intf) = @_;
+    
+    my $output = dhcp_conf_header();
+    my $hostname = get_hostname();
+
+    $output .= "option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n\n";
+#-- FD ligne ajoutée pour LIVEBOX ORANGE Option 90
+    $output .= "option rfc3118-auth code 90 = string;\n\n";
+
+    $output .= "interface \"$intf\" {\n";
+    if (defined($hostname)) {
+       $output .= "\tsend host-name \"$hostname\";\n";
+    }
+    $output .= "\trequest subnet-mask, broadcast-address, routers, domain-name-servers";
+    my $domainname = is_domain_name_set();
+    if (!defined($domainname)) {
+       $output .= ", domain-name";
+    } 
+
+    my $mtu = get_mtu($intf);
+    $output .= ", interface-mtu" unless $mtu;
+    $output .= ";\n";
+
+    $output .= get_client_options($intf);
+
+    $output .= "}\n\n";
+
+    dhcp_write_file($conf_file, $output);
+}
+
+# Is interface disabled in configuration (only valid in config mode)
+sub is_intf_disabled {
+    my $name = shift;
+    my $intf = new Vyatta::Interface($name);
+    $intf or die "Unknown interface name/type: $name\n";
+
+    my $config = new Vyatta::Config;
+    $config->setLevel($intf->path());
+
+    return $config->exists("disable");
+}
+
+sub run_dhclient {
+    my ($intf, $op_mode) = @_;
+
+    my ($intf_config_file, $intf_process_id_file, $intf_leases_file)
+        = generate_dhclient_intf_files($intf);
+
+    # perform config mode actions if not called from op-mode
+    if (!defined $op_mode) {
+      dhcp_update_config($intf_config_file, $intf);
+      return if is_intf_disabled($intf);
+    }
+
+    my $cmd = '';
+    if ( -e  $intf_process_id_file) {
+        my $pid = `cat $intf_process_id_file`; chomp $pid;
+        $cmd = "kill $pid 2> /dev/null; rm -f $intf_process_id_file 2> /dev/null;";
+    }
+    $cmd .= "$dhcp_daemon -q -nw -cf $intf_config_file -pf $intf_process_id_file  -lf $intf_leases_file $intf 2> /dev/null &";
+    # adding & at the end to make the process into a daemon immediately
+    system ($cmd) == 0
+	or warn "start $dhcp_daemon failed: $?\n";
+}
+
+sub stop_dhclient {
+    my ($intf, $op_mode) = @_;
+
+    # perform config mode actions if not called from op-mode
+    if (!defined $op_mode) {
+      return if is_intf_disabled($intf);
+    }
+
+    my ($intf_config_file, $intf_process_id_file, $intf_leases_file)
+	= generate_dhclient_intf_files($intf);
+    my $release_cmd = "$dhcp_daemon -q -cf $intf_config_file -pf $intf_process_id_file -lf $intf_leases_file -r $intf 2> /dev/null;";
+    $release_cmd .= "rm -f $intf_process_id_file 2> /dev/null";
+    system ($release_cmd) == 0
+	or warn "stop $dhcp_daemon failed: $?\n";
+}
+
+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 "ip link set $intf down"
+	    and die "Could not set $intf down ($!)\n";
+	system "ip link set $intf address $mac"
+	    and die "Could not set $intf address ($!)\n";
+	system "ip link set $intf up"
+	    and die "Could not set $intf up ($!)\n";
+    } else {
+	system "ip link set $intf address $mac"
+	    and die "Could not set $intf address ($!)\n";
+    }
+    exit 0;
+}
+ 
+sub is_valid_mac {
+    my ($mac, $intf) = @_;
+    my @octets = split /:/, $mac;
+    
+    ($#octets == 5) or die "Error: wrong number of octets: $#octets\n";
+
+    ((hex($octets[0]) & 1) == 0) or die "Error: $mac is a multicast address\n";
+
+    my $sum = 0;
+    $sum += hex( $_) foreach @octets;
+    ( $sum != 0 ) or die "Error: zero is not a valid address\n";
+
+    exit 0;
+}
+
+# Validate the set of address values configured on an interface at commit
+# Check that full set of address address values are consistent. 
+#  1. Interface may not be part of bridge or bonding group
+#  2. Can not have both DHCP and a static IPv4 address.
+sub is_valid_addr_commit {
+    my ($ifname, @addrs) = @_;
+    my $intf = new Vyatta::Interface($ifname);
+    $intf or die "Unknown interface name/type: $ifname\n";
+
+    my $config = new Vyatta::Config;
+    $config->setLevel($intf->path());
+
+    my $bridge = $config->returnValue("bridge-group bridge");
+    die "Can't configure address on interface that is port of bridge.\n"
+	if (defined($bridge));
+
+    my $bond = $config->returnValue("bond-group");
+    die "Can't configure address on interface that is slaved to bonding interface.\n"
+	if (defined($bond));
+
+    # Map of all the ip addresses
+    my %ipaddr_hash = map { $_ => 1 } getIP();
+
+    my ($dhcp, $static_v4);
+    foreach my $addr (@addrs) {
+	next if ($addr eq 'dhcpv6');
+	if ($addr eq 'dhcp') {
+	    $dhcp = 1;
+  } elsif (!Vyatta::Interface::is_uniq_address($addr)) {
+    my $h = Vyatta::Misc::get_ipnet_intf_hash();
+            print "Error: duplicate address $addr on $h->{$addr}\n";
+            exit 1;
+	} elsif ( is_ipv4($addr) ) {
+	    $static_v4 = 1;
+        }
+    }
+
+    die "Can't configure static IPv4 address and DHCP on the same interface.\n"
+	    if ($static_v4 && $dhcp);
+
+    exit 0;
+}
+
+# Is interface currently in admin down state?
+sub is_intf_down {
+    my $name = shift;
+    my $intf = new Vyatta::Interface($name);
+
+    return 1 unless $intf;
+    return ! $intf->up();
+}
+
+sub dhcp {
+    my ($request, $intf) = @_;
+
+    die "$intf is not using DHCP to get an IP address\n"
+	unless ($request eq 'start' || is_dhcp_enabled($intf));
+    
+    die "$intf is disabled.\n"
+    	if ($request ne 'stop' && is_intf_down($intf));
+
+    my $tmp_dhclient_dir = '/var/run/vyatta/dhclient/';
+    my $release_file = $tmp_dhclient_dir . 'dhclient_release_' . $intf;
+    if ($request eq "release") {
+	die "IP address for $intf has already been released.\n"
+	    if (-e $release_file);
+
+	print "Releasing DHCP lease on $intf ...\n";
+	stop_dhclient($intf, 'op_mode');
+	mkdir ($tmp_dhclient_dir) if (! -d $tmp_dhclient_dir );
+	touch ($release_file);
+    } elsif ($request eq "renew") {
+        print "Renewing DHCP lease on $intf ...\n";
+        run_dhclient($intf, 'op_mode');
+	unlink ($release_file);
+    } elsif ($request eq "start") {
+	print "Starting DHCP client on $intf ...\n";
+	touch("/var/run/$intf");
+	run_dhclient($intf);
+    } elsif ($request eq "stop") {
+	print "Stopping DHCP client on $intf ...\n";
+	stop_dhclient($intf);
+	unlink("/var/run/dhclient_$intf\_lease");
+	unlink("/var/run/$intf");
+	unlink("/var/run/vyatta/dhclient/dhclient_release_$intf");
+        unlink("/var/run/dhclient_$intf\.conf");
+    } else {
+	die "Unknown DHCP request: $request\n";
+    }
+
+    exit 0;
+}
+
+sub is_valid_name {
+    my ($type, $name) = @_;
+    die "Missing --dev argument\n" unless $name;
+
+    my $intf = new Vyatta::Interface($name);
+    die "$name does not match any known interface name type\n"
+	unless $intf;
+
+    my $vif = $intf->vif();
+    die "$name is the name of VIF interface\n" ,
+        "Need to use \"interface ",$intf->physicalDevice()," vif $vif\"\n"
+	    if $vif;
+
+    die "$name is a ", $intf->type(), " interface not an $type interface\n"
+	if ($type ne 'all' and $intf->type() ne $type);
+
+    die "$type interface $name does not exist on system\n"
+	unless grep { $name eq $_ } getInterfaces();
+
+    exit 0;
+}
+
+sub exists_name {
+    my $name = shift;
+    die "Missing --dev argument\n" unless $name;
+
+    warn "interface $name does not exist on system\n"
+	unless grep { $name eq $_ } getInterfaces();
+    exit 0;
+}
+
+# generate one line with all known interfaces (for allowed)
+sub show_interfaces {
+    my $type = shift;
+    my @interfaces = getInterfaces();
+    my @match;
+
+    foreach my $name (@interfaces) {
+	my $intf = new Vyatta::Interface($name);
+	next unless $intf;		# skip unknown types
+	next if $skip_interface{$name};
+	next unless ($type eq 'all' || $type eq $intf->type());
+
+	if ($vif_name) {
+	    next unless $intf->vif();
+	    push @match, $intf->vif()
+		if ($vif_name eq $intf->physicalDevice());
+	} else {
+	    push @match, $name
+		unless $intf->vif() and $type ne 'all';
+	}
+    }
+    print join(' ', @match), "\n";
+}
+
+# Determine current values for autoneg, speed, duplex
+sub get_ethtool {
+    my $dev = shift;
+
+    open( my $ethtool, '-|', "$ETHTOOL $dev 2>&1" )
+      or die "ethtool failed: $!\n";
+
+    # ethtool produces:
+    #
+    # Settings for eth1:
+    # Supported ports: [ TP ]
+    # ...
+    # Speed: 1000Mb/s
+    # Duplex: Full
+    # ...
+    # Auto-negotiation: on
+    my ($rate, $duplex);
+    my $autoneg = 0;
+    while (<$ethtool>) {
+	chomp;
+	return if ( /^Cannot get device settings/ );
+
+	if ( /^\s+Speed: (\d+)Mb/ ) {
+	    $rate = $1;
+	} elsif ( /^\s+Duplex:\s(.*)$/ ) {
+	    $duplex = lc $1;
+        } elsif ( /^\s+Auto-negotiation: on/ ) {
+	    $autoneg = 1;
+	}
+    }
+    close $ethtool;
+    return ($autoneg, $rate, $duplex);
+}
+
+sub set_speed_duplex {
+    my ($intf, $nspeed, $nduplex) = @_;
+    die "Missing --dev argument\n" unless $intf;
+
+    # read old values to avoid meaningless speed changes
+    my ($autoneg, $ospeed, $oduplex) = get_ethtool($intf);
+
+    if (defined($autoneg) && $autoneg == 1) {
+	# Device is already in autonegotiation mode
+	return if ($nspeed eq 'auto');
+    } elsif (defined($ospeed) && defined($oduplex)) {
+	# Device has explicit speed/duplex but they already match
+	return if (($nspeed eq $ospeed) && ($nduplex eq $oduplex));
+    }
+
+    my $cmd = "$ETHTOOL -s $intf";
+    if ($nspeed eq 'auto') {
+	$cmd .= " autoneg on";
+    } else {
+	$cmd .= " speed $nspeed duplex $nduplex autoneg off";
+    }
+
+    exec $cmd;
+    die "exec of $ETHTOOL failed: $!";
+}
+
+# Check if speed and duplex value is supported by device
+sub is_supported_speed {
+    my ($dev, $speed, $duplex) = @_;
+
+    my $wanted = sprintf("%dbase%s/%s", $speed,
+			 ($speed == 2500) ? 'X' : 'T', ucfirst($duplex));
+
+    open( my $ethtool, '-|', "$ETHTOOL $dev 2>/dev/null" )
+      or die "ethtool failed: $!\n";
+
+    # ethtool output:
+    #
+    # Settings for eth1:
+    #	Supported ports: [ TP ]
+    #	Supported link modes:   10baseT/Half 10baseT/Full
+    #	                        100baseT/Half 100baseT/Full
+    #	                        1000baseT/Half 1000baseT/Full
+    #   Supports auto-negotiation: Yes
+    my $mode;
+    while (<$ethtool>) {
+	chomp;
+	if ($mode) {
+	    last unless /^\t /;
+	} else {
+	    next unless /^\tSupported link modes: /;
+	    $mode = 1;
+	}
+
+	return 1 if /$wanted/;
+    }
+
+    close $ethtool;
+    return;
+}
+
+# Validate speed and duplex settings prior to commit
+sub check_speed_duplex {
+    my ($dev, $speed, $duplex) = @_;
+
+    # most basic and default case
+    exit 0 if ($speed eq 'auto' && $duplex eq 'auto');
+
+    die "If speed is hardcoded, duplex must also be hardcoded\n"
+	if ($duplex eq 'auto');
+
+    die "If duplex is hardcoded, speed must also be hardcoded\n"
+	if ($speed eq 'auto');
+
+    die "Speed $speed, duplex $duplex not supported on $dev\n"
+	unless is_supported_speed($dev, $speed, $duplex);
+
+    exit 0;
+}
+
+# Produce list of valid speed values for device
+sub allowed_speed {
+    my ($dev) = @_;
+
+    open( my $ethtool, '-|', "$ETHTOOL $dev 2>/dev/null" )
+      or die "ethtool failed: $!\n";
+
+    my %speeds;
+    my $first = 1;
+    while (<$ethtool>) {
+	chomp;
+
+	if ($first) {
+	    next unless s/\tSupported link modes:\s//;
+	    $first = 0;
+	} else {
+	    last unless /^\t /;
+	}
+
+	foreach my $val (split / /) {
+	    $speeds{$1} = 1 if $val =~ /(\d+)base/;
+	}
+    }
+
+    close $ethtool;
+    print 'auto ', join(' ', sort keys %speeds), "\n";
+}
+
+sub _restore_ipv6_addr {
+    my ($name, @addrs) = @_;
+
+    foreach my $addr (@addrs) {
+        next if ($addr eq 'dhcp');
+        next if ($addr eq 'dhcpv6');
+        my $version = is_ip_v4_or_v6($addr);
+        next unless $version;
+        next unless ($version == 6);
+    
+        system("sudo ip -6 addr add $addr dev $name") == 0
+            or die "restoring $addr failed: $!\n";
+    }
+}
+
+# work around for loss of ipv6 addresses on admin done
+sub restore_ipv6_addr {
+    my $name = shift;
+    my $config = new Vyatta::Config;
+
+    # No longer need to restore
+    return;
+
+    my $intf = new Vyatta::Interface($name);
+    die "$name does not match any known interface name type\n"
+	unless $intf;
+
+    my $path = $intf->path();
+
+    $config->setLevel($path);
+    my @addrs = $config->returnValues('address');
+    _restore_ipv6_addr($name, @addrs);
+
+    if ($config->exists('vif')) {
+        my @vifs = $config->listNodes('vif');
+        foreach my $vif (@vifs) {
+            $config->setLevel("$path vif $vif");            
+            @addrs = $config->returnValues('address');
+            _restore_ipv6_addr("$name.$vif", @addrs);
+        }
+    }
+}
+
+sub check_non_switched {
+    my $i_intf = shift;
+    my $config = new Vyatta::Config;
+    $config->setLevel("interfaces switch switch0 switch-port");
+
+    my $intfs =  [$config->returnValues("interface")];
+    foreach my $intf ( @{$intfs} ) {
+        exit 1 if ($intf eq $i_intf);
+    }
+}