+#!/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: udptunnel-reconf.pl,v 1.2 2000/12/11 02:41:27 ian Exp $
+
+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;