2 # Display a form for editing or creating a firewall rule
4 require './ipfw-lib.pl';
6 $rules = &get_config();
9 # Special case - deleting selected rules
10 %nums = map { $_, 1 } split(/\0/, $in{'d'});
11 @$rules = grep { !$nums{$_->{'num'}} } @$rules;
12 &lock_file($ipfw_file);
14 &unlock_file($ipfw_file);
15 &webmin_log("delsel", undef, undef,
16 { 'count' => scalar(keys %nums) });
22 &ui_print_header(undef, $text{'edit_title1'}, "");
23 $rule = { 'action' => 'allow',
28 $rule = $rules->[$in{'idx'}];
29 &ui_print_header(undef, &text('edit_title2', $rule->{'num'}), "");
32 print &ui_form_start("save_rule.cgi", "post");
33 print &ui_hidden("new", $in{'new'}),"\n";
34 print &ui_hidden("idx", $in{'idx'}),"\n";
35 print &ui_hidden("before", $in{'before'}),"\n";
36 print &ui_hidden("after", $in{'after'}),"\n";
37 @tds = ( "width=20%", undef );
39 print &ui_table_start($text{'edit_header1'}, "width=100%", 2);
42 print &ui_table_row($text{'edit_cmt'},
43 $rule->{'cmt'} =~ /\n/ ?
44 &ui_textarea("cmt", $rule->{'cmt'}, 3, 50) :
45 &ui_textbox("cmt", $rule->{'cmt'}, 50),
48 # Number for new rules
49 if ($in{'new'} && !$in{'before'} && !$in{'after'}) {
50 print &ui_table_row($text{'edit_num'},
51 &ui_opt_textbox("num", undef, 6, $text{'default'}));
54 # Rule action and argument
55 $ra = &real_action($rule->{'action'});
56 push(@action, $ra) if ($ra && &indexof($ra, @actions) < 0);
57 $acts = "<table cellpadding=1 cellspacing=1>\n";
59 foreach $a (@actions) {
60 $acts .= "<tr>\n" if ($i%2 == 0);
61 $acts .= "<td nowrap>";
62 local $ma = $rule->{'action'} eq $a;
63 $acts .= &ui_oneradio("action", $a,
64 $text{"laction_".$a} || $text{"action_".$a} || uc($a),
67 $acts .= &ui_textbox("action_skipto",
68 $ma ? $rule->{'aarg'} : "", 8);
71 local ($ip, $port) = split(/,/, $rule->{'aarg'});
72 $acts .= &ui_textbox("action_fwdip", $ma ? $ip : "", 15).":".
73 &ui_textbox("action_fwdport", $ma ? $port : "", 5);
75 elsif ($a eq "divert" || $a eq "pipe" || $a eq "queue" || $a eq "tee") {
76 $acts .= &ui_textbox("action_port",
77 $ma ? $rule->{'aarg'} : "", 5);
79 elsif ($a eq "unreach") {
80 $acts .= &ui_select("action_unreach", $ma ? $rule->{'aarg'} :"",
81 [ map { [ $_, $_ ] } @unreaches ]);
84 $acts .= "</tr>\n" if ($i++%2 == 1);
86 $acts .= "</table>\n";
87 print &ui_table_row($text{'edit_action'}, $acts,
91 print &ui_table_row($text{'edit_log'},
92 &ui_oneradio("log", 0, $text{'no'},
94 &ui_oneradio("log", 1,
96 &ui_textbox("logamount",
97 $rule->{'logamount'}, 5)),
101 print &ui_table_row($text{'edit_keep-state'},
102 &yes_no_ignored_input("keep-state"), 1, \@tds);
104 print &ui_table_end();
108 print "$text{'edit_desc'}<br>\n";
109 print &ui_table_start($text{'edit_header3'}, "width=100%", 4);
112 if (ref($rule->{'proto'})) {
113 # Multiple or-block values!
114 print &ui_table_row($text{'edit_proto'},
115 &orblock_input("proto", $rule->{'proto'}));
118 local @protos = &list_protocols();
119 $rule->{'proto'} = "all" if ($rule->{'proto'} eq "ip");
120 print &ui_table_row($text{'edit_proto'},
121 &ui_select("proto", $rule->{'proto'},
122 [ [ "all", $text{'edit_any'} ],
123 map { [ $_, uc($_) ] } @protos ]),
127 # Incoming / outgoing
128 $iomode = $rule->{'in'} || $rule->{'out'} && $rule->{'out_not'} ? 1 :
129 $rule->{'out'} || $rule->{'in'} && $rule->{'in_not'} ? 2 : 0;
130 print &ui_table_row($text{'edit_inout'},
131 &ui_select("inout", $iomode,
132 [ [ 0, "<$text{'edit_ignored'}>" ],
133 [ 1, $text{'edit_inout1'} ],
134 [ 2, $text{'edit_inout2'} ] ]), 1, \@tds);
137 print &ui_table_row($text{'edit_via'},
138 &interface_choice("via", $rule->{'via'}), 1, \@tds);
140 print &ui_table_end();
143 # Source and destination sections
144 foreach $s ("from", "to") {
145 print &ui_table_start($text{'edit_header'.$s}, "width=100%", 2);
148 if (ref($rule->{$s})) {
149 print &ui_table_row($text{'edit_'.$s},
150 &orblock_input($s, $rule->{$s}));
153 local $mode = $rule->{$s} eq "any" ? 0 :
154 $rule->{$s} eq "me" ? 1 : 2;
155 print &ui_table_row($text{'edit_'.$s},
156 &ui_oneradio($s."_mode", 0, $text{'edit_sany'},
158 &ui_oneradio($s."_mode", 1, $text{'edit_sme'},
160 &ui_oneradio($s."_mode", 2, $text{'edit_saddr'},
162 &ui_textbox($s, $mode == 2 ? $rule->{$s} : "", 40),
164 print &ui_table_row("",
165 &ui_checkbox($s."_not", 1, $text{'edit_snot'},
169 #print &ui_table_hr();
172 if (ref($rule->{$s."_ports"})) {
173 print &ui_table_row($text{'edit_port'.$s},
174 &orblock_input($s."_ports", $rule->{$s."_ports"}));
177 local $mode = defined($rule->{$s."_ports"}) ? 1 : 0;
178 print &ui_table_row($text{'edit_port'.$s},
179 &ui_oneradio($s."_ports_mode", 0, $text{'edit_pany'},
181 &ui_oneradio($s."_ports_mode", 1, $text{'edit_ports'},
183 &ui_textbox($s."_ports", $mode == 1 ? $rule->{$s."_ports"}
186 if ($ipfw_version >= 2) {
187 print &ui_table_row("",
188 &ui_checkbox($s."_ports_not", 1, $text{'edit_pnot'},
189 $rule->{$s."_ports_not"}),
195 local $rs = $s eq "from" ? "recv" : "xmit";
196 print &ui_table_row($text{'edit_'.$rs},
197 &interface_choice($rs, $rule->{$rs}), 1, \@tds);
199 print &ui_table_end();
204 @tds = ( "", "nowrap" );
205 # XXX or-block support
206 print &ui_table_start($text{'edit_header2'}, "width=100%", 4);
208 # Established traffic
209 print &ui_table_row($text{'edit_established'},
210 &yes_no_ignored_input("established"), 1, \@tds);
213 print &ui_table_row($text{'edit_setup'},
214 &yes_no_ignored_input("setup"), 1, \@tds);
217 print &ui_table_row($text{'edit_bridged'},
218 &yes_no_ignored_input("bridged"), 1, \@tds);
221 print &ui_table_row($text{'edit_frag'},
222 &yes_no_ignored_input("frag"), 1, \@tds);
224 # MAC addresses (if supported)
225 if ($ipfw_version >= 2) {
226 local ($md, $ms) = $rule->{'mac'} ? @{$rule->{'mac'}} : ( "any", "any" );
227 print &ui_table_row($text{'edit_mac1'},
228 &ui_radio("mac1_def", $ms eq "any" ? 1 : 0,
229 [ [ 1, $text{'edit_ignored'} ],
230 [ 0, $text{'edit_macaddr'} ] ] )." ".
231 &ui_textbox("mac1", $ms eq "any" ? "" : $ms, 20), 3, \@tds);
232 print &ui_table_row($text{'edit_mac2'},
233 &ui_radio("mac2_def", $md eq "any" ? 1 : 0,
234 [ [ 1, $text{'edit_ignored'} ],
235 [ 0, $text{'edit_macaddr'} ] ] )." ".
236 &ui_textbox("mac2", $md eq "any" ? "" : $md, 20), 3, \@tds);
240 if (defined($rule->{'uid'})) {
241 $user = getpwuid($rule->{'uid'});
242 $user = "#".$rule->{'uid'} if (!defined($user));
244 print &ui_table_row($text{'edit_uid'},
245 &ui_radio("uid_def", $user ? 0 : 1,
246 [ [ 1, $text{'edit_ignored'} ],
247 [ 0, $text{'edit_user'} ] ] )." ".
248 &ui_user_textbox("uid", $user), 3, \@tds);
249 if (defined($rule->{'gid'})) {
250 $group = getgrgid($rule->{'gid'});
251 $group = "#".$rule->{'gid'} if (!defined($group));
253 print &ui_table_row($text{'edit_gid'},
254 &ui_radio("gid_def", $group ? 0 : 1,
255 [ [ 1, $text{'edit_ignored'} ],
256 [ 0, $text{'edit_group'} ] ] )." ".
257 &ui_group_textbox("gid", $group), 3, \@tds);
260 %gottypes = map { $_, 1 }
261 map { $_ =~ /^(\d+)\-(\d+)$/ ? ( $1 .. $2 ) : ( $_ ) }
262 split(/,/, $rule->{'icmptypes'});
263 $icmptypes = "<select name=icmptypes size=5 multiple>\n";
264 for($i=0; $i<@icmptypes; $i++) {
265 if ($icmptypes[$i] || $gottypes{$i}) {
266 $icmptypes .= sprintf "<option value=%d %s>%s\n",
267 $i, $gottypes{$i} ? "selected" : "",
268 $icmptypes[$i] || "Type $i";
271 $icmptypes .= "</select>\n";
272 print &ui_table_row($text{'edit_icmptypes'}, $icmptypes, 1, \@tds);
275 %gotflags = map { $_, 1 } split(/,/, $rule->{'tcpflags'});
276 $tcpflags = "<select name=tcpflags size=5 multiple>\n";
277 foreach $i (@tcpflags) {
278 $tcpflags .= sprintf "<option value=%s %s>%s\n",
279 $i, $gotflags{$i} ? "selected" : "", $i;
281 foreach $i (@tcpflags) {
282 $tcpflags .= sprintf "<option value=!%s %s>%s\n",
283 $i, $gotflags{"!$i"} ? "selected" : "", &text('edit_not', $i);
285 $tcpflags .= "</select>\n";
286 print &ui_table_row($text{'edit_tcpflags'}, $tcpflags, 1, \@tds);
289 print &ui_table_row($text{'edit_limit'},
290 &ui_select("limit", $rule->{'limit'} ? $rule->{'limit'}->[0] : "",
291 [ [ "", "<$text{'edit_unlimited'}>" ],
292 [ "src-addr", $text{'edit_src-addr'} ],
293 [ "src-port", $text{'edit_src-port'} ],
294 [ "dst-addr", $text{'edit_dst-addr'} ],
295 [ "dst-port", $text{'edit_dst-port'} ] ])." ".
296 &ui_textbox("limit2", $rule->{'limit'} ? $rule->{'limit'}->[1]
300 # Destination ports directive
301 print &ui_table_row($text{'edit_dstport'},
302 &ui_opt_textbox("dstport",
303 $rule->{'dst-port'} ? join(" ", @{$rule->{'dst-port'}}) : undef,
304 30, $text{'edit_pany'}), 3, \@tds);
306 # Source ports directive
307 print &ui_table_row($text{'edit_srcport'},
308 &ui_opt_textbox("srcport",
309 $rule->{'src-port'} ? join(" ", @{$rule->{'src-port'}}) : undef,
310 30, $text{'edit_pany'}), 3, \@tds);
312 print &ui_table_end();
315 print &ui_form_end([ [ 'create', $text{'create'} ] ], "100%");
318 print &ui_form_end([ [ 'save', $text{'save'} ],
319 [ 'delete', $text{'delete'} ] ], "100%");
322 &ui_print_footer("", $text{'index_return'});
324 # orblock_input(name, &orblock)
327 return $text{'edit_orblock'}." ".
328 &ui_textbox($_[0], join(" ", @{$_[1]}), 50).
329 &ui_hidden($_[0]."_orblock", 1);
332 # yes_no_ignored_input(name)
333 sub yes_no_ignored_input
335 local $mode = $rule->{$_[0]} && $rule->{$_[0]."_not"} ? 2 :
336 $rule->{$_[0]} ? 1 : 0;
337 return &ui_radio($_[0], $mode,
338 [ [ 1, $text{'yes'} ],
339 [ 0, $text{'no'} ] ]);