#!/usr/bin/perl

# Copyright (C) 2002 NEC Corporation
# All Rights Reserved.

# RCS: $Id: iptablesconf

require "/opt/nec/mail/wbmc/lib/wbmc.pl";

chdir("/opt/nec/mail/wbmc/adm/system/security");
require "./iptablesconf.pl";
&readIptablesConfFile($M_SECFN_IPTABLES_CUR_CONF);
&readFltSrvFile();
chdir("../../bin");

# logging option
$alog = "";
$dlog = "";

if ($ARGV[0] eq "-d"){
	$alog = "-l";
	$dlog = "-l";
}

@iptables = ();

# ƽ
&clearAll();
&dropAll("on");
&setForward();
&setInput();
&dropAll("off");
&callIptables();

#
# ̾
#	clearAll - ƤΥꥢ
#
# 
#	clearAll()
#
# 
#	ʤ
#
# 
#	ʤ
#
sub clearAll{
	
	push(@iptables , "-t nat -P PREROUTING ACCEPT");
	push(@iptables , "-t nat -P POSTROUTING ACCEPT");
	push(@iptables , "-t nat -P OUTPUT ACCEPT");
	push(@iptables , "-t nat -F");
	
	return;
	
}

#
# ̾
#	dropAll - 
#
# 
#	dropAll($flag)
#
# 
#	$flag - "on" ƤINPUTѥåȤ˴ "off" ƤINPUTѥåȤ
#
# 
#	ʤ
#
sub dropAll{

	my($flag) = @_;
	
	if ($flag eq "on"){
		push(@iptables , "-t nat -A PREROUTING -i ! lo -j DROP");
	} else {
		push(@iptables , "-t nat -D PREROUTING -i ! lo -j DROP");
	}
	
	return;
	
}

#
# ̾
#	setForward - MASQUERADE
#
# 
#	setForward()
#
# 
#	ʤ
#
# 
#	ʤ
#
sub setForward{

	my($i);
	
	if ($g_secfw eq $M_SECFW_OFF){
		return;
	}
	
	for ($i = 0 ; $i < $g_secifcnt ; $i++){
		if ($g_secif[$i]->{MASQ} eq $M_SECIF_MASQ_ON){
			push(@iptables , "-A FORWARD -i $g_secif[$i]->{NAME} -j MASQUERADE");
		}
	}
	
	return;
	
}

#
# ̾
#	setInput - ե륿󥰥롼κ
#
# 
#	setInput()
#
# 
#	ʤ
#
# 
#	ʤ
#
sub setInput{

	my($i , $if , $chain , @chainlist);
	
	@chainlist = ();
	$if = "";
	
	for ($i = 0 ; $i < $g_secifcnt ; $i++){
		if ($g_secif[$i]->{FILTERING} eq $M_SECIF_FLT_OFF){
			next;
		}
		
		if ($g_secif[$i]->{FILTER} eq ""){
			return;
		} else {
			$if = $g_secif[$i]->{NAME};
			&setIfInput($g_secif[$i]->{FILTER});
		}
	}
	
	if ($if ne ""){
		&createDefaultInput();
	}
	
	return;
	
}

#
# ̾
#	setIfInput - 
#
# 
#	setIfInput($g_secif[$i]->{FILTER})
#
# 
#	$g_secif[$i]->{FILTER} : 1 , 2 , 3
#
# 
#	ʤ
#
sub setIfInput{

	my($filter) = @_;
	my($i , $buf);
	local(@protocol , @dstport , @srcaddr);
	
	@protocol = ();
	@dstport = ();
	@srcaddr = ();
	
	&getIfRuleList($filter , *protocol , *dstport , *srcaddr);
	
	for ($i = 0 ; $i < @protocol ; $i++){
		$buf = "";
		if ($protocol[$i] ne ""){
			$buf .= " -p $protocol[$i]";
		}
		
		if ($dstport[$i] ne ""){
			if ($protocol[$i] eq "icmp"){
				$buf .= " --icmp-type $dstport[$i]";
			} else {
				$buf .= " --dport $dstport[$i]";
			}
		}
		
		if ($srcaddr[$i] ne ""){
			$buf .= " -s $srcaddr[$i]";
		}
		
		push(@iptables , "-t nat -A PREROUTING $buf -j ACCEPT $alog");
	}
	
	return;
	
}

#
# ̾
#	callIptables - 
#
# 
#	callIptables()
#
# 
#	ʤ
#
# 
#	ʤ
#
sub callIptables{

	foreach (@iptables){
		system("/sbin/iptables $_");
	}
	
	return;
	
}

