Handle hostnames with upper-case letters
[webmin.git] / firewall / edit_rule.cgi
1 #!/usr/local/bin/perl
2 # edit_rule.cgi
3 # Display the details of one firewall rule, or allow the adding of a new one
4
5 require './firewall-lib.pl';
6 &ReadParse();
7 @tables = &get_iptables_save();
8 $table = $tables[$in{'table'}];
9 &can_edit_table($table->{'name'}) || &error($text{'etable'});
10 if ($in{'clone'} ne '') {
11         &ui_print_header(undef, $text{'edit_title3'}, "");
12         %clone = %{$table->{'rules'}->[$in{'clone'}]};
13         $rule = \%clone;
14         }
15 elsif ($in{'new'}) {
16         &ui_print_header(undef, $text{'edit_title1'}, "");
17         $rule = { 'chain' => $in{'chain'},
18                   'j' => &can_jump('DROP') ? 'DROP' : "" };
19         }
20 else {
21         &ui_print_header(undef, $text{'edit_title2'}, "");
22         $rule = $table->{'rules'}->[$in{'idx'}];
23         &can_jump($rule) || &error($text{'ejump'});
24         }
25
26 print "<form action=save_rule.cgi method=post>\n";
27 foreach $f ('table', 'idx', 'new', 'chain', 'before', 'after') {
28         print &ui_hidden($f, $in{$f});
29         }
30
31 # Display action section
32 print "<table border width=100%>\n";
33 print "<tr $tb> <td><b>$text{'edit_header1'}</b></td> </tr>\n";
34 print "<tr $cb> <td><table width=100%>\n";
35
36 print "<tr> <td><b>$text{'edit_chain'}</b></td>\n";
37 print "<td>",$text{"index_chain_".lc($rule->{'chain'})} ||
38              &text('index_chain', "<tt>$rule->{'chain'}</tt>"),"</td> </tr>\n";
39
40 print "<tr> <td><b>$text{'edit_cmt'}</b></td>\n";
41 if ($config{'comment_mod'} || $rule->{'comment'}) {
42         # Get comment from --comment option
43         printf "<td><input name=cmt size=50 value='%s'></td> </tr>\n",
44                 &html_escape($rule->{'comment'}->[1]);
45         }
46 else {
47         # Get comment from # at end of line
48         printf "<td><input name=cmt size=50 value='%s'></td> </tr>\n",
49                 &html_escape($rule->{'cmt'});
50         }
51
52 print "<tr> <td valign=top><b>$text{'edit_jump'}</b></td> <td>\n";
53 if ($table->{'name'} eq 'nat') {
54         @jumps = ( undef, 'ACCEPT', 'DROP' );
55         if ($rule->{'chain'} eq 'POSTROUTING') {
56                 push(@jumps, 'MASQUERADE', 'SNAT');
57                 }
58         elsif ($rule->{'chain'} eq 'PREROUTING' ||
59                $rule->{'chain'} eq 'OUTPUT') {
60                 push(@jumps, 'REDIRECT', 'DNAT');
61                 }
62         else {
63                 push(@jumps, 'MASQUERADE', 'SNAT', 'REDIRECT', 'DNAT');
64                 }
65         }
66 else {
67         @jumps = ( undef, 'ACCEPT', 'DROP', 'REJECT', 'QUEUE', 'RETURN', 'LOG' );
68         }
69 print "<table>\n";
70 $i = 0;
71 foreach $j (grep { &can_jump($_) } @jumps) {
72         print "<tr>\n" if ($i%5 == 0);
73         printf "<td><input type=radio name=jump value='%s' %s>&nbsp;%s</td>\n",
74                 $j, $rule->{'j'}->[1] eq $j ? "checked" : "",
75                 $text{"index_jump_".lc($j)};
76         $found++ if ($rule->{'j'}->[1] eq $j);
77         $i++;
78         print "</tr>\n" if ($i%5 == 0);
79         }
80 print "<td colspan=2>\n";
81 printf "<input type=radio name=jump value=* %s>&nbsp;%s&nbsp;",
82         $found ? "" : "checked", $text{'edit_jump_other'};
83 printf "<input name=other size=12 value='%s'></td> </tr>\n",
84         $found ? "" : $rule->{'j'}->[1];
85 print "</table></td></tr>\n";
86
87 if (&indexof('REJECT', @jumps) >= 0 && &can_jump("REJECT")) {
88         # Show input for REJECT icmp type
89         if ($rule->{'j'}->[1] eq 'REJECT') {
90                 $rwith = $rule->{'reject-with'}->[1];
91                 }
92         print "<tr> <td><b>$text{'edit_rwith'}</b></td>\n";
93         printf "<td><input type=radio name=rwithdef value=1 %s> %s\n",
94                 $rwith eq "" ? "checked" : "", $text{'default'};
95         printf "<input type=radio name=rwithdef value=0 %s>\n",
96                 $rwith eq "" ? "" : "checked";
97         local @rtypes = ( "icmp-net-unreachable", "icmp-host-unreachable",
98                           "icmp-port-unreachable", "icmp-proto-unreachable",
99                           "icmp-net-prohibited", "icmp-host-prohibited",
100                           "echo-reply", "tcp-reset" );
101         print &text('edit_rwithtype',
102                     &icmptype_input("rwithtype", $rwith, \@rtypes)),
103                     "</td> </tr>\n";
104         }
105
106 if (($table->{'name'} eq 'nat' && $rule->{'chain'} ne 'POSTROUTING') &&
107      &can_jump("REDIRECT")) {
108         # Show inputs for redirect host and port
109         if ($rule->{'j'}->[1] eq 'REDIRECT') {
110                 ($rtofrom, $rtoto) = split(/\-/, $rule->{'to-ports'}->[1]);
111                 }
112         print "<tr> <td><b>$text{'edit_rtoports'}</b></td>\n";
113         printf "<td><input type=radio name=rtodef value=1 %s> %s\n",
114                 $rtofrom eq "" ? "checked" : "", $text{'default'};
115         printf "<input type=radio name=rtodef value=0 %s>\n",
116                 $rtofrom eq "" ? "" : "checked";
117         print &text('edit_prange',
118                     "<input name=rtofrom size=6 value='$rtofrom'>",
119                     "<input name=rtoto size=6 value='$rtoto'>"),"</td> </tr>\n";
120         }
121
122 if (($table->{'name'} eq 'nat' && $rule->{'chain'} ne 'PREROUTING' &&
123      $rule->{'chain'} ne 'OUTPUT') &&
124     &can_jump("MASQUERADE")) {
125         # Show inputs for masquerading ports
126         if ($rule->{'j'}->[1] eq 'MASQUERADE') {
127                 ($mtofrom, $mtoto) = split(/\-/, $rule->{'to-ports'}->[1]);
128                 }
129         print "<tr> <td><b>$text{'edit_mtoports'}</b></td>\n";
130         printf "<td><input type=radio name=mtodef value=1 %s> %s\n",
131                 $mtofrom eq "" ? "checked" : "", $text{'edit_any'};
132         printf "<input type=radio name=mtodef value=0 %s>\n",
133                 $mtofrom eq "" ? "" : "checked";
134         print &text('edit_prange',
135                     "<input name=mtofrom size=6 value='$mtofrom'>",
136                     "<input name=mtoto size=6 value='$mtoto'>"),"</td> </tr>\n";
137         }
138
139 if (($table->{'name'} eq 'nat' && $rule->{'chain'} ne 'POSTROUTING') &&
140     &can_jump("DNAT")) {
141         if ($rule->{'j'}->[1] eq 'DNAT') {
142                 if ($rule->{'to-destination'}->[1] =~
143                     /^([0-9\.]+)(\-([0-9\.]+))?(:(\d+)(\-(\d+))?)?$/) {
144                         $dipfrom = $1;
145                         $dipto = $3;
146                         $dpfrom = $5;
147                         $dpto = $7;
148                         }
149                 }
150         print "<tr> <td><b>$text{'edit_dnat'}</b></td>\n";
151         printf "<td><input type=radio name=dnatdef value=1 %s> %s\n",
152                 $dipfrom eq "" ? "checked" : "", $text{'default'};
153         printf "<input type=radio name=dnatdef value=0 %s>\n",
154                 $dipfrom eq "" ? "" : "checked";
155         print &text('edit_dnatip',
156                     "<input name=dipfrom size=15 value='$dipfrom'>",
157                     "<input name=dipto size=15 value='$dipto'>"),"\n";
158         print &text('edit_prange',
159                     "<input name=dpfrom size=6 value='$dpfrom'>",
160                     "<input name=dpto size=6 value='$dpto'>"),"</td> </tr>\n";
161         }
162
163 if (($table->{'name'} eq 'nat' && $rule->{'chain'} ne 'PREROUTING' &&
164      $rule->{'chain'} ne 'OUTPUT') &&
165     &can_jump("SNAT")) {
166         if ($rule->{'j'}->[1] eq 'SNAT') {
167                 if ($rule->{'to-source'}->[1] =~
168                     /^([0-9\.]+)(\-([0-9\.]+))?(:(\d+)(\-(\d+))?)?$/) {
169                         $sipfrom = $1;
170                         $sipto = $3;
171                         $spfrom = $5;
172                         $spto = $7;
173                         }
174                 }
175         print "<tr> <td><b>$text{'edit_snat'}</b></td>\n";
176         printf "<td><input type=radio name=snatdef value=1 %s> %s\n",
177                 $sipfrom eq "" ? "checked" : "", $text{'default'};
178         printf "<input type=radio name=snatdef value=0 %s>\n",
179                 $sipfrom eq "" ? "" : "checked";
180         print &text('edit_dnatip',
181                     "<input name=sipfrom size=15 value='$sipfrom'>",
182                     "<input name=sipto size=15 value='$sipto'>"),"\n";
183         print &text('edit_prange',
184                     "<input name=spfrom size=6 value='$spfrom'>",
185                     "<input name=spto size=6 value='$spto'>"),"</td> </tr>\n";
186         }
187
188 print "</table></td></tr></table><br>\n";
189
190 # Display conditions section
191 print "$text{'edit_desc'}<br>\n";
192 print "<table border width=100%>\n";
193 print "<tr $tb> <td><b>$text{'edit_header2'}</b></td> </tr>\n";
194 print "<tr $cb> <td><table width=100%>\n";
195
196 print "<tr> <td><b>$text{'edit_source'}</b></td>\n";
197 print "<td>",&print_mode("source", $rule->{'s'}),"\n";
198 printf "<input name=source size=30 value='%s'></td> </tr>\n",
199         $rule->{'s'}->[1];
200
201 print "<tr> <td><b>$text{'edit_dest'}</b></td>\n";
202 print "<td>",&print_mode("dest", $rule->{'d'}),"\n";
203 printf "<input name=dest size=30 value='%s'></td> </tr>\n",
204         $rule->{'d'}->[1];
205
206 print "<tr> <td><b>$text{'edit_in'}</b></td>\n";
207 print "<td>",&print_mode("in", $rule->{'i'}),"\n";
208 print &interface_choice("in", $rule->{'i'}->[1]),"</td> </tr>\n";
209
210 print "<tr> <td><b>$text{'edit_out'}</b></td>\n";
211 print "<td>",&print_mode("out", $rule->{'o'}),"\n";
212 print &interface_choice("out", $rule->{'o'}->[1]),"</td> </tr>\n";
213
214 $f = !$rule->{'f'} ? 0 : $rule->{'f'}->[0] eq "!" ? 2 : 1;
215 print "<tr> <td><b>$text{'edit_frag'}</b></td>\n";
216 printf "<td><input type=radio name=frag value=0 %s> %s\n",
217         $f == 0 ? "checked" : "", $text{'edit_ignore'};
218 printf "<input type=radio name=frag value=1 %s> %s\n",
219         $f == 1 ? "checked" : "", $text{'edit_fragis'};
220 printf "<input type=radio name=frag value=2 %s> %s</td> </tr>\n",
221         $f == 2 ? "checked" : "", $text{'edit_fragnot'};
222
223 print "<tr> <td><b>$text{'edit_proto'}</b></td>\n";
224 print "<td>",&print_mode("proto", $rule->{'p'}),"\n";
225 print &protocol_input("proto", $rule->{'p'}->[1]),"</td> </tr>\n";
226
227 print "<tr> <td colspan=2><hr></td> </tr>\n";
228
229 print "<tr> <td><b>$text{'edit_sport'}</b></td>\n";
230 print "<td>",&print_mode("sport", $rule->{'sports'} || $rule->{'sport'}),"\n";
231 print &port_input("sport", $rule->{'sports'}->[1] || $rule->{'sport'}->[1]),
232       "</td> </tr>\n";
233
234 print "<tr> <td><b>$text{'edit_dport'}</b></td>\n";
235 print "<td>",&print_mode("dport", $rule->{'dports'} || $rule->{'dport'}),"\n";
236 print &port_input("dport", $rule->{'dports'}->[1] || $rule->{'dport'}->[1]),
237       "</td> </tr>\n";
238
239 print "<tr> <td><b>$text{'edit_ports'}</b></td>\n";
240 print "<td>",&print_mode("ports", $rule->{'ports'}),"\n";
241 printf "<input name=ports size=20 value='%s'></td> </tr>\n",
242         $rule->{'ports'}->[1];
243
244 print "<tr> <td><b>$text{'edit_tcpflags'}</b></td>\n";
245 print "<td><table><tr><td>",&print_mode("tcpflags", $rule->{'tcp-flags'}),"\n";
246 print "</td> <td>",&text('edit_flags',
247             &tcpflag_input("tcpflags0", $rule->{'tcp-flags'}->[1]),
248             &tcpflag_input("tcpflags1", $rule->{'tcp-flags'}->[2])),
249       "</td></tr></table> </td> </tr>\n";
250
251 print "<tr> <td><b>$text{'edit_tcpoption'}</b></td>\n";
252 print "<td>",&print_mode("tcpoption", $rule->{'tcp-option'}),"\n";
253 printf "<input name=tcpoption size=6 value='%s'></td> </tr>\n",
254         $rule->{'tcp-option'}->[1];
255
256 print "<tr> <td colspan=2><hr></td> </tr>\n";
257
258 print "<tr> <td><b>$text{'edit_icmptype'}</b></td>\n";
259 print "<td>",&print_mode("icmptype", $rule->{'icmp-type'}),"\n";
260 print &icmptype_input("icmptype", $rule->{'icmp-type'}->[1]),"</td> </tr>\n";
261
262 print "<tr> <td><b>$text{'edit_mac'}</b></td>\n";
263 print "<td>",&print_mode("macsource", $rule->{'mac-source'}),"\n";
264 printf "<input name=macsource size=18 value='%s'></td> </tr>\n",
265         $rule->{'mac-source'}->[1];
266
267 print "<tr> <td colspan=2><hr></td> </tr>\n";
268
269 print "<tr> <td><b>$text{'edit_limit'}</b></td>\n";
270 print "<td>",&print_mode("limit", $rule->{'limit'},
271                          $text{'edit_below'}, $text{'edit_above'}, 1),"\n";
272 ($n, $u) = $rule->{'limit'}->[1] =~ /^(\d+)\/(\S+)$/ ? ($1, $2) : ();
273 print "<input name=limit0 size=6 value='$n'>\n";
274 print "/ <select name=limit1>\n";
275 foreach $l ('second', 'minute', 'hour', 'day') {
276         printf "<option value=%s %s>%s\n",
277                 $l, $u eq $l ? "selected" : "", $l;
278         }
279 print "</select></td> </tr>\n";
280
281 print "<tr> <td><b>$text{'edit_limitburst'}</b></td>\n";
282 print "<td>",&print_mode("limitburst", $rule->{'limit-burst'},
283                          $text{'edit_below'}, $text{'edit_above'}, 1),"\n";
284 printf "<input name=limitburst size=6 value='%s'></td> </tr>\n",
285         $rule->{'limit-burst'}->[1];
286
287 if ($rule->{'chain'} eq 'OUTPUT') {
288         print "<tr> <td colspan=2><hr></td> </tr>\n";
289
290         print "<tr> <td><b>$text{'edit_uidowner'}</b></td>\n";
291         print "<td>",&print_mode("uidowner", $rule->{'uid-owner'}),"\n";
292         printf "<input name=uidowner size=13 value='%s'> %s</td> </tr>\n",
293                 $rule->{'uid-owner'}->[1], &user_chooser_button("uidowner");
294
295         print "<tr> <td><b>$text{'edit_gidowner'}</b></td>\n";
296         print "<td>",&print_mode("gidowner", $rule->{'gid-owner'}),"\n";
297         printf "<input name=gidowner size=13 value='%s'> %s</td> </tr>\n",
298                 $rule->{'gid-owner'}->[1], &group_chooser_button("gidowner");
299
300         print "<tr> <td><b>$text{'edit_pidowner'}</b></td>\n";
301         print "<td>",&print_mode("pidowner", $rule->{'pid-owner'}),"\n";
302         printf "<input name=pidowner size=6 value='%s'></td> </tr>\n",
303                 $rule->{'pid-owner'}->[1];
304
305         print "<tr> <td><b>$text{'edit_sidowner'}</b></td>\n";
306         print "<td>",&print_mode("sidowner", $rule->{'sid-owner'}),"\n";
307         printf "<input name=sidowner size=6 value='%s'></td> </tr>\n",
308                 $rule->{'sid-owner'}->[1];
309         }
310
311 print "<tr> <td colspan=2><hr></td> </tr>\n";
312
313 # Connection states
314 print "<tr> <td valign=top><b>$text{'edit_state'}</b></td>\n";
315 print "<td><table cellpadding=0 cellspacing=0><tr><td valign=top>",
316       &print_mode("state", $rule->{'state'}),"</td>\n";
317 print "<td>&nbsp;<select name=state multiple size=4>\n";
318 %states = map { $_,1 } split(/,/, $rule->{'state'}->[1]);
319 foreach $s ('NEW', 'ESTABLISHED', 'RELATED', 'INVALID', 'UNTRACKED') {
320         printf "<option value=%s %s>%s (%s)\n",
321                 $s, $states{$s} ? "selected" : "",
322                 $text{"edit_state_".lc($s)}, $s;
323         }
324 print "</select></td></tr></table></td> </tr>\n";
325
326 # Type of service
327 print "<tr> <td><b>$text{'edit_tos'}</b></td>\n";
328 print "<td>",&print_mode("tos", $rule->{'tos'}),"\n";
329 print &tos_input("tos", $rule->{'tos'}->[1]),"</td> </tr>\n";
330
331 print "<tr> <td colspan=2><hr></td> </tr>\n";
332
333 # Input physical device
334 print "<tr> <td><b>$text{'edit_physdevin'}</b></td>\n";
335 print "<td>",&print_mode("physdevin", $rule->{'physdev-in'}),"\n";
336 print &interface_choice("physdevin", $rule->{'physdev-in'}->[1]);
337 print "</td> </tr>\n";
338
339 # Output physical device
340 print "<tr> <td><b>$text{'edit_physdevout'}</b></td>\n";
341 print "<td>",&print_mode("physdevout", $rule->{'physdev-out'}),"\n";
342 print &interface_choice("physdevout", $rule->{'physdev-out'}->[1]);
343 print "</td> </tr>\n";
344
345 # Physdev match modes
346 print "<tr> <td><b>$text{'edit_physdevisin'}</b></td>\n";
347 print "<td>",&print_mode("physdevisin", $rule->{'physdev-is-in'},
348                          $text{'yes'}, $text{'no'}),"</td> </tr>\n";
349 print "<tr> <td><b>$text{'edit_physdevisout'}</b></td>\n";
350 print "<td>",&print_mode("physdevisout", $rule->{'physdev-is-out'},
351                          $text{'yes'}, $text{'no'}),"</td> </tr>\n";
352 print "<tr> <td><b>$text{'edit_physdevisbridged'}</b></td>\n";
353 print "<td>",&print_mode("physdevisbridged", $rule->{'physdev-is-bridged'},
354                          $text{'yes'}, $text{'no'}),"</td> </tr>\n";
355
356 print "<tr> <td colspan=2><hr></td> </tr>\n";
357
358 # Show unknown modules
359 @mods = grep { !/^(tcp|udp|icmp|multiport|mac|limit|owner|state|tos|comment|physdev)$/ } map { $_->[1] } @{$rule->{'m'}};
360 print "<tr> <td><b>$text{'edit_mods'}</b></td>\n";
361 printf "<td colspan=3><input name=mods size=50 value='%s'></td> </tr>\n",
362         join(" ", @mods);
363
364 # Show unknown parameters
365 $rule->{'args'} =~ s/^\s+//;
366 $rule->{'args'} =~ s/\s+$//;
367 print "<tr> <td><b>$text{'edit_args'}</b></td>\n";
368 printf "<td colspan=3><input name=args size=50 value='%s'></td> </tr>\n",
369         $rule->{'args'};
370
371 print "</table></td></tr></table>\n";
372 print "<table width=100%><tr>\n";
373 if ($in{'new'}) {
374         print "<td><input type=submit value='$text{'create'}'></td>\n";
375         }
376 else {
377         print "<td><input type=submit value='$text{'save'}'></td>\n";
378         print "<td align=center><input type=submit name=clone ",
379               "value='$text{'edit_clone'}'></td>\n";
380         print "<td align=right><input type=submit name=delete ",
381               "value='$text{'delete'}'></td>\n";
382         }
383 print "</tr></table>\n";
384
385 &ui_print_footer("index.cgi?table=$in{'table'}", $text{'index_return'});
386
387 # print_mode(name, &value, [yes-option, no-option], [no-no-option])
388 sub print_mode
389 {
390 local $m = !$_[1] ? 0 :
391            $_[1]->[0] eq "!" ? 2 : 1;
392 local $rv = "<select name=$_[0]_mode>\n";
393 $rv .= sprintf "<option value=0 %s> &lt;%s&gt;\n",
394         $m == 0 ? "selected" : "", $text{'edit_ignore'};
395 $rv .= sprintf "<option value=1 %s> %s\n",
396         $m == 1 ? "selected" : "", $_[2] || $text{'edit_is'};
397 if (!$_[4] || $m == 2) {
398         $rv .= sprintf "<option value=2 %s> %s\n",
399                 $m == 2 ? "selected" : "", $_[3] || $text{'edit_not'};
400         }
401 $rv .= "</select>\n";
402 return $rv;
403 }
404
405 # port_input(name, value)
406 sub port_input
407 {
408 local ($s, $e, $p);
409 if ($_[1] =~ /^(\d*):(\d*)$/) {
410         $s = $1; $e = $2;
411         }
412 else {
413         $p = $_[1] || "";
414         }
415 local $rv = sprintf "<input type=radio name=$_[0]_type value=0 %s> %s\n",
416                 defined($p) ? "checked" : "", $text{'edit_port0'};
417 $rv .= "<input name=$_[0] size=15 value='$p'>\n";
418 $rv .= sprintf "<input type=radio name=$_[0]_type value=1 %s>\n",
419                 defined($p) ? "" : "checked";
420 $rv .= &text('edit_port1', "<input name=$_[0]_from size=5 value='$s'>",
421                            "<input name=$_[0]_to size=5 value='$e'>");
422 return $rv;
423 }
424
425 # tcpflag_input(name, value)
426 sub tcpflag_input
427 {
428 local %flags = map { $_, 1 } split(/,/, $_[1]);
429 local $f;
430 local $rv = "<font size=-1>\n";
431 foreach $f ('SYN', 'ACK', 'FIN', 'RST', 'URG', 'PSH') {
432         $rv .= sprintf "<input type=checkbox name=$_[0] value=%s %s> %s\n",
433                 $f, $flags{$f} || $flags{'ALL'} ? "checked" : "",
434                 "<tt>$f</tt>";
435         }
436 $rv .= "</font>\n";
437 return $rv;
438 }
439
440 # icmptype_input(name, value, [&types])
441 sub icmptype_input
442 {
443 local ($started, @types, $major, $minor);
444 $major = -1;
445 if ($_[2]) {
446         @types = @{$_[2]};
447         }
448 else {
449         open(IPTABLES, "iptables -p icmp -h 2>/dev/null |");
450         while(<IPTABLES>) {
451                 if (/valid\s+icmp\s+types:/i) {
452                         $started = 1;
453                         }
454                 elsif (!/\S/) {
455                         $started = 0;
456                         }
457                 elsif ($started && /^\s*(\S+)/) {
458                         push(@types, $1);
459                         }
460                 }
461         close(IPTABLES);
462         }
463 if (@types && $_[1] !~ /^\d+$/ && $_[1] !~ /^\d+\/\d+$/) {
464         local $rv = "<select name=$_[0]>\n";
465         foreach $t (@types) {
466                 $rv .= sprintf "<option value=%s %s>%s\n",
467                                 $t, $_[1] eq $t ? "selected" : "", $t;
468                 }
469         $rv .= "</select>\n";
470         return $rv;
471         }
472 else {
473         return "<input name=$_[0] size=6 value='$_[1]'>";
474         }
475 }
476
477 # protocol_input(name, value)
478 sub protocol_input
479 {
480 local @stdprotos = ( 'tcp', 'udp', 'icmp', undef );
481 local @otherprotos;
482 open(PROTOS, "/etc/protocols");
483 while(<PROTOS>) {
484         s/\r|\n//g;
485         s/#.*$//;
486         push(@otherprotos, $1) if (/^(\S+)\s+(\d+)/);
487         }
488 close(PROTOS);
489 @otherprotos = sort { lc($a) cmp lc($b) } @otherprotos;
490 local $p;
491 local $rv = "<select name=$_[0]>\n";
492 local $found = $rule->{'p'}->[1] ? 0 : 1;
493 foreach $p (&unique(@stdprotos, @otherprotos)) {
494         $rv .= sprintf "<option value='%s' %s>%s\n",
495                         $p, $rule->{'p'}->[1] eq $p && $p ? "selected" : "",
496                         uc($p) || "-------";
497         $found++ if ($rule->{'p'}->[1] eq $p && $p);
498         }
499 $rv .= sprintf "<option value='%s' %s>%s\n",
500                 '', !$found ? "selected" : "", $text{'edit_oifc'};
501 $rv .= "</select>\n";
502 $rv .= &ui_textbox($_[0]."_other", $found ? undef : $rule->{'p'}->[1], 5);
503 return $rv;
504 }
505
506 # tos_input(name, value)
507 sub tos_input
508 {
509 local ($started, @opts);
510 open(IPTABLES, "iptables -m tos -h 2>/dev/null |");
511 while(<IPTABLES>) {
512         if (/TOS.*options:/i) {
513                 $started = 1;
514                 }
515         elsif ($started && /^\s+(\S+)\s+(\d+)\s+\((0x[0-9a-f]+)\)/i) {
516                 push(@opts, [ $1, $3 ]);
517                 }
518         }
519 close(IPTABLES);
520 if (@opts) {
521         local $rv = "<select name=$_[0]>\n";
522         foreach $o (@opts) {
523                 $rv .= sprintf "<option value=%s %s>%s\n",
524                         $o->[0], $o->[0] eq $_[1] ? "selected" : "",
525                         "$o->[0] ($o->[1])";
526                 }
527         $rv .= "</select>\n";
528         return $rv;
529         }
530 else {
531         return "<input name=$_[0] size=20 value='$_[1]'>\n";
532         }
533 }
534