#!/usr/bin/php-cgi

<?php
/***********************************************************************************
CREWCOMMWIFI IPSET INTERFACE API
WRITTEN BY: JOSE MARI REYES

HISTORY:

11/20/2019		INITIAL CODE COMPLETION
01/08/2020		SYSINFO INCLUDE TO DETECT HARDWARE AND WHAT CHAIN TO USE
02/20/2020		MULTIPLE PORT IS NOW SUPPORTED. RANGE AND SET OF PORTS
02/26/2020		BUG FIX MULTIPORT 

IP SET EXTENSION FOR FIREWALL ADVANCE FILTERING.
TO USE THIS FUNCTION. MAKE SURE THAT THE DNS FILTERING AND FIREWALL ARE ALREADY EXECUTED
BEFORE CALLING THIS FUNCTION



Command Syntax
---------------------

	ipset_parse($filter1);
	

	
Filter Synopsis
-----------------

	A filter contains the following:

	<domain_set>|<source>|p<rotocol>|<port>|[ACTION (A/B)];


	The function can accept multiple filter set delimited by semicolon.  filter1;filter2;....



domain_set  		collection of related domain name for filtering.  for multiple domin use comma instead
          			ex.  abc.com,google.com  etc
 
source		 	source LAN.  ip address or [C or B] Crew Lan or Business Lan, otherwise set to zero (0) if non

protocol   		(T or U) tcp or udp

port       		port number (Multiport is supported)

			Port ranges should be separated with colon :    example 80:1000 

			Port indexes should be separated with comma.  ex.  80,53,8080,443
					
			Port Range   :   example:  80:8080
			Multiple Port:   example:  80,443,1090,8080 


ACTION     		A - Accept  B - Block

************************************************************************************/
define("IPSET_FILE", "/etc/smsg/fireipset");
define ("IPSET", "/usr/sbin/ipset"); 
define("DNSCONFIG", "/etc/dnsmasq.conf");
define('FIREWALL_FILE', "/etc/smsg/firesmsg");

echo "<pre>";
//$cmd = "arp.net,foo.com,192.168.32.1|C|T|80|A;abc.com,bar.com,google.com|0|U|455|A;";
//$cmd = "whatsapp.net,whatsapp.com|C|T|80,443,554|A;";

//ipset_parse($cmd);	
	

/*****************************************	
IPSET FUNCTION
ADDED 11/18/2019
*******************************************/	
function ipset_parse($filter)
{
	if (strlen($filter) <= 0)
		$filter = file_get_contents(IPSET_FILE);	
	else
		file_put_contents(IPSET_FILE, $filter);

		 
	 
	$fset = explode(";", $filter);

	print_r($fset);
	echo "\n\n";
	
	for ($i = 0; $i < count($fset)-1; $i++)
	{
		ipset($fset[$i], $i);
		
	}
	  	
}	





