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