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