#!/usr/local/bin/php-cgi -f . * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ require_once("globals.inc"); require_once("config.inc"); require_once("functions.inc"); require_once("filter.inc"); require_once("shaper.inc"); require_once("interfaces.inc"); require_once("xmlrpc_client.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() { global $config, $g; if (file_exists("{$g['varrun_path']}/booting") || platform_booting()) { return; } $rpc_client = new pfsense_xmlrpc_client(); $resp = $rpc_client->xmlrpc_method('host_firmware_version'); log_error(sprintf(gettext("XMLRPC versioncheck:").$resp['config_version'] ." -- ". $config['version'])); if (!isset($resp['config_version'])) { update_filter_reload_status("The {$g['product_name']} software configuration version of the other member could not be determined. Skipping synchronization to avoid causing a problem!"); log_error("The {$g['product_name']} software configuration version of the other member could not be determined. Skipping synchronization to avoid causing a problem!"); return false; } elseif ($resp['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; } return false; } function carp_sync_xml($sections) { global $config, $g; if (file_exists("{$g['varrun_path']}/booting") || platform_booting()) { return true; } /* 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; } } } $xml = array(); 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]; break; default: $xml[$section] = $config_copy[$section]; } } $rpc_client = new pfsense_xmlrpc_client(); $resp = $rpc_client->xmlrpc_method('restore_config_section', $xml); if ($resp != null) { $url = $rpc_client->getUrl(); update_filter_reload_status("XMLRPC sync successfully completed with {$url}."); return true; } return false; } 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; } 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['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'] != "") { if (!is_array($config['system']['authserver'])) { $config['system']['authserver'] = array(); } $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 (!carp_check_version()) { return; } update_filter_reload_status("Signaling CARP reload signal..."); if (!carp_sync_xml($sections)) { return; } $rpc_client = new pfsense_xmlrpc_client(); $resp = $rpc_client->xmlrpc_method('filter_configure', "", 900); }