summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAn-Cheng Huang <ancheng@vyatta.com>2008-07-09 15:02:40 -0700
committerAn-Cheng Huang <ancheng@vyatta.com>2008-07-09 15:02:40 -0700
commit76bdc334604d3871d73453aebbd3cd095a4377fb (patch)
tree960722e293224b07d0e6e152c9f32211b001a7e8
parent981800dff80cfa85dc939aac43a1ad9f3aa9ea3c (diff)
downloadvyatta-cfg-vpn-76bdc334604d3871d73453aebbd3cd095a4377fb.tar.gz
vyatta-cfg-vpn-76bdc334604d3871d73453aebbd3cd095a4377fb.zip
fix for bugs 3044, 3047, and 3048: support ipsec road warriors.
-rwxr-xr-xscripts/vpn-config.pl96
-rw-r--r--templates/vpn/ipsec/site-to-site/peer/node.def1
-rw-r--r--templates/vpn/ipsec/site-to-site/peer/node.tag/authentication/id/node.def6
3 files changed, 91 insertions, 12 deletions
diff --git a/scripts/vpn-config.pl b/scripts/vpn-config.pl
index b82ebfd..219c4fe 100755
--- a/scripts/vpn-config.pl
+++ b/scripts/vpn-config.pl
@@ -227,6 +227,12 @@ if ($vcVPN->exists('ipsec')) {
$genout .= "ipsec$counter=$interface";
++$counter;
}
+ if (hasLocalWildcard($vcVPN, 0)) {
+ if ($counter > 0) {
+ $genout .= ' ';
+ }
+ $genout .= '%defaultroute';
+ }
$genout .= "\"\n";
}
@@ -329,6 +335,7 @@ if ($vcVPN->exists('ipsec')) {
#
# Connection configurations
#
+ my $wildcard_psk = undef;
my @peers = $vcVPN->listNodes('ipsec site-to-site peer');
if (@peers == 0) {
#$error = 1;
@@ -346,10 +353,14 @@ if ($vcVPN->exists('ipsec')) {
}
my $lip = $vcVPN->returnValue("ipsec site-to-site peer $peer local-ip");
+ my $authid = $vcVPN->returnValue(
+ "ipsec site-to-site peer $peer authentication id");
if (!defined($lip) || $lip eq "") {
$error = 1;
print STDERR "VPN configuration error. No local IP specified for peer \"$peer\"\n";
- } else {
+ } elsif ($lip ne '0.0.0.0') {
+ # not '0.0.0.0' special case.
+ # check interface addresses.
use VyattaMisc;
if (!VyattaMisc::isIPinInterfaces($vc, $lip, @interfaces)) {
@@ -396,26 +407,46 @@ if ($vcVPN->exists('ipsec')) {
$error = 1;
print STDERR "VPN configuration error. The ESP group \"$peer_tunnel_esp_group\" specified for peer \"$peer\" tunnel $tunnel has not been configured.\n";
}
-
- $genout .= "\nconn peer-$peer-tunnel-$tunnel\n";
+
+ my $conn_head = "\nconn peer-$peer-tunnel-$tunnel\n";
+ $conn_head =~ s/ peer-@/ peer-/;
+ $genout .= $conn_head;
#
# Assign left and right to local and remote interfaces
#
if (defined($lip)) {
- my $left = $lip;
- $genout .= "\tleft=$left\n";
+ if ($lip eq '0.0.0.0') {
+ if (!defined($authid)) {
+ print STDERR 'VPN configuration error. '
+ . 'The "authentication id" must be '
+ . 'configured if local IP is 0.0.0.0.'
+ . "\n";
+ $error = 1;
+ }
+ $genout .= "\tleft=%defaultroute\n";
+ $genout .= "\tleftid=$authid\n";
+ } else {
+ $genout .= "\tleft=$lip\n";
+ }
}
my $any_peer = 0;
my $right;
- if (($peer eq 'any') or ($peer eq '0.0.0.0')) {
+ my $rightid = undef;
+ if ($peer =~ /^\@/) {
+ # peer is an "ID"
+ $rightid = $peer;
+ }
+ if (($peer eq 'any') or ($peer eq '0.0.0.0')
+ or defined($rightid)) {
$right = '%any';
$any_peer = 1;
} else {
$right = $peer;
}
$genout .= "\tright=$right\n";
+ $genout .= "\trightid=$rightid\n" if (defined($rightid));
if ($any_peer) {
$genout .= "\trekey=no\n";
}
@@ -658,12 +689,24 @@ if ($vcVPN->exists('ipsec')) {
}
my $right;
- if (($peer eq 'any') or ($peer eq '0.0.0.0')) {
+ if (($peer eq 'any') or ($peer eq '0.0.0.0')
+ or ($peer =~ /^\@/)) {
$right = '%any';
+ if (defined($wildcard_psk)) {
+ if ($wildcard_psk ne $psk) {
+ $error = 1;
+ print STDERR 'VPN configuration error. '
+ . 'All dynamic peers must have the same '
+ . "'pre-shared-secret'.\n";
+ }
+ } else {
+ $wildcard_psk = $psk;
+ }
} else {
$right = $peer;
}
- $genout_secrets .= "$lip $right : PSK \"$psk\"\n";
+ my $index1 = ($lip eq '0.0.0.0') ? "$authid" : $lip;
+ $genout_secrets .= "$index1 $right : PSK \"$psk\"\n";
$genout .= "\tauthby=secret\n";
} elsif (defined($auth_mode) && $auth_mode eq 'rsa') {
@@ -873,6 +916,7 @@ sub partial_restart {
my %tunnels = $vcVPN->listNodeStatus("ipsec site-to-site peer $peer tunnel");
while (my ($tunnel, $tunnel_status) = each %tunnels) {
my $conn = "peer-$peer-tunnel-$tunnel";
+ $conn =~ s/peer-@/peer-/;
if ($tunnel_status eq 'added') {
addConnection($peer, $tunnel, $conn_add, $conn_up);
} elsif ($tunnel_status eq 'changed') {
@@ -889,6 +933,7 @@ sub partial_restart {
my @tunnels = $vcVPN->listOrigNodes("ipsec site-to-site peer $peer tunnel");
foreach my $tunnel (@tunnels) {
my $conn = "peer-$peer-tunnel-$tunnel";
+ $conn =~ s/peer-@/peer-/;
deleteConnection($conn, $conn_down, $conn_delete);
}
} elsif ($peer_status eq 'static') {
@@ -918,11 +963,13 @@ sub vpn_exec {
if ($error == 0) {
my $cmd_out = qx($command);
+ my $rval = ($? >> 8);
print LOG "Output:\n$cmd_out\n---\n";
- print LOG "Return code: $?\n";
- if ($?) {
- if ($? == 26624 && ($command =~ /^ipsec auto --asynchronous --up/g)) {
- print LOG "Return code 26624 OK when bringing up VPN connection.\n";
+ print LOG "Return code: $rval\n";
+ if ($rval) {
+ if ($command =~ /^ipsec auto --asynchronous --up/
+ && ($rval == 104 || $rval == 29)) {
+ print LOG "OK when bringing up VPN connection\n";
} else {
$error = 1;
print LOG "VPN commit error. Unable to $desc, received error code $?\n";
@@ -954,6 +1001,7 @@ sub vpn_log {
sub addConnection {
my ($peer, $tunnel, $conn_add, $conn_up) = @_;
my $conn = "peer-$peer-tunnel-$tunnel";
+ $conn =~ s/peer-@/peer-/;
push(@$conn_add, $conn);
if ($peer ne '0.0.0.0') {
push(@$conn_up, $conn);
@@ -963,6 +1011,7 @@ sub addConnection {
sub replaceConnection {
my ($peer, $tunnel, $conn_down, $conn_replace, $conn_up) = @_;
my $conn = "peer-$peer-tunnel-$tunnel";
+ $conn =~ s/peer-@/peer-/;
push(@$conn_down, $conn);
push(@$conn_replace, $conn);
if ($peer ne '0.0.0.0') {
@@ -1018,6 +1067,9 @@ sub isFullRestartRequired {
# FIXME: in reality this global doesn't affect every tunnel
$restartf = 1;
+ } elsif (hasLocalWildcard($vcVPN, 0) != hasLocalWildcard($vcVPN, 1)) {
+ # local wild card has changed. this affects ipsec-interfaces.
+ $restartf = 1;
}
return $restartf;
@@ -1071,4 +1123,24 @@ sub printTreeOrig {
}
}
+sub hasLocalWildcard {
+ my $vc = shift;
+ my $orig = shift;
+ my @peers = $vc->listNodes('ipsec site-to-site peer');
+ if ($orig) {
+ @peers = $vc->listOrigNodes('ipsec site-to-site peer');
+ }
+ return 0 if (@peers == 0);
+ foreach my $peer (@peers) {
+ my $lip
+ = $vcVPN->returnValue("ipsec site-to-site peer $peer local-ip");
+ if ($orig) {
+ $lip = $vcVPN->returnOrigValue(
+ "ipsec site-to-site peer $peer local-ip");
+ }
+ return 1 if ($lip eq '0.0.0.0');
+ }
+ return 0;
+}
+
# end of file
diff --git a/templates/vpn/ipsec/site-to-site/peer/node.def b/templates/vpn/ipsec/site-to-site/peer/node.def
index e4e349e..2118990 100644
--- a/templates/vpn/ipsec/site-to-site/peer/node.def
+++ b/templates/vpn/ipsec/site-to-site/peer/node.def
@@ -4,3 +4,4 @@ help: Set VPN peers
comp_help: Allowed values:
<x.x.x.x> Set IP address of the peer
<text> Set the hostname of the peer
+ @<text> Set the ID of the peer
diff --git a/templates/vpn/ipsec/site-to-site/peer/node.tag/authentication/id/node.def b/templates/vpn/ipsec/site-to-site/peer/node.tag/authentication/id/node.def
new file mode 100644
index 0000000..c5e66c1
--- /dev/null
+++ b/templates/vpn/ipsec/site-to-site/peer/node.tag/authentication/id/node.def
@@ -0,0 +1,6 @@
+help: Set ID for peer authentication
+type: txt
+syntax:expression: pattern $VAR(@) "^@[a-zA-Z_][a-zA-Z0-9_-]*$"
+ ; "invalid ID \"$VAR(@)\""
+comp_help:Possible completions:
+ @<text> ID used for peer authentication