chiark / gitweb /
ea4c86f0d337f80ce7d29921bb90eeee9f1473be
[userv-utils.git] / ipif / udptunnel-reconf.pl
1 #!/usr/bin/perl
2 # udptunnel-reconf
3 # Set up the relevant stuff in /etc/userv/vpn, and then run
4 # this.  It should tell you what to do to inittab and ipif-networks.
5
6 # This is free software; you can redistribute it and/or modify it
7 # under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
10 #
11 # This program is distributed in the hope that it will be useful, but
12 # WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 # General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with userv-utils; if not, write to the Free Software
18 # Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 #
20 # $Id$
21
22 use Socket;
23
24 # @@@-
25 $shareuserv= "`pwd`";
26 $etcvpn= "`pwd`";
27 $varlibvpn= "`pwd`";
28 # -@@@
29
30 sub badusage () { die "usage: udptunnel-reconf [<directory>]\n"; }
31 $debug=0;
32
33 sub fault ($) { die "$0: $_[0]\n"; }
34
35 while ($ARGV[0] =~ m/^-/) {
36     $_= shift @ARGV;
37     last if m/^--$/;
38     if (m/^-d$/) { $debug++; next; }
39     badusage();
40 }
41
42 if (@ARGV) { $etcvpn= shift @ARGV; }
43 badusage() if @ARGV;
44
45 chdir $etcvpn or fault("$etcvpn: $!");
46
47 sub run_m4 ($$$) {
48     my ($wanted, $site, $variable) = @_;
49     $x= "m4 -P -DWANTED=$wanted -DWHVARIABLE=V_$variable -DV_global=global ".
50         "-DV_site=$site -DV_varlibvpn=$varlibvpn ".
51         "-DV_defaults=$shareuserv/udptunnel-vpn-defaults ".
52         "$shareuserv/udptunnel-vpn-config.m4";
53     print STDERR $x,"\n" if $debug>=2;
54     open X, "$x |" or die $!;
55     undef $/;
56     $m4out= <X>;
57     $/= "\n";
58     close X; $? and exit -1;
59     $m4out =~ s/^\s+//;
60     $m4out =~ s/\n+/\n/g;
61     $m4out =~ s/\s+$//;
62     print STDERR "$wanted/$variable($site) -> \`$m4out'\n" if $debug>=1;
63 #    $m4out='' if $wanted eq 'VARIABLE' && substr($m4out,0,2) eq 'V_';
64     return $m4out;
65 }
66
67 sub check_junk ($$) {
68     my ($emsg, $site) = @_;
69     $j= run_m4('JUNK',$site,'');
70     $j =~ s/^\# //g;
71     fault("$emsg: $j") if length $j;
72 }
73
74 sub var_global ($) { return run_m4('VARIABLE','',$_[0]) }
75 sub var_site ($) { return run_m4('VARIABLE',$site,$_[0]) }
76
77 check_junk("error in config",'');
78
79 @actives= split /\s+/, run_m4('ACTIVES','','');
80 @passives= split /\s+/, run_m4('PASSIVES','','');
81
82 foreach $site (@actives, @passives) {
83     check_junk("error in config for site $site",$site);
84 }
85
86 sub parse_addr_mask ($) {
87     my ($r) = @_;
88     my ($mask,$iaddr);
89     if ($r =~ s,/(\d+)$,,) { $mask=$1; } else { $mask=32; }
90     fault("invalid mask length $1") if $mask<0 || $mask>32;
91     $mask= $mask ? ~0 << (32-$mask) : 0;
92     $iaddr= inet_aton($r); fault("invalid address $r") unless defined $iaddr;
93     $iaddr= (unpack "N",$iaddr)[0];
94     return ($iaddr, $mask);
95 }
96
97 sub ipif_permit ($$$$) {
98     my ($group,$local,$net,$why) = @_;
99     my ($pmask,$piaddr,$fmask,$fiaddr,@lgroup,$lgid);
100
101     @lgroup= getgrnam($group);
102     @lgroup or fault("invalid group \`$group' ($why)");
103     $lgid= $lgroup[2];
104
105     if (!$local) {
106         ($piaddr,$pmask) = parse_addr_mask($net);
107         foreach $fref (@forbid_remote) {
108             ($fiaddr,$fmask) = @$fref;
109             $jmask= $fmask & $pmask;
110 #printf STDERR "%8lx %8lx %l8x %8lx", $pmask,$pmask
111             fault("local network $net claimed as remote ($why)")
112                 if (($fiaddr&$jmask) == ($piaddr&$jmask));
113         }
114     }
115     $ipif_file .= "$lgid,$local$net,    $group, $why\n";
116 }
117
118 $glgroup= var_global('lgroup');
119 $glend= var_site('lend')."/32";
120 if ($glend !~ m/^V_/ && $glgroup !~ m/^V_/ &&
121     length $glend && length $glgroup) {
122     ipif_permit($glgroup, '=', "$glend", 'local endpoint');
123 } else {
124     $glend='X'; $glgroup='X';
125 }
126
127 foreach $site (@actives, @passives) {
128     $forbid_remote= var_site('forbid_remote');
129     @forbid_remote= ();
130     if ($forbid_remote ne '-') {
131         foreach $r (split /[, \t]+/, $forbid_remote) {
132             push @forbid_remote, [ parse_addr_mask($r) ];
133         }
134     }
135
136     $tlend= var_site('lend')."/32";
137     $tlgroup= var_site('lgroup');
138     if ($tlend ne $glend || $tlgroup ne $glgroup) {
139         ipif_permit($tlgroup, '=', $tlend, "$site - local endpoint");
140     }
141     $trend= var_site('rend').'/32';
142     $ix= 0;
143     $trnets= var_site('rnets');
144     ipif_permit($tlgroup, '', $trend, "$site - remote endpoint");
145     if ($trnets ne '-') {
146         foreach $rnet (split /,/, $trnets) {
147             ipif_permit($tlgroup, '', $rnet, "$site - remote network #$ix");
148                 $ix++;
149         }
150     }
151 }
152
153 sub write_file ($$$$) {
154     my ($fn,$why,$head,$body) = @_;
155     length $fn or fault("location to write $why not specified");
156     open F, ">$fn.new" or fault("create $fn.new: $!");
157     print F $head."\n# AUTOGENERATED BY $0 - DO NOT EDIT\n".$body or die $!;
158     close F or die $!;
159     rename "$fn.new",$fn or die $!;
160 }
161
162 $ipifnetsfile= var_global(ipifnetsfile);
163 write_file($ipifnetsfile,'ipifnetsfile','', $ipif_file);
164
165 $active_file= '';
166 $inittab= '';
167 $ix= 0;
168 foreach $site (@actives) {
169     $active_file.= "$site\t".var_site('activesxinfo')."\n";
170     $inittab.= sprintf("t%d", $ix++).':'.var_site('inittab_line')."\n";
171     $invoke_file= var_site('invoke_file');
172     write_file($invoke_file, 'invoke_file',
173                var_site('invoke_head'), var_site('invoke_body'));
174     chmod 0777&~umask, $invoke_file or die $!;
175 }
176 write_file(var_global('activesfile'),'activesfile', '',$active_file);
177
178 print
179 "# You can cut and paste all or part of this into your inittab if you like:\n",
180     $inittab;
181
182 print
183 "# And consider adding this line, or some of this file's contents,\n".
184 "# to your /etc/userv/ipif-networks:\n",
185     "$ipifnetsfile\n"
186     if $ipifnetsfile =~ m,^/,;
187
188 $passive_file= '';
189 foreach $site (@passives) {
190     $passive_file.= "$site\t".var_site('passivesxinfo')."\n";
191 }
192 write_file(var_global('passivesfile'),'passivesfile', '',$passive_file);
193
194 system var_global('postconfigure'); $? and exit -1;
195
196 exit 0;