<?php
if(isset($_SERVER['REMOTE_ADDR'])) die();

$Enabled = 1;
$ClassesEnabled = 1;
$SessionDisable = true;
include_once('../../global.php');
include('../routerboard.php');
include('common.php');
$PathFirewall = array('ip', 'firewall', 'mangle');

$Routerboard = new Routerboard();
$Routerboard->UserName = $Config['MainRouter']['UserName'];
$Routerboard->Timeout = $Config['MainRouter']['ConnectTimeout'];
$Routerboard->HostName = $Config['MainRouter']['HostName'];
$Routerboard->Debug = true;

$InetInterface = $Config['MainRouter']['InetInterface'];


// Generate address tree
$AddressTree = array('Address' => new NetworkAddressIPv4(), 'Name' => 'main', 'Items' => array());

// Divide rules by subnet number
$DbResult = $Database->query('SELECT `Id`, `Name`, `AddressRange`, `Mask` FROM `NetworkSubnet` WHERE Member=0');
while($Subnet = $DbResult->fetch_assoc())
{
  $NewAddress = new NetworkAddressIPv4();
  $NewAddress->AddressFromString($Subnet['AddressRange']);
  $NewAddress->Prefix = $Subnet['Mask'];
  InsertToAddressTree($AddressTree, $NewAddress, 'subnet-'.RouterOSIdent($Subnet['Name'])); 
}

// Process users
$DbResult = $Database->query('SELECT `Member`.*, `Subject`.`Name` FROM `Member` LEFT JOIN `Subject` ON `Subject`.`Id` = `Member`.`Subject`');
while($Member = $DbResult->fetch_assoc())
{
  $Member['Name'] = RouterOSIdent($Member['Name'].'-'.$Member['Id'] );
  echo('Uživatel '.$Member['Name'].': ');

  $DbResult2 = $Database->select('NetworkDevice', '*', '`Used` = 1 AND `Member` = '.$Member['Id']);
  while($Device = $DbResult2->fetch_assoc())
  {
    $DbResult3 = $Database->select('NetworkInterface', '*', '`Device` = '.$Device['Id'].' AND `LocalIP` != ""');
    while($Interface = $DbResult3->fetch_assoc())
    {
      $Name = $Device['Name'];
      if($Interface['Name'] != '') $Name .= '-'.$Interface['Name'];
      $Name = RouterOSIdent($Name);
      echo($Name.', ');
      $NewAddress = new NetworkAddressIPv4();
      $NewAddress->AddressFromString($Interface['LocalIP']);
      $NewAddress->Prefix = 32;
      InsertToAddressTree($AddressTree, $NewAddress, $Name);
    }
  }
  
  $DbResult2 = $Database->select('NetworkSubnet', '*', '`Member`='.$Member['Id']);
  while($Subnet = $DbResult2->fetch_assoc())
  {
    $Subnet['Name'] = RouterOSIdent('subnet-'.$Subnet['Name']);
    echo($Subnet['Name'].', ');
    $NewAddress = new NetworkAddressIPv4();
    $NewAddress->AddressFromString($Subnet['AddressRange']);
    $NewAddress->Prefix = $Subnet['Mask'];
    InsertToAddressTree($AddressTree, $NewAddress, $Subnet['Name']);
  }
  echo("\n");
}

ShowSubnetNode($AddressTree);

function ProcessNode($Node)
{
  global $InetInterface, $ItemsFirewall;
  
  foreach($Node['Items'] as $Index => $Item)
  {
    if(count($Item['Items']) == 0)
    {
      // Hosts
      $ParentSubnetId = GetSubgroupByRange($Node['Address']->AddressToString().'/'.$Node['Address']->Prefix);
      $PacketMark = GetMarkByComment($Item['Name'].'-out');
      $ItemsFirewall[] = array('chain' => 'inet-'.$ParentSubnetId.'-out', 'src-address' => $Item['Address']->AddressToString().'/'.$Item['Address']->Prefix, 'out-interface' =>  $InetInterface, 'action' => 'mark-packet', 'new-packet-mark' => $PacketMark, 'passthrough' => 'no', 'comment' => $Item['Name'].'-out');
      $PacketMark = GetMarkByComment($Item['Name'].'-in');
      $ItemsFirewall[] = array('chain' => 'inet-'.$ParentSubnetId.'-in', 'dst-address' => $Item['Address']->AddressToString().'/'.$Item['Address']->Prefix, 'in-interface' => $InetInterface, 'action' => 'mark-packet', 'new-packet-mark' => $PacketMark, 'passthrough' => 'no', 'comment' => $Item['Name'].'-in');
    } else
    {
      // Subnets
      $ParentSubnetId = GetSubgroupByRange($Node['Address']->AddressToString().'/'.$Node['Address']->Prefix);
      $SubnetId = GetSubgroupByRange($Item['Address']->AddressToString().'/'.$Item['Address']->Prefix);
      $PacketMark = GetMarkByComment($Item['Name'].'-out');
      
      $ItemsFirewall[] = array('chain' => 'inet-'.$ParentSubnetId.'-out', 'src-address' => $Item['Address']->AddressToString().'/'.$Item['Address']->Prefix, 'out-interface' => $InetInterface, 'action' => 'jump', 'jump-target' => 'inet-'.$SubnetId.'-out', 'comment' => $Item['Name'].'-out');    
      $ItemsFirewall[] = array('chain' => 'inet-'.$ParentSubnetId.'-in', 'dst-address' => $Item['Address']->AddressToString().'/'.$Item['Address']->Prefix, 'in-interface' => $InetInterface, 'action' => 'jump', 'jump-target' => 'inet-'.$SubnetId.'-in', 'comment' => $Item['Name'].'-in');   
      
      ProcessNode($Item);      
    }    
  }
}

// Generate firewall rules
$ItemsFirewall = array();

// Root of tree and main limit
$ItemsFirewall[] = array('chain' => 'forward', 'out-interface' => $InetInterface, 'action' => 'jump', 'jump-target' => 'inet-1-out', 'comment' => 'main-out');
$ItemsFirewall[] = array('chain' => 'forward', 'in-interface' => $InetInterface, 'action' => 'jump', 'jump-target' => 'inet-1-in', 'comment' => 'main-in');

ProcessNode($AddressTree);

// Slow free internet
$PacketMark = GetMarkByComment('free-out');
$ItemsFirewall[] = array('chain' => 'inet-1-out', 'out-interface' => $InetInterface, 'action' => 'mark-packet', 'new-packet-mark' => $PacketMark, 'comment' => 'free-out', 'passthrough' => 'no');
$PacketMark = GetMarkByComment('free-in');
$ItemsFirewall[] = array('chain' => 'inet-1-in', 'in-interface' => $InetInterface, 'action' => 'mark-packet', 'new-packet-mark' => $PacketMark, 'comment' => 'free-in', 'passthrough' => 'no');


print_r($ItemsFirewall);
$Routerboard->ListUpdate($PathFirewall, array('chain', 'dst-address', 'in-interface', 'action', 'new-packet-mark', 'passthrough', 'comment', 'out-interface', 'src-address', 'jump-target'), $ItemsFirewall, array(), true);

?>
