Handle hostnames with upper-case letters
[webmin.git] / ipfilter / edit_rule.cgi
1 #!/usr/local/bin/perl
2 # Display a form for editing or creating a firewall rule
3
4 require './ipfilter-lib.pl';
5 &ReadParse();
6 $rules = &get_config();
7
8 if ($in{'delsel'}) {
9         # Special case - deleting selected rules
10         @nums = sort { $b cmp $a } split(/\0/, $in{'d'});
11         if (@nums) {
12                 &lock_file($rules->[$nums[0]]->{'file'});
13                 foreach $n (@nums) {
14                         &delete_rule($rules->[$n]);
15                         }
16                 &flush_file_lines();
17                 &unlock_file($rules->[$nums[0]]->{'file'});
18                 &webmin_log("delsel", "rule", undef,
19                             { 'count' => scalar(@nums) });
20                 }
21         &redirect("");
22         exit;
23         }
24
25 if ($in{'new'}) {
26         &ui_print_header(undef, $text{'edit_title1'}, "");
27         $rule = { 'action' => 'pass',
28                   'all' => 1,
29                   'active' => 1,
30                   'dir' => 'in',
31                   'quick' => 1 };
32         }
33 else {
34         $rule = $rules->[$in{'idx'}];
35         &ui_print_header(undef, $text{'edit_title2'}, "");
36         }
37
38 # Javascript for disabling fields
39 print <<EOF;
40 <script>
41 function all_change(dis)
42 {
43 var f = document.forms[0];
44 for(i=0; i<f.elements.length; i++) {
45         e = f.elements[i];
46         if (e.name.substring(0, 3) != "tos" &&
47             (e.name.substring(0, 4) == "from" ||
48              e.name.substring(0, 2) == "to")) {
49                 e.disabled = dis;
50                 }
51         }
52 }
53 </script>
54 EOF
55
56 print &ui_form_start("save_rule.cgi", "post");
57 print &ui_hidden("new", $in{'new'}),"\n";
58 print &ui_hidden("idx", $in{'idx'}),"\n";
59 print &ui_hidden("before", $in{'before'}),"\n";
60 print &ui_hidden("after", $in{'after'}),"\n";
61 @tds = ( "width=20%", undef );
62
63 print &ui_table_start($text{'edit_header1'}, "width=100%", 2);
64
65 # Comment
66 print &ui_table_row($text{'edit_cmt'},
67                     $rule->{'cmt'} =~ /\n/ ? 
68                         &ui_textarea("cmt", $rule->{'cmt'}, 3, 50) :
69                         &ui_textbox("cmt", $rule->{'cmt'}, 50),
70                     undef, \@tds);
71
72 # Enabled
73 print &ui_table_row($text{'edit_active'},
74                     &ui_radio("active", $rule->{'active'} ? 1 : 0,
75                               [ [ 1, $text{'edit_active1'} ],
76                                 [ 0, $text{'edit_active0'} ] ]));
77
78 # Rule action and argument
79 $ra = $rule->{'action'};
80 push(@action, $ra) if ($ra && &indexof($ra, @actions) < 0);
81 $acts = "<table cellpadding=1 cellspacing=1>\n";
82 $i = 0;
83 %action_fields = ( 'block' => [ 'block_return', 'block_return_dest' ],
84                    'log' => [ 'log_pri', 'log_fac', 'log_body', 'log_first',
85                               'log_orblock' ],
86                    'skip' => [ 'skip' ],
87                    'call' => [ 'call', 'call_now' ] );
88 foreach $a (@actions) {
89         $acts .= "<tr> <td>";
90         local $ma = $rule->{'action'} eq $a;
91         @myfields = @{$action_fields{$a}};
92         @notfields = map { @{$action_fields{$_}} }
93                          grep { $_ ne $a } (keys %action_fields);
94         $acts .= &ui_oneradio("action", $a,
95                         $text{"laction_".$a} || $text{"action_".$a} || uc($a),
96                         $ma,
97                         &js_disable_inputs(\@notfields, \@myfields, "onClick"));
98         if ($a eq "block") {
99                 # Show ICMP block options
100                 local @codes = ( [ "", $text{'edit_none'} ],
101                                  [ "rst", $text{'edit_rst'} ] );
102                 push(@codes, map { [ $_ ] } @icmp_codes);
103                 push(@codes, [ $rule->{'block-return'} ])
104                         if ($rule->{'block-return'} &&
105                             $rule->{'block-return'} ne "rst" &&
106                             &indexof($rule->{'block-return'}, @icmp_codes) < 0);
107                 $acts .= &ui_select("block_return", $rule->{'block-return'},
108                                     \@codes, 0, 0, 1, !$ma)."\n";
109                 $acts .= &ui_checkbox("block_return_dest", 1,
110                                       $text{'edit_return_dest'},
111                                       $rule->{'block-return-dest'},
112                                       undef, !$ma);
113                 }
114         elsif ($a eq "log") {
115                 # Show logging options
116                 $acts .= &logging_options("log", 1, !$ma);
117                 }
118         elsif ($a eq "skip") {
119                 # Show rule to skip to
120                 $acts .= &ui_textbox("skip", $rule->{'skip'}, 10, !$ma);
121                 }
122         elsif ($a eq "call") {
123                 # Show function name
124                 $acts .= &ui_textbox("call", $rule->{'call'}, 20, !$ma)."\n".
125                          &ui_checkbox("call_now", 1, $text{'edit_callnow'},
126                                       $rule->{'call-now'}, undef, !$ma);
127                 }
128         $acts .= "</td> </tr>";
129         }
130 $acts .= "</table>\n";
131 print &ui_table_row($text{'edit_action'}, $acts,
132                     undef, \@tds);
133
134 print &ui_table_end(),"<br>\n";
135
136 # Show section for source and destination
137 print &ui_table_start($text{'edit_header2'}, "width=100%", 2);
138
139 print &ui_table_row($text{'edit_all'},
140     &ui_radio("all", $rule->{'all'} || 0,
141               [ [ 1, $text{'edit_all1'}, "onClick='all_change(true)'" ],
142                 [ 0, $text{'edit_all0'}, "onClick='all_change(false)'" ] ]));
143
144 foreach $f ("from", "to") {
145         print &ui_table_hr();
146         ($ft, $pt) = &object_input($rule, $f);
147         print &ui_table_row($text{'edit_'.$f}, $ft);
148         print &ui_table_row($text{'edit_port'.$f}, $pt);
149         }
150
151 print &ui_table_end(),"<br>\n";
152
153 # Show section for protocol, ttl, tos
154 print &ui_table_start($text{'edit_header3'}, "width=100%", 4);
155
156 print &ui_table_row($text{'edit_dir'},
157     &ui_radio("dir", $rule->{'dir'}, [ [ "in", $text{'dir_in'} ],
158                                        [ "out", $text{'dir_out'} ] ]));
159
160 print &ui_table_row($text{'edit_proto'},
161     &protocol_input("proto", $rule->{'proto'}, 1, 0));
162
163 print &ui_table_row($text{'edit_tos'},
164     &ui_opt_textbox("tos", $rule->{'tos'}, 8, $text{'edit_tosany'}));
165
166 print &ui_table_row($text{'edit_ttl'},
167     &ui_opt_textbox("ttl", $rule->{'ttl'}, 8, $text{'edit_tosany'}));
168
169 print &ui_table_row($text{'edit_on'},
170                     &interface_choice("on", $rule->{'on'}));
171
172 print &ui_table_row($text{'edit_flags'},
173     &ui_opt_textbox("flags1", $rule->{'flags1'}, 8, $text{'edit_flagsany'},
174                     undef, 0, [ "flags2" ]).
175                     " $text{'edit_flags2'} ".
176                     &ui_textbox("flags2", $rule->{'flags2'}, 8,
177                                 !$rule->{'flags1'}));
178
179 print &ui_table_row($text{'edit_icmp'},
180     &ui_select("icmptype", $rule->{'icmp-type'},
181                [ [ "", $text{'edit_icmpany'} ],
182                  map { [ $_ ] } @icmp_types ],
183                0, 0, $rule->{'icmp-type'} ? 1 : 0).
184     " $text{'edit_icmpcode'} ".
185     &ui_select("icmpcode", $rule->{'icmp-type-code'},
186                [ [ "", $text{'edit_codeany'} ],
187                  map { [ $_ ] } @icmp_codes ],
188                0, 0, $rule->{'icmp-code'} ? 1 : 0), 3);
189
190 print &ui_table_end(),"<br>\n";
191
192 # Show section for other options
193 print &ui_table_start($text{'edit_header4'}, "width=100%", 2);
194 print "<table>\n";
195
196 print "<tr> <td colspan=2>",&ui_checkbox("quick", 1, $text{'edit_quick'},
197                                $rule->{'quick'}),"</td> </tr>\n";
198
199 # Show logging options as action
200 print "<tr> <td>",&ui_checkbox("olog", 1, $text{'edit_olog'},
201                $rule->{'olog'},
202                &js_checkbox_disable("olog", [ ], [ "olog_pri", "olog_fac", "olog_body", "olog_first", "olog_block" ], "onClick")),"</td>\n";
203 print "<td>",&logging_options("olog", 1, !$rule->{'olog'}),"</td> </tr>\n";
204  
205 # Show tagging ID
206 print "<tr> <td>",&ui_checkbox("tag", 1, $text{'edit_tag'},
207         $rule->{'tag'},
208         &js_checkbox_disable("tag", [ ], [ "tagid" ], "onClick")),"</td>\n";
209 print "<td>",&ui_textbox("tagid", $rule->{'tag'}, 10, !$rule->{'tag'}),
210       "</td> </tr>\n";
211
212 # Show duplicate destination
213 print "<tr> <td>",&ui_checkbox("dup_to", 1, $text{'edit_dupto'},
214         $rule->{'dup-to'},
215         &js_checkbox_disable("dup_to", [ ],
216                              [ "dup_toiface", "dup_toiface_other",
217                                "dup_toip" ], "onClick")),"</td>\n";
218 ($iface, $ip) = split(/:/, $rule->{'dup-to'});
219 print "<td>",&interface_choice("dup_toiface", $iface, 1,
220                                !$rule->{'dup-to'}),"\n";
221 print "$text{'edit_duptoip'}\n";
222 print &ui_textbox("dup_toip", $ip, 13,
223                   !$rule->{'dup-to'})," $text{'edit_opt'}</td> </tr>\n";
224
225 # Show fast routing destination
226 print "<tr> <td>",&ui_checkbox("fastroute", 1, $text{'edit_fastroute'},
227         $rule->{'fastroute'},
228         &js_checkbox_disable("fastroute", [ ],
229                              [ "fastrouteiface", "fastrouteiface_other",
230                                "fastrouteip" ], "onClick")),"</td>\n";
231 print "<td>",&interface_choice("fastrouteiface", $rule->{'fastroute'}, 1,
232                                !$rule->{'fastroute'}),"\n";
233 print "$text{'edit_fastrouteip'}\n";
234 print &ui_textbox("fastrouteip", $rule->{'fastroute-ip'}, 13,
235                   !$rule->{'fastroute'})," $text{'edit_opt'}</td> </tr>\n";
236
237 # Show reply destination
238 print "<tr> <td>",&ui_checkbox("reply_to", 1, $text{'edit_replyto'},
239         $rule->{'reply-to'},
240         &js_checkbox_disable("reply_to", [ ],
241                              [ "reply_toiface", "reply_toiface_other",
242                                "reply_toip" ], "onClick")),"</td>\n";
243 print "<td>",&interface_choice("reply_toiface", $rule->{'reply-to'}, 1,
244                                !$rule->{'reply-to'}),"\n";
245 print "$text{'edit_fastrouteip'}\n";
246 print &ui_textbox("reply_toip", $rule->{'reply-to-ip'}, 13,
247                   !$rule->{'reply-to'})," $text{'edit_opt'}</td> </tr>\n";
248
249 # Show state keeping options
250 print "<tr> <td>",&ui_checkbox("keep", 1, $text{'edit_keep'},
251         $rule->{'keep'},
252         &js_checkbox_disable("keep", [ ] , [ "keepmode" ], "onClick")),"</td>\n";
253 print "<td>",&ui_select("keepmode", $rule->{'keep'} || "state",
254                 [ [ "state", $text{'edit_keepstate'} ],
255                   [ "frags", $text{'edit_keepfrags'} ] ],
256                 1, 0, 0, !$rule->{'keep'}),"<td> </tr>\n";
257
258 print &ui_table_end();
259
260 if ($in{'new'}) {
261         print &ui_form_end([ [ 'create', $text{'create'} ] ], "100%");
262         }
263 else {
264         print &ui_form_end([ [ 'save', $text{'save'} ],
265                              [ 'delete', $text{'delete'} ] ], "100%");
266         }
267 $dis = $rule->{'all'} ? "true" : "false";
268 print "<script>all_change($dis);</script>\n";
269 &ui_print_footer("", $text{'index_return'});
270
271 # yes_no_ignored_input(name)
272 sub yes_no_ignored_input
273 {
274 local $mode = $rule->{$_[0]} && $rule->{$_[0]."_not"} ? 2 :
275               $rule->{$_[0]} ? 1 : 0;
276 return &ui_radio($_[0], $mode,
277                  [ [ 1, $text{'yes'} ],
278                    [ 0, $text{'no'} ] ]);
279 }
280
281 # logging_options(prefix, split, disable?)
282 sub logging_options
283 {
284 local ($pfx, $split, $dis) = @_;
285 local $rv;
286 local $ll = $rule->{$pfx."-level"};
287 local ($f, $p);
288 if ($ll =~ /^(\S+)\.(\S+)$/) {
289         $p = $2; $f = $1;
290         }
291 elsif ($ll =~ /\S/) {
292         $p = $ll;
293         }
294 $rv .= &ui_select($pfx."_pri", $p,
295           [ [ "", $text{'default'} ], map { [ $_ ] } @log_priorities ],
296           0, 0, 1, $dis);
297 $rv .= " $text{'edit_fac'} ";
298 $rv .= &ui_select($pfx."_fac", $f,
299           [ [ "", $text{'default'} ], map { [ $_ ] } @log_facilities ],
300           0, 0, 1, $dis)."\n";
301 $rv .= "<br>&nbsp;&nbsp;&nbsp;\n" if ($_[1]);
302 $rv .= &ui_checkbox($pfx."_body", 1, $text{'edit_log_body'},
303                     $rule->{$pfx.'-body'}, undef, $dis)."\n";
304 $rv .= &ui_checkbox($pfx."_first", 1, $text{'edit_log_first'},
305                     $rule->{$pfx.'-first'}, undef, $dis)."\n";
306 $rv .= &ui_checkbox($pfx."_orblock", 1, $text{'edit_log_orblock'},
307                     $rule->{$pfx.'-or-block'}, undef, $dis)."\n";
308 return $rv;
309 }
310
311