commit dff71b6bbec5575cde975e47c6405b1fcad9c65b
Author: Scott Ullrich <sullrich@pfsense.org>
Date:   Sun Aug 29 21:15:14 2010 -0400

    Add Captive Portal CARP configuration synchronization

diff --git a/etc/rc.filter_synchronize b/etc/rc.filter_synchronize
index ff5156f73e..773130210f 100755
--- a/etc/rc.filter_synchronize
+++ b/etc/rc.filter_synchronize
@@ -48,104 +48,104 @@ require_once("interfaces.inc");
  *                                   the configuration section
  */
 function backup_vip_config_section() {
-        global $config;
-        $new_section = &$config['virtualip'];
-        foreach($new_section['vip'] as $section) {
-                if($section['mode'] == "proxyarp") {
-                        unset($section);
-                }
-                if($section['advskew'] <> "") {
-                        $section_val = intval($section['advskew']);
-                        $section_val=$section_val+100;
-                        if($section_val > 255)
-                                $section_val = 255;
-                        $section['advskew'] = $section_val;
-                }
-                $temp['vip'][] = $section;
-   }
-   return $temp;
+	global $config;
+	$new_section = &$config['virtualip'];
+	foreach($new_section['vip'] as $section) {
+		if($section['mode'] == "proxyarp") {
+			unset($section);
+		}
+		if($section['advskew'] <> "") {
+			$section_val = intval($section['advskew']);
+			$section_val=$section_val+100;
+			if($section_val > 255)
+				$section_val = 255;
+			$section['advskew'] = $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;
+	$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_sync_xml($url, $password, $sections, $port = 80, $method = 'pfsense.restore_config_section') {
-        global $config, $g;
+	global $config, $g;
 
-        if(file_exists("{$g['varrun_path']}/booting"))
-                return;
+	if(file_exists("{$g['varrun_path']}/booting"))
+		return;
 
-        update_filter_reload_status("Syncing CARP data to {$url}");
+	update_filter_reload_status("Syncing CARP data to {$url}");
 
-        /* make a copy of config */
-        $config_copy = $config;
+	/* make a copy of config */
+	$config_copy = $config;
 
-        /* strip out nosync items */
-        if (is_array($config_copy['nat']['advancedoutbound']['rule'])) {
-		$rulescnt = count($config_copy['nat']['advancedoutbound']['rule']);
-        	for ($x = 0; $x < $rulescnt; $x++) {
-                	$config_copy['nat']['advancedoutbound']['rule'][$x]['descr'] = remove_special_characters($config_copy['nat']['advancedoutbound']['rule'][$x]['descr']);
-                	if (isset ($config_copy['nat']['advancedoutbound']['rule'][$x]['nosync']))
-                        	unset ($config_copy['nat']['advancedoutbound']['rule'][$x]);
-        	}
+	/* strip out nosync items */
+	if (is_array($config_copy['nat']['advancedoutbound']['rule'])) {
+	$rulescnt = count($config_copy['nat']['advancedoutbound']['rule']);
+	for ($x = 0; $x < $rulescnt; $x++) {
+		$config_copy['nat']['advancedoutbound']['rule'][$x]['descr'] = remove_special_characters($config_copy['nat']['advancedoutbound']['rule'][$x]['descr']);
+		if (isset ($config_copy['nat']['advancedoutbound']['rule'][$x]['nosync']))
+			unset ($config_copy['nat']['advancedoutbound']['rule'][$x]);
 		}
-        if (is_array($config_copy['nat']['rule'])) {
+	}
+	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]);
+		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'])) {
+	}
+	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]);
+		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'])) {
+	}
+	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]);
-        	}
+		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'])) {
+	}
+	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]);
-        	}
+		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['virtualip']['vip'])) {
+	}
+	if (is_array($config_copy['virtualip']['vip'])) {
 		$vipcnt = count($config_copy['virtualip']['vip']);
-        	for ($x = 0; $x < $vipcnt; $x++) {
-                	$config_copy['virtualip']['vip'][$x]['descr'] = remove_special_characters($config_copy['virtualip']['vip'][$x]['descr']);
-                	if (isset ($config_copy['virtualip']['vip'][$x]['nosync']) or $config_copy['virtualip']['vip'][$x]['mode'] == "proxyarp")
-                        	unset ($config_copy['virtualip']['vip'][$x]);
-        	}
+		for ($x = 0; $x < $vipcnt; $x++) {
+			$config_copy['virtualip']['vip'][$x]['descr'] = remove_special_characters($config_copy['virtualip']['vip'][$x]['descr']);
+			if (isset ($config_copy['virtualip']['vip'][$x]['nosync']) or $config_copy['virtualip']['vip'][$x]['mode'] == "proxyarp")
+				unset ($config_copy['virtualip']['vip'][$x]);
 		}
-        if (is_array($config_copy['ipsec']['tunnel'])) {
+	}
+	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]);
-        	}
+		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) {
@@ -157,10 +157,10 @@ function carp_sync_xml($url, $password, $sections, $port = 80, $method = 'pfsens
 		}
 	}
 
