<?php /** * Copyright (C) 2016 Deciso B.V. * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ namespace OPNsense\Firewall; use \OPNsense\Core\Config; /** * Class Plugin * @package OPNsense\Firewall */ class Plugin { private $anchors = array(); private $filterRules = array(); private $interfaceMapping = array(); private $gatewayMapping = array(); /** * init firewall plugin component */ public function __construct() { } /** * set interface mapping to use * @param array $mapping named array */ public function setInterfaceMapping(&$mapping) { $this->interfaceMapping = array(); $this->interfaceMapping['loopback'] = array('if' => 'lo0', 'descr' => 'loopback'); $this->interfaceMapping = array_merge($this->interfaceMapping, $mapping); } /** * set defined gateways (route-to) * @param array $gateways named array */ public function setGateways($gateways) { if (is_array($gateways)) { foreach ($gateways as $key => $gw) { if (Util::isIpAddress($gw['gateway']) && !empty($gw['interface'])) { $this->gatewayMapping[$key] = array("logic" => "route-to ( {$gw['interface']} {$gw['gateway']} )"); } } } } /** * set defined gateway groups (route-to) * @param array $groups named array */ public function setGatewayGroups($groups) { if (is_array($groups)) { foreach ($groups as $key => $gwgr) { $routeto = array(); foreach ($gwgr as $gw) { if (Util::isIpAddress($gw['gwip']) && !empty($gw['int'])) { $routeto[] = str_repeat("( {$gw['int']} {$gw['gwip']} )", $gw['weight']); } } if (count($routeto) > 0) { $routetologic = "route-to {".implode(' ', $routeto)."}"; if (count($routeto) > 1) { $routetologic .= " round-robin "; } if (!empty(Config::getInstance()->object()->system->lb_use_sticky)) { $routetologic .= " sticky-address "; } $this->gatewayMapping[$key] = array("logic" => $routetologic); } } } } /** * @return array */ public function getInterfaceMapping() { return $this->interfaceMapping; } /** * register anchor * @param string $name anchor name * @param string $type anchor type (fw for filter, other options are nat,rdr,binat) * @param string $priority sort order from low to high * @param string $placement placement head,tail * @return null */ public function registerAnchor($name, $type = "fw", $priority = 0, $placement = "tail") { $anchorKey = sprintf("%s.%s.%08d.%08d", $type, $placement, $priority, count($this->anchors)); $this->anchors[$anchorKey] = $name; ksort($this->anchors); } /** * fetch anchors as text (pf ruleset part) * @param string $types anchor types (fw for filter, other options are nat,rdr,binat. comma seperated) * @param string $placement placement head,tail * @return string */ public function anchorToText($types = "fw", $placement = "tail") { $result = ""; foreach (explode(',', $types) as $type) { foreach ($this->anchors as $anchorKey => $anchor) { if (strpos($anchorKey, "{$type}.{$placement}") === 0) { $result .= $type == "fw" ? "" : "{$type}-"; $result .= "anchor \"{$anchor}\"\n"; } } } return $result; } /** * register a filter rule * @param int $prio priority * @param array $conf configuration * @param array $defaults merge these defaults when provided */ public function registerFilterRule($prio, $conf, $defaults = null) { if ($defaults != null) { $conf = array_merge($defaults, $conf); } $rule = new FilterRule($this->interfaceMapping, $this->gatewayMapping, $conf); if (empty($this->filterRules[$prio])) { $this->filterRules[$prio] = array(); } $this->filterRules[$prio][] = $rule; } /** * filter rules to text * @return string */ public function outputFilterRules() { $output = ""; ksort($this->filterRules); foreach ($this->filterRules as $prio => $ruleset) { foreach ($ruleset as $rule) { $output .= (string)$rule; } } return $output; } }