#
# ̾
#	getIfRuleList - 
#
# 
#	getIfRuleList($filter , *protocol , *dstport , *srcaddr)
#
# 
#	$filter : ե륿ʸ(1 , 2 , 3...)
#	@protocol : ץȥꥹ
#	@dstport : ݡȥꥹ
#	@srcaddr : ɥ쥹
#
# 
#	ʤ
#
sub getIfRuleList{

	local($filter , *protocol , *dstport , *srcaddr) = @_;
	my($i , $index , $j , $addr , $portstr , $num);

	if ($filter eq $M_SECIF_FLT_NONE){
		return;
	}
	
	@fltent = split(/,/ , $filter);
	
	for ($i = 0 ; $i < @fltent ; $i++){
		$index = &searchIptablesConfDataFlt($fltent[$i]);
		if ($index == -1){
			next;
		}
		
		if ($g_secflt[$index]->{SRCADDR} eq $M_SECFLT_SRCADDR_ALL){
			$addr = "";
		} else {
			$addr = $g_secflt[$index]->{SRCADDR};
		}
		
		$portstr = &makeCompletePort($g_secflt[$index]->{DSTPORT});
		$num = &getPortList($portstr , *protocol , *dstport);
		
		for ($j = 0 ; $j < $num ; $j++){
			push(@srcaddr , $addr);
		}
	}
	
	return;
	
}

#
# ̾
#	makeCompletePort - 
#
# 
#	makeCompletePort($port)
#
# 
#	$port : ݡֹ
#
# 
#	ݡʸ
#
sub makeCompletePort{

	my($port) = @_;
	my(@ent);
	my($i , $index , $ret);
	
	if ($port eq $M_SECFLT_DSTPORT_ALL){
		return("");
	}
	
	$ret = "";
	@ent = split(/\s+/ , $port);
	
	for ($i = 0 ; $i < @ent ; $i++){
		if ($ent[$i] =~ /([^\/]+)\/(.+)$/){
			$ret .= " $ent[$i]";
		} else {
			$index = &searchFltSrvData($ent[$i]);
			if ($index != -1){
				$ret .= " $g_secsrv[$index]->{'PORT'}";
			} else {
				next;
			}
		}
	}
	
	$ret =~ s/^\s//;
	
	return($ret);
	
}

#
# ̾
#	getPortList - 
#
# 
#	getPortList($port , *protolist , *portlist)
#
# 
#	$port : 
#	@protolist : 
#	@portlist : 
#
# 
#	num : 
#
sub getPortList{

	local($port , *protolist , *portlist) = @_;
	my($num);
	
	if ($port eq ""){
		push(@protolist , "");
		push(@portlist , "");
		return(1);
	}
	
	$num = 0;
	
	@ent = split(/\s+/ , $port);
	
	for ($i = 0 ; $i < @ent ; $i++){
		$buf = $ent[$i];
		$buf =~ /([^\/]+)\/(.+)$/;
		$protocol = $1;
		$portbuf = $2;
		@ent1 = split(/,/ , $portbuf);
		for ($j = 0 ; $j < @ent1 ; $j++){
			push(@protolist , $protocol);
			push(@portlist , $ent1[$j]);
			$num++;
		}
	}
	
	return($num);
	
}

#
# ̾
#	createDefaultInput - ǥեȤꤹ롼
#
# 
#	createDefaultInput()
#
# 
#	ʤ
#
# 
#	ʤ
#
sub createDefaultInput{

	my(@type);
	
	@type = ("echo-reply" , "destination-unreachable" , "source-quench" , 
			"redirect" , "router-advertisement" , "time-exceeded" , 
			"parameter-problem" , "timestamp-reply" , "address-mask-reply");
	
	push(@iptables , "-t nat -A PREROUTING -p tcp ! --syn -j ACCEPT $alog");
	
	foreach (@type){
		push(@iptables , "-t nat -A PREROUTING -p icmp --icmp-type $_ -j ACCEPT $alog");
	}
	
	push(@iptables , "-t nat -A PREROUTING -p tcp --syn -j DROP $dlog");
	push(@iptables , "-t nat -A PREROUTING -p udp -j DROP $dlog");
	push(@iptables , "-t nat -A PREROUTING -p icmp -j DROP $dlog");

	return;
	
}

#
#
#
#
#
#
#
#
#
#
#
#
sub writeIpForward{

	my($value);
	
	if ($g_secfw eq $M_SECFW_OFF){
		$value = "0";
	} else {
		$value = "1";
	}
	
	system("echo $value > /proc/sys/net/ipv4/ip_forward");
	
	return;
	
}