summaryrefslogtreecommitdiffstats
path: root/src/etc/rc.filter_synchronize
diff options
context:
space:
mode:
Diffstat (limited to 'src/etc/rc.filter_synchronize')
-rwxr-xr-xsrc/etc/rc.filter_synchronize488
1 files changed, 488 insertions, 0 deletions
diff --git a/src/etc/rc.filter_synchronize b/src/etc/rc.filter_synchronize
new file mode 100755
index 0000000..f31fa34
--- /dev/null
+++ b/src/etc/rc.filter_synchronize
@@ -0,0 +1,488 @@
+#!/usr/local/bin/php-cgi -f
+<?php
+/*
+ rc.filter_synchronize
+ Copyright (C) 2004-2006 Scott Ullrich
+ Copyright (C) 2005 Bill Marquette
+ Copyright (C) 2006 Peter Allgeyer
+ Copyright (C) 2008 Ermal Lu├ži
+ All rights reserved.
+
+ originally part of m0n0wall (http://m0n0.ch/wall)
+ Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>.
+ 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.
+
+*/
+
+require_once("globals.inc");
+require_once("config.inc");
+require_once("functions.inc");
+require_once("filter.inc");
+require_once("shaper.inc");
+require_once("xmlrpc.inc");
+require_once("interfaces.inc");
+
+/*
+ * backup_vip_config_section($section): returns as an xml file string of
+ * the configuration section
+ */
+function backup_vip_config_section() {
+ global $config;
+
+ if (!is_array($config['virtualip']['vip'])) {
+ return;
+ }
+ $temp = array();
+ $temp['vip'] = array();
+ foreach ($config['virtualip']['vip'] as $section) {
+ if (($section['mode'] == 'proxyarp' || $section['mode'] == 'ipalias') &&
+ (strpos($section['interface'], '_vip') === FALSE) &&
+ (strpos($section['interface'], 'lo0') === FALSE)) {
+ continue;
+ }
+ if ($section['advskew'] <> "") {
+ $section_val = intval($section['advskew']);
+ $section_val=$section_val+100;
+ if ($section_val > 254) {
+ $section_val = 254;
+ }
+ $section['advskew'] = $section_val;
+ }
+ if ($section['advbase'] <> "") {
+ $section_val = intval($section['advbase']);
+ if ($section_val > 254) {
+ $section_val = 254;
+ }
+ $section['advbase'] = $section_val;
+ }
+ $temp['vip'][] = $section;
+ }
+ return $temp;
+}
+
+function remove_special_characters($string) {
+ $match_array = "";
+ preg_match_all("/[a-zA-Z0-9\_\-]+/", $string, $match_array);
+ $string = "";
+ foreach ($match_array[0] as $ma) {
+ if ($string <> "") {
+ $string .= " ";
+ }
+ $string .= $ma;
+ }
+ return $string;
+}
+
+function carp_check_version($url, $username, $password, $port = 80, $method = 'pfsense.host_firmware_version') {
+ global $config, $g;
+
+ if (file_exists("{$g['varrun_path']}/booting") || platform_booting()) {
+ return;
+ }
+
+ $params = array(
+ XML_RPC_encode($password)
+ );
+
+ $numberofruns = 0;
+ while ($numberofruns < 2) {
+ $msg = new XML_RPC_Message($method, $params);
+ $cli = new XML_RPC_Client('/xmlrpc.php', $url, $port);
+ $cli->setCredentials($username, $password);
+ if ($numberofruns > 0) {
+ $cli->setDebug(1);
+ }
+ /* send our XMLRPC message and timeout after 240 seconds */
+ $resp = $cli->send($msg, "240");
+ if (!is_object($resp)) {
+ $error = "A communications error occurred while attempting XMLRPC sync with username {$username} {$url}:{$port}.";
+ } elseif ($resp->faultCode()) {
+ $error = "An error code was received while attempting XMLRPC sync with username {$username} {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString();
+ } else {
+ $parsed_response = XML_RPC_decode($resp->value());
+ if (!is_array($parsed_response)) {
+ if (trim($parsed_response) == "Authentication failed") {
+ $error = "An authentication failure occurred while trying to access {$url}:{$port} ({$method}).";
+ log_error($error);
+ file_notice("sync_settings", $error, "Settings Sync", "");
+ return false;
+ }
+ } else {
+ if (!isset($parsed_response['config_version']) ||
+ ($parsed_response['config_version'] < $config['version']) ||
+ ($parsed_response['config_version'] > $config['version'])) {
+ update_filter_reload_status("The other member is on a different configuration version of {$g['product_name']}. Sync will not be done to prevent problems!");
+ log_error("The other member is on a different configuration version of {$g['product_name']}. Sync will not be done to prevent problems!");
+ return false;
+ } else {
+ return true;
+ }
+ }
+ }
+ log_error($error);
+ file_notice("sync_settings", $error, "Settings Sync", "");
+ $numberofruns++;
+ }
+
+ return false;
+}
+
+function carp_sync_xml($url, $username, $password, $sections, $port = 80, $method = 'pfsense.restore_config_section') {
+ global $config, $g;
+
+ if (file_exists("{$g['varrun_path']}/booting") || platform_booting()) {
+ return;
+ }
+
+ update_filter_reload_status("Syncing CARP data to {$url}");
+
+ /* make a copy of config */
+ $config_copy = $config;
+
+ /* strip out nosync items */
+ if (is_array($config_copy['nat']['outbound']['rule'])) {
+ $rulescnt = count($config_copy['nat']['outbound']['rule']);
+ for ($x = 0; $x < $rulescnt; $x++) {
+ $config_copy['nat']['outbound']['rule'][$x]['descr'] = remove_special_characters($config_copy['nat']['outbound']['rule'][$x]['descr']);
+ if (isset ($config_copy['nat']['outbound']['rule'][$x]['nosync'])) {
+ unset ($config_copy['nat']['outbound']['rule'][$x]);
+ }
+ }
+ }
+ if (is_array($config_copy['nat']['rule'])) {
+ $natcnt = count($config_copy['nat']['rule']);
+ for ($x = 0; $x < $natcnt; $x++) {
+ $config_copy['nat']['rule'][$x]['descr'] = remove_special_characters($config_copy['nat']['rule'][$x]['descr']);
+ if (isset ($config_copy['nat']['rule'][$x]['nosync'])) {
+ unset ($config_copy['nat']['rule'][$x]);
+ }
+ }
+ }
+ if (is_array($config_copy['filter']['rule'])) {
+ $filtercnt = count($config_copy['filter']['rule']);
+ for ($x = 0; $x < $filtercnt; $x++) {
+ $config_copy['filter']['rule'][$x]['descr'] = remove_special_characters($config_copy['filter']['rule'][$x]['descr']);
+ if (isset ($config_copy['filter']['rule'][$x]['nosync'])) {
+ unset ($config_copy['filter']['rule'][$x]);
+ }
+ }
+ }
+ if (is_array($config_copy['aliases']['alias'])) {
+ $aliascnt = count($config_copy['aliases']['alias']);
+ for ($x = 0; $x < $aliascnt; $x++) {
+ $config_copy['aliases']['alias'][$x]['descr'] = remove_special_characters($config_copy['aliases']['alias'][$x]['descr']);
+ if (isset ($config_copy['aliases']['alias'][$x]['nosync'])) {
+ unset ($config_copy['aliases']['alias'][$x]);
+ }
+ }
+ }
+ if (is_array($config_copy['dnsmasq']['hosts'])) {
+ $dnscnt = count($config_copy['dnsmasq']['hosts']);
+ for ($x = 0; $x < $dnscnt; $x++) {
+ $config_copy['dnsmasq']['hosts'][$x]['descr'] = remove_special_characters($config_copy['dnsmasq']['hosts'][$x]['descr']);
+ if (isset ($config_copy['dnsmasq']['hosts'][$x]['nosync'])) {
+ unset ($config_copy['dnsmasq']['hosts'][$x]);
+ }
+ }
+ }
+ if (is_array($config_copy['ipsec']['tunnel'])) {
+ $ipseccnt = count($config_copy['ipsec']['tunnel']);
+ for ($x = 0; $x < $ipseccnt; $x++) {
+ $config_copy['ipsec']['tunnel'][$x]['descr'] = remove_special_characters($config_copy['ipsec']['tunnel'][$x]['descr']);
+ if (isset ($config_copy['ipsec']['tunnel'][$x]['nosync'])) {
+ unset ($config_copy['ipsec']['tunnel'][$x]);
+ }
+ }
+ }
+
+ if (is_array($config_copy['dhcpd'])) {
+ foreach ($config_copy['dhcpd'] as $dhcpif => $dhcpifconf) {
+ if ($dhcpifconf['failover_peerip'] <> "") {
+ $int = guess_interface_from_ip($dhcpifconf['failover_peerip']);
+ $intip = find_interface_ip($int);
+ $config_copy['dhcpd'][$dhcpif]['failover_peerip'] = $intip;
+ }
+ }
+ }
+
+ foreach ($sections as $section) {
+ /* we can't use array_intersect_key()
+ * due to the vip 'special case'
+ */
+ switch ($section) {
+ case 'virtualip':
+ $xml[$section] = backup_vip_config_section();
+ break;
+ case 'user':
+ $xml['system'][$section] = $config_copy['system'][$section];
+ $xml['system']['nextuid'] = $config_copy['system']['nextuid'];
+ break;
+ case 'group':
+ $xml['system'][$section] = $config_copy['system'][$section];
+ $xml['system']['nextgid'] = $config_copy['system']['nextgid'];
+ break;
+ case 'authserver':
+ $xml['system'][$section] = $config_copy['system'][$section];
+ default:
+ $xml[$section] = $config_copy[$section];
+ }
+ }
+
+ $params = array(
+ XML_RPC_encode($password),
+ XML_RPC_encode($xml)
+ );
+
+ $numberofruns = 0;
+ while ($numberofruns < 2) {
+ log_error("Beginning XMLRPC sync to {$url}:{$port}.");
+ $msg = new XML_RPC_Message($method, $params);
+ $cli = new XML_RPC_Client('/xmlrpc.php', $url, $port);
+ $cli->setCredentials($username, $password);
+ if ($numberofruns > 0) {
+ $cli->setDebug(1);
+ }
+ /* send our XMLRPC message and timeout after 240 seconds */
+ $resp = $cli->send($msg, "240");
+ if (!is_object($resp)) {
+ $error = "A communications error occurred while attempting XMLRPC sync with username {$username} {$url}:{$port}.";
+ log_error($error);
+ file_notice("sync_settings", $error, "Settings Sync", "");
+ } elseif ($resp->faultCode()) {
+ $error = "An error code was received while attempting XMLRPC sync with username {$username} {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString();
+ log_error($error);
+ file_notice("sync_settings", $error, "Settings Sync", "");
+ } else {
+ $parsed_response = XML_RPC_decode($resp->value());
+ if (!is_array($parsed_response) && trim($parsed_response) == "Authentication failed") {
+ $error = "An authentication failure occurred while trying to access {$url}:{$port} ($method).";
+ log_error($error);
+ file_notice("sync_settings", $error, "Settings Sync", "");
+ return -1;
+ } else {
+ log_error("XMLRPC sync successfully completed with {$url}:{$port}.");
+ update_filter_reload_status("XMLRPC sync successfully completed with {$url}:{$port}.");
+ }
+ $numberofruns = 3;
+ }
+ $numberofruns++;
+ }
+}
+
+if (platform_booting()) {
+ return;
+}
+
+if (is_array($config['hasync'])) {
+ update_filter_reload_status("Building high availability sync information");
+ $hasync = $config['hasync'];
+
+ if (empty($hasync['synchronizetoip'])) {
+ /* this gets hit on every filter sync on the secondary, a log here creates a lot of log spam and I never saw it actually log anything useful */
+ return;
+ }
+
+ /*
+ * XXX: The way we're finding the port right now is really suboptimal -
+ * we can't assume that the other machine is setup identically.
+ */
+ if (!empty($config['system']['webgui']['protocol'])) {
+ $synchronizetoip = $config['system']['webgui']['protocol'];
+ $synchronizetoip .= "://";
+ }
+
+ /* if port is empty lets rely on the protocol selection */
+ $port = $config['system']['webgui']['port'];
+ if (empty($port)) {
+ if ($config['system']['webgui']['protocol'] == "http") {
+ $port = "80";
+ } else {
+ $port = "443";
+ }
+ }
+
+ if (is_ipaddrv6($hasync['synchronizetoip'])) {
+ $hasync['synchronizetoip'] = "[{$hasync['synchronizetoip']}]";
+ }
+ $synchronizetoip .= $hasync['synchronizetoip'];
+ if ($hasync['synchronizerules'] != "") {
+ if (!is_array($config['filter'])) {
+ $config['filter'] = array();
+ }
+ $sections[] = 'filter';
+ }
+ if ($hasync['synchronizenat'] != "") {
+ if (!is_array($config['nat'])) {
+ $config['nat'] = array();
+ }
+ $sections[] = 'nat';
+ }
+ if ($hasync['synchronizealiases'] != "") {
+ if (!is_array($config['aliases'])) {
+ $config['aliases'] = array();
+ }
+ $sections[] = 'aliases';
+ }
+ if ($hasync['synchronizedhcpd'] != "" and is_array($config['dhcpd'])) {
+ $sections[] = 'dhcpd';
+ }
+ if ($hasync['synchronizewol'] != "") {
+ if (!is_array($config['wol'])) {
+ $config['wol'] = array();
+ }
+ $sections[] = 'wol';
+ }
+ if ($hasync['synchronizetrafficshaper'] != "" and is_array($config['shaper'])) {
+ $sections[] = 'shaper';
+ }
+ if ($hasync['synchronizetrafficshaperlimiter'] != "" and is_array($config['dnshaper'])) {
+ $sections[] = 'dnshaper';
+ }
+ if ($hasync['synchronizetrafficshaperlayer7'] != "" and is_array($config['l7shaper'])) {
+ $sections[] = 'l7shaper';
+ }
+ if ($hasync['synchronizestaticroutes'] != "") {
+ if (!is_array($config['staticroutes'])) {
+ $config['staticroutes'] = array();
+ }
+ if (!is_array($config['staticroutes']['route'])) {
+ $config['staticroutes']['route'] = array();
+ }
+ $sections[] = 'staticroutes';
+ if (!is_array($config['gateways'])) {
+ $config['gateways'] = array();
+ }
+ $sections[] = 'gateways';
+ }
+ if ($hasync['synchronizevirtualip'] != "") {
+ if (!is_array($config['virtualip'])) {
+ $config['virtualip'] = array();
+ }
+ $sections[] = 'virtualip';
+ }
+ if ($hasync['synchronizelb'] != "") {
+ if (!is_array($config['load_balancer'])) {
+ $config['load_balancer'] = array();
+ }
+ $sections[] = 'load_balancer';
+ }
+ if ($hasync['synchronizeipsec'] != "") {
+ if (!is_array($config['ipsec'])) {
+ $config['ipsec'] = array();
+ }
+ $sections[] = 'ipsec';
+ }
+ if ($hasync['synchronizeopenvpn'] != "") {
+ if (!is_array($config['openvpn'])) {
+ $config['openvpn'] = array();
+ }
+ $sections[] = 'openvpn';
+ }
+ if ($hasync['synchronizecerts'] != "" || $hasync['synchronizeopenvpn'] != "") {
+ if (!is_array($config['cert'])) {
+ $config['cert'] = array();
+ }
+ $sections[] = 'cert';
+
+ if (!is_array($config['ca'])) {
+ $config['ca'] = array();
+ }
+ $sections[] = 'ca';
+
+ if (!is_array($config['crl'])) {
+ $config['crl'] = array();
+ }
+ $sections[] = 'crl';
+ }
+ if ($hasync['synchronizeusers'] != "") {
+ $sections[] = 'user';
+ $sections[] = 'group';
+ }
+ if ($hasync['synchronizeauthservers'] != "") {
+ $sections[] = 'authserver';
+ }
+ if ($hasync['synchronizednsforwarder'] != "") {
+ if (is_array($config['dnsmasq'])) {
+ $sections[] = 'dnsmasq';
+ }
+ if (is_array($config['unbound'])) {
+ $sections[] = 'unbound';
+ }
+ }
+ if ($hasync['synchronizeschedules'] != "" || $hasync['synchronizerules'] != "") {
+ if (!is_array($config['schedules'])) {
+ $config['schedules'] = array();
+ }
+ $sections[] = 'schedules';
+ }
+ if ($hasync['synchronizecaptiveportal'] != "" and is_array($config['captiveportal'])) {
+ $sections[] = 'captiveportal';
+ }
+ if ($hasync['synchronizecaptiveportal'] != "" and is_array($config['vouchers'])) {
+ $sections[] = 'vouchers';
+ }
+
+ if (count($sections) <= 0) {
+ log_error("Nothing has been configured to be synched. Skipping....");
+ return;
+ }
+
+ if (empty($hasync['username'])) {
+ $username = "admin";
+ } else {
+ $username = $hasync['username'];
+ }
+
+ if (!carp_check_version($synchronizetoip, $username, $hasync['password'], $port)) {
+ return;
+ }
+
+ update_filter_reload_status("Signaling CARP reload signal...");
+ if (carp_sync_xml($synchronizetoip, $username, $hasync['password'], $sections, $port) == -1) {
+ return;
+ }
+ $cli = new XML_RPC_Client('/xmlrpc.php', $synchronizetoip, $port);
+ $params = array(
+ XML_RPC_encode($hasync['password'])
+ );
+
+ $msg = new XML_RPC_Message('pfsense.filter_configure', $params);
+ $cli->setCredentials($username, $hasync['password']);
+ $resp = $cli->send($msg, "900");
+
+ if (!is_object($resp)) {
+ $error = "A communications error occurred while attempting Filter sync with username {$username} {$synchronizetoip}:{$port}.";
+ log_error($error);
+ file_notice("sync_settings", $error, "Settings Sync", "");
+ } elseif ($resp->faultCode()) {
+ $error = "An error code was received while attempting Filter sync with username {$username} {$synchronizetoip}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString();
+ log_error($error);
+ file_notice("sync_settings", $error, "Settings Sync", "");
+ } else {
+ log_error("Filter sync successfully completed with {$synchronizetoip}:{$port}.");
+ $numberofruns = 3;
+ }
+}
+
+?>
OpenPOWER on IntegriCloud