function ipset($cmd, $index)
{
	
		$clist = explode("|", $cmd);
		print_r($clist);
		
		$domain_ip 	= $clist[0];
		$src 		= $clist[1];
		$proto 		= $clist[2];
		$port		= $clist[3];
		$target		= $clist[4];
		
		
		
		
		$filter = "";
		$ipsrc  = "";
		
		
		//------- create hash --------------
		$hash = "ccwset$index";
		$cmdline = "ipset -N $hash iphash";
		$filter = "\n$cmdline\n";
		//----------------------------------
		
		
		//--------------process dnsmasq.conf---------------
		$domain_ip = str_replace(",", "/", $domain_ip);
		$dom = "\nipset=/$domain_ip/$hash";
		echo ">>>>$dom\n";
		save_dnsmasq($dom);
		//--------------------------------------------------
		
		
		if ($src != "0")
		{
			$ipsrc = "-s ";	
			
			if ($src == "B") 
				$ipsrc .= ipset_get_business_lan();
			elseif ($src == "C") 
				$ipsrc .= ipset_get_crew_lan();
			else
			{	
				$ipsrc .= $src;
			}
		}	   

		
		$proto  = ($proto == "U") ? "udp" : "tcp";
		$target =  ($target == "A") ? "ACCEPT" : "DROP"; 
	
		

		if (strpos($port, ',') !== false) //multiport comma separated
		{
			$col_ports = explode(",", $port);
		
			for ($i = 0; $i < count($col_ports); $i++)
			{
				$intport = (int) $col_ports[$i];	
				$chain   = which_chain($intport);
		
				$src = "";	
				if (strcmp($chain, 'delegate_output') != 0) $src = $ipsrc;
	
				$filter .= "iptables -w -I $chain $src -m set --match-set $hash dst -p $proto --dport $intport -j $target\n";
			}
		}
		else //single or range ports
		{
			$chain = which_chain($port);
			
			if(strpos($port, ':') !== false) //muiti port range
				$filter .= "iptables -w -I $chain $ipsrc -m set --match-set $hash dst -p $proto -m multiport --dports $port -j $target\n";
			else
				$filter .= "iptables -w -I $chain $ipsrc -m set --match-set $hash dst -p $proto --dport $port -j $target\n";
		}
 
 
		save_firesmsg($filter);
		
		echo "\nfilter=$filter\n\n";
		
		return $filter;
		
}	



function which_chain($port)
{
include_once('/www/cgi-bin/sysinfo');

	//decide what chain
	$intport = (int) $port;
		
	if ($intport == 80)
	{
		$info = sysinfo();
		$chain = ($info == LS) ? "delegate_forward" : "delegate_output";
	}
	else
		$chain = "delegate_forward";

	return $chain;
}



function set_file_permission($filename, $cmd)
{
        if ($cmd == 'R') $ex = "chmod ugo+w " . $filename;
        if ($cmd == 'W') $ex = "chmod ugo-w " . $filename;
	if ($cmd == '+X') $ex = "chmod ugo+x" . $filename;
        exec($ex);
}




function save_dnsmasq($data)
{
	
	if (is_exist_in_file(DNSCONFIG, $data) == false)
	{
		set_file_permission(DNSCONFIG, "W");
		file_put_contents(DNSCONFIG, $data, FILE_APPEND);
		fflush(0);
		set_file_permission(DNSCONFIG, "R");
	}
	
	

}


function save_firesmsg($data)
{
	
	if (is_exist_in_file(FIREWALL_FILE, $data) == false)
		file_put_contents(FIREWALL_FILE, $data, FILE_APPEND);

}



function is_exist_in_file($file, $needle)
{
	$flag = false;
	$v = trim($needle);
	if ($ptr = fopen($file, "r")) {
		while(!feof($ptr)) 
		{
			$line = trim(fgets($ptr));
			
			if (strcmp($v, $line) == 0)
			{
				echo "FOUND IN $file\n";
				$flag = true;
				break;
			}
		}	
    
		fclose($ptr);
	}
	
	return $flag;
}




function ipset_get_business_lan()
{
	$ip  = "";
        $net = "";

	$iface = BUS_IFACE;

    $ip = shell_exec("ifconfig $iface | awk '/inet addr:/ { sub(/addr:/, \"\", $2); print $2 }'");

    $ip = explode('.', $ip);

    $net = $ip[0] . "." . $ip[1] . "." . $ip[2] . ".0/24";

    return $net;

}

function ipset_get_crew_lan()
{
	return ipset_get_tun0_ip_net();
}


function ipset_get_tun0_ip_net()
{
	$ip  = "";
	$net = "";
	
	$ip = shell_exec("ifconfig tun0 | awk '/inet addr:/ { sub(/addr:/, \"\", $2); print $2 }'");
	
	$ip = explode('.', $ip);
	
	$net = $ip[0] . "." . $ip[1] . "." . $ip[2] . ".0/24";

	return $net;	
}


?> 
 
