From bdef00e75a4474a136f3bb2432c98d5ac338fcaa Mon Sep 17 00:00:00 2001 From: Stig Thormodsrud Date: Tue, 22 Jul 2008 18:36:45 -0700 Subject: Fix 3300: VPN over PPPOE completely fails on reboot --- Makefile.am | 6 +- scripts/vpn-config.pl | 20 ++++- scripts/vpn-ppp-down | 35 ++++++++ scripts/vpn-ppp-up | 35 ++++++++ scripts/vyatta-vpn-ppp-updown.pl | 173 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 265 insertions(+), 4 deletions(-) create mode 100755 scripts/vpn-ppp-down create mode 100755 scripts/vpn-ppp-up create mode 100755 scripts/vyatta-vpn-ppp-updown.pl diff --git a/Makefile.am b/Makefile.am index ca00fae..a623854 100644 --- a/Makefile.am +++ b/Makefile.am @@ -8,6 +8,7 @@ curverdir = $(sysconfdir)/config-migrate/current sbin_SCRIPTS = sbin_SCRIPTS += scripts/vpn-config.pl +sbin_SCRIPTS += scripts/vyatta-vpn-ppp-updown.pl share_perl5_DATA = scripts/VyattaVPNUtil.pm @@ -19,4 +20,7 @@ cpiop = find . ! -regex '\(.*~\|.*\.bak\|.*\.swp\|.*\#.*\#\)' -print0 | \ install-exec-hook: mkdir -p $(DESTDIR)$(cfgdir) cd templates; $(cpiop) $(DESTDIR)$(cfgdir) - + mkdir -p $(DESTDIR)/etc/ppp/ip-up.d + mkdir -p $(DESTDIR)/etc/ppp/ip-down.d + cp scripts/vpn-ppp-up $(DESTDIR)/etc/ppp/ip-up.d/ + cp scripts/vpn-ppp-down $(DESTDIR)/etc/ppp/ip-down.d/ diff --git a/scripts/vpn-config.pl b/scripts/vpn-config.pl index 3a62a04..ad7cae1 100755 --- a/scripts/vpn-config.pl +++ b/scripts/vpn-config.pl @@ -221,6 +221,9 @@ if ($vcVPN->exists('ipsec')) { $genout .= "\tinterfaces=\""; my $counter = 0; foreach my $interface (@interfaces) { + if (!(-d "/sys/class/net/$interface")) { + next; + } if ($counter > 0) { $genout .= ' '; } @@ -973,10 +976,21 @@ sub vpn_exec { && ($rval == 104 || $rval == 29)) { print LOG "OK when bringing up VPN connection\n"; } else { - $error = 1; + # + # We use to consider the commit failed if we got a error + # from the call to ipsec, but this causes the configuration + # to not get included in the running config. Now that + # we support dynamic interface/address (e.g. dhcp, pppoe) + # we want a valid config to get committed even if the + # interface doesn't exist yet. That way we can use + # "clear vpn ipsec-process" to bring up the tunnel once + # the interface is instantiated. For pppoe we will add + # a script to /etc/ppp/ip-up.d to bring up the vpn + # tunnel. + # print LOG "VPN commit error. Unable to $desc, received error code $?\n"; - print STDERR "VPN commit error. Unable to $desc, received error code $?\n"; - print STDERR "$cmd_out\n"; + print "Warning: unable to [$desc], received error code $?\n"; + print "$cmd_out\n"; } } } else { diff --git a/scripts/vpn-ppp-down b/scripts/vpn-ppp-down new file mode 100755 index 0000000..d72681d --- /dev/null +++ b/scripts/vpn-ppp-down @@ -0,0 +1,35 @@ +#!/bin/sh +# +# Module: vpn-ppp-down +# +# **** 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 Vyatta, Inc. +# All Rights Reserved. +# +# Authors: Stig Thormodsrud +# Date: July 2008 +# Description: wrapper for vyatta-vpn-pppoe +# +# **** End License **** +# + +# $1 Interface name ppp0 +# $2 The tty ttyS1 +# $3 The link speed 38400 +# $4 Local IP number 12.34.56.78 +# $5 Peer IP number 12.34.56.99 +# $6 Optional ``ipparam'' value foo + +source /etc/default/vyatta + +/opt/vyatta/sbin/vyatta-vpn-ppp-updown.pl $6 down diff --git a/scripts/vpn-ppp-up b/scripts/vpn-ppp-up new file mode 100755 index 0000000..1a72475 --- /dev/null +++ b/scripts/vpn-ppp-up @@ -0,0 +1,35 @@ +#!/bin/sh +# +# Module: vpn-ppp-up +# +# **** 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 Vyatta, Inc. +# All Rights Reserved. +# +# Authors: Stig Thormodsrud +# Date: July 2008 +# Description: wrapper for vyatta-vpn-pppoe +# +# **** End License **** +# + +# $1 Interface name ppp0 +# $2 The tty ttyS1 +# $3 The link speed 38400 +# $4 Local IP number 12.34.56.78 +# $5 Peer IP number 12.34.56.99 +# $6 Optional ``ipparam'' value foo + +source /etc/default/vyatta + +/opt/vyatta/sbin/vyatta-vpn-ppp-updown.pl $6 up diff --git a/scripts/vyatta-vpn-ppp-updown.pl b/scripts/vyatta-vpn-ppp-updown.pl new file mode 100755 index 0000000..5f440e9 --- /dev/null +++ b/scripts/vyatta-vpn-ppp-updown.pl @@ -0,0 +1,173 @@ +#!/usr/bin/perl -w +# +# Module: vyatta-vpn-pppoe +# +# **** 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 Vyatta, Inc. +# All Rights Reserved. +# +# Authors: Stig Thormodsrud +# Date: July 2008 +# Description: bring up/down vpn tunnel for pppoe/pppoa interfaces +# +# **** End License **** +# + +use lib "/opt/vyatta/share/perl5/"; +use VyattaConfig; +use POSIX; +use strict; +use warnings; + +my $conf_file = '/etc/ipsec.conf'; +my $log_file = '/var/log/pppoe-vpn.log'; + + +sub logit { + my $timestamp = strftime("%Y%m%d-%H:%M.%S", localtime); + open my $fh, ">>", $log_file; + print $fh "$timestamp: ", @_ , "\n"; + close $fh; +} + +sub find_next_ipsec { + my $list = shift; + + my $last = -1; + + while ($list =~ s/ipsec([0-9]+)\=\w+\d+//) { + $last = $1 if $1 > $last; + } + return $last + 1; +} + +sub is_dup { + my ($line, $intf) = @_; + + while ($line =~ s/ipsec[0-9]+\=(\w+\d+)//) { + return 1 if $1 eq $intf; + } + return 0; +} + +sub vpn_add_intf { + my ($line, $intf) = @_; + + logit("UP $intf"); + + return (0, $line) if is_dup($line, $intf); + + my $intf_list; + my $new_line; + my $defaultroute = ''; + if ($line !~ /interfaces\=\"(.*)\"/) { + return (0, $line); + } + $intf_list = $1; + if ($intf_list =~ s/ \%defaultroute//) { + $defaultroute = ' %defaultroute'; + } + my $ipsec_num = find_next_ipsec($intf_list); + $intf_list .= " ipsec$ipsec_num\=$intf"; + $new_line = " interfaces=\"$intf_list$defaultroute\""; + return (1, $new_line); +} + +sub vpn_remove_intf { + my ($line, $intf) = @_; + + logit("DOWN $intf"); + if ($line =~ s/ipsec[0-9]+\=$intf//) { + return (1, $line); + } else { + return (0, $line); + } + +} + + +my $pppoe_intf = $ARGV[0]; +my $mode = $ARGV[1]; + +my $config = new VyattaConfig; +$config->setLevel("vpn ipsec ipsec-interfaces"); +my @ipsec_intfs = $config->returnOrigValues("interface"); + +# +# done if no vpn interfaces +# +exit 0 if scalar(@ipsec_intfs) == 0; + +my $found = 0; +foreach my $intf (@ipsec_intfs) { + $found++ if $pppoe_intf eq $intf; +} + +# +# done if interface comming up isn't in vpn ipsec-interfaces +# +exit 0 if $found == 0; + +# +# read current ipsec.conf +# +open(my $FD, '<', $conf_file) + or die "Can't open [$conf_file] for read"; +my @lines = <$FD>; +close $FD; + +my @new_config = (); +my $changed = 0; +foreach my $line (@lines) { + if ($line =~ /interfaces=\"/) { + my $new_line; + if ($mode eq 'up') { + ($changed, $new_line) = vpn_add_intf($line, $pppoe_intf); + $new_line .= "\n"; + } else { + ($changed, $new_line) = vpn_remove_intf($line, $pppoe_intf); + } + push @new_config, $new_line; + chomp $line; chomp $new_line; + logit("replacing [$line]"); + logit("with [$new_line]"); + } else { + push @new_config, $line; + } +} + +exit 0 if $changed == 0; + +# +# write out new ipsec.conf +# +my $tmp_conf = "/tmp/ipsec.conf.$$"; +open($FD, '>', $tmp_conf) + or die "Can't open [$tmp_conf] for write"; +print $FD @new_config; +close $FD; + +my ($cmd, $rc); +$cmd = "mv $tmp_conf $conf_file"; +$rc =system($cmd); +logit("$cmd = $rc"); +$cmd = "/usr/sbin/ipsec setup --start 2> /dev/null"; +$rc =system($cmd); +logit("$cmd = $rc"); +$cmd = "/usr/sbin/ipsec auto --rereadall 2> /dev/null"; +$rc = system($cmd); +logit("$cmd = $rc"); + +exit 0; + +# end of file -- cgit v1.2.3