X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?a=blobdiff_plain;f=ipif%2Fudptunnel-reconf.pl;fp=ipif%2Fudptunnel-reconf.pl;h=e21d123959749039ce92cb25f8229fbf9fa8075b;hb=2e082dfed76851117cafd488388a010cac25df09;hp=0000000000000000000000000000000000000000;hpb=f56780b78838933d6ee89f05d639234c5eb5986b;p=userv-utils.git diff --git a/ipif/udptunnel-reconf.pl b/ipif/udptunnel-reconf.pl new file mode 100755 index 0000000..e21d123 --- /dev/null +++ b/ipif/udptunnel-reconf.pl @@ -0,0 +1,194 @@ +#!/usr/bin/perl +# udptunnel-reconf +# Set up the relevant stuff in /etc/userv/vpn, and then run +# this. It should tell you what to do to inittab and ipif-networks. + +# This is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with userv-utils; if not, write to the Free Software +# Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# $Id$ + +use Socket; + +# @@@- +$shareuserv= "`pwd`"; +$etcvpn= "`pwd`"; +$varlibvpn= "`pwd`"; +# -@@@ + +sub badusage () { die "usage: udptunnel-reconf []\n"; } +$debug=0; + +sub fault ($) { die "$0: $_[0]\n"; } + +while ($ARGV[0] =~ m/^-/) { + $_= shift @ARGV; + last if m/^--$/; + if (m/^-d$/) { $debug++; next; } + badusage(); +} + +if (@ARGV) { $etcvpn= shift @ARGV; } +badusage() if @ARGV; + +chdir $etcvpn or fault("$etcvpn: $!"); + +sub run_m4 ($$$) { + my ($wanted, $site, $variable) = @_; + $x= "m4 -P -DWANTED=$wanted -DWHVARIABLE=V_$variable -DV_global=global ". + "-DV_site=$site -DV_varlibvpn=$varlibvpn ". + "-DV_defaults=$shareuserv/udptunnel-vpn-defaults ". + "$shareuserv/udptunnel-vpn-config.m4"; + print STDERR $x,"\n" if $debug>=2; + open X, "$x |" or die $!; + undef $/; + $m4out= ; + $/= "\n"; + close X; $? and exit -1; + $m4out =~ s/^\s+//; + $m4out =~ s/\n+/\n/g; + $m4out =~ s/\s+$//; + print STDERR "$wanted/$variable($site) -> \`$m4out'\n" if $debug>=1; +# $m4out='' if $wanted eq 'VARIABLE' && substr($m4out,0,2) eq 'V_'; + return $m4out; +} + +sub check_junk ($$) { + my ($emsg, $site) = @_; + $j= run_m4('JUNK',$site,''); + $j =~ s/^\# //g; + fault("$emsg: $j") if length $j; +} + +sub var_global ($) { return run_m4('VARIABLE','',$_[0]) } +sub var_site ($) { return run_m4('VARIABLE',$site,$_[0]) } + +check_junk("error in config",''); + +@actives= split /\s+/, run_m4('ACTIVES','',''); +@passives= split /\s+/, run_m4('PASSIVES','',''); + +foreach $site (@actives, @passives) { + check_junk("error in config for site $site",$site); +} + +sub parse_addr_mask ($) { + my ($r) = @_; + my ($mask,$iaddr); + if ($r =~ s,/(\d+)$,,) { $mask=$1; } else { $mask=32; } + fault("invalid mask length $1") if $mask<0 || $mask>32; + $mask= $mask ? ~0 << (32-$mask) : 0; + $iaddr= inet_aton($r); fault("invalid address $r") unless defined $iaddr; + $iaddr= (unpack "N",$iaddr)[0]; + return ($iaddr, $mask); +} + +$forbid_remote= var_global('forbid_remote'); +@forbid_remote= (); +foreach $r (split /[, \t]+/, $forbid_remote) { + push @forbid_remote, [ parse_addr_mask($r) ]; +} + +sub ipif_permit ($$$$) { + my ($group,$local,$net,$why) = @_; + my ($pmask,$piaddr,$fmask,$fiaddr,@lgroup,$lgid); + + @lgroup= getgrnam($group); + @lgroup or fault("invalid group \`$group' ($why)"); + $lgid= $lgroup[2]; + + if (!$local) { + ($piaddr,$pmask) = parse_addr_mask($net); + foreach $fref (@forbid_remote) { + ($fiaddr,$fmask) = @$fref; + $jmask= $fmask & $pmask; +#printf STDERR "%8lx %8lx %l8x %8lx", $pmask,$pmask + fault("local network $net claimed as remote ($why)") + if (($fiaddr&$jmask) == ($piaddr&$jmask)); + } + } + $ipif_file .= "$lgid,$local$net, $group, $why\n"; +} + +$glgroup= var_global('lgroup'); +$glend= var_site('lend')."/32"; +if ($glend !~ m/^V_/ && $glgroup !~ m/^V_/ && + length $glend && length $glgroup) { + ipif_permit($glgroup, '=', "$glend", 'local endpoint'); +} else { + $glend='X'; $glgroup='X'; +} + +foreach $site (@actives, @passives) { + $tlend= var_site('lend')."/32"; + $tlgroup= var_site('lgroup'); + if ($tlend ne $glend || $tlgroup ne $glgroup) { + ipif_permit($tlgroup, '=', $tlend, "$site - local endpoint"); + } + $trend= var_site('rend').'/32'; + $ix= 0; + $trnets= var_site('rnets'); + ipif_permit($tlgroup, '', $trend, "$site - remote endpoint"); + if ($trnets ne '-') { + foreach $rnet (split /,/, $trnets) { + ipif_permit($tlgroup, '', $rnet, "$site - remote network #$ix"); + $ix++; + } + } +} + +sub write_file ($$$$) { + my ($fn,$why,$head,$body) = @_; + length $fn or fault("location to write $why not specified"); + open F, ">$fn.new" or fault("create $fn.new: $!"); + print F $head."\n# AUTOGENERATED BY $0 - DO NOT EDIT\n".$body or die $!; + close F or die $!; + rename "$fn.new",$fn or die $!; +} + +$ipifnetsfile= var_global(ipifnetsfile); +write_file($ipifnetsfile,'ipifnetsfile','', $ipif_file); + +$active_file= ''; +$inittab= ''; +$ix= 0; +foreach $site (@actives) { + $active_file.= "$site\t".var_site('activesxinfo')."\n"; + $inittab.= sprintf("t%d", $ix++).':'.var_site('inittab_line')."\n"; + $invoke_file= var_site('invoke_file'); + write_file($invoke_file, 'invoke_file', + var_site('invoke_head'), var_site('invoke_body')); + chmod 0777&~umask, $invoke_file or die $!; +} +write_file(var_global('activesfile'),'activesfile', '',$active_file); + +print +"# You can cut and paste all or part of this into your inittab if you like:\n", + $inittab; + +print +"# And consider adding this line, or some of this file's contents,\n". +"# to your /etc/userv/ipif-networks:\n", + "$ipifnetsfile\n" + if $ipifnetsfile =~ m,^/,; + +$passive_file= ''; +foreach $site (@passives) { + $passive_file.= "$site\t".var_site('passivesxinfo')."\n"; +} +write_file(var_global('passivesfile'),'passivesfile', '',$passive_file); + +system var_global('postconfigure'); $? and exit -1; + +exit 0;