chiark / gitweb /
Merge udptunnelconf branch; cvs up -j branchpoint-2000-12-10-udptunnelconf -j mergepo...
[userv-utils.git] / ipif / udptunnel-reconf.pl
diff --git a/ipif/udptunnel-reconf.pl b/ipif/udptunnel-reconf.pl
new file mode 100755 (executable)
index 0000000..e21d123
--- /dev/null
@@ -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 [<directory>]\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= <X>;
+    $/= "\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;