#!/usr/local/bin/perl
# index.cgi
# Display current iptables firewall configuration from save file

require './firewall-lib.pl';
&ReadParse();
&header($text{'index_title'}, undef, "intro", 0, 1, 0,
	&help_search_link("iptables", "man", "doc"));
print "<hr>\n";

# Check for iptables and iptables-restore commands
foreach $c ("iptables", "iptables-restore") {
	if (!&has_command($c)) {
		print "<p>",&text('index_ecommand', "<tt>$c</tt>"),"<p>\n";
		print "<hr>\n";
		&footer("/", $text{'index'});
		exit;
		}
	}

# Check if the kernel supports iptables
$out = `iptables -n -t filter -L OUTPUT 2>&1`;
if ($?) {
	print "<p>",&text('index_ekernel', "<pre>$out</pre>"),"<p>\n";
	print "<hr>\n";
	&footer("/", $text{'index'});
	exit;
	}

# Check if the distro supports iptables
if (defined(&check_iptables) && ($err = &check_iptables())) {
	print "<p>$err</p>\n";
	print "<hr>\n";
	&footer("/", $text{'index'});
	exit;
	}

if (&foreign_check("init")) {
	local %iconfig = &foreign_config("init");
	$init_support++ if ($iconfig{'init_base'});
	if (defined(&started_at_boot)) {
		$atboot = &started_at_boot();
		}
	else {
		&foreign_require("init", "init-lib.pl");
		$atboot = &init::action_status("webmin-iptables") == 2;
		}
	}

# Check if the save file exists. If not, check for any existing firewall
# rules, and offer to create a save file from them
if (!-s $iptables_save_file) {
	@tables = &get_iptables_save("iptables-save |");
	foreach $t (@tables) {
		$rules++ if (@{$t->{'rules'}});
		foreach $c (keys %{$t->{'defaults'}}) {
			$chains++ if ($t->{'defaults'}->{$c} ne 'ACCEPT');
			}
		$hastable{$t->{'name'}}++;
		}
	foreach $t (@known_tables) {
		system("iptables -t $t -L >/dev/null") if (!$hastable{$t});
		}
	if ($rules || $chains) {
		# Offer to save the current rules
		print &text('index_existing', $rules,
			    "<tt>$iptables_save_file</tt>"),"<p>\n";
		print "<form action=convert.cgi>\n";
		print "<center><input type=submit ",
		      "value='$text{'index_saveex'}'><p>\n";
		if ($init_support && !$atboot) {
			print "<input type=checkbox name=atboot value=1> ",
			      "$text{'index_atboot'}\n";
			}
		print "</center></form><p>\n";

		print "<table border width=100%>\n";
		print "<tr $tb><td><b>$text{'index_headerex'}</b></td></tr>\n";
		print "<tr $cb> <td><pre>";
		open(OUT, "iptables-save |");
		while(<OUT>) {
			print &html_escape($_);
			}
		close(OUT);
		print "</pre></td> </tr></table>\n";
		}
	else {
		# Offer to set up a firewall
		print &text('index_setup',
			    "<tt>$iptables_save_file</tt>"),"<p>\n";
		print "<form action=setup.cgi>\n";
		print "<center><table><tr><td>\n";
		print "<input type=radio name=auto value=0 checked> ",
		      "$text{'index_auto0'}<p>\n";
		print "<input type=radio name=auto value=1> ",
		      "$text{'index_auto1'} ",
		      &interface_choice("iface1"),"<p>\n";
		print "<input type=radio name=auto value=2> ",
		      "$text{'index_auto2'} ",
		      &interface_choice("iface2"),"<p>\n";
		print "</td></tr></table>\n";
		print "<input type=submit value='$text{'index_auto'}'><p>\n";
		if ($init_support && !$atboot) {
			print "<input type=checkbox name=atboot value=1> ",
			      "$text{'index_atboot'}\n";
			}
		print "</center></form>\n";
		}
	}
