Commit | Line | Data |
---|---|---|
2e082dfe | 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 | ||
c07be359 | 6 | # This file is part of ipif, part of userv-utils |
7 | # | |
9028e234 IJ |
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 | # | |
2e082dfe | 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 | |
9028e234 | 16 | # the Free Software Foundation; either version 3 of the License, or |
2e082dfe | 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 | |
9028e234 | 25 | # along with userv-utils; if not, see http://www.gnu.org/licenses/. |
2e082dfe | 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"; | |
babeab5a | 63 | $!=0; close X; $? and die "m4 failed with code $? $!"; |
2e082dfe | 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 | ||
2e082dfe | 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) { | |
1c18e501 | 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 | ||
2e082dfe | 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= ''; | |
99d1b3be | 171 | $knownhosts_file= ''; |
2e082dfe | 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"; | |
99d1b3be | 177 | $hostkey= var_site('rhostkey'); |
178 | $knownhosts_file.= var_site('sshdest').' '.$hostkey."\n" | |
179 | if length $hostkey; | |
2e082dfe | 180 | $invoke_file= var_site('invoke_file'); |
181 | write_file($invoke_file, 'invoke_file', | |
99d1b3be | 182 | var_site('invoke_head')."\n", var_site('invoke_body')); |
2e082dfe | 183 | chmod 0777&~umask, $invoke_file or die $!; |
184 | } | |
99d1b3be | 185 | write_file(var_global('knownhostsfile'),'knownhostsfile', '',$knownhosts_file); |
2e082dfe | 186 | write_file(var_global('activesfile'),'activesfile', '',$active_file); |
187 | ||
188 | ||
189 | "# You can cut and paste all or part of this into your inittab if you like:\n", | |
190 | $inittab; | |
191 | ||
192 | ||
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; |