]>
Commit | Line | Data |
---|---|---|
1dcf513a FB |
1 | #!/usr/bin/perl |
2 | ############################################################################### | |
3 | # # | |
4 | # VLAN Management for IPFire # | |
5 | # Copyright (C) 2019 Florian Bührle <fbuehrle@ipfire.org> # | |
6 | # # | |
7 | # This program is free software: you can redistribute it and/or modify # | |
8 | # it under the terms of the GNU General Public License as published by # | |
9 | # the Free Software Foundation, either version 3 of the License, or # | |
10 | # (at your option) any later version. # | |
11 | # # | |
12 | # This program is distributed in the hope that it will be useful, # | |
13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of # | |
14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # | |
15 | # GNU General Public License for more details. # | |
16 | # # | |
17 | # You should have received a copy of the GNU General Public License # | |
18 | # along with this program. If not, see <http://www.gnu.org/licenses/>. # | |
19 | # # | |
20 | ############################################################################### | |
21 | ||
22 | use strict; | |
23 | use Scalar::Util qw(looks_like_number); | |
24 | ||
25 | require '/var/ipfire/general-functions.pl'; | |
26 | require "${General::swroot}/lang.pl"; | |
27 | require "${General::swroot}/header.pl"; | |
28 | ||
63a1c81a | 29 | ###--- HTML HEAD ---### |
5c33a761 | 30 | my $extraHead = <<END |
1dcf513a | 31 | <style> |
fc31c28d | 32 | table#zoneconf { |
1dcf513a | 33 | width: 100%; |
23b26ce5 | 34 | border-collapse: collapse; |
5e6eba88 | 35 | border-style: hidden; |
23b26ce5 | 36 | table-layout: fixed; |
1dcf513a FB |
37 | } |
38 | ||
5e6eba88 | 39 | /* row height */ |
fc31c28d | 40 | #zoneconf tr { |
1dcf513a FB |
41 | height: 4em; |
42 | } | |
8de94a23 LAH |
43 | #zoneconf tr.half-height { |
44 | height: 2em; | |
45 | } | |
46 | #zoneconf tr.half-height > td { | |
47 | padding: 2px 10px; | |
48 | } | |
49 | ||
5e6eba88 LAH |
50 | /* section separators */ |
51 | #zoneconf tr.divider-top { | |
52 | border-top: 2px solid $Header::bordercolour; | |
53 | } | |
54 | #zoneconf tr.divider-bottom { | |
55 | border-bottom: 2px solid $Header::bordercolour; | |
56 | } | |
1dcf513a | 57 | |
5e6eba88 | 58 | /* table cells */ |
fc31c28d LAH |
59 | #zoneconf td { |
60 | padding: 5px 10px; | |
5e6eba88 | 61 | border-left: 0.5px solid $Header::bordercolour; |
fc31c28d | 62 | text-align: center; |
1dcf513a FB |
63 | } |
64 | ||
5e6eba88 | 65 | /* grey header cells */ |
fc31c28d | 66 | #zoneconf td.heading { |
5e6eba88 | 67 | background-color: lightgrey; |
fc31c28d LAH |
68 | color: white; |
69 | } | |
5e6eba88 | 70 | #zoneconf td.heading.bold::first-line { |
fc31c28d LAH |
71 | font-weight: bold; |
72 | line-height: 1.6; | |
1dcf513a FB |
73 | } |
74 | ||
5e6eba88 | 75 | /* narrow left column with background color */ |
fc31c28d LAH |
76 | #zoneconf tr > td:first-child { |
77 | width: 11em; | |
23b26ce5 | 78 | } |
5e6eba88 LAH |
79 | #zoneconf tr.nic-row > td:first-child { |
80 | background-color: darkgray; | |
81 | } | |
82 | #zoneconf tr.nic-row { | |
83 | border-bottom: 0.5px solid $Header::bordercolour; | |
84 | } | |
8de94a23 LAH |
85 | #zoneconf tr.option-row > td:first-child { |
86 | background-color: gray; | |
87 | } | |
7478903f | 88 | |
fc31c28d | 89 | /* alternating row background color */ |
5e6eba88 LAH |
90 | #zoneconf tr { |
91 | background-color: $Header::table2colour; | |
92 | } | |
fc31c28d | 93 | #zoneconf tr:nth-child(2n+3) { |
5e6eba88 | 94 | background-color: $Header::table1colour; |
1dcf513a FB |
95 | } |
96 | ||
5e6eba88 | 97 | /* special cell colors */ |
fc31c28d | 98 | #zoneconf td.green { |
1dcf513a FB |
99 | background-color: $Header::colourgreen; |
100 | } | |
101 | ||
fc31c28d | 102 | #zoneconf td.red { |
1dcf513a FB |
103 | background-color: $Header::colourred; |
104 | } | |
105 | ||
fc31c28d | 106 | #zoneconf td.blue { |
1dcf513a FB |
107 | background-color: $Header::colourblue; |
108 | } | |
109 | ||
fc31c28d | 110 | #zoneconf td.orange { |
1dcf513a FB |
111 | background-color: $Header::colourorange; |
112 | } | |
113 | ||
fc31c28d LAH |
114 | #zoneconf td.topleft { |
115 | background-color: $Header::pagecolour; | |
1dcf513a FB |
116 | } |
117 | ||
7f44ec04 AK |
118 | input.vlanid { |
119 | width: 4em; | |
120 | } | |
8de94a23 LAH |
121 | input.stp-priority { |
122 | width: 5em; | |
123 | } | |
7f44ec04 | 124 | |
1dcf513a | 125 | #submit-container { |
1dcf513a | 126 | width: 100%; |
23b26ce5 | 127 | padding-top: 20px; |
1d6bc7a0 | 128 | text-align: right; |
23b26ce5 | 129 | color: red; |
1dcf513a FB |
130 | } |
131 | ||
132 | #submit-container.input { | |
133 | margin-left: auto; | |
134 | } | |
1dcf513a | 135 | </style> |
5c33a761 LAH |
136 | |
137 | <script src="/include/zoneconf.js"></script> | |
1dcf513a FB |
138 | END |
139 | ; | |
63a1c81a | 140 | ###--- END HTML HEAD ---### |
1dcf513a | 141 | |
63a1c81a | 142 | ### Read configuration ### |
1dcf513a FB |
143 | my %ethsettings = (); |
144 | my %vlansettings = (); | |
145 | my %cgiparams = (); | |
146 | ||
7478903f FB |
147 | my $restart_notice = ""; |
148 | ||
1dcf513a FB |
149 | &General::readhash("${General::swroot}/ethernet/settings",\%ethsettings); |
150 | &General::readhash("${General::swroot}/ethernet/vlans",\%vlansettings); | |
151 | ||
152 | &Header::getcgihash(\%cgiparams); | |
153 | &Header::showhttpheaders(); | |
154 | ||
155 | # Define all zones we will check for NIC assignment | |
63a1c81a | 156 | my @zones = ("red", "green", "orange", "blue"); |
1dcf513a FB |
157 | |
158 | # Get all physical NICs present | |
159 | opendir(my $dh, "/sys/class/net/"); | |
160 | my @nics = (); | |
161 | ||
162 | while (my $nic = readdir($dh)) { | |
163 | if (-e "/sys/class/net/$nic/device") { # Indicates that the NIC is physical | |
164 | push(@nics, [&Network::get_nic_property($nic, "address"), $nic, 0]); | |
165 | } | |
166 | } | |
167 | ||
168 | closedir($dh); | |
169 | ||
170 | @nics = sort {$a->[0] cmp $b->[0]} @nics; # Sort nics by their MAC address | |
171 | ||
172 | # Name the physical NICs | |
173 | # Even though they may not be really named like this, we will name them ethX or wlanX | |
174 | my $ethcount = 0; | |
175 | my $wlancount = 0; | |
176 | ||
177 | foreach (@nics) { | |
178 | my $nic = $_->[1]; | |
179 | ||
180 | if (-e "/sys/class/net/$nic/wireless") { | |
181 | $_->[1] = "wlan$wlancount"; | |
182 | $_->[2] = 1; | |
183 | $wlancount++; | |
184 | } else { | |
185 | $_->[1] = "eth$ethcount"; | |
186 | $ethcount++; | |
187 | } | |
188 | } | |
189 | ||
63a1c81a LAH |
190 | ### Functions ### |
191 | ||
192 | # Check if a zone is in IP mode or in PPP, PPPoE, VDSL, ... mode | |
193 | sub is_zonetype_ip { | |
194 | my $zone_type = shift; | |
195 | return ($zone_type eq "STATIC" || $zone_type eq "DHCP"); | |
196 | } | |
197 | ||
198 | # Check if a zone is activated (device assigned) | |
199 | sub is_zone_activated { | |
200 | my $zone = uc shift; | |
201 | return ($ethsettings{"${zone}_DEV"} ne ""); | |
202 | } | |
203 | ||
204 | ### START PAGE ### | |
5c33a761 | 205 | &Header::openpage($Lang::tr{"zoneconf title"}, 1, $extraHead); |
1dcf513a FB |
206 | &Header::openbigbox('100%', 'center'); |
207 | ||
208 | ### Evaluate POST parameters ### | |
209 | ||
210 | if ($cgiparams{"ACTION"} eq $Lang::tr{"save"}) { | |
211 | my %VALIDATE_nic_check = (); | |
212 | my $VALIDATE_error = ""; | |
213 | ||
214 | foreach (@zones) { | |
215 | my $uc = uc $_; | |
216 | my $slave_string = ""; | |
217 | my $zone_mode = $cgiparams{"MODE $uc"}; | |
218 | my $VALIDATE_vlancount = 0; | |
f60b61e0 FB |
219 | my $VALIDATE_zoneslaves = 0; |
220 | ||
1dcf513a FB |
221 | $ethsettings{"${uc}_MACADDR"} = ""; |
222 | $ethsettings{"${uc}_MODE"} = ""; | |
223 | $ethsettings{"${uc}_SLAVES"} = ""; | |
224 | $vlansettings{"${uc}_PARENT_DEV"} = ""; | |
225 | $vlansettings{"${uc}_VLAN_ID"} = ""; | |
226 | $vlansettings{"${uc}_MAC_ADDRESS"} = ""; | |
227 | ||
228 | # If RED is not in DHCP or static mode, we only set its MACADDR property | |
229 | if ($uc eq "RED" && ! $cgiparams{"PPPACCESS"} eq "") { | |
230 | foreach (@nics) { | |
231 | my $mac = $_->[0]; | |
232 | ||
233 | if ($mac eq $cgiparams{"PPPACCESS"}) { | |
234 | $ethsettings{"${uc}_MACADDR"} = $mac; | |
235 | ||
236 | # Check if this interface is already accessed by any other zone | |
237 | # If this is the case, show an error message | |
238 | if ($VALIDATE_nic_check{"ACC $mac"}) { | |
239 | $VALIDATE_error = $Lang::tr{"zoneconf val ppp assignment error"}; | |
240 | } | |
241 | ||
242 | $VALIDATE_nic_check{"RESTRICT $mac"} = 1; | |
243 | last; | |
244 | } | |
245 | } | |
246 | ||
63a1c81a | 247 | # skip NIC/VLAN assignment and additional zone options for RED in PPP mode |
1dcf513a FB |
248 | next; |
249 | } | |
250 | ||
251 | foreach (@nics) { | |
252 | my $mac = $_->[0]; | |
253 | my $nic_access = $cgiparams{"ACCESS $uc $mac"}; | |
254 | ||
bb90622c MT |
255 | next unless ($nic_access); |
256 | ||
a6695868 | 257 | if ($nic_access ne "NONE") { |
1dcf513a FB |
258 | if ($VALIDATE_nic_check{"RESTRICT $mac"}) { # If this interface is already assigned to RED in PPP mode, throw an error |
259 | $VALIDATE_error = $Lang::tr{"zoneconf val ppp assignment error"}; | |
f60b61e0 FB |
260 | last; |
261 | } | |
262 | ||
a6695868 | 263 | if ($zone_mode ne "BRIDGE" && $VALIDATE_zoneslaves > 0 && $nic_access ne "") { |
f60b61e0 FB |
264 | $VALIDATE_error = $Lang::tr{"zoneconf val zoneslave amount error"}; |
265 | last; | |
1dcf513a FB |
266 | } |
267 | ||
268 | $VALIDATE_nic_check{"ACC $mac"} = 1; | |
f60b61e0 | 269 | $VALIDATE_zoneslaves++; |
1dcf513a FB |
270 | } |
271 | ||
272 | if ($nic_access eq "NATIVE") { | |
273 | if ($VALIDATE_nic_check{"NATIVE $mac"}) { | |
274 | $VALIDATE_error = $Lang::tr{"zoneconf val native assignment error"}; | |
f60b61e0 | 275 | last; |
1dcf513a FB |
276 | } |
277 | ||
278 | $VALIDATE_nic_check{"NATIVE $mac"} = 1; | |
279 | ||
280 | if ($zone_mode eq "BRIDGE") { | |
281 | $slave_string = "${slave_string}${mac} "; | |
282 | } else { | |
283 | $ethsettings{"${uc}_MACADDR"} = $mac; | |
284 | } | |
285 | } elsif ($nic_access eq "VLAN") { | |
286 | my $vlan_tag = $cgiparams{"TAG $uc $mac"}; | |
287 | ||
288 | if ($VALIDATE_nic_check{"VLAN $mac $vlan_tag"}) { | |
289 | $VALIDATE_error = $Lang::tr{"zoneconf val vlan tag assignment error"}; | |
f60b61e0 | 290 | last; |
1dcf513a FB |
291 | } |
292 | ||
293 | $VALIDATE_nic_check{"VLAN $mac $vlan_tag"} = 1; | |
294 | ||
295 | if (! looks_like_number($vlan_tag)) { | |
f60b61e0 | 296 | last; |
1dcf513a FB |
297 | } |
298 | if ($vlan_tag < 1 || $vlan_tag > 4095) { | |
f60b61e0 | 299 | last; |
1dcf513a FB |
300 | } |
301 | ||
302 | my $rnd_mac = &Network::random_mac(); | |
303 | ||
304 | $vlansettings{"${uc}_PARENT_DEV"} = $mac; | |
305 | $vlansettings{"${uc}_VLAN_ID"} = $vlan_tag; | |
306 | $vlansettings{"${uc}_MAC_ADDRESS"} = $rnd_mac; | |
307 | ||
308 | if ($zone_mode eq "BRIDGE") { | |
309 | $slave_string = "${slave_string}${rnd_mac} "; | |
310 | } | |
311 | ||
312 | $VALIDATE_vlancount++; # We can't allow more than one VLAN per zone | |
313 | } | |
314 | } | |
315 | ||
316 | if ($VALIDATE_vlancount > 1) { | |
317 | $VALIDATE_error = $Lang::tr{"zoneconf val vlan amount assignment error"}; | |
f60b61e0 | 318 | last; |
1dcf513a FB |
319 | } |
320 | ||
321 | chop($slave_string); | |
322 | ||
323 | if ($zone_mode eq "BRIDGE") { | |
324 | $ethsettings{"${uc}_MODE"} = "bridge"; | |
325 | $ethsettings{"${uc}_SLAVES"} = $slave_string; | |
326 | } elsif ($zone_mode eq "MACVTAP") { | |
327 | $ethsettings{"${uc}_MODE"} = "macvtap"; | |
328 | } | |
8de94a23 LAH |
329 | |
330 | # STP options | |
331 | # (this has already been skipped when RED is in PPP mode, so we don't need to check for PPP here) | |
332 | $ethsettings{"${uc}_STP"} = ""; | |
333 | my $stp_enabled = $cgiparams{"STP-$uc"} eq "on"; | |
334 | my $stp_priority = $cgiparams{"STP-PRIORITY-$uc"}; | |
335 | ||
336 | if($stp_enabled) { | |
337 | unless($ethsettings{"${uc}_MODE"} eq "bridge") { # STP is only available in bridge mode | |
338 | $VALIDATE_error = $Lang::tr{"zoneconf val stp zone mode error"}; | |
339 | last; | |
340 | } | |
341 | unless (looks_like_number($stp_priority) && ($stp_priority >= 1) && ($stp_priority <= 65535)) { # STP bridge priority range: 1..65535 | |
342 | $VALIDATE_error = $Lang::tr{"zoneconf val stp priority range error"}; | |
343 | last; | |
344 | } | |
345 | $ethsettings{"${uc}_STP"} = "on"; # network-hotplug-bridges expects "on" | |
346 | $ethsettings{"${uc}_STP_PRIORITY"} = $stp_priority; | |
347 | } | |
1dcf513a FB |
348 | } |
349 | ||
63a1c81a | 350 | # validation failed, show error message and exit |
1dcf513a FB |
351 | if ($VALIDATE_error) { |
352 | &Header::openbox('100%', 'left', $Lang::tr{"error"}); | |
353 | ||
8797526d | 354 | print "$VALIDATE_error<br><br><a href='$ENV{'SCRIPT_NAME'}'>$Lang::tr{'back'}</a>\n"; |
1dcf513a FB |
355 | |
356 | &Header::closebox(); | |
357 | &Header::closebigbox(); | |
358 | &Header::closepage(); | |
359 | ||
360 | exit 0; | |
361 | } | |
362 | ||
63a1c81a | 363 | # new settings are valid, write configuration files |
1dcf513a FB |
364 | &General::writehash("${General::swroot}/ethernet/settings",\%ethsettings); |
365 | &General::writehash("${General::swroot}/ethernet/vlans",\%vlansettings); | |
7478903f | 366 | |
23b26ce5 | 367 | $restart_notice = $Lang::tr{'zoneconf notice reboot'}; |
1dcf513a FB |
368 | } |
369 | ||
1dcf513a FB |
370 | ### START OF TABLE ### |
371 | ||
63a1c81a LAH |
372 | &Header::openbox('100%', 'left', $Lang::tr{"zoneconf nic assignment"}); |
373 | ||
1dcf513a | 374 | print <<END |
0ec8e31a | 375 | <form method='post' enctype='multipart/form-data'> |
fc31c28d | 376 | <table id="zoneconf"> |
5e6eba88 | 377 | <tr class="divider-bottom"> |
fc31c28d | 378 | <td class="topleft"></td> |
1dcf513a FB |
379 | END |
380 | ; | |
381 | ||
0ec8e31a | 382 | # Fill the table header with all activated zones |
1dcf513a | 383 | foreach (@zones) { |
1dcf513a | 384 | my $uc = uc $_; |
1dcf513a | 385 | |
63a1c81a LAH |
386 | # If the zone is not activated, don't show it |
387 | next unless is_zone_activated($_); | |
f60b61e0 | 388 | |
63a1c81a | 389 | # If the red zone is in PPP mode, don't show a mode dropdown |
23b26ce5 | 390 | if ($uc eq "RED") { |
1dcf513a | 391 | my $red_type = $ethsettings{"RED_TYPE"}; |
1dcf513a | 392 | |
63a1c81a LAH |
393 | unless (is_zonetype_ip($red_type)) { |
394 | print "\t\t<td class='heading bold $_'>$uc ($red_type)</td>\n"; | |
1dcf513a | 395 | |
1dcf513a FB |
396 | next; # We're done here |
397 | } | |
398 | } | |
399 | ||
400 | my %mode_selected = (); | |
401 | my $zone_mode = $ethsettings{"${uc}_MODE"}; | |
402 | ||
403 | if ($zone_mode eq "") { | |
404 | $mode_selected{"DEFAULT"} = "selected"; | |
405 | } elsif ($zone_mode eq "bridge") { | |
406 | $mode_selected{"BRIDGE"} = "selected"; | |
407 | } elsif ($zone_mode eq "macvtap") { | |
408 | $mode_selected{"MACVTAP"} = "selected"; | |
409 | } | |
410 | ||
411 | print <<END | |
5e6eba88 | 412 | <td class='heading bold $_'>$uc<br> |
b4434345 | 413 | <select name="MODE $uc" data-zone="$uc" onchange="changeZoneMode(this)"> |
1dcf513a FB |
414 | <option value="DEFAULT" $mode_selected{"DEFAULT"}>$Lang::tr{"zoneconf nicmode default"}</option> |
415 | <option value="BRIDGE" $mode_selected{"BRIDGE"}>$Lang::tr{"zoneconf nicmode bridge"}</option> | |
416 | <option value="MACVTAP" $mode_selected{"MACVTAP"}>$Lang::tr{"zoneconf nicmode macvtap"}</option> | |
417 | </select> | |
418 | </td> | |
419 | END | |
420 | ; | |
0ec8e31a FB |
421 | } |
422 | ||
96d0c761 | 423 | print "\t</tr>\n"; |
0ec8e31a | 424 | |
63a1c81a | 425 | # NIC assignment matrix |
0ec8e31a | 426 | foreach (@nics) { |
23b26ce5 | 427 | my $mac = $_->[0]; |
0ec8e31a | 428 | my $nic = $_->[1]; |
23b26ce5 | 429 | my $wlan = $_->[2]; |
0ec8e31a | 430 | |
5e6eba88 LAH |
431 | print "\t<tr class='nic-row'>\n"; |
432 | print "\t\t<td class='heading bold'>$nic<br>$mac</td>\n"; | |
0ec8e31a | 433 | |
23b26ce5 MT |
434 | # Iterate through all zones and check if the current NIC is assigned to it |
435 | foreach (@zones) { | |
436 | my $uc = uc $_; | |
5c33a761 | 437 | my $highlight = ""; |
0ec8e31a | 438 | |
63a1c81a LAH |
439 | # If the zone is not activated, don't show it |
440 | next unless is_zone_activated($_); | |
1dcf513a | 441 | |
23b26ce5 | 442 | if ($uc eq "RED") { |
23b26ce5 | 443 | # VLANs/Bridging is not possible if the RED interface is set to PPP, PPPoE, VDSL, ... |
63a1c81a | 444 | unless (is_zonetype_ip($ethsettings{"RED_TYPE"})) { |
23b26ce5 | 445 | my $checked = ""; |
1dcf513a | 446 | |
0ec8e31a FB |
447 | if ($mac eq $ethsettings{"${uc}_MACADDR"}) { |
448 | $checked = "checked"; | |
5c33a761 | 449 | $highlight = $_; |
0ec8e31a FB |
450 | } |
451 | ||
96d0c761 | 452 | print <<END |
5c33a761 LAH |
453 | <td class="$highlight"> |
454 | <input type="radio" name="PPPACCESS" value="$mac" data-zone="RED" data-mac="$mac" onchange="highlightAccess(this)" $checked> | |
96d0c761 LAH |
455 | </td> |
456 | END | |
457 | ; | |
23b26ce5 MT |
458 | next; # We're done here |
459 | } | |
460 | } | |
461 | ||
462 | my %access_selected = (); | |
463 | my $zone_mode = $ethsettings{"${uc}_MODE"}; | |
464 | my $zone_parent_dev = $vlansettings{"${uc}_PARENT_DEV"}; # ZONE_PARENT_DEV is set if this zone accesses any interface via a VLAN | |
465 | my $field_disabled = "disabled"; # Only enable the VLAN ID input field if the current access mode is VLAN | |
1dcf513a FB |
466 | my $zone_vlan_id = ""; |
467 | ||
23b26ce5 MT |
468 | # If ZONE_PARENT_DEV is set to a NICs name (e.g. green0 or eth0) instead of a MAC address, we have to find out this NICs MAC address |
469 | $zone_parent_dev = &Network::get_mac_by_name($zone_parent_dev); | |
0ec8e31a | 470 | |
23b26ce5 MT |
471 | # If the current NIC is accessed by the current zone via a VLAN, the ZONE_PARENT_DEV option corresponds to the current NIC |
472 | if ($mac eq $zone_parent_dev) { | |
1dcf513a FB |
473 | $access_selected{"VLAN"} = "selected"; |
474 | $field_disabled = ""; | |
475 | $zone_vlan_id = $vlansettings{"${uc}_VLAN_ID"}; | |
0ec8e31a | 476 | } elsif ($zone_mode eq "bridge") { # If the current zone is in bridge mode, all corresponding NICs (Native as well as VLAN) are set via the ZONE_SLAVES option |
1dcf513a FB |
477 | my @slaves = split(/ /, $ethsettings{"${uc}_SLAVES"}); |
478 | ||
479 | foreach (@slaves) { | |
480 | # Slaves can be set to a NICs name so we have to find out its MAC address | |
481 | $_ = &Network::get_mac_by_name($_); | |
482 | ||
483 | if ($_ eq $mac) { | |
484 | $access_selected{"NATIVE"} = "selected"; | |
485 | last; | |
486 | } | |
487 | } | |
0ec8e31a FB |
488 | } elsif ($mac eq $ethsettings{"${uc}_MACADDR"}) { # Native access via ZONE_MACADDR is only set if the zone does not access a NIC via a VLAN and the zone is not in bridge mode |
489 | $access_selected{"NATIVE"} = "selected"; | |
1dcf513a FB |
490 | } |
491 | ||
23b26ce5 | 492 | $access_selected{"NONE"} = ($access_selected{"NATIVE"} eq "") && ($access_selected{"VLAN"} eq "") ? "selected" : ""; |
1dcf513a FB |
493 | my $vlan_disabled = ($wlan) ? "disabled" : ""; |
494 | ||
5c33a761 LAH |
495 | # If the interface is assigned, hightlight table cell |
496 | if ($access_selected{"NONE"} eq "") { | |
497 | $highlight = $_; | |
498 | } | |
499 | ||
23b26ce5 | 500 | print <<END |
5c33a761 LAH |
501 | <td class="$highlight"> |
502 | <select name="ACCESS $uc $mac" data-zone="$uc" data-mac="$mac" onchange="highlightAccess(this)"> | |
96d0c761 LAH |
503 | <option value="NONE" $access_selected{"NONE"}>- $Lang::tr{"zoneconf access none"} -</option> |
504 | <option value="NATIVE" $access_selected{"NATIVE"}>$Lang::tr{"zoneconf access native"}</option> | |
505 | <option value="VLAN" $access_selected{"VLAN"} $vlan_disabled>$Lang::tr{"zoneconf access vlan"}</option> | |
506 | </select> | |
8797526d | 507 | <input type="number" class="vlanid" id="TAG-$uc-$mac" name="TAG $uc $mac" min="1" max="4095" value="$zone_vlan_id" $field_disabled> |
96d0c761 | 508 | </td> |
1dcf513a FB |
509 | END |
510 | ; | |
23b26ce5 | 511 | } |
1dcf513a | 512 | |
96d0c761 | 513 | print "\t</tr>\n"; |
1dcf513a FB |
514 | } |
515 | ||
8de94a23 LAH |
516 | # STP options |
517 | my @stp_html = (); # form fields buffer (two rows) | |
518 | ||
519 | foreach (@zones) { # load settings and prepare form elements for each zone | |
520 | my $uc = uc $_; | |
521 | ||
522 | # skip if zone is not activated | |
523 | next unless is_zone_activated($_); | |
524 | ||
525 | # STP is not available if the RED interface is set to PPP, PPPoE, VDSL, ... | |
526 | if ($uc eq "RED") { | |
527 | unless (is_zonetype_ip($ethsettings{"RED_TYPE"})) { | |
528 | push(@stp_html, ["\t\t<td></td>\n", "\t\t<td></td>\n"]); # print empty cell | |
529 | next; | |
530 | } | |
531 | } | |
532 | ||
533 | # load configuration | |
534 | my $stp_available = $ethsettings{"${uc}_MODE"} eq "bridge"; # STP is only available in bridge mode | |
535 | my $stp_enabled = $ethsettings{"${uc}_STP"} eq "on"; | |
536 | my $stp_priority = $ethsettings{"${uc}_STP_PRIORITY"}; | |
537 | ||
538 | # form element modifiers | |
539 | my $checked = ""; | |
540 | my $disabled = ""; | |
541 | $checked = "checked" if ($stp_available && $stp_enabled); | |
542 | $disabled = "disabled" unless $stp_available; | |
543 | ||
544 | # enable checkbox HTML | |
545 | my $row_1 = <<END | |
546 | <td> | |
b4434345 | 547 | <input type="checkbox" id="STP-$uc" name="STP-$uc" data-zone="$uc" onchange="changeEnableSTP(this)" $disabled $checked> |
8de94a23 LAH |
548 | </td> |
549 | END | |
550 | ; | |
551 | $disabled = "disabled" unless $stp_enabled; # STP priority can't be entered if STP is disabled | |
552 | ||
553 | # priority input box HTML | |
554 | my $row_2 = <<END | |
555 | <td> | |
b4434345 | 556 | <input type="number" class="stp-priority" id="STP-PRIORITY-$uc" name="STP-PRIORITY-$uc" min="1" max="65535" value="$stp_priority" $disabled> |
8de94a23 LAH |
557 | </td> |
558 | END | |
559 | ; | |
560 | # add fields to buffer | |
561 | push(@stp_html, [$row_1, $row_2]); | |
562 | } | |
563 | ||
564 | # print two rows of prepared form elements | |
565 | print <<END | |
566 | <tr class="half-height divider-top option-row"> | |
567 | <td class="heading bold">$Lang::tr{"zoneconf stp enable"}</td> | |
568 | END | |
569 | ; | |
570 | foreach (@stp_html) { | |
571 | print $_->[0]; # row 1 | |
572 | } | |
573 | print <<END | |
574 | </tr> | |
575 | <tr class="half-height option-row"> | |
576 | <td class="heading">$Lang::tr{"zoneconf stp priority"}</td> | |
577 | END | |
578 | ; | |
579 | foreach (@stp_html) { | |
580 | print $_->[1]; # row 2 | |
581 | } | |
582 | print "\t</tr>\n"; | |
583 | ||
63a1c81a | 584 | # footer and submit button |
1dcf513a FB |
585 | print <<END |
586 | </table> | |
1d6bc7a0 MT |
587 | |
588 | <div id="submit-container"> | |
23b26ce5 | 589 | $restart_notice |
1d6bc7a0 MT |
590 | <input type="submit" name="ACTION" value="$Lang::tr{"save"}"> |
591 | </div> | |
592 | </form> | |
1dcf513a FB |
593 | END |
594 | ; | |
595 | ||
596 | ### END OF TABLE ### | |
597 | ||
598 | &Header::closebox(); | |
599 | &Header::closebigbox(); | |
600 | &Header::closepage(); |