summaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
authorStig Thormodsrud <stig@vyatta.com>2007-11-27 10:37:15 -0800
committerStig Thormodsrud <stig@vyatta.com>2007-11-27 10:37:15 -0800
commitfae7c4099efc2f247ed9eb4a52f3839bcedf987a (patch)
tree07c0a7c5a20c5d86c0cfbdfa2801a261c2741194 /scripts
parent65b95aa0fd0210501bd828299f561925269b6321 (diff)
downloadvyatta-cfg-fae7c4099efc2f247ed9eb4a52f3839bcedf987a.tar.gz
vyatta-cfg-fae7c4099efc2f247ed9eb4a52f3839bcedf987a.zip
Fix 2497: check for duplicate ip address.
Also while we're add it, allow user to set an ipv6 address or get address from dhcp.
Diffstat (limited to 'scripts')
-rw-r--r--scripts/vyatta-interfaces.pl339
1 files changed, 339 insertions, 0 deletions
diff --git a/scripts/vyatta-interfaces.pl b/scripts/vyatta-interfaces.pl
new file mode 100644
index 0000000..d7ba950
--- /dev/null
+++ b/scripts/vyatta-interfaces.pl
@@ -0,0 +1,339 @@
+#!/usr/bin/perl
+#
+# Module: vyatta-interfaces.pl
+#
+# **** License ****
+# Version: VPL 1.0
+#
+# The contents of this file are subject to the Vyatta Public License
+# Version 1.0 ("License"); you may not use this file except in
+# compliance with the License. You may obtain a copy of the License at
+# http://www.vyatta.com/vpl
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# 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 VyattaConfig;
+use VyattaMisc;
+use Getopt::Long;
+
+use NetAddr::IP;
+
+use strict;
+use warnings;
+
+my $dhcp_daemon = '/sbin/dhclient';
+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, $dev);
+GetOptions("eth-addr-update=s" => \$eth_update,
+ "eth-addr-delete=s" => \$eth_delete,
+ "valid-addr=s" => \$addr,
+ "dev=s" => \$dev,
+);
+
+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); }
+
+
+sub is_ip_duplicate {
+ my $ip = shift;
+
+ #
+ # get a list of all ipv4 and ipv6 addresses
+ #
+ my @ipaddrs = `ip addr show | grep inet | cut -d" " -f6`;
+ chomp @ipaddrs;
+ my %ipaddrs_hash = map { $_ => 1 } @ipaddrs;
+
+ if (defined $ipaddrs_hash{$ip}) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+sub is_dhcp_running {
+ if (-f $dhcp_pid) {
+ my $pid = `cat $dhcp_pid`;
+ chomp $pid;
+ my $ps = `ps -p $pid -o comm=`;
+
+ if (defined($ps) && $ps ne "") {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+sub dhcp_start_daemon {
+ my $cmd = "$dhcp_daemon -q -nw &";
+ system($cmd);
+}
+
+sub dhcp_stop_daemon {
+ if (is_dhcp_running()) {
+ my $pid = `cat $dhcp_pid`;
+ system("kill $pid");
+ }
+ system("rm -f $dhcp_pid");
+}
+
+sub dhcp_restart_daemon {
+ if (is_dhcp_running()) {
+ dhcp_stop_daemon();
+ }
+ dhcp_start_daemon();
+}
+
+sub dhcp_release_addr {
+ my $intf = shift;
+ my $cmd = "$dhcp_daemon -q -r $intf 2> /dev/null";
+ system($cmd);
+}
+
+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";
+ $output .= "request subnet-mask, broadcast-address, time-offset, routers,\n";
+ $output .= "\tdomain-name, domain-name-servers, host-name,\n";
+ $output .= "\tinterface-mtu;\n\n";
+ return $output;
+}
+
+sub dhcp_get_interfaces {
+ my @dhcp_intfs;
+
+ my $config = new VyattaConfig;
+
+ $config->setLevel("interfaces ethernet");
+ my @eths = $config->listNodes();
+ foreach my $eth (@eths) {
+ $config->setLevel("interfaces ethernet $eth");
+ if ($config->exists("address")) {
+ my @addrs = $config->returnValues("address");
+ foreach my $addr (@addrs) {
+ if (defined $addr && $addr eq "dhcp") {
+ push @dhcp_intfs, $eth;
+ }
+ }
+ }
+ $config->setLevel("interfaces ethernet $eth vif");
+ my @vifs = $config->listNodes();
+ foreach my $vif (@vifs) {
+ $config->setLevel("interfaces ethernet $eth vif $vif");
+ my @addrs = $config->returnValues("address");
+ foreach my $addr (@addrs) {
+ if (defined $addr && $addr eq "dhcp") {
+ push @dhcp_intfs, "$eth.$vif";
+ }
+ }
+ }
+ }
+ return @dhcp_intfs;
+}
+
+sub is_dhcp_enabled {
+ my $intf = shift;
+
+ my $config = new VyattaConfig;
+
+ if ($intf =~ m/(\w+)\.(\d)/) {
+ $config->setLevel("interfaces ethernet $1 vif $2");
+ } else {
+ $config->setLevel("interfaces ethernet $intf");
+ }
+ my @addrs = $config->returnOrigValues("address");
+ foreach my $addr (@addrs) {
+ if (defined $addr && $addr eq "dhcp") {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+sub is_address_enabled {
+ my $intf = shift;
+
+ my $config = new VyattaConfig;
+
+ if ($intf =~ m/(\w+)\.(\d)/) {
+ $config->setLevel("interfaces ethernet $1 vif $2");
+ } else {
+ $config->setLevel("interfaces ethernet $intf");
+ }
+ my @addrs = $config->returnOrigValues("address");
+ foreach my $addr (@addrs) {
+ if (defined $addr && $addr ne "dhcp") {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+sub dhcp_update_config {
+ my $output = dhcp_conf_header();
+
+ my $config = new VyattaConfig;
+ my $dhcp_instances = 0;
+ my @dhcp_intfs = dhcp_get_interfaces();
+ foreach my $intf (@dhcp_intfs) {
+ $output .= "interface \"$intf\" {\n}\n\n";
+ $dhcp_instances++;
+ }
+
+ if ($dhcp_instances > 0) {
+ my $conf_file = $dhcp_conf;
+ dhcp_write_file($conf_file, $output);
+ dhcp_restart_daemon();
+ }
+ return $dhcp_instances;
+}
+
+sub update_dhcp_client {
+ my $dhcp_instances = dhcp_update_config();
+ if ($dhcp_instances == 0) {
+ dhcp_stop_daemon();
+ }
+}
+
+sub is_ip_v4_or_v6 {
+ my $addr = shift;
+
+ my $ip = NetAddr::IP->new($addr);
+ if (defined $ip && $ip->version() == 4) {
+ return 4;
+ }
+ $ip = NetAddr::IP->new6($addr);
+ if (defined $ip && $ip->version() == 6) {
+ return 6;
+ }
+
+ return undef;
+}
+
+sub update_eth_addrs {
+ my ($addr, $intf) = @_;
+
+ if ($addr eq "dhcp") {
+ update_dhcp_client();
+ return;
+ }
+ my $version = is_ip_v4_or_v6($addr);
+ if (!defined $version) {
+ exit 1;
+ }
+
+ if ($version == 4) {
+ return system("ip addr add $addr broadcast + dev $intf");
+ }
+ if ($version == 6) {
+ return system("ip -6 addr add $addr dev $intf");
+ }
+ print "Error: Invalid address/prefix [$addr] for interface $intf\n";
+ exit 1;
+}
+
+sub delete_eth_addrs {
+ my ($addr, $intf) = @_;
+
+ if ($addr eq "dhcp") {
+ dhcp_release_addr($intf);
+ update_dhcp_client();
+ return;
+ }
+ my $version = is_ip_v4_or_v6($addr);
+ if (!defined $version) {
+ exit 1;
+ }
+ if ($version == 4) {
+ return system("ip addr del $addr dev $intf");
+ }
+ if ($version == 6) {
+ return system("ip -6 addr del $addr dev $intf");
+ }
+}
+
+sub is_valid_addr {
+ my ($addr_net, $intf) = @_;
+
+ if ($addr_net eq "dhcp") {
+ if (is_dhcp_enabled($intf)) {
+ print "Error: dhcp already configured for $intf\n";
+ exit 1;
+ }
+ if (is_address_enabled($intf)) {
+ print "Error: remove static addresses before enabling dhcp for $intf\n";
+ exit 1;
+ }
+ exit 0;
+ }
+
+ my ($addr, $net);
+ if ($addr_net =~ m/^([0-9\.\:]+)\/(\d+)$/) {
+ $addr = $1;
+ $net = $2;
+ } else {
+ exit 1;
+ }
+
+ my $version = is_ip_v4_or_v6($addr_net);
+ if (!defined $version) {
+ exit 1;
+ }
+
+ if (is_dhcp_enabled($intf)) {
+ print "Error: remove dhcp before adding static addresses for $intf\n";
+ exit 1;
+ }
+ if (is_ip_duplicate($addr_net)) {
+ print "Error: duplicate address/prefix [$addr_net]\n";
+ exit 1;
+ }
+
+ if ($version == 4) {
+ if ($net > 0 && $net <= 32) {
+ exit 0;
+ }
+ }
+ if ($version == 6) {
+ if ($net > 1 && $net <= 128) {
+ exit 0;
+ }
+ }
+
+ exit 1;
+}
+
+exit 0;
+
+# end of file