]>
Commit | Line | Data |
---|---|---|
1 | #!/usr/bin/perl\r | |
2 | #\r | |
3 | # SmoothWall CGIs\r | |
4 | #\r | |
5 | # This code is distributed under the terms of the GPL\r | |
6 | #\r | |
7 | # (c) The SmoothWall Team\r | |
8 | #\r | |
9 | # Copyright (C) 01-02-2002 Graham Smith <grhm@grhm.co.uk>\r | |
10 | # - Fixed DHCP Leases added\r | |
11 | #\r | |
12 | # $Id: dhcp.cgi,v 1.14.2.81 2006/01/20 12:05:29 franck78 Exp $\r | |
13 | #\r | |
14 | # Franck -rewrite for two or more interface\r | |
15 | # nov/2004 -check range is in correct subnet\r | |
16 | # -add NTP option\r | |
17 | # -add display sorting of actives leases\r | |
18 | # dec/2004 -add comment field to fixed leases\r | |
19 | # \r | |
20 | # to do : choose a correct format for displaying dates\r | |
21 | #\r | |
22 | use strict;\r | |
23 | \r | |
24 | # enable only the following on debugging purpose\r | |
25 | #use warnings;\r | |
26 | #use CGI::Carp 'fatalsToBrowser';\r | |
27 | \r | |
28 | require 'CONFIG_ROOT/general-functions.pl';\r | |
29 | require "${General::swroot}/lang.pl";\r | |
30 | require "${General::swroot}/header.pl";\r | |
31 | #workaround to suppress a warning when a variable is used only once\r | |
32 | my @dummy = ( ${Header::colouryellow} );\r | |
33 | undef (@dummy);\r | |
34 | \r | |
35 | our %dhcpsettings=();\r | |
36 | our %netsettings=();\r | |
37 | my %mainsettings=();\r | |
38 | my %timesettings=();\r | |
39 | my $setting = "${General::swroot}/dhcp/settings";\r | |
40 | our $filename1 = "${General::swroot}/dhcp/advoptions"; # Field separator is TAB in this file (comma is standart)\r | |
41 | # because we need commas in the some data\r | |
42 | our $filename2 = "${General::swroot}/dhcp/fixleases";\r | |
43 | our $filename3 = "${General::swroot}/dhcp/advoptions-list"; # Describe the allowed syntax for dhcp options\r | |
44 | my $errormessage = '';\r | |
45 | my $warnNTPmessage = '';\r | |
46 | my @nosaved=();\r | |
47 | \r | |
48 | #Basic syntax allowed for new Option definition. Not implemented: RECORDS & array of RECORDS \r | |
49 | our $OptionTypes = 'boolean|((un)?signed )?integer (8|16|32)|ip-address|text|string|encapsulate \w+|array of ip-address';\r | |
50 | \r | |
51 | &Header::showhttpheaders();\r | |
52 | our @ITFs=('GREEN','BLUE');\r | |
53 | \r | |
54 | #Settings1 for the first screen box\r | |
55 | foreach my $itf (@ITFs) {\r | |
56 | $dhcpsettings{"ENABLE_${itf}"} = 'off';\r | |
57 | $dhcpsettings{"ENABLEBOOTP_${itf}"} = 'off';\r | |
58 | $dhcpsettings{"START_ADDR_${itf}"} = '';\r | |
59 | $dhcpsettings{"END_ADDR_${itf}"} = '';\r | |
60 | $dhcpsettings{"DOMAIN_NAME_${itf}"} = '';\r | |
61 | $dhcpsettings{"DEFAULT_LEASE_TIME_${itf}"} = '';\r | |
62 | $dhcpsettings{"MAX_LEASE_TIME_${itf}"} = '';\r | |
63 | $dhcpsettings{"WINS1_${itf}"} = '';\r | |
64 | $dhcpsettings{"WINS2_${itf}"} = '';\r | |
65 | $dhcpsettings{"DNS1_${itf}"} = '';\r | |
66 | $dhcpsettings{"DNS2_${itf}"} = '';\r | |
67 | $dhcpsettings{"NTP1_${itf}"} = '';\r | |
68 | $dhcpsettings{"NTP2_${itf}"} = '';\r | |
69 | }\r | |
70 | \r | |
71 | $dhcpsettings{'SORT_FLEASELIST'} = 'FIPADDR';\r | |
72 | $dhcpsettings{'SORT_LEASELIST'} = 'IPADDR';\r | |
73 | \r | |
74 | #Settings2 for editing the multi-line list\r | |
75 | #Must not be saved with writehash !\r | |
76 | $dhcpsettings{'FIX_MAC'} = '';\r | |
77 | $dhcpsettings{'FIX_ADDR'} = '';\r | |
78 | $dhcpsettings{'FIX_ENABLED'} = 'off';\r | |
79 | $dhcpsettings{'FIX_NEXTADDR'} = '';\r | |
80 | $dhcpsettings{'FIX_FILENAME'} = '';\r | |
81 | $dhcpsettings{'FIX_ROOTPATH'} = '';\r | |
82 | $dhcpsettings{'FIX_REMARK'} = '';\r | |
83 | $dhcpsettings{'ACTION'} = '';\r | |
84 | $dhcpsettings{'KEY1'} = '';\r | |
85 | $dhcpsettings{'KEY2'} = '';\r | |
86 | @nosaved=('FIX_MAC','FIX_ADDR','FIX_ENABLED','FIX_NEXTADDR',\r | |
87 | 'FIX_FILENAME','FIX_ROOTPATH','FIX_REMARK');\r | |
88 | \r | |
89 | $dhcpsettings{'ADVOPT_ENABLED'} = '';\r | |
90 | $dhcpsettings{'ADVOPT_NAME'} = '';\r | |
91 | $dhcpsettings{'ADVOPT_DATA'} = '';\r | |
92 | unshift (@nosaved,'ADVOPT_ENABLED','ADVOPT_NAME','ADVOPT_DATA');\r | |
93 | foreach my $itf (@ITFs) {\r | |
94 | $dhcpsettings{"ADVOPT_SCOPE_${itf}"} = 'off';\r | |
95 | unshift (@nosaved, "ADVOPT_SCOPE_${itf}");\r | |
96 | }\r | |
97 | \r | |
98 | # Read Ipcop settings\r | |
99 | &General::readhash("${General::swroot}/ethernet/settings", \%netsettings);\r | |
100 | &General::readhash("${General::swroot}/main/settings", \%mainsettings);\r | |
101 | &General::readhash("${General::swroot}/time/settings", \%timesettings);\r | |
102 | \r | |
103 | #Get GUI values\r | |
104 | &Header::getcgihash(\%dhcpsettings);\r | |
105 | \r | |
106 | open(FILE, "$filename1") or die 'Unable to open dhcp advanced options file.';\r | |
107 | our @current1 = <FILE>;\r | |
108 | close(FILE);\r | |
109 | # Extract OptionDefinition\r | |
110 | foreach my $line (@current1) {\r | |
111 | #chomp($line); # remove newline #don't know why, but this remove newline in @current1 .... !\r | |
112 | my @temp = split(/\t/,$line);\r | |
113 | AddNewOptionDefinition ($temp[1] . ' ' . $temp[2]);\r | |
114 | }\r | |
115 | \r | |
116 | open(FILE, "$filename2") or die 'Unable to open fixed leases file.';\r | |
117 | our @current2 = <FILE>;\r | |
118 | close(FILE);\r | |
119 | \r | |
120 | # Check Settings1 first because they are needed by &buildconf\r | |
121 | if ($dhcpsettings{'ACTION'} eq $Lang::tr{'save'}) {\r | |
122 | foreach my $itf (@ITFs) {\r | |
123 | if ($dhcpsettings{"ENABLE_${itf}"} eq 'on' ) {\r | |
124 | # "Start" is defined, need "End" and vice versa\r | |
125 | if ($dhcpsettings{"START_ADDR_${itf}"}) {\r | |
126 | if (!(&General::validip($dhcpsettings{"START_ADDR_${itf}"}))) {\r | |
127 | $errormessage = "DHCP on ${itf}: " . $Lang::tr{'invalid start address'};\r | |
128 | goto ERROR;\r | |
129 | }\r | |
130 | if (!$dhcpsettings{"END_ADDR_${itf}"}) {\r | |
131 | $errormessage = "DHCP on ${itf}: " . $Lang::tr{'invalid end address'};\r | |
132 | goto ERROR;\r | |
133 | }\r | |
134 | if (! &General::IpInSubnet ( $dhcpsettings{"START_ADDR_${itf}"}, \r | |
135 | $netsettings{"${itf}_NETADDRESS"},\r | |
136 | $netsettings{"${itf}_NETMASK"})) {\r | |
137 | $errormessage = "DHCP on ${itf}: " . $Lang::tr{'invalid start address'};\r | |
138 | goto ERROR;\r | |
139 | }\r | |
140 | }\r | |
141 | \r | |
142 | if ($dhcpsettings{"END_ADDR_${itf}"}) {\r | |
143 | if (!(&General::validip($dhcpsettings{"END_ADDR_${itf}"}))) {\r | |
144 | $errormessage = "DHCP on ${itf}: " . $Lang::tr{'invalid end address'};\r | |
145 | goto ERROR;\r | |
146 | }\r | |
147 | if (!$dhcpsettings{"START_ADDR_${itf}"}) {\r | |
148 | $errormessage = "DHCP on ${itf}: " . $Lang::tr{'invalid start address'};\r | |
149 | goto ERROR;\r | |
150 | }\r | |
151 | if (! &General::IpInSubnet ( $dhcpsettings{"END_ADDR_${itf}"}, \r | |
152 | $netsettings{"${itf}_NETADDRESS"},\r | |
153 | $netsettings{"${itf}_NETMASK"})) { \r | |
154 | $errormessage = "DHCP on ${itf}: " . $Lang::tr{'invalid end address'};\r | |
155 | goto ERROR;\r | |
156 | }\r | |
157 | #swap if necessary! (support 255.255.0.0 range, I doubt we need more) GE\r | |
158 | my @startoct = split (/\./, $dhcpsettings{"START_ADDR_${itf}"});\r | |
159 | my @endoct = split (/\./, $dhcpsettings{"END_ADDR_${itf}"});\r | |
160 | if ( $endoct[2]*256+$endoct[3] < $startoct[2]*256+$startoct[3] ) {\r | |
161 | ($dhcpsettings{"START_ADDR_${itf}"},$dhcpsettings{"END_ADDR_${itf}"}) =\r | |
162 | ($dhcpsettings{"END_ADDR_${itf}"},$dhcpsettings{"START_ADDR_${itf}"});\r | |
163 | }\r | |
164 | }\r | |
165 | \r | |
166 | if (!($dhcpsettings{"DEFAULT_LEASE_TIME_${itf}"} =~ /^\d+$/)) {\r | |
167 | $errormessage = "DHCP on ${itf}: " . $Lang::tr{'invalid default lease time'} . $dhcpsettings{'DEFAULT_LEASE_TIME_${itf}'};\r | |
168 | goto ERROR;\r | |
169 | }\r | |
170 | \r | |
171 | if (!($dhcpsettings{"MAX_LEASE_TIME_${itf}"} =~ /^\d+$/)) {\r | |
172 | $errormessage = "DHCP on ${itf}: " . $Lang::tr{'invalid max lease time'} . $dhcpsettings{'MAX_LEASE_TIME_${itf}'};\r | |
173 | goto ERROR;\r | |
174 | }\r | |
175 | \r | |
176 | if ($dhcpsettings{"DNS1_${itf}"}) {\r | |
177 | if (!(&General::validip($dhcpsettings{"DNS1_${itf}"}))) {\r | |
178 | $errormessage = "DHCP on ${itf}: " . $Lang::tr{'invalid primary dns'};\r | |
179 | goto ERROR;\r | |
180 | }\r | |
181 | }\r | |
182 | if ($dhcpsettings{"DNS2_${itf}"}) {\r | |
183 | if (!(&General::validip($dhcpsettings{"DNS2_${itf}"}))) {\r | |
184 | $errormessage = "DHCP on ${itf}: " . $Lang::tr{'invalid secondary dns'};\r | |
185 | goto ERROR;\r | |
186 | }\r | |
187 | if (! $dhcpsettings{"DNS1_${itf}"}) {\r | |
188 | $errormessage = "DHCP on ${itf}: " . $Lang::tr{'cannot specify secondary dns without specifying primary'}; \r | |
189 | goto ERROR;\r | |
190 | }\r | |
191 | }\r | |
192 | \r | |
193 | if ($dhcpsettings{"WINS1_${itf}"}) {\r | |
194 | if (!(&General::validip($dhcpsettings{"WINS1_${itf}"}))) {\r | |
195 | $errormessage = "DHCP on ${itf}: " . $Lang::tr{'invalid wins address'};\r | |
196 | goto ERROR;\r | |
197 | }\r | |
198 | }\r | |
199 | if ($dhcpsettings{"WINS2_${itf}"}) {\r | |
200 | if (!(&General::validip($dhcpsettings{"WINS2_${itf}"}))) {\r | |
201 | $errormessage = "DHCP on ${itf}: " . $Lang::tr{'invalid wins address'};\r | |
202 | goto ERROR;\r | |
203 | }\r | |
204 | if (! $dhcpsettings{"WINS1_${itf}"} ) {\r | |
205 | $errormessage = "DHCP on ${itf}: " . $Lang::tr{'cannot specify secondary wins without specifying primary'};\r | |
206 | goto ERROR;\r | |
207 | } \r | |
208 | }\r | |
209 | \r | |
210 | if ($dhcpsettings{"NTP1_${itf}"}) {\r | |
211 | if (!(&General::validip($dhcpsettings{"NTP1_${itf}"}))) {\r | |
212 | $errormessage = "DHCP on ${itf}: " . $Lang::tr{'invalid primary ntp'};\r | |
213 | goto ERROR;\r | |
214 | }\r | |
215 | if ($dhcpsettings{"NTP1_${itf}"} eq $netsettings{"${itf}_ADDRESS"} && ($timesettings{'ENABLECLNTP'} ne 'on')) {\r | |
216 | $warnNTPmessage = "DHCP on ${itf}: " . $Lang::tr{'local ntp server specified but not enabled'};\r | |
217 | #goto ERROR;\r | |
218 | }\r | |
219 | }\r | |
220 | if ($dhcpsettings{"NTP2_${itf}"}) {\r | |
221 | if (!(&General::validip($dhcpsettings{"NTP2_${itf}"}))) {\r | |
222 | $errormessage = "DHCP on ${itf}: " . $Lang::tr{'invalid secondary ntp'};\r | |
223 | goto ERROR;\r | |
224 | }\r | |
225 | if ($dhcpsettings{"NTP2_${itf}"} eq $netsettings{"${itf}_ADDRESS"} && ($timesettings{'ENABLECLNTP'} ne 'on')) {\r | |
226 | $warnNTPmessage = "DHCP on ${itf}: " . $Lang::tr{'local ntp server specified but not enabled'};\r | |
227 | #goto ERROR;\r | |
228 | }\r | |
229 | if (! $dhcpsettings{"NTP1_${itf}"}) {\r | |
230 | $errormessage = "DHCP on ${itf}: " . $Lang::tr{'cannot specify secondary ntp without specifying primary'};\r | |
231 | goto ERROR;\r | |
232 | }\r | |
233 | }\r | |
234 | } # enabled\r | |
235 | }#loop interface verify\r | |
236 | \r | |
237 | map (delete ($dhcpsettings{$_}) ,@nosaved,'ACTION','KEY1','KEY2'); # Must not be saved \r | |
238 | &General::writehash($setting, \%dhcpsettings); # Save good settings\r | |
239 | $dhcpsettings{'ACTION'} = $Lang::tr{'save'}; # create an 'ACTION'\r | |
240 | map ($dhcpsettings{$_} = '',@nosaved,'KEY1','KEY2'); # and reinit vars to empty\r | |
241 | &buildconf;\r | |
242 | ERROR: # Leave the faulty field untouched\r | |
243 | } else {\r | |
244 | &General::readhash($setting, \%dhcpsettings); # Get saved settings and reset to good if needed\r | |
245 | }\r | |
246 | \r | |
247 | ## Sorting of fixed leases\r | |
248 | if ($ENV{'QUERY_STRING'} =~ /^FETHER|^FIPADDR/ ) {\r | |
249 | my $newsort=$ENV{'QUERY_STRING'};\r | |
250 | my $act=$dhcpsettings{'SORT_FLEASELIST'};\r | |
251 | #Reverse actual sort ?\r | |
252 | if ($act =~ $newsort) {\r | |
253 | my $Rev='';\r | |
254 | if ($act !~ 'Rev') {\r | |
255 | $Rev='Rev';\r | |
256 | }\r | |
257 | $newsort.=$Rev;\r | |
258 | }\r | |
259 | $dhcpsettings{'SORT_FLEASELIST'}=$newsort;\r | |
260 | map (delete ($dhcpsettings{$_}) ,@nosaved,'ACTION','KEY1','KEY2'); # Must never be saved \r | |
261 | &General::writehash($setting, \%dhcpsettings);\r | |
262 | &sortcurrent2;\r | |
263 | $dhcpsettings{'ACTION'} = 'SORT'; # create an 'ACTION'\r | |
264 | map ($dhcpsettings{$_} = '',@nosaved,'KEY1','KEY2');# and reinit vars to empty \r | |
265 | }\r | |
266 | \r | |
267 | #Sorting of allocated leases\r | |
268 | &Header::CheckSortOrder;\r | |
269 | \r | |
270 | \r | |
271 | ## Now manipulate the two multi-line list with Settings2. \r | |
272 | # '1' suffix is for ADVANCED OPTIONS\r | |
273 | # '2' suffix is for FIXED LEASES\r | |
274 | \r | |
275 | # Toggle enable/disable field on specified options.\r | |
276 | \r | |
277 | if ($dhcpsettings{'ACTION'} eq $Lang::tr{'toggle enable disable'}.'1') {\r | |
278 | #move out new line\r | |
279 | chomp(@current1[$dhcpsettings{'KEY1'}]);\r | |
280 | my @temp = split(/\t/,@current1[$dhcpsettings{'KEY1'}]); #use TAB separator !\r | |
281 | $temp[0] = $temp[0] eq 'on' ? '' : 'on'; # Toggle the field\r | |
282 | @current1[$dhcpsettings{'KEY1'}] = join ("\t",@temp)."\n";\r | |
283 | $dhcpsettings{'KEY1'} = ''; # End edit mode\r | |
284 | &General::log($Lang::tr{'dhcp advopt modified'});\r | |
285 | open(FILE, ">$filename1") or die 'Unable to open dhcp advanced options file.';\r | |
286 | print FILE @current1;\r | |
287 | close(FILE);\r | |
288 | \r | |
289 | #Write changes to dhcpd.conf.\r | |
290 | &buildconf;\r | |
291 | }\r | |
292 | \r | |
293 | \r | |
294 | \r | |
295 | if ($dhcpsettings{'ACTION'} eq $Lang::tr{'add'}.'1' &&\r | |
296 | $dhcpsettings{'SUBMIT'} ne $Lang::tr{'dhcp advopt help'}) {\r | |
297 | $dhcpsettings{'ADVOPT_NAME'} =~ s/[^ \w-]//g; # prevent execution of code by removing everything except letters/space\r | |
298 | $dhcpsettings{'ADVOPT_DATA'} =~ s/`//g; # back tik ` ? not allowed !\r | |
299 | \r | |
300 | if ($dhcpsettings{'ADVOPT_DATA'} eq '') {\r | |
301 | $errormessage=$Lang::tr{'dhcp advopt blank value'};\r | |
302 | }\r | |
303 | \r | |
304 | # Test for a new option definition string (join field name & data)\r | |
305 | if (ExistNewOptionDefinition ($dhcpsettings{'ADVOPT_NAME'} . ' ' . $dhcpsettings{'ADVOPT_DATA'})) {\r | |
306 | #only edit permitted if option definition exists\r | |
307 | $errormessage = $Lang::tr{'dhcp advopt definition exists'} if ($dhcpsettings{'KEY1'} eq '');\r | |
308 | $dhcpsettings{'ADVOPT_ENABLED'} = 'on'; # force active\r | |
309 | map ($dhcpsettings{"ADVOPT_SCOPE_$_"} = 'off', @ITFs); # force global\r | |
310 | } elsif (AddNewOptionDefinition ($dhcpsettings{'ADVOPT_NAME'} . ' ' . $dhcpsettings{'ADVOPT_DATA'})) {\r | |
311 | #was a new option definition\r | |
312 | $dhcpsettings{'ADVOPT_ENABLED'} = 'on'; # force active\r | |
313 | map ($dhcpsettings{"ADVOPT_SCOPE_$_"} = 'off', @ITFs); # force global\r | |
314 | } elsif (ValidNewOption ($dhcpsettings{'ADVOPT_NAME'} . ' ' . $dhcpsettings{'ADVOPT_DATA'})) {\r | |
315 | #was a new option\r | |
316 | } elsif (! `grep "\$option $dhcpsettings{'ADVOPT_NAME'} " $filename3`) {\r | |
317 | $errormessage=$Lang::tr{'dhcp advopt unknown'}.': '.$dhcpsettings{'ADVOPT_NAME'};\r | |
318 | }\r | |
319 | \r | |
320 | unless ($errormessage) {\r | |
321 | \r | |
322 | my $scope = '';\r | |
323 | foreach my $itf (@ITFs) { # buils "RED,GREEN,ORANGE,... based on selection\r | |
324 | $scope .= $dhcpsettings{"ADVOPT_SCOPE_${itf}"} eq 'on' ? "\t$itf" : "\toff" ;\r | |
325 | }\r | |
326 | if ($dhcpsettings{'KEY1'} eq '') { #add or edit ? TAB separator !\r | |
327 | unshift (@current1, "$dhcpsettings{'ADVOPT_ENABLED'}\t$dhcpsettings{'ADVOPT_NAME'}\t$dhcpsettings{'ADVOPT_DATA'}$scope\n");\r | |
328 | &General::log($Lang::tr{'dhcp advopt added'});\r | |
329 | } else {\r | |
330 | @current1[$dhcpsettings{'KEY1'}] = "$dhcpsettings{'ADVOPT_ENABLED'}\t$dhcpsettings{'ADVOPT_NAME'}\t$dhcpsettings{'ADVOPT_DATA'}$scope\n";\r | |
331 | $dhcpsettings{'KEY1'} = ''; # End edit mode\r | |
332 | &General::log($Lang::tr{'dhcp advopt modified'});\r | |
333 | }\r | |
334 | \r | |
335 | #Write changes to dhcpd.conf.\r | |
336 | &sortcurrent1; # sort newly added/modified entry\r | |
337 | &buildconf; # before calling buildconf which use fixed lease file !\r | |
338 | }\r | |
339 | }\r | |
340 | \r | |
341 | if ($dhcpsettings{'ACTION'} eq $Lang::tr{'edit'}.'1') {\r | |
342 | #move out new line\r | |
343 | my $line = @current1[$dhcpsettings{'KEY1'}];\r | |
344 | chomp($line);\r | |
345 | my @temp = split(/\t/, $line);\r | |
346 | $dhcpsettings{'ADVOPT_ENABLED'}=$temp[0];\r | |
347 | $dhcpsettings{'ADVOPT_NAME'}=$temp[1];\r | |
348 | $dhcpsettings{'ADVOPT_DATA'}=$temp[2];\r | |
349 | \r | |
350 | # read next fields which are the name (color) of an interface if this interface is scoped\r | |
351 | for (my $key=0; $key<@ITFs; $key++) {\r | |
352 | my $itf = $temp[3+$key];\r | |
353 | if ($itf ne 'off') # Only is an interface name is read\r | |
354 | {\r | |
355 | $dhcpsettings{"ADVOPT_SCOPE_${itf}"} = 'on';\r | |
356 | } \r | |
357 | }\r | |
358 | }\r | |
359 | \r | |
360 | if ($dhcpsettings{'ACTION'} eq $Lang::tr{'remove'}.'1') {\r | |
361 | splice (@current1,$dhcpsettings{'KEY1'},1);\r | |
362 | open(FILE, ">$filename1") or die 'Unable to open dhcp advanced options file.';\r | |
363 | print FILE @current1;\r | |
364 | close(FILE);\r | |
365 | $dhcpsettings{'KEY1'} = ''; # End remove mode\r | |
366 | &General::log($Lang::tr{'dhcp advopt removed'});\r | |
367 | #Write changes to dhcpd.conf.\r | |
368 | &buildconf;\r | |
369 | }\r | |
370 | #end KEY1\r | |
371 | \r | |
372 | \r | |
373 | # Toggle enable/disable field on specified lease.\r | |
374 | if ($dhcpsettings{'ACTION'} eq $Lang::tr{'toggle enable disable'}.'2') {\r | |
375 | #move out new line\r | |
376 | chomp(@current2[$dhcpsettings{'KEY2'}]);\r | |
377 | my @temp = split(/\,/,@current2[$dhcpsettings{'KEY2'}]);\r | |
378 | $temp[2] = $temp[2] eq 'on' ? '' : 'on'; # Toggle the field\r | |
379 | @current2[$dhcpsettings{'KEY2'}] = join (',',@temp)."\n";\r | |
380 | $dhcpsettings{'KEY2'} = ''; # End edit mode\r | |
381 | &General::log($Lang::tr{'fixed ip lease modified'});\r | |
382 | open(FILE, ">$filename2") or die 'Unable to open fixed leases file.';\r | |
383 | print FILE @current2;\r | |
384 | close(FILE);\r | |
385 | \r | |
386 | #Write changes to dhcpd.conf.\r | |
387 | &buildconf;\r | |
388 | }\r | |
389 | \r | |
390 | if ($dhcpsettings{'ACTION'} eq $Lang::tr{'add'}.'2') {\r | |
391 | $dhcpsettings{'FIX_MAC'} =~ tr/-/:/;\r | |
392 | unless(&General::validip($dhcpsettings{'FIX_ADDR'})) { $errormessage = $Lang::tr{'invalid fixed ip address'}; }\r | |
393 | unless(&General::validmac($dhcpsettings{'FIX_MAC'})) { $errormessage = $Lang::tr{'invalid fixed mac address'}; }\r | |
394 | if ($dhcpsettings{'FIX_NEXTADDR'}) {\r | |
395 | unless(&General::validip($dhcpsettings{'FIX_NEXTADDR'})) { $errormessage = $Lang::tr{'invalid fixed ip address'}; }\r | |
396 | }\r | |
397 | \r | |
398 | my $key = 0;\r | |
399 | CHECK:foreach my $line (@current2) {\r | |
400 | my @temp = split(/\,/,$line);\r | |
401 | if($dhcpsettings{'KEY2'} ne $key) {\r | |
402 | # same MAC is OK on different subnets. This test is not complete because\r | |
403 | # if ip are not inside a known subnet, I don't warn.\r | |
404 | # Also it may be needed to put duplicate fixed lease in their right subnet definition..\r | |
405 | foreach my $itf (@ITFs) {\r | |
406 | my $scoped = &General::IpInSubnet($dhcpsettings{'FIX_ADDR'},\r | |
407 | $netsettings{"${itf}_NETADDRESS"}, \r | |
408 | $netsettings{"${itf}_NETMASK"}) &&\r | |
409 | $dhcpsettings{"ENABLE_${itf}"} eq 'on';\r | |
410 | if ( $scoped &&\r | |
411 | (lc($dhcpsettings{'FIX_MAC'}) eq lc($temp[0])) &&\r | |
412 | &General::IpInSubnet($temp[1],\r | |
413 | $netsettings{"${itf}_NETADDRESS"}, \r | |
414 | $netsettings{"${itf}_NETMASK"})) {\r | |
415 | $errormessage = "$Lang::tr{'mac address in use'} $dhcpsettings{'FIX_MAC'}";\r | |
416 | last CHECK;\r | |
417 | }\r | |
418 | }\r | |
419 | }\r | |
420 | $key++;\r | |
421 | }\r | |
422 | \r | |
423 | unless ($errormessage) {\r | |
424 | $dhcpsettings{'FIX_REMARK'} = &Header::cleanhtml($dhcpsettings{'FIX_REMARK'});\r | |
425 | $dhcpsettings{'FIX_NEXTADDR'} = &Header::cleanhtml($dhcpsettings{'FIX_NEXTADDR'});\r | |
426 | $dhcpsettings{'FIX_FILENAME'} = &Header::cleanhtml($dhcpsettings{'FIX_FILENAME'});\r | |
427 | $dhcpsettings{'FIX_ROOTPATH'} = &Header::cleanhtml($dhcpsettings{'FIX_ROOTPATH'});\r | |
428 | if ($dhcpsettings{'KEY2'} eq '') { #add or edit ?\r | |
429 | unshift (@current2, "$dhcpsettings{'FIX_MAC'},$dhcpsettings{'FIX_ADDR'},$dhcpsettings{'FIX_ENABLED'},$dhcpsettings{'FIX_NEXTADDR'},$dhcpsettings{'FIX_FILENAME'},$dhcpsettings{'FIX_ROOTPATH'},$dhcpsettings{'FIX_REMARK'}\n");\r | |
430 | &General::log($Lang::tr{'fixed ip lease added'});\r | |
431 | } else {\r | |
432 | @current2[$dhcpsettings{'KEY2'}] = "$dhcpsettings{'FIX_MAC'},$dhcpsettings{'FIX_ADDR'},$dhcpsettings{'FIX_ENABLED'},$dhcpsettings{'FIX_NEXTADDR'},$dhcpsettings{'FIX_FILENAME'},$dhcpsettings{'FIX_ROOTPATH'},$dhcpsettings{'FIX_REMARK'}\n";\r | |
433 | $dhcpsettings{'KEY2'} = ''; # End edit mode\r | |
434 | &General::log($Lang::tr{'fixed ip lease modified'});\r | |
435 | }\r | |
436 | \r | |
437 | #Write changes to dhcpd.conf.\r | |
438 | &sortcurrent2; # sort newly added/modified entry\r | |
439 | &buildconf; # before calling buildconf which use fixed lease file !\r | |
440 | }\r | |
441 | }\r | |
442 | \r | |
443 | if ($dhcpsettings{'ACTION_ALL'} eq '+') {\r | |
444 | my $news = 0;\r | |
445 | foreach (keys %dhcpsettings) {\r | |
446 | if (/^(\d+\.\d+\.\d+\.\d+)-([0-9a-fA-F:]+)$/) { # checked names are index of the line\r | |
447 | my $ip=$1;\r | |
448 | my $mac=$2;\r | |
449 | if (!grep (/$2/,@current2)) {\r | |
450 | unshift (@current2, "$mac,$ip,on,,,,imported\n");\r | |
451 | $news++;\r | |
452 | }\r | |
453 | }\r | |
454 | }\r | |
455 | if ($news) {\r | |
456 | #Write changes to dhcpd.conf.\r | |
457 | $warnNTPmessage = $Lang::tr{'fixed ip lease added'}."($news)";\r | |
458 | &General::log($warnNTPmessage);\r | |
459 | &sortcurrent2; # sort newly added/modified entry\r | |
460 | &buildconf; # before calling buildconf which use fixed lease file !\r | |
461 | }\r | |
462 | }\r | |
463 | \r | |
464 | if ($dhcpsettings{'ACTION'} eq $Lang::tr{'edit'}.'2') {\r | |
465 | #move out new line\r | |
466 | my $line = @current2[$dhcpsettings{'KEY2'}];\r | |
467 | chomp($line);\r | |
468 | my @temp = split(/\,/, $line);\r | |
469 | $dhcpsettings{'FIX_MAC'}=$temp[0];\r | |
470 | $dhcpsettings{'FIX_ADDR'}=$temp[1];\r | |
471 | $dhcpsettings{'FIX_ENABLED'}=$temp[2];\r | |
472 | $dhcpsettings{'FIX_NEXTADDR'}=$temp[3];\r | |
473 | $dhcpsettings{'FIX_FILENAME'}=$temp[4];\r | |
474 | $dhcpsettings{'FIX_ROOTPATH'}=$temp[5];\r | |
475 | $dhcpsettings{'FIX_REMARK'}=$temp[6];\r | |
476 | }\r | |
477 | \r | |
478 | if ($dhcpsettings{'ACTION'} eq $Lang::tr{'remove'}.'2') {\r | |
479 | splice (@current2,$dhcpsettings{'KEY2'},1);\r | |
480 | open(FILE, ">$filename2") or die 'Unable to open fixed lease file.';\r | |
481 | print FILE @current2;\r | |
482 | close(FILE);\r | |
483 | $dhcpsettings{'KEY2'} = ''; # End remove mode\r | |
484 | &General::log($Lang::tr{'fixed ip lease removed'});\r | |
485 | #Write changes to dhcpd.conf.\r | |
486 | &buildconf;\r | |
487 | }\r | |
488 | #end KEY2 defined\r | |
489 | \r | |
490 | \r | |
491 | \r | |
492 | \r | |
493 | if ($dhcpsettings{'ACTION'} eq '' ) { # First launch from GUI\r | |
494 | \r | |
495 | # Set default DHCP values only if blank and disabled\r | |
496 | foreach my $itf (@ITFs) {\r | |
497 | if ($dhcpsettings{"ENABLE_${itf}"} ne 'on' ) {\r | |
498 | $dhcpsettings{"DNS1_${itf}"} = $netsettings{"${itf}_ADDRESS"};\r | |
499 | $dhcpsettings{"DEFAULT_LEASE_TIME_${itf}"} = '60';\r | |
500 | $dhcpsettings{"MAX_LEASE_TIME_${itf}"} = '120';\r | |
501 | $dhcpsettings{"DOMAIN_NAME_${itf}"} = $mainsettings{'DOMAINNAME'};\r | |
502 | }\r | |
503 | }\r | |
504 | $dhcpsettings{'FIX_ENABLED'} = 'on';\r | |
505 | }\r | |
506 | \r | |
507 | &Header::openpage($Lang::tr{'dhcp configuration'}, 1, '');\r | |
508 | &Header::openbigbox('100%', 'left', '', $errormessage);\r | |
509 | \r | |
510 | if ($errormessage) {\r | |
511 | &Header::openbox('100%', 'left', $Lang::tr{'error messages'});\r | |
512 | print "<font class='base'>$errormessage </font>\n";\r | |
513 | &Header::closebox();\r | |
514 | }\r | |
515 | if ($warnNTPmessage) {\r | |
516 | $warnNTPmessage = "<font color=${Header::colourred}><b>$Lang::tr{'capswarning'}</b></font>: $warnNTPmessage";\r | |
517 | }\r | |
518 | \r | |
519 | &Header::openbox('100%', 'left', 'DHCP');\r | |
520 | print "<form method='post' action='$ENV{'SCRIPT_NAME'}'>";\r | |
521 | \r | |
522 | foreach my $itf (@ITFs) {\r | |
523 | my %checked=();\r | |
524 | $checked{'ENABLE'}{'on'} = ( $dhcpsettings{"ENABLE_${itf}"} ne 'on') ? '' : "checked='checked'";\r | |
525 | $checked{'ENABLEBOOTP'}{'on'} = ( $dhcpsettings{"ENABLEBOOTP_${itf}"} ne 'on') ? '' : "checked='checked'";\r | |
526 | \r | |
527 | if ($netsettings{"${itf}_DEV"} ne '' ) { # Show only defined interface\r | |
528 | my $lc_itf=lc($itf);\r | |
529 | print <<END\r | |
530 | <table width='100%'>\r | |
531 | <tr>\r | |
532 | <td width='25%' class='boldbase'><b><font color='${lc_itf}'>$Lang::tr{"$lc_itf interface"}</font></b></td>\r | |
533 | <td class='base'>$Lang::tr{'enabled'}\r | |
534 | <input type='checkbox' name='ENABLE_${itf}' $checked{'ENABLE'}{'on'} /></td>\r | |
535 | <td width='25%' class='base'>$Lang::tr{'ip address'}/$Lang::tr{'netmask'}:</td><td><b>$netsettings{"${itf}_ADDRESS"}/$netsettings{"${itf}_NETMASK"}</b></td>\r | |
536 | </tr><tr>\r | |
537 | <td width='25%' class='base'>$Lang::tr{'start address'} <img src='/blob.gif' alt='*' /></td>\r | |
538 | <td width='25%'><input type='text' name='START_ADDR_${itf}' value='$dhcpsettings{"START_ADDR_${itf}"}' /></td>\r | |
539 | <td width='25%' class='base'>$Lang::tr{'end address'} <img src='/blob.gif' alt='*' /></td>\r | |
540 | <td width='25%'><input type='text' name='END_ADDR_${itf}' value='$dhcpsettings{"END_ADDR_${itf}"}' /></td>\r | |
541 | </tr><tr>\r | |
542 | <td class='base'>$Lang::tr{'default lease time'}</td>\r | |
543 | <td><input type='text' name='DEFAULT_LEASE_TIME_${itf}' value='$dhcpsettings{"DEFAULT_LEASE_TIME_${itf}"}' /></td>\r | |
544 | <td class='base'>$Lang::tr{'max lease time'}</td>\r | |
545 | <td><input type='text' name='MAX_LEASE_TIME_${itf}' value='$dhcpsettings{"MAX_LEASE_TIME_${itf}"}' /></td>\r | |
546 | </tr><tr>\r | |
547 | <td class='base'>$Lang::tr{'domain name suffix'} <img src='/blob.gif' alt='*' /></td>\r | |
548 | <td><input type='text' name='DOMAIN_NAME_${itf}' value='$dhcpsettings{"DOMAIN_NAME_${itf}"}' /></td>\r | |
549 | <td>$Lang::tr{'dhcp allow bootp'}:</td>\r | |
550 | <td><input type='checkbox' name='ENABLEBOOTP_${itf}' $checked{'ENABLEBOOTP'}{'on'} /></td>\r | |
551 | </tr><tr>\r | |
552 | <td class='base'>$Lang::tr{'primary dns'}</td>\r | |
553 | <td><input type='text' name='DNS1_${itf}' value='$dhcpsettings{"DNS1_${itf}"}' /></td>\r | |
554 | <td class='base'>$Lang::tr{'secondary dns'} <img src='/blob.gif' alt='*' /></td>\r | |
555 | <td><input type='text' name='DNS2_${itf}' value='$dhcpsettings{"DNS2_${itf}"}' /></td>\r | |
556 | </tr><tr>\r | |
557 | <td class='base'>$Lang::tr{'primary ntp server'}: <img src='/blob.gif' alt='*' /></td>\r | |
558 | <td><input type='text' name='NTP1_${itf}' value='$dhcpsettings{"NTP1_${itf}"}' /></td>\r | |
559 | <td class='base'>$Lang::tr{'secondary ntp server'}: <img src='/blob.gif' alt='*' /></td>\r | |
560 | <td><input type='text' name='NTP2_${itf}' value='$dhcpsettings{"NTP2_${itf}"}' /></td>\r | |
561 | </tr><tr>\r | |
562 | <td class='base'>$Lang::tr{'primary wins server address'}: <img src='/blob.gif' alt='*' /></td>\r | |
563 | <td><input type='text' name='WINS1_${itf}' value='$dhcpsettings{"WINS1_${itf}"}' /></td>\r | |
564 | <td class='base'>$Lang::tr{'secondary wins server address'}: <img src='/blob.gif' alt='*' /></td>\r | |
565 | <td><input type='text' name='WINS2_${itf}' value='$dhcpsettings{"WINS2_${itf}"}' /></td>\r | |
566 | </tr>\r | |
567 | </table>\r | |
568 | <hr />\r | |
569 | END\r | |
570 | ;\r | |
571 | }# Show only defined interface\r | |
572 | }#foreach itf\r | |
573 | print <<END\r | |
574 | <table width='100%'>\r | |
575 | <tr>\r | |
576 | <td class='base' width='25%'><img src='/blob.gif' align='top' alt='*' /> $Lang::tr{'this field may be blank'}</td>\r | |
577 | <td class='base' width='30%'>$warnNTPmessage</td>\r | |
578 | <td width='40%' align='center'><input type='submit' name='ACTION' value='$Lang::tr{'save'}' /></td>\r | |
579 | <td width='5%' align='right'>\r | |
580 | <a href='${General::adminmanualurl}/services.html#services_dhcp' target='_blank'>\r | |
581 | <img src='/images/web-support.png' alt='$Lang::tr{'online help en'}' title='$Lang::tr{'online help en'}' /></a></td>\r | |
582 | </tr>\r | |
583 | </table>\r | |
584 | </form>\r | |
585 | END\r | |
586 | ;\r | |
587 | \r | |
588 | &Header::closebox();\r | |
589 | \r | |
590 | &Header::openbox('100%', 'left', $Lang::tr{'dhcp advopt list'});\r | |
591 | # DHCP Advanced options settings\r | |
592 | my %checked=();\r | |
593 | $checked{'ADVOPT_ENABLED'}{'on'} = ($dhcpsettings{'ADVOPT_ENABLED'} ne 'on') ? '' : "checked='checked'";\r | |
594 | \r | |
595 | print "<form method='post' action='$ENV{'SCRIPT_NAME'}'><table width='100%'>";\r | |
596 | my $buttontext = $Lang::tr{'add'};\r | |
597 | if ($dhcpsettings{'KEY1'} ne '') {\r | |
598 | $buttontext = $Lang::tr{'update'};\r | |
599 | print "<tr><td class='boldbase'><b>$Lang::tr{'dhcp advopt edit'}</b></td></tr>";\r | |
600 | } else {\r | |
601 | print "<tr><td class='boldbase'><b>$Lang::tr{'dhcp advopt add'}</b></td></tr>"\r | |
602 | }\r | |
603 | \r | |
604 | #search if the 'option' is in the list and print the syntax model\r | |
605 | my $opt = `grep "\$option $dhcpsettings{'ADVOPT_NAME'} " $filename3`;\r | |
606 | if ($opt ne '') {\r | |
607 | $opt =~ s/option $dhcpsettings{'ADVOPT_NAME'}/Syntax:/; # "option xyz abc" => "syntax: abc"\r | |
608 | $opt =~ s/;//;\r | |
609 | $opt = "<tr><td></td><td></td><td colspan='2'>$opt</td></tr>";\r | |
610 | }\r | |
611 | print <<END\r | |
612 | <tr>\r | |
613 | <td class='base'>$Lang::tr{'dhcp advopt name'}:</td>\r | |
614 | <td><input type='text' name='ADVOPT_NAME' value='$dhcpsettings{'ADVOPT_NAME'}' size='18' /></td>\r | |
615 | <td class='base'>$Lang::tr{'dhcp advopt value'}:</td>\r | |
616 | <td><input type='text' name='ADVOPT_DATA' value='$dhcpsettings{'ADVOPT_DATA'}' size='40' /></td>\r | |
617 | </tr>$opt<tr>\r | |
618 | <td class='base'>$Lang::tr{'enabled'}</td><td><input type='checkbox' name='ADVOPT_ENABLED' $checked{'ADVOPT_ENABLED'}{'on'} /></td>\r | |
619 | <td class='base'>$Lang::tr{'dhcp advopt scope'}: <img src='/blob.gif' alt='*' /></td>\r | |
620 | <td>\r | |
621 | END\r | |
622 | ;\r | |
623 | \r | |
624 | # Put a checkbox for each interface. Checkbox visible disabled if interface is disabled \r | |
625 | foreach my $itf (@ITFs) {\r | |
626 | my $lc_itf=lc($itf);\r | |
627 | $checked{'ADVOPT_SCOPE_${itf}'}{'on'} = $dhcpsettings{"ADVOPT_SCOPE_${itf}"} ne 'on' ? '' : "checked='checked'"; \r | |
628 | print "$Lang::tr{\"${lc_itf}\"} <input type='checkbox' name='ADVOPT_SCOPE_${itf}' $checked{'ADVOPT_SCOPE_${itf}'}{'on'} ";\r | |
629 | print $dhcpsettings{"ENABLE_${itf}"} eq 'on' ? "/>" : "disabled='disabled' />";\r | |
630 | print " ";\r | |
631 | }\r | |
632 | \r | |
633 | print <<END\r | |
634 | </td>\r | |
635 | </tr>\r | |
636 | </table>\r | |
637 | <hr />\r | |
638 | <table width='100%'>\r | |
639 | <tr>\r | |
640 | <td class='base' width='50%'><img src='/blob.gif' align='top' alt='*' /> $Lang::tr{'dhcp advopt scope help'}</td>\r | |
641 | <td width='50%' align='center'>\r | |
642 | <input type='hidden' name='ACTION' value='$Lang::tr{'add'}1' />\r | |
643 | <input type='submit' name='SUBMIT' value='$buttontext' />\r | |
644 | <input type='submit' name='SUBMIT' value='$Lang::tr{'dhcp advopt help'}' />\r | |
645 | <input type='hidden' name='KEY1' value='$dhcpsettings{'KEY1'}' />\r | |
646 | </td>\r | |
647 | </tr>\r | |
648 | </table>\r | |
649 | </form>\r | |
650 | END\r | |
651 | ;\r | |
652 | #Edited line number (KEY1) passed until cleared by 'save' or 'remove' or 'new sort order'\r | |
653 | \r | |
654 | # print help taken from the file describing options\r | |
655 | if ($dhcpsettings{'SUBMIT'} eq $Lang::tr{'dhcp advopt help'}) {\r | |
656 | print "<hr />";\r | |
657 | print "<table width='100%'>";\r | |
658 | print "<tr><td width='30%'><b>$Lang::tr{'dhcp advopt name'}</b></td><td width='70%'><b>$Lang::tr{'dhcp advopt value'}</b></td>";\r | |
659 | open(FILE, "$filename3");\r | |
660 | my @current3 = <FILE>;\r | |
661 | close(FILE);\r | |
662 | foreach my $line (@current3) {\r | |
663 | $line =~ /option ([a-z0-9-]+) (.*);/;\r | |
664 | print "<tr><td>$1</td><td>$2</td></tr>\n";\r | |
665 | }\r | |
666 | print "<tr><td colspan='2'><hr /></td></tr>\n";\r | |
667 | print '<tr><td>string type</td><td>"quoted string" or 00:01:FF...</td></tr>';\r | |
668 | print '<tr><td>ip-address type </td><td>10.0.0.1 | www.dot.com</td></tr>';\r | |
669 | print '<tr><td>int,uint types</td><td>numbers</td></tr>';\r | |
670 | print '<tr><td>flag type</td><td>on | off</td></tr>';\r | |
671 | print '</table>';\r | |
672 | print "<hr />";\r | |
673 | print "<table width='100%'>";\r | |
674 | print "<tr><td width='30%'><b>$Lang::tr{'dhcp advopt custom definition'}</b></td><td width='70%'><b>$Lang::tr{'dhcp advopt value'}</b></td>";\r | |
675 | print "<tr><td>any-name </td><td> code NNN=$OptionTypes</td></tr>";\r | |
676 | print '<tr><td>a-string</td><td>code 100=string</td></tr>';\r | |
677 | print '<tr><td>a-number</td><td>code 101=signed integer 8</td></tr>';\r | |
678 | print '<tr><td>wpad</td><td>code 252=text</td></tr>';\r | |
679 | print '<tr><td>wpad</td><td>"http://www.server.fr/path-to/proxy.pac"</td></tr>';\r | |
680 | print '</table>';\r | |
681 | \r | |
682 | }\r | |
683 | \r | |
684 | print <<END\r | |
685 | <hr />\r | |
686 | <table width='100%'>\r | |
687 | <tr>\r | |
688 | <td width='30%' class='boldbase' align='center'><b>$Lang::tr{'dhcp advopt name'}</b></td>\r | |
689 | <td width='50%' class='boldbase' align='center'><b>$Lang::tr{'dhcp advopt value'}</b></td>\r | |
690 | <td width='20%' class='boldbase' align='center'><b>$Lang::tr{'dhcp advopt scope'}</b></td>\r | |
691 | <td colspan='3' class='boldbase' align='center'><b>$Lang::tr{'action'}</b></td>\r | |
692 | </tr>\r | |
693 | END\r | |
694 | ;\r | |
695 | my $key = 0;\r | |
696 | foreach my $line (@current1) {\r | |
697 | my $gif = '';\r | |
698 | my $gdesc = '';\r | |
699 | chomp($line); # remove newline\r | |
700 | my @temp = split(/\t/,$line);\r | |
701 | \r | |
702 | if ($temp[0] eq "on") {\r | |
703 | $gif = 'on.gif';\r | |
704 | $gdesc = $Lang::tr{'click to disable'};\r | |
705 | } else {\r | |
706 | $gif = 'off.gif';\r | |
707 | $gdesc = $Lang::tr{'click to enable'}; \r | |
708 | }\r | |
709 | \r | |
710 | if ($dhcpsettings{'KEY1'} eq $key) {\r | |
711 | print "<tr bgcolor='${Header::colouryellow}'>";\r | |
712 | } elsif ($key % 2) {\r | |
713 | print "<tr bgcolor='${Header::table2colour}'>";\r | |
714 | } else {\r | |
715 | print "<tr bgcolor='${Header::table1colour}'>"; \r | |
716 | }\r | |
717 | \r | |
718 | print <<END\r | |
719 | <td align='center'>$temp[1]</td>\r | |
720 | <td align='center'>$temp[2]</td>\r | |
721 | <td align='center'>\r | |
722 | END\r | |
723 | ;\r | |
724 | # Prepare a global flag to make easy reading\r | |
725 | my $global = '';\r | |
726 | my $disabledTogle = '';\r | |
727 | my $disabledEditRemove = '';\r | |
728 | if ( ExistNewOptionDefinition ($temp[1] . ' ' . $temp[2]) ) {\r | |
729 | $global = $Lang::tr{'dhcp advopt definition'};\r | |
730 | $disabledTogle = "disabled='disabled'";\r | |
731 | # Search if it is a used NewOptionDefinition to also disable edit & delete\r | |
732 | $disabledEditRemove = "disabled='disabled'" if (IsUsedNewOptionDefinition ($temp[1], $temp[2]));\r | |
733 | } else {\r | |
734 | $global = $Lang::tr{'dhcp advopt scope global'};\r | |
735 | }\r | |
736 | \r | |
737 | \r | |
738 | # Print each checked interface\r | |
739 | for (my $key=0; $key<@ITFs; $key++) {\r | |
740 | my $itf = $temp[3+$key];\r | |
741 | if ($itf ne 'off') { # Only if an interface name is read\r | |
742 | print "$itf";\r | |
743 | $global=''; # fall to local scope !\r | |
744 | }\r | |
745 | }\r | |
746 | print <<END\r | |
747 | $global</td>\r | |
748 | <td align='center'>\r | |
749 | <form method='post' action='$ENV{'SCRIPT_NAME'}'>\r | |
750 | <input type='hidden' name='ACTION' value='$Lang::tr{'toggle enable disable'}1' />\r | |
751 | <input $disabledTogle type='image' name='$Lang::tr{'toggle enable disable'}' src='/images/$gif' alt='$gdesc' title='$gdesc' />\r | |
752 | <input type='hidden' name='KEY1' value='$key' />\r | |
753 | </form>\r | |
754 | </td>\r | |
755 | \r | |
756 | <td align='center'>\r | |
757 | <form method='post' action='$ENV{'SCRIPT_NAME'}'>\r | |
758 | <input type='hidden' name='ACTION' value='$Lang::tr{'edit'}1' />\r | |
759 | <input $disabledEditRemove type='image' name='$Lang::tr{'edit'}' src='/images/edit.gif' alt='$Lang::tr{'edit'}' title='$Lang::tr{'edit'}' />\r | |
760 | <input type='hidden' name='KEY1' value='$key' />\r | |
761 | </form>\r | |
762 | </td>\r | |
763 | \r | |
764 | <td align='center'>\r | |
765 | <form method='post' action='$ENV{'SCRIPT_NAME'}'>\r | |
766 | <input type='hidden' name='ACTION' value='$Lang::tr{'remove'}1' />\r | |
767 | <input $disabledEditRemove type='image' name='$Lang::tr{'remove'}' src='/images/delete.gif' alt='$Lang::tr{'remove'}' title='$Lang::tr{'remove'}' />\r | |
768 | <input type='hidden' name='KEY1' value='$key' />\r | |
769 | </form>\r | |
770 | </td>\r | |
771 | </tr>\r | |
772 | END\r | |
773 | ;\r | |
774 | $key++;\r | |
775 | }\r | |
776 | \r | |
777 | print "</table>";\r | |
778 | \r | |
779 | # If there are dhcp options, print Key to action icons\r | |
780 | if ($key) {\r | |
781 | print <<END\r | |
782 | <table>\r | |
783 | <tr>\r | |
784 | <td class='boldbase'> <b>$Lang::tr{'legend'}: </b></td>\r | |
785 | <td><img src='/images/on.gif' alt='$Lang::tr{'click to disable'}' /></td>\r | |
786 | <td class='base'>$Lang::tr{'click to disable'}</td>\r | |
787 | <td> </td>\r | |
788 | <td><img src='/images/off.gif' alt='$Lang::tr{'click to enable'}' /></td>\r | |
789 | <td class='base'>$Lang::tr{'click to enable'}</td>\r | |
790 | <td> </td>\r | |
791 | <td><img src='/images/edit.gif' alt='$Lang::tr{'edit'}' /></td>\r | |
792 | <td class='base'>$Lang::tr{'edit'}</td>\r | |
793 | <td> </td>\r | |
794 | <td><img src='/images/delete.gif' alt='$Lang::tr{'remove'}' /></td>\r | |
795 | <td class='base'>$Lang::tr{'remove'}</td>\r | |
796 | </tr>\r | |
797 | </table>\r | |
798 | END\r | |
799 | ;\r | |
800 | }\r | |
801 | &Header::closebox();\r | |
802 | \r | |
803 | &Header::openbox('100%', 'left', $Lang::tr{'current fixed leases'});\r | |
804 | # Fixed leases screens\r | |
805 | $checked{'FIX_ENABLED'}{'on'} = ($dhcpsettings{'FIX_ENABLED'} ne 'on') ? '' : "checked='checked'";\r | |
806 | \r | |
807 | $buttontext = $Lang::tr{'add'};\r | |
808 | print "<form method='post' action='$ENV{'SCRIPT_NAME'}'><table width='100%'>";\r | |
809 | \r | |
810 | if ($dhcpsettings{'KEY2'} ne '') {\r | |
811 | $buttontext = $Lang::tr{'update'};\r | |
812 | print "<tr><td class='boldbase' colspan='3'><b>$Lang::tr{'edit an existing lease'}</b></td></tr>";\r | |
813 | } else {\r | |
814 | print "<tr><td class='boldbase' colspan='3'><b>$Lang::tr{'add new lease'}</b></td></tr>"\r | |
815 | }\r | |
816 | print <<END\r | |
817 | <tr>\r | |
818 | <td class='base'>$Lang::tr{'mac address'}:</td>\r | |
819 | <td><input type='text' name='FIX_MAC' value='$dhcpsettings{'FIX_MAC'}' size='18' /></td>\r | |
820 | <td class='base'>$Lang::tr{'ip address'}:</td>\r | |
821 | <td><input type='text' name='FIX_ADDR' value='$dhcpsettings{'FIX_ADDR'}' size='18' /></td>\r | |
822 | <td class='base'>$Lang::tr{'remark'}: <img src='/blob.gif' alt='*' /></td>\r | |
823 | <td><input type='text' name='FIX_REMARK' value='$dhcpsettings{'FIX_REMARK'}' size='18' /></td>\r | |
824 | </tr><tr>\r | |
825 | <td class='base'>$Lang::tr{'enabled'}</td><td><input type='checkbox' name='FIX_ENABLED' $checked{'FIX_ENABLED'}{'on'} /></td>\r | |
826 | </tr><tr>\r | |
827 | <td colspan = '3'><b>$Lang::tr{'dhcp bootp pxe data'}</b></td>\r | |
828 | </tr><tr>\r | |
829 | <td class='base'>next-server: <img src='/blob.gif' alt='*' /></td>\r | |
830 | <td><input type='text' name='FIX_NEXTADDR' value='$dhcpsettings{'FIX_NEXTADDR'}' size='18' /></td>\r | |
831 | <td class='base'>filename: <img src='/blob.gif' alt='*' /></td>\r | |
832 | <td><input type='text' name='FIX_FILENAME' value='$dhcpsettings{'FIX_FILENAME'}' size='18' /></td>\r | |
833 | <td class='base'>root path: <img src='/blob.gif' alt='*' /></td>\r | |
834 | <td><input type='text' name='FIX_ROOTPATH' value='$dhcpsettings{'FIX_ROOTPATH'}' size='18' /></td>\r | |
835 | </tr>\r | |
836 | </table>\r | |
837 | <hr />\r | |
838 | <table width='100%'>\r | |
839 | <tr>\r | |
840 | <td class='base' width='50%'><img src='/blob.gif' align='top' alt='*' /> $Lang::tr{'this field may be blank'}</td>\r | |
841 | <td width='50%' align='center'>\r | |
842 | <input type='hidden' name='ACTION' value='$Lang::tr{'add'}2' />\r | |
843 | <input type='submit' name='SUBMIT' value='$buttontext' />\r | |
844 | <input type='hidden' name='KEY2' value='$dhcpsettings{'KEY2'}' /></td>\r | |
845 | </tr>\r | |
846 | </table>\r | |
847 | </form>\r | |
848 | END\r | |
849 | ;\r | |
850 | #Edited line number (KEY2) passed until cleared by 'save' or 'remove' or 'new sort order'\r | |
851 | \r | |
852 | print <<END\r | |
853 | <hr />\r | |
854 | <table width='100%'>\r | |
855 | <tr>\r | |
856 | <td width='20%' align='center'><a href='$ENV{'SCRIPT_NAME'}?FETHER'><b>$Lang::tr{'mac address'}</b></a></td>\r | |
857 | <td width='20%' align='center'><a href='$ENV{'SCRIPT_NAME'}?FIPADDR'><b>$Lang::tr{'ip address'}</b></a></td>\r | |
858 | <td width='15%' align='center'><b>$Lang::tr{'remark'}</b></td>\r | |
859 | <td width='15%' class='boldbase' align='center'><b>next-server</b></td>\r | |
860 | <td width='15%' class='boldbase' align='center'><b>filename</b></td>\r | |
861 | <td width='15%' class='boldbase' align='center'><b>root path</b></td>\r | |
862 | <td colspan='3' class='boldbase' align='center'><b>$Lang::tr{'action'}</b></td>\r | |
863 | </tr>\r | |
864 | END\r | |
865 | ;\r | |
866 | my $ipdup = 0;\r | |
867 | my %ipinuse = ();\r | |
868 | my %macdupl = (); # Duplicate MACs have to be on different subnets\r | |
869 | my %ipoutside = ();\r | |
870 | \r | |
871 | # mark duplicate ip or duplicate MAC\r | |
872 | foreach my $line (@current2) {\r | |
873 | my @temp = split(/\,/,$line);\r | |
874 | $macdupl{$temp[0]} += 1;\r | |
875 | if ($macdupl{$temp[0]} > 1) { \r | |
876 | $ipdup = 1; # Flag up duplicates for use later\r | |
877 | }\r | |
878 | $ipinuse{$temp[1]} += 1;\r | |
879 | if ($ipinuse{$temp[1]} > 1) { \r | |
880 | $ipdup = 1; # Flag up duplicates for use later\r | |
881 | }\r | |
882 | # Mark IP addresses outwith known subnets\r | |
883 | $ipoutside{$temp[1]} = 1;\r | |
884 | foreach my $itf (@ITFs) {\r | |
885 | if ( &General::IpInSubnet($temp[1],\r | |
886 | $netsettings{"${itf}_NETADDRESS"}, \r | |
887 | $netsettings{"${itf}_NETMASK"})) {\r | |
888 | $ipoutside{$temp[1]} = 0;\r | |
889 | }\r | |
890 | }\r | |
891 | }\r | |
892 | \r | |
893 | $key = 0;\r | |
894 | foreach my $line (@current2) {\r | |
895 | my $gif = '';\r | |
896 | my $gdesc = '';\r | |
897 | chomp($line); # remove newline\r | |
898 | my @temp = split(/\,/,$line);\r | |
899 | \r | |
900 | if ($temp[2] eq "on") {\r | |
901 | $gif = 'on.gif';\r | |
902 | $gdesc = $Lang::tr{'click to disable'};\r | |
903 | } else {\r | |
904 | $gif = 'off.gif';\r | |
905 | $gdesc = $Lang::tr{'click to enable'}; \r | |
906 | }\r | |
907 | \r | |
908 | if ($dhcpsettings{'KEY2'} eq $key) {\r | |
909 | print "<tr bgcolor='${Header::colouryellow}'>";\r | |
910 | } elsif ($key % 2) {\r | |
911 | print "<tr bgcolor='${Header::table2colour}'>";\r | |
912 | } else {\r | |
913 | print "<tr bgcolor='${Header::table1colour}'>"; \r | |
914 | }\r | |
915 | my $TAG0 = '';\r | |
916 | my $TAG1 = '';\r | |
917 | my $TAG2 = '';\r | |
918 | my $TAG3 = '';\r | |
919 | my $TAG4 = '';\r | |
920 | if ($ipinuse{$temp[1]} > 1) { \r | |
921 | $TAG0 = '<b>';\r | |
922 | $TAG1 = '</b>';\r | |
923 | }\r | |
924 | if ($macdupl{$temp[0]} > 1) { \r | |
925 | $TAG2 = '<b>';\r | |
926 | $TAG3 = '</b>';\r | |
927 | }\r | |
928 | if ($ipoutside{$temp[1]} > 0) { \r | |
929 | $TAG4 = "bgcolor='orange'" if ($dhcpsettings{'KEY2'} ne $key);\r | |
930 | }\r | |
931 | \r | |
932 | print <<END\r | |
933 | <td align='center'>$TAG2$temp[0]$TAG3</td>\r | |
934 | <td align='center' $TAG4>$TAG0$temp[1]$TAG1</td>\r | |
935 | <td align='center'>$temp[6] </td>\r | |
936 | <td align='center'>$temp[3] </td>\r | |
937 | <td align='center'>$temp[4] </td>\r | |
938 | <td align='center'>$temp[5] </td>\r | |
939 | \r | |
940 | <td align='center'>\r | |
941 | <form method='post' action='$ENV{'SCRIPT_NAME'}'>\r | |
942 | <input type='hidden' name='ACTION' value='$Lang::tr{'toggle enable disable'}2' />\r | |
943 | <input type='image' name='$Lang::tr{'toggle enable disable'}' src='/images/$gif' alt='$gdesc' title='$gdesc' />\r | |
944 | <input type='hidden' name='KEY2' value='$key' />\r | |
945 | </form>\r | |
946 | </td>\r | |
947 | \r | |
948 | <td align='center'>\r | |
949 | <form method='post' action='$ENV{'SCRIPT_NAME'}'>\r | |
950 | <input type='hidden' name='ACTION' value='$Lang::tr{'edit'}2' />\r | |
951 | <input type='image' name='$Lang::tr{'edit'}' src='/images/edit.gif' alt='$Lang::tr{'edit'}' title='$Lang::tr{'edit'}' />\r | |
952 | <input type='hidden' name='KEY2' value='$key' />\r | |
953 | </form>\r | |
954 | </td>\r | |
955 | \r | |
956 | <td align='center'>\r | |
957 | <form method='post' action='$ENV{'SCRIPT_NAME'}'>\r | |
958 | <input type='hidden' name='ACTION' value='$Lang::tr{'remove'}2' />\r | |
959 | <input type='image' name='$Lang::tr{'remove'}' src='/images/delete.gif' alt='$Lang::tr{'remove'}' title='$Lang::tr{'remove'}' />\r | |
960 | <input type='hidden' name='KEY2' value='$key' />\r | |
961 | </form>\r | |
962 | </td>\r | |
963 | </tr>\r | |
964 | END\r | |
965 | ;\r | |
966 | $key++;\r | |
967 | }\r | |
968 | print "</table>";\r | |
969 | \r | |
970 | # If the fixed lease file contains entries, print Key to action icons\r | |
971 | if ($key) {\r | |
972 | my $dup = $ipdup ? "<td class='base'>$Lang::tr{'duplicate ip bold'}</td>" :'';\r | |
973 | print <<END\r | |
974 | <table>\r | |
975 | <tr>\r | |
976 | <td class='boldbase'> <b>$Lang::tr{'legend'}: </b></td>\r | |
977 | <td><img src='/images/on.gif' alt='$Lang::tr{'click to disable'}' /></td>\r | |
978 | <td class='base'>$Lang::tr{'click to disable'}</td>\r | |
979 | <td> </td>\r | |
980 | <td><img src='/images/off.gif' alt='$Lang::tr{'click to enable'}' /></td>\r | |
981 | <td class='base'>$Lang::tr{'click to enable'}</td>\r | |
982 | <td> </td>\r | |
983 | <td><img src='/images/edit.gif' alt='$Lang::tr{'edit'}' /></td>\r | |
984 | <td class='base'>$Lang::tr{'edit'}</td>\r | |
985 | <td> </td>\r | |
986 | <td><img src='/images/delete.gif' alt='$Lang::tr{'remove'}' /></td>\r | |
987 | <td class='base'>$Lang::tr{'remove'}</td>\r | |
988 | </tr>\r | |
989 | <tr>\r | |
990 | <td> </td>\r | |
991 | <td bgcolor='orange'> </td>\r | |
992 | <td class='base'>$Lang::tr{'ip address outside subnets'}</td>\r | |
993 | <td> </td>\r | |
994 | <td> </td>\r | |
995 | $dup\r | |
996 | </tr>\r | |
997 | </table>\r | |
998 | END\r | |
999 | ;\r | |
1000 | }\r | |
1001 | \r | |
1002 | &Header::closebox();\r | |
1003 | \r | |
1004 | \r | |
1005 | foreach my $itf (@ITFs) {\r | |
1006 | if ($dhcpsettings{"ENABLE_${itf}"} eq 'on') {\r | |
1007 | # display leases with a list of actions to do with the global select checkbox.\r | |
1008 | &Header::PrintActualLeases("+"); # "+" => create fixed leases from nodeaddress\r | |
1009 | last; #Print one time only for all interfaces\r | |
1010 | };\r | |
1011 | }\r | |
1012 | \r | |
1013 | &Header::closebigbox();\r | |
1014 | &Header::closepage();\r | |
1015 | \r | |
1016 | ## Ouf it's the end !\r | |
1017 | \r | |
1018 | sub sortcurrent1 # by now, do not sort, just write\r | |
1019 | {\r | |
1020 | open(FILE, ">$filename1") or die 'Unable to open dhcp advanced options file.';\r | |
1021 | print FILE @current1;\r | |
1022 | close(FILE);\r | |
1023 | }\r | |
1024 | \r | |
1025 | \r | |
1026 | # Sort the "current2" array according to choices\r | |
1027 | sub sortcurrent2\r | |
1028 | {\r | |
1029 | our %entries = ();\r | |
1030 | \r | |
1031 | sub fixedleasesort {\r | |
1032 | my $qs='';\r | |
1033 | if (rindex ($dhcpsettings{'SORT_FLEASELIST'},'Rev') != -1) {\r | |
1034 | $qs=substr ($dhcpsettings{'SORT_FLEASELIST'},0,length($dhcpsettings{'SORT_FLEASELIST'})-3);\r | |
1035 | if ($qs eq 'FIPADDR') {\r | |
1036 | my @a = split(/\./,$entries{$a}->{$qs});\r | |
1037 | my @b = split(/\./,$entries{$b}->{$qs});\r | |
1038 | ($b[0]<=>$a[0]) ||\r | |
1039 | ($b[1]<=>$a[1]) ||\r | |
1040 | ($b[2]<=>$a[2]) ||\r | |
1041 | ($b[3]<=>$a[3]);\r | |
1042 | } else {\r | |
1043 | $entries{$b}->{$qs} cmp $entries{$a}->{$qs};\r | |
1044 | }\r | |
1045 | } else { #not reverse\r | |
1046 | $qs=$dhcpsettings{'SORT_FLEASELIST'};\r | |
1047 | if ($qs eq 'FIPADDR') {\r | |
1048 | my @a = split(/\./,$entries{$a}->{$qs});\r | |
1049 | my @b = split(/\./,$entries{$b}->{$qs});\r | |
1050 | ($a[0]<=>$b[0]) ||\r | |
1051 | ($a[1]<=>$b[1]) ||\r | |
1052 | ($a[2]<=>$b[2]) ||\r | |
1053 | ($a[3]<=>$b[3]);\r | |
1054 | } else {\r | |
1055 | $entries{$a}->{$qs} cmp $entries{$b}->{$qs};\r | |
1056 | }\r | |
1057 | }\r | |
1058 | }\r | |
1059 | \r | |
1060 | #Use an associative array (%entries)\r | |
1061 | foreach my $line (@current2) {\r | |
1062 | chomp( $line); #remove newline because can be on field 5 or 6 (addition of REMARK)\r | |
1063 | my @temp = split (',',$line);\r | |
1064 | my @record = ('FETHER',$temp[0],'FIPADDR',$temp[1],'DATA',join(',',@temp[2..6]));\r | |
1065 | my $record = {}; # create a reference to empty hash\r | |
1066 | %{$record} = @record; # populate that hash with @record\r | |
1067 | # use combination of ether & IP as key to allow duplicates in either but not both\r | |
1068 | $entries{$record->{FETHER} . $record->{FIPADDR}} = $record; # add this to a hash of hashes\r | |
1069 | }\r | |
1070 | \r | |
1071 | open(FILE, ">$filename2") or die 'Unable to open fixed lease file.';\r | |
1072 | foreach my $entry ( sort fixedleasesort keys %entries) {\r | |
1073 | print FILE "$entries{$entry}->{FETHER},$entries{$entry}->{FIPADDR},$entries{$entry}->{DATA}\n";\r | |
1074 | }\r | |
1075 | close(FILE);\r | |
1076 | \r | |
1077 | # Reload sorted @current2\r | |
1078 | open (FILE, "$filename2");\r | |
1079 | @current2 = <FILE>;\r | |
1080 | close (FILE);\r | |
1081 | undef (%entries); #This array is reused latter. Clear it.\r | |
1082 | }\r | |
1083 | \r | |
1084 | # Build the configuration file mixing settings, fixed leases and advanced options\r | |
1085 | sub buildconf {\r | |
1086 | open(FILE, ">/${General::swroot}/dhcp/dhcpd.conf") or die "Unable to write dhcpd.conf file";\r | |
1087 | flock(FILE, 2);\r | |
1088 | \r | |
1089 | # Global settings\r | |
1090 | print FILE "ddns-update-style none;\n";\r | |
1091 | print FILE "deny bootp; #default\n";\r | |
1092 | print FILE "authoritative;\n";\r | |
1093 | \r | |
1094 | # Write first new option definition\r | |
1095 | foreach my $line (@current1) {\r | |
1096 | chomp($line); # remove newline\r | |
1097 | my @temp = split(/\t/,$line);\r | |
1098 | if (ExistNewOptionDefinition ($temp[1] . ' ' . $temp[2])) {\r | |
1099 | print FILE "option $temp[1] $temp[2];\n";\r | |
1100 | }\r | |
1101 | }\r | |
1102 | # Write other global options\r | |
1103 | foreach my $line (@current1) {\r | |
1104 | chomp($line); # remove newline\r | |
1105 | my @temp = split(/\t/,$line);\r | |
1106 | \r | |
1107 | if ($temp[0] eq 'on' && !ExistNewOptionDefinition ($temp[1] . ' ' . $temp[2])){ # active & !definition\r | |
1108 | my $global=1;\r | |
1109 | for (my $key=0; $key<@ITFs; $key++) {\r | |
1110 | my $itf = $temp[3+$key];\r | |
1111 | if ($itf ne 'off') # Only if an interface name is read\r | |
1112 | {\r | |
1113 | $global=0;\r | |
1114 | }\r | |
1115 | }\r | |
1116 | if ($global) {\r | |
1117 | print FILE "option $temp[1] $temp[2];\n";\r | |
1118 | }\r | |
1119 | }# on \r | |
1120 | }# foreach line\r | |
1121 | \r | |
1122 | #Subnet range definition\r | |
1123 | foreach my $itf (@ITFs) {\r | |
1124 | my $lc_itf=lc($itf);\r | |
1125 | if ($dhcpsettings{"ENABLE_${itf}"} eq 'on' ){\r | |
1126 | print FILE "\nsubnet " . $netsettings{"${itf}_NETADDRESS"} . " netmask ". $netsettings{"${itf}_NETMASK"} . " #$itf\n";\r | |
1127 | print FILE "{\n";\r | |
1128 | print FILE "\trange " . $dhcpsettings{"START_ADDR_${itf}"} . ' ' . $dhcpsettings{"END_ADDR_${itf}"}.";\n" if ($dhcpsettings{"START_ADDR_${itf}"});\r | |
1129 | print FILE "\toption subnet-mask " . $netsettings{"${itf}_NETMASK"} . ";\n";\r | |
1130 | print FILE "\toption domain-name \"" . $dhcpsettings{"DOMAIN_NAME_${itf}"} . "\";\n";\r | |
1131 | print FILE "\toption routers " . $netsettings{"${itf}_ADDRESS"} . ";\n";\r | |
1132 | print FILE "\toption domain-name-servers " . $dhcpsettings{"DNS1_${itf}"} if ($dhcpsettings{"DNS1_${itf}"});\r | |
1133 | print FILE ", " . $dhcpsettings{"DNS2_${itf}"} if ($dhcpsettings{"DNS2_${itf}"});\r | |
1134 | print FILE ";\n" if ($dhcpsettings{"DNS1_${itf}"});\r | |
1135 | print FILE "\toption ntp-servers " . $dhcpsettings{"NTP1_${itf}"} if ($dhcpsettings{"NTP1_${itf}"});\r | |
1136 | print FILE ", " . $dhcpsettings{"NTP2_${itf}"} if ($dhcpsettings{"NTP2_${itf}"});\r | |
1137 | print FILE ";\n" if ($dhcpsettings{"NTP1_${itf}"});\r | |
1138 | print FILE "\toption netbios-name-servers " . $dhcpsettings{"WINS1_${itf}"} if ($dhcpsettings{"WINS1_${itf}"});\r | |
1139 | print FILE ", " . $dhcpsettings{"WINS2_${itf}"} if ($dhcpsettings{"WINS2_${itf}"});\r | |
1140 | print FILE ";\n" if ($dhcpsettings{"WINS1_${itf}"});\r | |
1141 | print FILE "\tdefault-lease-time " . ($dhcpsettings{"DEFAULT_LEASE_TIME_${itf}"} * 60). ";\n";\r | |
1142 | print FILE "\tmax-lease-time " . ($dhcpsettings{"MAX_LEASE_TIME_${itf}"} * 60) . ";\n";\r | |
1143 | print FILE "\tallow bootp;\n" if ($dhcpsettings{"ENABLEBOOTP_${itf}"} eq 'on');\r | |
1144 | \r | |
1145 | \r | |
1146 | \r | |
1147 | # Write scoped options\r | |
1148 | foreach my $line (@current1) {\r | |
1149 | chomp($line); # remove newline\r | |
1150 | my @temp = split(/\t/,$line); # Use TAB separator !\r | |
1151 | \r | |
1152 | if ($temp[0] eq 'on'){\r | |
1153 | for (my $key=0; $key<@ITFs; $key++) {\r | |
1154 | if ($itf eq $temp[3+$key]) # Only is an interface name is read\r | |
1155 | {\r | |
1156 | print FILE "\toption $temp[1] $temp[2];\n";\r | |
1157 | }\r | |
1158 | }\r | |
1159 | }# on \r | |
1160 | }# foreach line\r | |
1161 | print FILE "} #$itf\n";\r | |
1162 | \r | |
1163 | system ('/bin/touch', "${General::swroot}/dhcp/enable_${lc_itf}");\r | |
1164 | &General::log("DHCP on ${itf}: " . $Lang::tr{'dhcp server enabled'})\r | |
1165 | } else {\r | |
1166 | unlink "${General::swroot}/dhcp/enable_${lc_itf}";\r | |
1167 | &General::log("DHCP on ${itf}: " . $Lang::tr{'dhcp server disabled'})\r | |
1168 | }\r | |
1169 | }\r | |
1170 | \r | |
1171 | #write fixed leases if any. Does not handle duplicates to write them elsewhere than the global scope.\r | |
1172 | my $key = 0;\r | |
1173 | foreach my $line (@current2) {\r | |
1174 | chomp($line);\r | |
1175 | my @temp = split(/\,/,$line);\r | |
1176 | if ($temp[2] eq "on") {\r | |
1177 | print FILE "\nhost fix$key # $temp[6]\n";\r | |
1178 | print FILE "{\n";\r | |
1179 | print FILE "\thardware ethernet $temp[0];\n";\r | |
1180 | print FILE "\tfixed-address $temp[1];\n";\r | |
1181 | print FILE "\tnext-server $temp[3];\n" if ($temp[3]);\r | |
1182 | print FILE "\tfilename \"$temp[4]\";\n" if ($temp[4]);\r | |
1183 | print FILE "\toption root-path \"$temp[5]\";\n" if ($temp[5]);\r | |
1184 | print FILE "}\n";\r | |
1185 | $key++;\r | |
1186 | }\r | |
1187 | }\r | |
1188 | close FILE;\r | |
1189 | system '/usr/local/bin/restartdhcp';\r | |
1190 | }\r | |
1191 | \r | |
1192 | #\r | |
1193 | # Receive a string and if it match model for a new option,\r | |
1194 | # add it to the list %newOptions\r | |
1195 | #\r | |
1196 | my %NewOptions = ();\r | |
1197 | \r | |
1198 | sub AddNewOptionDefinition {\r | |
1199 | my ($line) = @_;\r | |
1200 | if ( $line =~ /^([-\w]+)( code \d+=($OptionTypes))/ ) {\r | |
1201 | $NewOptions{$1} = $2;\r | |
1202 | #&General::log ("new:<$1><$2>");\r | |
1203 | return 1;\r | |
1204 | }\r | |
1205 | return 0;\r | |
1206 | }\r | |
1207 | \r | |
1208 | #\r | |
1209 | # Check existence of definition for a new option\r | |
1210 | #\r | |
1211 | sub ExistNewOptionDefinition {\r | |
1212 | my ($line) = @_;\r | |
1213 | \r | |
1214 | if ( $line =~ /^([-\w]+)( code \d+=($OptionTypes))/ ) {\r | |
1215 | return defined $NewOptions{$1};\r | |
1216 | }\r | |
1217 | return 0;\r | |
1218 | }\r | |
1219 | \r | |
1220 | #\r | |
1221 | # Check if it is a new option (definition must exist)\r | |
1222 | # "code=" test eliminate a false response when definition exists\r | |
1223 | # but this string is a definition with bad $OptionTypes.\r | |
1224 | sub ValidNewOption {\r | |
1225 | my ($line) = @_;\r | |
1226 | if ($line =~ /^([-\w]+) (.*)/ ) {\r | |
1227 | return defined ( $NewOptions{$1} ) && $2 !~ /code=/;\r | |
1228 | }\r | |
1229 | return 0;\r | |
1230 | }\r | |
1231 | \r | |
1232 | #\r | |
1233 | # Check if the new option $opt is used, except the definition of itself!\r | |
1234 | #\r | |
1235 | sub IsUsedNewOptionDefinition {\r | |
1236 | my ($opt,$val) = @_;\r | |
1237 | \r | |
1238 | foreach my $line (@current1) {\r | |
1239 | #chomp($line); # remove newline #don't know why, but this remove newline in @current1 .... !\r | |
1240 | my @temp = split(/\t/,$line);\r | |
1241 | # if we find something "opt value" & value != "code nnn=" it's ok.\r | |
1242 | return 1 if ( ($opt eq $temp[1]) && ($temp[2] !~ /code \d+=/) );\r | |
1243 | }\r | |
1244 | return 0;\r | |
1245 | }\r |