-        foreach ($sections as $section) {
-                /*  we can't use array_intersect_key()
-                 *  due to the vip 'special case'
-                 */
+	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();
@@ -174,49 +174,49 @@ function carp_sync_xml($url, $password, $sections, $port = 80, $method = 'pfsens
 			default:
 				$xml[$section] = $config_copy[$section];
 		}
-        }
+	}
 
-        $params = array(
-                XML_RPC_encode($password),
-                XML_RPC_encode($xml)
-        );
+	$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);
-                $username = $config['system']['user'][0]['name'];
-                $cli->setCredentials($username, $password);
-                if($numberofruns > 1)
-                        $cli->setDebug(1);
-                /* send our XMLRPC message and timeout after 240 seconds */
-                $resp = $cli->send($msg, "240");
-				if($resp->faultCode()) {
-					$error = "A communications error occurred while attempting communication with {$url}:{$port} (pfsense.exec_php).";
-					log_error($error);
-					return;	
-				}
-                if(!$resp) {
-                        $error = "A communications error occured 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 {
-                        log_error("XMLRPC sync successfully completed with {$url}:{$port}.");
-                        $numberofruns = 3;
-                }
-				$parsed_response =  XML_RPC_Decode($resp->value());
-				if(!is_array($firewall_info) && trim($firewall_info) == "Authentication failed") {
-					$error = "A authentication failure occurred while trying to access {$url}:{$port} (pfsense.exec_php).";
-					log_error($error);
-					$numberofruns = 5;
-				}
-                $numberofruns++;
-        }
+	$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);
+		$username = $config['system']['user'][0]['name'];
+		$cli->setCredentials($username, $password);
+		if($numberofruns > 1)
+			$cli->setDebug(1);
+		/* send our XMLRPC message and timeout after 240 seconds */
+		$resp = $cli->send($msg, "240");
+		if($resp->faultCode()) {
+			$error = "A communications error occurred while attempting communication with {$url}:{$port} (pfsense.exec_php).";
+			log_error($error);
+			return;	
+		}
+		if(!$resp) {
+			$error = "A communications error occured 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 {
+			log_error("XMLRPC sync successfully completed with {$url}:{$port}.");
+			$numberofruns = 3;
+		}
+		$parsed_response =  XML_RPC_Decode($resp->value());
+		if(!is_array($firewall_info) && trim($firewall_info) == "Authentication failed") {
+			$error = "A authentication failure occurred while trying to access {$url}:{$port} (pfsense.exec_php).";
+			log_error($error);
+			$numberofruns = 5;
+		}
+		$numberofruns++;
+	}
 }
 
 global $g;