else {
	# Verify that all known tables exist, and if not add them to the
	# save file
	@tables = &get_iptables_save();
	foreach $t (@tables) {
		$hastable{$t->{'name'}}++;
		}
	foreach $t (@known_tables) {
		if (!$hastable{$t}) {
			local ($missing) = &get_iptables_save(
						"iptables-save --table $t |");
			if ($missing) {
				delete($missing->{'line'});
				&save_table($missing);
				}
			$need_reload++;
			}
		}
	@tables = &get_iptables_save() if ($need_reload);

	# Allow selection of a table
	if (!defined($in{'table'})) {
		foreach $t (@tables) {
			if (@{$t->{'rules'}}) {
				$in{'table'} = $t->{'index'};
				last;
				}
			}
		}
	$table = $tables[$in{'table'}];

	print "<table width=100%><tr>\n";
	print "<form action=index.cgi>\n";
	print "<td><input type=submit value='$text{'index_change'}'>\n";
	print "<select name=table>\n";
	foreach $t (@tables) {
		printf "<option value=%s %s>%s\n",
			$t->{'index'}, $t eq $table ? "selected" : "",
			&text('index_table_'.$t->{'name'}) || $t->{'name'};
		}
	print "</select></td></form>\n";

	print "<form action=newchain.cgi>\n";
	print "<td align=right><input type=hidden name=table ",
	      "value='$in{'table'}'>\n";
	print "<input type=submit value='$text{'index_cadd'}'>\n";
	print "<input name=chain size=20></td></form>\n";
	print "</tr></table>\n";

	# Display a table of rules for each chain
	foreach $c (sort { $a cmp $b } keys %{$table->{'defaults'}}) {
		print "<hr>\n";
		@rules = grep { lc($_->{'chain'}) eq lc($c) }
			      @{$table->{'rules'}};
		print "<b>",$text{"index_chain_".lc($c)} ||
			    &text('index_chain', "<tt>$c</tt>"),"</b><br>\n";
		print "<form action=save_policy.cgi>\n";
		print "<input type=hidden name=table value='$in{'table'}'>\n";
		print "<input type=hidden name=chain value='$c'>\n";
		if (@rules) {
			print "<table border width=100%>\n";
			print "<tr $tb> ",
			      "<td width=10%><b>$text{'index_action'}</b></td>",
			      "<td width=80%><b>$text{'index_desc'}</b></td> ",
			      "<td width=5%><b>$text{'index_move'}</b></td> ",
			      "<td width=5%><b>$text{'index_add'}</b></td> ",
			      "</tr>\n";
			foreach $r (@rules) {
				print "<tr $cb>\n";
				local $act =
				  $text{"index_jump_".lc($r->{'j'}->[1])} ||
				  &text('index_jump', $r->{'j'}->[1]);
				print "<td nowrap width=10%><a href='edit_rule.cgi?table=$in{'table'}&idx=$r->{'index'}'>$act</a></td>\n";
				print "<td width=80%>",
				      &describe_rule($r),"</td>\n";
				print "<td width=5%>";
				if ($r eq $rules[@rules-1]) {
					print "<img src=images/gap.gif>";
					}
				else {
					print "<a href='move.cgi?table=",
					      "$in{'table'}&idx=$r->{'index'}&",
					      "down=1'><img src=",
					      "images/down.gif border=0></a>";
					}
				if ($r eq $rules[0]) {
					print "<img src=images/gap.gif>";
					}
				else {
					print "<a href='move.cgi?table=",
					      "$in{'table'}&idx=$r->{'index'}&",
					      "up=1'><img src=images/up.gif ",
					      "border=0></a>";
					}
				print "</td>\n";
				print "<td width=5% nowrap>\n";
				print "<a href='edit_rule.cgi?table=",
				      "$in{'table'}&chain=$c&new=1&",
				      "after=$r->{'index'}'><img src=",
				      "images/after.gif border=0></a>";
				print "<a href='edit_rule.cgi?table=",
				      "$in{'table'}&chain=$c&new=1&",
				      "before=$r->{'index'}'><img src=",
				      "images/before.gif border=0></a>";
				print "</td>\n";
				print "</tr>\n";
				}
			print "</table>\n";
			}
		else {
			print "<b>$text{'index_none'}</b><br>\n";
			}

		# Show policy changing button for chains that support it,
		# and rule-adding button
		print "<table width=100%><tr>\n";
		local $d = $table->{'defaults'}->{$c};
		if ($d ne '-') {
			print "<td width=33% nowrap><input type=submit ",
			      "value='$text{'index_policy'}'>\n";
			print "<select name=policy>\n";
			foreach $t ('ACCEPT', 'DROP', 'QUEUE', 'RETURN') {
				printf "<option value=%s %s>%s\n",
					$t, $d eq $t ? "selected" : "",
					$text{"index_policy_".lc($t)};
				}
			print "</select></td>\n";
			print "<td align=center width=33%>\n";
			if (@rules) {
				print "<input type=submit name=clear ",
				      "value='$text{'index_cclear'}'>\n";
				}
			print "</td>\n";
			}
		else {
			print "<td width=66%><input type=submit name=delete ",
			      "value='$text{'index_cdelete'}'></td>\n";
			}
		print "<td align=right width=33%><input type=submit name=add ",
		      "value='$text{'index_radd'}'></td>\n";
		print "</tr></table></form>\n";
		}

	# Display buttons for applying and un-applying the configuration,
	# and for creating an init script if possible
	print "<hr>\n";
	print "<table width=100%>\n";

	print "<tr><form action=apply.cgi>\n";
	print "<input type=hidden name=table value='$in{'table'}'>\n";
	print "<td><input type=submit value='$text{'index_apply'}'></td>\n";
	print "<td>$text{'index_applydesc'}</td>\n";
	print "</form></tr>\n";

	print "<tr><form action=unapply.cgi>\n";
	print "<input type=hidden name=table value='$in{'table'}'>\n";
	print "<td><input type=submit value='$text{'index_unapply'}'></td>\n";
	print "<td>$text{'index_unapplydesc'}</td>\n";
	print "</form></tr>\n";

	if ($init_support) {
		print "<tr><form action=bootup.cgi>\n";
		print "<input type=hidden name=table value='$in{'table'}'>\n";
		print "<td nowrap><input type=submit ",
		      "value='$text{'index_bootup'}'>\n";
		printf "<input type=radio name=boot value=1 %s> %s\n",
			$atboot ? "checked" : "", $text{'yes'};
		printf "<input type=radio name=boot value=0 %s> %s</td>\n",
			$atboot ? "" : "checked", $text{'no'};
		print "<td>$text{'index_bootupdesc'}</td>\n";
		print "</form></tr>\n";
		}

	print "</table>\n";
	}

print "<hr>\n";
&footer("/", $text{'index'});

