summaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'scripts')
-rwxr-xr-xscripts/VyattaConfigLoad.pm62
-rwxr-xr-xscripts/VyattaConfigOutput.pm43
-rw-r--r--scripts/vyatta-config-gen-sets.pl58
-rw-r--r--[-rwxr-xr-x]scripts/vyatta-interfaces.pl244
-rwxr-xr-xscripts/vyatta-load-config.pl75
-rwxr-xr-xscripts/vyatta-save-config.pl69
6 files changed, 380 insertions, 171 deletions
diff --git a/scripts/VyattaConfigLoad.pm b/scripts/VyattaConfigLoad.pm
index b69723a..f1339c3 100755
--- a/scripts/VyattaConfigLoad.pm
+++ b/scripts/VyattaConfigLoad.pm
@@ -23,49 +23,56 @@ package VyattaConfigLoad;
use strict;
use sort 'stable';
use lib "/opt/vyatta/share/perl5/";
-use XorpConfigParser;
+use XorpConfigParser;
use VyattaConfig;
# configuration ordering. higher rank configured before lower rank.
my $default_rank = 0;
my %config_rank = (
- 'qos-policy' => 110,
- 'firewall' => 102,
- 'service nat' => 101,
- 'interfaces' => 100,
- 'interfaces bridge' => 99,
- 'interfaces ethernet' => 98,
- 'interfaces tunnel' => 91,
- 'system' => 90,
- 'protocols static' => 85,
- 'service ssh' => 84,
- 'service telnet' => 83,
- 'policy' => 82,
- 'vpn' => 80,
+ 'qos-policy' => 1100,
+ 'firewall' => 1020,
+ 'service nat' => 1010,
+ 'interfaces' => 1000,
+ 'interfaces bridge' => 990,
+ 'interfaces ethernet' => 980,
+ 'interfaces tunnel' => 910,
+ 'system gateway-address' => 890,
+ 'system name-server' => 880,
+ 'system login user' => 870,
+ 'system' => 860,
+ 'protocols static' => 850,
+ 'service ssh' => 840,
+ 'service telnet' => 830,
+ 'policy' => 820,
+ 'protocols bgp' => 790,
+ 'protocols ospf parameters' => 785,
+ 'protocols ospf' => 780,
+ 'protocols rip' => 770,
+ 'vpn' => 600,
+
);
-my %wildcard_rank = (
- 'interfaces ethernet * vrrp' => 50,
- 'interfaces ethernet * vif * vrrp' => 50,
+my %regex_rank = (
+ 'interfaces ethernet \S* vrrp' => 500,
+ 'interfaces ethernet \S* vif \S* vrrp' => 500,
+ 'protocols bgp \d+ parameters' => 810,
+ 'protocols bgp \d+ neighbor \S*[^\d.]\S*' => 800,
);
my @all_nodes = ();
my @all_naked_nodes = ();
-# the wildcard matching could use some serious optimization. but probably
-# not when we only have a couple of entries.
-sub match_wildcard {
+sub match_regex {
my ($pattern, $str) = @_;
- $pattern =~ s/\*/\\S*/g;
$pattern =~ s/^(.*)$/\^$1\$/;
return ($str =~ m/$pattern/) ? 1 : 0;
}
-sub get_wildcard_rank {
+sub get_regex_rank {
my ($str) = @_;
- foreach (keys %wildcard_rank) {
- if (match_wildcard($_, $str)) {
- return $wildcard_rank{$_};
+ foreach (keys %regex_rank) {
+ if (match_regex($_, $str)) {
+ return $regex_rank{$_};
}
}
return undef;
@@ -79,7 +86,7 @@ sub get_config_rank {
if (defined($config_rank{$path_str})) {
return ($config_rank{$path_str});
}
- my $wrank = get_wildcard_rank($path_str);
+ my $wrank = get_regex_rank($path_str);
return $wrank if (defined($wrank));
pop @path;
}
@@ -289,6 +296,9 @@ sub findDeletedNodes {
$active_cfg->setLevel(join ' ', @active_path);
my @active_nodes = $active_cfg->listOrigNodes();
foreach (@active_nodes) {
+ if ($_ eq 'def') {
+ next;
+ }
if ($_ eq 'node.val') {
findDeletedValues($new_ref, \@active_path);
next;
diff --git a/scripts/VyattaConfigOutput.pm b/scripts/VyattaConfigOutput.pm
index 2766b64..5358c21 100755
--- a/scripts/VyattaConfigOutput.pm
+++ b/scripts/VyattaConfigOutput.pm
@@ -133,8 +133,12 @@ sub displayValues {
$nval = "\"$nval\"";
}
}
+
+ my %cnodes = $config->listNodeStatus();
+ my @cnames = sort keys %cnodes;
+
if (defined($simple_show)) {
- if (!defined($default) || $default ne $oval || $show_all) {
+ if (!$cnodes{'def'} || $show_all) {
if ($is_password && $hide_password) {
$oval = $HIDE_PASSWORD;
}
@@ -155,7 +159,7 @@ sub displayValues {
$diff = '>';
}
}
- if (!defined($default) || $default ne $value || $show_all) {
+ if (!$cnodes{'def'} || $show_all) {
if ($is_password && $hide_password) {
$value = $HIDE_PASSWORD;
}
@@ -186,9 +190,12 @@ sub displayDeletedOrigChildren {
my $is_tag = $config->isTagNode([ @cur_path, $child ]);
$config->setLevel(join ' ', (@cur_path, $child));
my @cnames = sort $config->listOrigNodes();
- if ($#cnames == 0 && $cnames[0] eq 'node.val') {
+
+ if ($cnames[0] eq 'node.val') {
displayValues([ @cur_path, $child ], $prefix, $child,
$dont_show_as_deleted);
+ } elsif ($cnames[0] eq 'def') {
+ #ignore
} elsif (scalar($#cnames) >= 0) {
if ($is_tag) {
@cnames = sort versioncmp @cnames;
@@ -242,7 +249,20 @@ sub displayChildren {
$config->setLevel(join ' ', (@cur_path, $child));
my %cnodes = $config->listNodeStatus();
my @cnames = sort keys %cnodes;
- if ($#cnames == 0 && $cnames[0] eq 'node.val') {
+
+ #if node.val exists and ct == 0 w/o def or ct ==1 w/ def
+ my $leaf = 0;
+ if ($cnodes{'def'}) {
+ if ($#cnames == 1 && $cnodes{'node.val'}) {
+ $leaf = 1;
+ }
+ } else {
+ if ($#cnames == 0 && $cnodes{'node.val'}) {
+ $leaf = 1;
+ }
+ }
+
+ if ($leaf == 1) {
displayValues([ @cur_path, $child ], $prefix, $child);
} elsif (scalar($#cnames) >= 0) {
if ($is_tag) {
@@ -309,7 +329,20 @@ sub outputNewConfig {
my %rnodes = $config->listNodeStatus();
if (scalar(keys %rnodes) > 0) {
my @rn = keys %rnodes;
- if ($#rn == 0 && $rn[0] eq 'node.val') {
+
+ #if node.val exists and ct == 0 w/o def or ct ==1 w/ def
+ my $leaf = 0;
+ if ($rnodes{'def'}) {
+ if ($#rn == 1 && $rnodes{'node.val'}) {
+ $leaf = 1;
+ }
+ } else {
+ if ($#rn == 0 && $rnodes{'node.val'}) {
+ $leaf = 1;
+ }
+ }
+
+ if ($leaf == 1) {
# this is a leaf value-node
displayValues([ @_ ], '', $_[$#_]);
} else {
diff --git a/scripts/vyatta-config-gen-sets.pl b/scripts/vyatta-config-gen-sets.pl
new file mode 100644
index 0000000..b9b083e
--- /dev/null
+++ b/scripts/vyatta-config-gen-sets.pl
@@ -0,0 +1,58 @@
+#!/usr/bin/perl
+
+# Author: An-Cheng Huang <ancheng@vyatta.com>
+# Date: 2007
+# Description: hack of vyatta-config-load.pl to simple generate
+# a list of the "set" commands from a config file.
+
+# **** 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.
+#
+# This code was originally developed by Vyatta, Inc.
+# Portions created by Vyatta are Copyright (C) 2006, 2007, 2008 Vyatta, Inc.
+# All Rights Reserved.
+# **** End License ****
+
+# Perl script for loading the startup config file.
+# $0: startup config file.
+
+use strict;
+use lib "/opt/vyatta/share/perl5/";
+use VyattaConfigLoad;
+
+my $conf_file = '/opt/vyatta/etc/config/config.boot';
+
+$conf_file = $ARGV[0] if defined $ARGV[0];
+
+# get a list of all config statement in the startup config file
+# (sorted by rank).
+my @all_nodes = VyattaConfigLoad::getStartupConfigStatements($conf_file);
+if (scalar(@all_nodes) == 0) {
+ # no config statements
+ exit 1;
+}
+my $cur_rank = ${$all_nodes[0]}[1];
+
+my $ret = 0;
+# higher-ranked statements committed before lower-ranked.
+foreach (@all_nodes) {
+ my ($path_ref, $rank) = @$_;
+ if ($rank != $cur_rank) {
+ # commit all nodes with the same rank together.
+ print "commit\n";
+ $cur_rank = $rank;
+ }
+ my $cmd = "set " . (join ' ', @$path_ref);
+ print "$cmd\n";
+}
+print "commit\n";
+
+exit 0;
+
diff --git a/scripts/vyatta-interfaces.pl b/scripts/vyatta-interfaces.pl
index aa82b78..1511c12 100755..100644
--- a/scripts/vyatta-interfaces.pl
+++ b/scripts/vyatta-interfaces.pl
@@ -37,26 +37,23 @@ use VyattaMisc;
use Getopt::Long;
use POSIX;
use NetAddr::IP;
-use Tie::File;
-use Fcntl qw (:flock);
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 $dhclient_dir = '/var/lib/dhcp3/';
-my ($eth_update, $eth_delete, $addr, $restart_dhclient, $dev, $mac, $mac_update);
+
+my ($eth_update, $eth_delete, $addr, $dev, $mac, $mac_update, $op_dhclient);
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,
+ "op-command=s" => \$op_dhclient,
);
if (defined $eth_update) { update_eth_addrs($eth_update, $dev); }
@@ -64,7 +61,7 @@ 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(); }
+if (defined $op_dhclient) { op_dhcp_command($op_dhclient, $dev); }
sub is_ip_configured {
my ($intf, $ip) = @_;
@@ -99,54 +96,6 @@ sub is_ip_duplicate {
}
}
-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 {
- #
- # check if vyatta has generated the config file, otherwise
- # an empty config will try to get new addresses for all
- # interfaces
- #
- my $grep = `grep vyatta-interfaces.pl $dhcp_conf | wc -l`;
- chomp $grep;
- if (!defined $grep or $grep != 1) {
- die "DHCP client not configured\n";
- }
- 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) = @_;
@@ -168,47 +117,25 @@ sub dhcp_conf_header {
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");
+ if ($intf =~ m/^eth/) {
+ if ($intf =~ m/(\w+)\.(\d+)/) {
+ $config->setLevel("interfaces ethernet $1 vif $2");
+ } else {
+ $config->setLevel("interfaces ethernet $intf");
+ }
+ } elsif ($intf =~ m/^br/) {
+ $config->setLevel("interfaces bridge $intf");
} else {
- $config->setLevel("interfaces ethernet $intf");
+ #
+ # currently we only support dhcp on ethernet
+ # and bridge interfaces.
+ #
+ return 0;
}
my @addrs = $config->returnOrigValues("address");
foreach my $addr (@addrs) {
@@ -223,11 +150,18 @@ sub is_address_enabled {
my $intf = shift;
my $config = new VyattaConfig;
-
- if ($intf =~ m/(\w+)\.(\d)/) {
- $config->setLevel("interfaces ethernet $1 vif $2");
+
+ if ($intf =~ m/^eth/) {
+ if ($intf =~ m/(\w+)\.(\d+)/) {
+ $config->setLevel("interfaces ethernet $1 vif $2");
+ } else {
+ $config->setLevel("interfaces ethernet $intf");
+ }
+ } elsif ($intf =~ m/^br/) {
+ $config->setLevel("interfaces bridge $intf");
} else {
- $config->setLevel("interfaces ethernet $intf");
+ print "unsupported dhcp interface [$intf]\n";
+ exit 1;
}
my @addrs = $config->returnOrigValues("address");
foreach my $addr (@addrs) {
@@ -246,34 +180,18 @@ sub get_hostname {
}
sub dhcp_update_config {
+ my ($conf_file, $intf) = @_;
+
my $output = dhcp_conf_header();
my $hostname = get_hostname();
- my $config = new VyattaConfig;
- my $dhcp_instances = 0;
- my @dhcp_intfs = dhcp_get_interfaces();
- foreach my $intf (@dhcp_intfs) {
- $output .= "interface \"$intf\" {\n";
- if (defined($hostname)) {
- $output .= "\tsend host-name \"$hostname\";\n";
- }
- $output .= "}\n\n";
- $dhcp_instances++;
+ $output .= "interface \"$intf\" {\n";
+ if (defined($hostname)) {
+ $output .= "\tsend host-name \"$hostname\";\n";
}
+ $output .= "}\n\n";
- 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();
- }
+ dhcp_write_file($conf_file, $output);
}
sub is_ip_v4_or_v6 {
@@ -299,11 +217,42 @@ sub is_ip_v4_or_v6 {
return undef;
}
+sub generate_dhclient_intf_files {
+ my $intf = shift;
+
+ $intf =~ s/\./_/g;
+ my $intf_config_file = $dhclient_dir . 'dhclient_' . $intf . '.conf';
+ my $intf_process_id_file = $dhclient_dir . 'dhclient_' . $intf . '.pid';
+ my $intf_leases_file = $dhclient_dir . 'dhclient_' . $intf . '.leases';
+ return ($intf_config_file, $intf_process_id_file, $intf_leases_file);
+
+}
+
+sub run_dhclient {
+ my $intf = shift;
+
+ my ($intf_config_file, $intf_process_id_file, $intf_leases_file) = generate_dhclient_intf_files($intf);
+ dhcp_update_config($intf_config_file, $intf);
+ my $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);
+}
+
+sub stop_dhclient {
+ my $intf = shift;
+
+ my ($intf_config_file, $intf_process_id_file, $intf_leases_file) = generate_dhclient_intf_files($intf);
+ my $cmd = "$dhcp_daemon -q -cf $intf_config_file -pf $intf_process_id_file -lf $intf_leases_file -r $intf 2> /dev/null";
+ system ($cmd);
+ system ("rm -f $intf_config_file");
+}
+
sub update_eth_addrs {
my ($addr, $intf) = @_;
if ($addr eq "dhcp") {
- update_dhcp_client();
+ run_dhclient($intf);
+ system ("touch /var/lib/dhcp3/$intf\;");
return;
}
my $version = is_ip_v4_or_v6($addr);
@@ -348,9 +297,8 @@ sub delete_eth_addrs {
my ($addr, $intf) = @_;
if ($addr eq "dhcp") {
- dhcp_release_addr($intf);
- update_dhcp_client();
- system("rm -f /var/lib/dhcp3/dhclient_$intf\_lease");
+ stop_dhclient($intf);
+ system("rm -f /var/lib/dhcp3/dhclient_$intf\_lease; rm -f /var/lib/dhcp3/$intf\; rm -f /var/lib/dhcp3/release_$intf\;");
exit 0;
}
my $version = is_ip_v4_or_v6($addr);
@@ -442,6 +390,28 @@ sub is_valid_addr {
exit 1;
}
+ my $ip = NetAddr::IP->new($addr_net);
+ my $network = $ip->network();
+ my $bcast = $ip->broadcast();
+
+ if ($ip->version == 4 and $ip->masklen() == 31) {
+ #
+ # RFC3021 allows for /31 to treat both address as host addresses
+ #
+ } elsif ($ip->masklen() != $ip->bits()) {
+ #
+ # allow /32 for ivp4 and /128 for ipv6
+ #
+ if ($ip->addr() eq $network->addr()) {
+ print "Can not assign network address as the IP address\n";
+ exit 1;
+ }
+ if ($ip->addr() eq $bcast->addr()) {
+ print "Can not assign broadcast address as the IP address\n";
+ exit 1;
+ }
+ }
+
if (is_dhcp_enabled($intf)) {
print "Error: remove dhcp before adding static addresses for $intf\n";
exit 1;
@@ -465,6 +435,36 @@ sub is_valid_addr {
exit 1;
}
+sub op_dhcp_command {
+ my ($op_command, $intf) = @_;
+
+ if (!is_dhcp_enabled($intf)) {
+ print "$intf is not using DHCP to get an IP address\n";
+ exit 1;
+ }
+
+ my $release_file = $dhclient_dir . 'release_' . $intf;
+ if ($op_command eq "dhcp-release") {
+ if (-e $release_file) {
+ print "IP address for $intf has already been released.\n";
+ exit 1;
+ } else {
+ print "Releasing DHCP lease on $intf ...\n";
+ stop_dhclient($intf);
+ system ("touch $release_file\;");
+ exit 0;
+ }
+ } elsif ($op_command eq "dhcp-renew") {
+ print "Renewing DHCP lease on $intf ...\n";
+ run_dhclient($intf);
+ system ("rm -f $release_file\;");
+ exit 0;
+ }
+
+ exit 0;
+
+}
+
exit 0;
# end of file
diff --git a/scripts/vyatta-load-config.pl b/scripts/vyatta-load-config.pl
index 05323e3..29d4dec 100755
--- a/scripts/vyatta-load-config.pl
+++ b/scripts/vyatta-load-config.pl
@@ -28,21 +28,84 @@ use VyattaConfigLoad;
my $etcdir = $ENV{vyatta_sysconfdir};
my $sbindir = $ENV{vyatta_sbindir};
my $bootpath = $etcdir . "/config";
+my $load_file = $bootpath . "/config.boot";
+my $url_tmp_file = $bootpath . "/config.boot.$$";
-if ($#ARGV != 0) {
+if ($#ARGV > 0) {
print "Usage: load <config_file_name>\n";
exit 1;
}
-my $load_file = $ARGV[0];
-if (!($load_file =~ /^\//)) {
+my $mode = 'local';
+my $proto;
+
+if (defined($ARGV[0])) {
+ $load_file = $ARGV[0];
+}
+
+if ($load_file =~ /^[^\/]\w+:\//) {
+ if ($load_file =~ /^(\w+):\/\/\w/) {
+ $mode = 'url';
+ $proto = lc($1);
+ if ($proto eq 'tftp') {
+ } elsif ($proto eq 'ftp') {
+ } elsif ($proto eq 'http') {
+ } elsif ($proto eq 'scp') {
+ } else {
+ print "Invalid url protocol [$proto]\n";
+ exit 1;
+ }
+ } else {
+ print "Invalid url [$load_file]\n";
+ exit 1;
+ }
+}
+
+if ($mode eq 'local' and !($load_file =~ /^\//)) {
# relative path
$load_file = "$bootpath/$load_file";
}
-if (!open(CFG, "<$load_file")) {
- print "Cannot open configuration file $load_file\n";
- exit 1;
+if ($mode eq 'local') {
+ if (!open(CFG, "<$load_file")) {
+ print "Cannot open configuration file $load_file\n";
+ exit 1;
+ }
+} elsif ($mode eq 'url') {
+ if (! -f '/usr/bin/curl') {
+ print "Package [curl] not installed\n";
+ exit 1;
+ }
+ if ($proto eq 'http') {
+ #
+ # error codes are send back in html, so 1st try a header
+ # and look for "HTTP/1.1 200 OK"
+ #
+ my $rc = `curl -q -I $load_file 2>&1`;
+ if ($rc =~ /HTTP\/\d+\.?\d\s+(\d+)\s+(.*)$/mi) {
+ my $rc_code = $1;
+ my $rc_string = $2;
+ if ($rc_code == 200) {
+ # good resonse
+ } else {
+ print "http error: [$rc_code] $rc_string\n";
+ exit 1;
+ }
+ } else {
+ print "Error: $rc\n";
+ exit 1;
+ }
+ }
+ my $rc = system("curl -# -o $url_tmp_file $load_file");
+ if ($rc) {
+ print "Can not open remote configuration file $load_file\n";
+ exit 1;
+ }
+ if (!open(CFG, "<$url_tmp_file")) {
+ print "Cannot open configuration file $load_file\n";
+ exit 1;
+ }
+ $load_file = $url_tmp_file;
}
while (<CFG>) {
if (/\/\*XORP Configuration File, v1.0\*\//) {
diff --git a/scripts/vyatta-save-config.pl b/scripts/vyatta-save-config.pl
index c759503..2c02766 100755
--- a/scripts/vyatta-save-config.pl
+++ b/scripts/vyatta-save-config.pl
@@ -26,6 +26,8 @@ use VyattaConfigOutput;
my $etcdir = "/opt/vyatta/etc";
my $bootpath = $etcdir . "/config";
my $save_file = $bootpath . "/config.boot";
+my $url_tmp_file = $bootpath . "/config.boot.$$";
+
if ($#ARGV > 0) {
print "Usage: save [config_file_name]\n";
@@ -34,25 +36,68 @@ if ($#ARGV > 0) {
if (defined($ARGV[0])) {
$save_file = $ARGV[0];
- if (!($save_file =~ /^\//)) {
- # relative path
- $save_file = "$bootpath/$save_file";
+}
+
+my $mode = 'local';
+my $proto;
+
+if ($save_file =~ /^[^\/]\w+:\//) {
+ if ($save_file =~ /^(\w+):\/\/\w/) {
+ $mode = 'url';
+ $proto = lc($1);
+ if ($proto eq 'tftp') {
+ } elsif ($proto eq 'ftp') {
+ } elsif ($proto eq 'scp') {
+ } else {
+ print "Invalid url protocol [$proto]\n";
+ exit 1;
+ }
+ } else {
+ print "Invalid url [$save_file]\n";
+ exit 1;
}
}
-# this overwrites the file if it exists. we could create a backup first.
-if (! open(SAVE, ">$save_file")) {
- print "Cannot open file '$save_file': $!\n";
- exit 1;
+if ($mode eq 'local' and !($save_file =~ /^\//)) {
+ # relative path
+ $save_file = "$bootpath/$save_file";
+}
+
+my $version_str = `/opt/vyatta/sbin/vyatta_current_conf_ver.pl`;
+print "Saving configuration to '$save_file'...\n";
+
+if ($mode eq 'local') {
+ # this overwrites the file if it exists. we could create a backup first.
+ if (! open(SAVE, ">$save_file")) {
+ print "Cannot open file '$save_file': $!\n";
+ exit 1;
+ }
+} elsif ($mode eq 'url') {
+ if (! -f '/usr/bin/curl') {
+ print "Package [curl] not installed\n";
+ exit 1;
+ }
+ if (! open(SAVE, ">$url_tmp_file")) {
+ print "Cannot open file '$url_tmp_file': $!\n";
+ exit 1;
+ }
}
-print "Saving configuration to '$save_file'...";
select SAVE;
VyattaConfigOutput::set_show_all(1);
VyattaConfigOutput::outputActiveConfig();
-my $version_str = `/opt/vyatta/sbin/vyatta_current_conf_ver.pl`;
-print SAVE $version_str;
-select STDOUT;
-print "\nDone\n";
+print $version_str;
close SAVE;
+select STDOUT;
+
+if ($mode eq 'url') {
+ my $rc = system("curl -# -T $url_tmp_file $save_file");
+ system("rm -f $url_tmp_file");
+ if ($rc) {
+ print "Error saving $save_file\n";
+ exit 1;
+ }
+}
+
+print "Done\n";
exit 0;