1 |
#!/usr/bin/perl |
2 |
|
3 |
# Drakwizard |
4 |
|
5 |
# Copyright (C) 2002, 2003 Mandrakesoft |
6 |
# |
7 |
# Authors: Arnaud Desmons <adesmons@mandrakesoft.com> |
8 |
# Florent Villard <warly@mandrakesoft.com> |
9 |
# |
10 |
# This program is free software; you can redistribute it and/or modify |
11 |
# it under the terms of the GNU General Public License as published by |
12 |
# the Free Software Foundation; either version 2, or (at your option) |
13 |
# any later version. |
14 |
# |
15 |
# This program is distributed in the hope that it will be useful, |
16 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
17 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
18 |
# GNU General Public License for more details. |
19 |
# |
20 |
# You should have received a copy of the GNU General Public License |
21 |
# along with this program; if not, write to the Free Software |
22 |
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
23 |
|
24 |
package MDK::Wizard::Dhcp; |
25 |
use strict; |
26 |
|
27 |
use common; |
28 |
use services; |
29 |
use MDK::Wizard::Varspaceval; |
30 |
use MDK::Wizard::Wizcommon; |
31 |
|
32 |
my $wiz = new MDK::Wizard::Wizcommon; |
33 |
|
34 |
my $wiz_ip_server = $wiz->{net}->itf_get("IPADDR"); |
35 |
my $wiz_tftpserverip = $wiz_ip_server; |
36 |
|
37 |
my $o = { |
38 |
name => N("DHCP Wizard"), |
39 |
var => { |
40 |
ip1 => '', |
41 |
ip2 => '', |
42 |
pxe => '1', |
43 |
gateway => '', |
44 |
wiz_authoritative => 0, |
45 |
interface => $wiz->{net}->default_itf |
46 |
}, |
47 |
needed_rpm => [ 'dhcp-server' ], |
48 |
defaultimage => "/usr/share/mcc/themes/default/dhcp_server-mdk.png", |
49 |
}; |
50 |
|
51 |
$o->{pages} = { |
52 |
welcome => { |
53 |
name => N("DHCP Wizard") . "\n\n\n" . N("DHCP is a service that automatically assigns networking addresses to your workstations.") . "\n\n\n" . N("This wizard will help you configuring the DHCP services of your server."), |
54 |
no_back => 1, |
55 |
next => 'interface', no_back => 1, |
56 |
}, |
57 |
interface => { |
58 |
name => N("Interface the dhcp server must listen to"), |
59 |
pre => sub { |
60 |
if (!$wiz_ip_server) { |
61 |
my $interface = 'eth0'; |
62 |
($wiz_ip_server) = `/sbin/ip addr show dev $interface` =~ /^\s*inet\s+(\d+\.\d+\.\d+\.\d+)/m; |
63 |
} |
64 |
$o->{var}{interface} |= $wiz->{net}->default_itf; |
65 |
}, |
66 |
data => [ |
67 |
{ list => [ keys %{$wiz->{net}{itf}} ], val => \$o->{var}{interface} }, |
68 |
], |
69 |
next => 'ip_range', |
70 |
no_back => 1, |
71 |
}, |
72 |
ip_range => { |
73 |
name => N("Range of addresses used by DHCP") . "\n" . N("Select the range of addresses assigned to the workstations by the DHCP service; unless you have special needs, you can safely accept the proposed values. (ie: 192.168.100.20 192.168.100.40)") . "\n\n" . N("If you want to enable PXE in your dhcp server please check the box (Pre-boot eXecution Environment, a protocol that allows computers to boot through the network)."), |
74 |
pre => sub { |
75 |
#($wiz_ip_server) = `/sbin/ip addr show dev $o->{var}{interface}` =~ /^\s*inet\s+(\d+\.\d+\.\d+\.\d+)/m; |
76 |
($wiz_ip_server) = $wiz->{net}{itf}{$o->{var}{interface}}{IPADDR}; |
77 |
$wiz_tftpserverip = $wiz_ip_server; |
78 |
my $d = $4 if $wiz_ip_server =~ /(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/; |
79 |
my $s = "$1.$2.$3" if $wiz_ip_server =~ /(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/; |
80 |
$o->{var}{ip1} = compute_range($d, $s); |
81 |
$o->{var}{ip2} = compute_range2($d, $s); |
82 |
}, |
83 |
data => [ |
84 |
{ label => N("Lowest IP address:"), val => \$o->{var}{ip1} }, |
85 |
{ label => N("Highest IP address:"), val => \$o->{var}{ip2} }, |
86 |
{ label => N("Gateway IP address:"), val => \$o->{var}{gateway} }, |
87 |
{ label => N("Enable PXE:"), type => 'bool', val => \$o->{var}{pxe} }, |
88 |
], |
89 |
next => 'summary', |
90 |
no_back => 1, |
91 |
}, |
92 |
dhcp_warning => { |
93 |
name => N("Warning") . "\n\n" . N("You are in dhcp, server may not work with your configuration."), |
94 |
ignore => 1, |
95 |
next => 'ip_range', |
96 |
}, |
97 |
ip_range_error => { |
98 |
name => N("Error") . "\n\n" . N("The IP range specified is not correct."), |
99 |
ignore => 1, |
100 |
next => 'ip_range', |
101 |
}, |
102 |
ip_range_warning => { |
103 |
name => N("Warning") . "\n\n" . N("The IP range specified is not in server address range."), |
104 |
ignore => 1, |
105 |
next => 'summary', |
106 |
}, |
107 |
server_in_range => { |
108 |
name => N("Error") . "\n\n" . N("The IP of the server must not be in range."), |
109 |
ignore => 1, |
110 |
next => 'ip_range', |
111 |
}, |
112 |
summary => { |
113 |
name => N("Configuring the DHCP server") . "\n\n" . N("The wizard collected the following parameters needed to configure your DHCP service:"), |
114 |
pre => sub { |
115 |
$o->{var}{pxeornot} = $o->{var}{pxe} ? N("enabled") : N("disabled"); |
116 |
}, |
117 |
data => [ |
118 |
{ label => N("Lowest IP address:"), val_ref => \$o->{var}{ip1} }, |
119 |
{ label => N("Highest IP address:"), val_ref => \$o->{var}{ip2} }, |
120 |
{ label => N("Gateway IP address:"), val_ref => \$o->{var}{gateway} }, |
121 |
{ label => N("Interface:"), val_ref => \$o->{var}{interface} }, |
122 |
{ label => N("Enable PXE:"), val_ref => \$o->{var}{pxeornot} }, |
123 |
], |
124 |
post => \&do_it, |
125 |
next => 'end', |
126 |
}, |
127 |
end => { |
128 |
name => N("Congratulations") . "\n\n" . N("The wizard successfully configured the DHCP services."), |
129 |
end => 1, |
130 |
no_back => 1, |
131 |
}, |
132 |
error_end => { |
133 |
name => N("Failed"), |
134 |
data => [ { label => N("Relaunch drakwizard, and try to change some parameters.") } ], |
135 |
no_back => 1, |
136 |
end => 1, |
137 |
}, |
138 |
}; |
139 |
|
140 |
|
141 |
|
142 |
sub compute_range { |
143 |
my ($d, $s) = @_; |
144 |
my $n = $d <= 64 ? "65" : $d <= 128 ? "129" : "1"; |
145 |
"$s.$n"; |
146 |
} |
147 |
|
148 |
sub compute_range2 { |
149 |
my ($d, $s) = @_; |
150 |
my $n = $d <= 128 ? "254" : $d > 192 ? "192" : "128"; |
151 |
"$s.$n"; |
152 |
} |
153 |
|
154 |
sub check_ip { return $_[0] < 0 || $_[0] > 255 ? 0 : 1 } |
155 |
|
156 |
sub check { |
157 |
my $r1_trunc = "$1.$2.$3" if $o->{var}{ip1} =~ /(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/; |
158 |
foreach ($1, $2, $3, $4) { check_ip($_) or return 'ip_range_error' } |
159 |
my $r2_trunc = "$1.$2.$3" if $o->{var}{ip2} =~ /(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/; |
160 |
foreach ($1, $2, $3, $4) { check_ip($_) or return 'ip_range_error' } |
161 |
my $d1 = $4 if $o->{var}{ip1} =~ /(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/; |
162 |
my $d2 = $4 if $o->{var}{ip2} =~ /(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/; |
163 |
my $s_trunc = "$1.$2.$3" if $wiz_ip_server =~ /(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/; |
164 |
my $ds = $4 if $wiz_ip_server =~ /(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/; |
165 |
if (!$r1_trunc) { standalone::explanations("DHCP wizard : incorrect adress range 1"); return 'ip_range_error' } |
166 |
if (!$r2_trunc) { standalone::explanations("DHCP wizard : incorrect adress range 2"); return 'ip_range_error' } |
167 |
if ($r1_trunc ne $s_trunc || $r2_trunc ne $s_trunc) { |
168 |
standalone::explanations("DHCP wizard : range not in network"); |
169 |
return 'ip_range_warning'; |
170 |
} |
171 |
if (!$d1 || !$d2 || $d1 > $d2) { standalone::explanations("DHCP wizard : bad range"); return 'ip_range_error' } |
172 |
if ($ds >= $d1 && $ds <= $d2) { standalone::explanations("DHCP wizard : server in range"); return 'server_in_range' } |
173 |
return 'interface' if keys %{$wiz->{net}{itf}} > 1; |
174 |
0; |
175 |
} |
176 |
|
177 |
sub do_it { |
178 |
$::testing and return; |
179 |
my $in = 'interactive'->vnew('su', 'DHCP'); |
180 |
check_starts_on_boot($in, 'dhcpd'); |
181 |
my $wiz_domain_name = $wiz->{net}->network_get("DOMAINNAME"); |
182 |
my $wiz_host_name = $wiz->{net}->network_get("HOSTNAME"); |
183 |
my $wiz_dns = $wiz->{net}->network_get("dnsServer"); |
184 |
if ($wiz_dns eq '127.0.0.1') { |
185 |
$wiz_dns = $wiz_ip_server; |
186 |
} |
187 |
if (!$o->{var}{gateway}) { |
188 |
my $t = `LC_ALL=C /sbin/ip route list scope global`; |
189 |
($o->{var}{gateway}) = $t =~ /default via (\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}) dev/; |
190 |
} |
191 |
my $wiz_ip_net = "$1.$2.$3.0" if $wiz_ip_server =~ /(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/; |
192 |
my $err = check(); |
193 |
return $err if $err; |
194 |
my $wiz_ip_range1 = $o->{var}{ip1}; |
195 |
my $wiz_ip_range2 = $o->{var}{ip2}; |
196 |
my $wiz_ip_netmask = $wiz->{net}->itf_get("NETMASK"); |
197 |
if (!$wiz_ip_netmask) { $wiz_ip_netmask = "255.255.255.0" } |
198 |
my $wiz_device = $o->{var}{interface}; |
199 |
# patch to rewrite when got new file about dhcp with INTERFACES value |
200 |
# currently, I put the device to configure as dhcp server |
201 |
# in /etc/sysconfig/dhcpd |
202 |
|
203 |
#[ -f /etc/sysconfig/dhcpd ] && cp -f /etc/sysconfig/dhcpd /var/tmp/wiz_bck/orig/dhcpd |
204 |
my $file = "/etc/sysconfig/dhcpd"; |
205 |
-f $file and MDK::Common::cp_af($file, $file . ".orig"); |
206 |
standalone::explanations("now patching etc/sysconfig/dhcpd"); |
207 |
if (!`grep INTERFACES $file`) { |
208 |
my $tmp = `/bin/mktemp /tmp/Dhcpconf.XXXXXX` or die "can't make a temp file: $!"; |
209 |
chomp($tmp); |
210 |
output($tmp, |
211 |
(map { |
212 |
if (m|INTERFACE|) { |
213 |
"# $_"; |
214 |
} |
215 |
# FIXME: we probably lack a "else": |
216 |
$_; |
217 |
} cat_or_die($file)), |
218 |
"\n# Added by drakwizard\nINTERFACES=$wiz_device"); |
219 |
system("mv $tmp $file"); |
220 |
} |
221 |
$file = "/etc/dhcpd.conf"; |
222 |
-f $file and MDK::Common::cp_af($file, $file . ".orig"); |
223 |
output($file, map { |
224 |
s|__hname__|$wiz_host_name|g; |
225 |
s|__dns__|$wiz_dns|g; |
226 |
s|__net__|$wiz_ip_net|g; |
227 |
s|__ip__|$wiz_ip_server|g; |
228 |
s|__mask__|$wiz_ip_netmask|g; |
229 |
s|__rng1__|$wiz_ip_range1|g; |
230 |
s|__rng2__|$wiz_ip_range2|g; |
231 |
s|__dname__|$wiz_domain_name|g; |
232 |
s|__gateway__|$o->{var}{gateway}|g; |
233 |
s|__tftpserverip__|$wiz_tftpserverip|g; |
234 |
s|__dhcpd_interface__|$wiz_device|g; |
235 |
$_; |
236 |
} cat_("/usr/share/wizards//dhcp_wizard/scripts/dhcpd.conf.default")); |
237 |
standalone::explanations("$file: hname = $wiz_host_name, net = $wiz_ip_net, ip = $wiz_ip_server, |
238 |
mask = $wiz_ip_netmask, rng1 = $wiz_ip_range1, rng2 = $wiz_ip_range2, dname = $wiz_domain_name"); |
239 |
MDK::Common::touch("/var/dhcpd/dhcpd.leases"); |
240 |
# modifying webmin config |
241 |
$file="/etc/webmin/dhcpd/config"; |
242 |
if (-f $file) { |
243 |
my %mdk = MDK::Wizard::Varspaceval->get($file); |
244 |
$mdk{lease_file} = "/var/dhcpd/dhcpd.leases"; |
245 |
$mdk{interfaces} = $wiz_device; |
246 |
standalone::explanations("$file: lease_file = $mdk{lease_file}, interfaces = $mdk{interfaces}"); |
247 |
MDK::Wizard::Varspaceval->commit($file, \%mdk); |
248 |
!$o->{var}{wiz_authoritative} and output($file, map { |
249 |
s|^\s*not\s*authoritative.*|#$&|i; |
250 |
$_; |
251 |
} cat_("/etc/dhcpd.conf")); |
252 |
} |
253 |
|
254 |
if ($o->{var}{pxe} eq '0') { |
255 |
substInFile { |
256 |
s/#\s+deny members of "PXE"/deny members of "PXE"/; |
257 |
} "/etc/dhcpd.conf"; |
258 |
} |
259 |
|
260 |
$o->{var}{gateway} or substInFile { |
261 |
s/#\s+doption routers.*//; |
262 |
} "/etc/dhcpd.conf"; |
263 |
|
264 |
reload_or_restart('dhcpd'); |
265 |
check_started('dhcpd'); |
266 |
} |
267 |
|
268 |
sub new { |
269 |
my ($class) = @_; |
270 |
bless $o, $class; |
271 |
} |
272 |
|
273 |
1; |