@@ -227,89 +227,95 @@ if (is_array($config['installedpackages']['carpsettings']['config'])) {
 	update_filter_reload_status("Building CARP sync information");
 	foreach($config['installedpackages']['carpsettings']['config'] as $carp) {
 		if ($carp['synchronizetoip'] != "" ) {
-			/*
-                         * 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 ($config['system']['webgui']['protocol'] != "") {
-                         	$synchronizetoip = $config['system']['webgui']['protocol'];
-                                $synchronizetoip .= "://";
-                         }
-                         $port = $config['system']['webgui']['port'];
-                         /* if port is empty lets rely on the protocol selection */
-                         if ($port == "") {
-                         	if ($config['system']['webgui']['protocol'] == "http")
-                                	$port = "80";
-                                else
-                                	$port = "443";
-                         }
-                         $synchronizetoip .= $carp['synchronizetoip'];
-                         if ($carp['synchronizerules'] != "" and is_array($config['filter']))
-                         	$sections[] = 'filter';
-                         if ($carp['synchronizenat'] != "" and is_array($config['nat']))
-                         	$sections[] = 'nat';
-                         if ($carp['synchronizealiases'] != "" and is_array($config['aliases']))
-                         	$sections[] = 'aliases';
-                         if ($carp['synchronizedhcpd'] != "" and is_array($config['dhcpd']))
-                                $sections[] = 'dhcpd';
-                         if ($carp['synchronizewol'] != "" and is_array($config['wol']))
-                                $sections[] = 'wol';
-                         if ($carp['synchronizetrafficshaper'] != "" and is_array($config['shaper']))
-                                $sections[] = 'shaper';
-                         if ($carp['synchronizestaticroutes'] != "" and is_array($config['staticroutes'])) {
-                                $sections[] = 'staticroutes';
-                                $sections[] = 'gateways';
-                         }
-                         if ($carp['synchronizevirtualip'] != "" and is_array($config['virtualip']))
-                                $sections[] = 'virtualip';
-                         if ($carp['synchronizelb'] != "" and is_array($config['load_balancer']))
-                                $sections[] = 'load_balancer';
-                         if ($carp['synchronizeipsec'] != "" and is_array($config['ipsec']))
-                                $sections[] = 'ipsec';
-                         if ($carp['synchronizeopenvpn'] != "" and is_array($config['openvpn'])) {
-                                $sections[] = 'openvpn';
-                                $mergesections[] = 'cert';
-                                $mergesections[] = 'ca';
-                         }
-                         if ($carp['synchronizeusers'] != "") {
-                                $mergesections[] = 'user';
-                                $mergesections[] = 'group';
-                         }
-                         if ($carp['synchronizednsforwarder'] != "" and is_array($config['dnsmasq']))
-                                $sections[] = 'dnsmasq';
-                         if ($carp['synchronizeschedules'] != "" and is_array($config['schedules']))
-                                $sections[] = 'schedules';
-                         if (count($sections) > 0) {
-                                update_filter_reload_status("Signaling CARP reload signal...");
-                                carp_sync_xml($synchronizetoip, $carp['password'], $sections, $port);
-				if (is_array($mergesections))
-					carp_sync_xml($synchronizetoip, $carp['password'], $mergesections, $port, 'pfsense.merge_config_section');
-                                $cli = new XML_RPC_Client('/xmlrpc.php', $synchronizetoip, $port);
-				$params = array(
-					XML_RPC_encode($carp['password'])
-				);
+		   /*
+			* 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 ($config['system']['webgui']['protocol'] != "") {
+			$synchronizetoip = $config['system']['webgui']['protocol'];
+			$synchronizetoip .= "://";
+		}
 
-                                $msg = new XML_RPC_Message('pfsense.filter_configure', $params);
-                                $username = $config['system']['user'][0]['name'];
-                                $cli->setCredentials($username, $carp['password']);
-                                $resp = $cli->send($msg, "900");
+		/* if port is empty lets rely on the protocol selection */
+		$port = $config['system']['webgui']['port'];
+		if ($port == "") {
+			if ($config['system']['webgui']['protocol'] == "http")
+				$port = "80";
+			else
+				$port = "443";
+		}
 
-				if(!$resp) {
-					$error = "A communications error occured 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;
-				}
-                         }
-			 break;
-                }
-        }
+		$synchronizetoip .= $carp['synchronizetoip'];
+		if ($carp['synchronizerules'] != "" and is_array($config['filter']))
+			$sections[] = 'filter';
+		if ($carp['synchronizenat'] != "" and is_array($config['nat']))
+			$sections[] = 'nat';
+		if ($carp['synchronizealiases'] != "" and is_array($config['aliases']))
+			$sections[] = 'aliases';
+		if ($carp['synchronizedhcpd'] != "" and is_array($config['dhcpd']))
+			$sections[] = 'dhcpd';
+		if ($carp['synchronizewol'] != "" and is_array($config['wol']))
+			$sections[] = 'wol';
+		if ($carp['synchronizetrafficshaper'] != "" and is_array($config['shaper']))
+			$sections[] = 'shaper';
+		if ($carp['synchronizestaticroutes'] != "" and is_array($config['staticroutes'])) {
+			$sections[] = 'staticroutes';
+			$sections[] = 'gateways';
+		}
+		if ($carp['synchronizevirtualip'] != "" and is_array($config['virtualip']))
+			$sections[] = 'virtualip';
+		if ($carp['synchronizelb'] != "" and is_array($config['load_balancer']))
+			$sections[] = 'load_balancer';
+		if ($carp['synchronizeipsec'] != "" and is_array($config['ipsec']))
+			$sections[] = 'ipsec';
+		if ($carp['synchronizeopenvpn'] != "" and is_array($config['openvpn'])) {
+			$sections[] = 'openvpn';
+			$mergesections[] = 'cert';
+			$mergesections[] = 'ca';
+		}
+		if ($carp['synchronizeusers'] != "") {
+			$mergesections[] = 'user';
+			$mergesections[] = 'group';
+		} 
+		if ($carp['synchronizednsforwarder'] != "" and is_array($config['dnsmasq']))
+			$sections[] = 'dnsmasq';
+		if ($carp['synchronizeschedules'] != "" and is_array($config['schedules']))
+			$sections[] = 'schedules';
+		if ($carp['synchronizecaptiveportal'] != "" and is_array($config['captiveportal']))
+			$sections[] = 'captiveportal';
+		if ($carp['synchronizecaptiveportal'] != "" and is_array($config['vouchers']))
+			$sections[] = 'vouchers';
+		if (count($sections) > 0) {
+			update_filter_reload_status("Signaling CARP reload signal...");
+			carp_sync_xml($synchronizetoip, $carp['password'], $sections, $port);
+			if (is_array($mergesections))
+				carp_sync_xml($synchronizetoip, $carp['password'], $mergesections, $port, 'pfsense.merge_config_section');
+			$cli = new XML_RPC_Client('/xmlrpc.php', $synchronizetoip, $port);
+			$params = array(
+				XML_RPC_encode($carp['password'])
+			);
+
+			$msg = new XML_RPC_Message('pfsense.filter_configure', $params);
+			$username = $config['system']['user'][0]['name'];
+			$cli->setCredentials($username, $carp['password']);
+			$resp = $cli->send($msg, "900");
+
+			if(!$resp) {
+				$error = "A communications error occured 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;
+			}
+		}
+		break;
+		}
+	}
 }
 
-?>
+?>
\ No newline at end of file
diff --git a/usr/local/pkg/carp_settings.xml b/usr/local/pkg/carp_settings.xml
index 170609f8e9..de0d226ba9 100644
--- a/usr/local/pkg/carp_settings.xml
+++ b/usr/local/pkg/carp_settings.xml
@@ -160,6 +160,12 @@
 			<description>When this option is enabled, this system will automatically sync the DNS Forwarder configuration to the other CARP host when changes are made.</description>
 			<type>checkbox</type>
 		</field>
+		<field>
+			<fielddescr>Synchronize Captive Portal</fielddescr>
+			<fieldname>synchronizecaptiveportal</fieldname>
+			<description>When this option is enabled, this system will automatically sync the Captive Portal configuration to the other CARP host when changes are made.</description>
+			<type>checkbox</type>
+		</field>
 		<field>
 			<fielddescr>Synchronize to IP</fielddescr>
 			<fieldname>synchronizetoip</fieldname>
