Project

General

Profile

« Previous | Next » 

Revision dff71b6b

Added by Scott Ullrich almost 15 years ago

Add Captive Portal CARP configuration synchronization

View differences:

etc/rc.filter_synchronize
48 48
 *                                   the configuration section
49 49
 */
50 50
function backup_vip_config_section() {
51
        global $config;
52
        $new_section = &$config['virtualip'];
53
        foreach($new_section['vip'] as $section) {
54
                if($section['mode'] == "proxyarp") {
55
                        unset($section);
56
                }
57
                if($section['advskew'] <> "") {
58
                        $section_val = intval($section['advskew']);
59
                        $section_val=$section_val+100;
60
                        if($section_val > 255)
61
                                $section_val = 255;
62
                        $section['advskew'] = $section_val;
63
                }
64
                $temp['vip'][] = $section;
65
   }
66
   return $temp;
51
	global $config;
52
	$new_section = &$config['virtualip'];
53
	foreach($new_section['vip'] as $section) {
54
		if($section['mode'] == "proxyarp") {
55
			unset($section);
56
		}
57
		if($section['advskew'] <> "") {
58
			$section_val = intval($section['advskew']);
59
			$section_val=$section_val+100;
60
			if($section_val > 255)
61
				$section_val = 255;
62
			$section['advskew'] = $section_val;
63
		}
64
		$temp['vip'][] = $section;
65
	}
66
	return $temp;
67 67
}
68 68

  
69 69
function remove_special_characters($string) {
70
        $match_array = "";
71
        preg_match_all("/[a-zA-Z0-9\_\-]+/",$string,$match_array);
72
        $string = "";
73
        foreach ($match_array[0] as $ma) {
74
                if ($string <> "")
75
                        $string .= " ";
76
                $string .= $ma;
77
        }
78
        return $string;
70
	$match_array = "";
71
	preg_match_all("/[a-zA-Z0-9\_\-]+/",$string,$match_array);
72
	$string = "";
73
	foreach ($match_array[0] as $ma) {
74
		if ($string <> "")
75
			$string .= " ";
76
		$string .= $ma;
77
	}
78
	return $string;
79 79
}
80 80

  
81 81
function carp_sync_xml($url, $password, $sections, $port = 80, $method = 'pfsense.restore_config_section') {
82
        global $config, $g;
82
	global $config, $g;
83 83

  
84
        if(file_exists("{$g['varrun_path']}/booting"))
85
                return;
84
	if(file_exists("{$g['varrun_path']}/booting"))
85
		return;
86 86

  
87
        update_filter_reload_status("Syncing CARP data to {$url}");
87
	update_filter_reload_status("Syncing CARP data to {$url}");
88 88

  
89
        /* make a copy of config */
90
        $config_copy = $config;
89
	/* make a copy of config */
90
	$config_copy = $config;
91 91

  
92
        /* strip out nosync items */
93
        if (is_array($config_copy['nat']['advancedoutbound']['rule'])) {
94
		$rulescnt = count($config_copy['nat']['advancedoutbound']['rule']);
95
        	for ($x = 0; $x < $rulescnt; $x++) {
96
                	$config_copy['nat']['advancedoutbound']['rule'][$x]['descr'] = remove_special_characters($config_copy['nat']['advancedoutbound']['rule'][$x]['descr']);
97
                	if (isset ($config_copy['nat']['advancedoutbound']['rule'][$x]['nosync']))
98
                        	unset ($config_copy['nat']['advancedoutbound']['rule'][$x]);
99
        	}
92
	/* strip out nosync items */
93
	if (is_array($config_copy['nat']['advancedoutbound']['rule'])) {
94
	$rulescnt = count($config_copy['nat']['advancedoutbound']['rule']);
95
	for ($x = 0; $x < $rulescnt; $x++) {
96
		$config_copy['nat']['advancedoutbound']['rule'][$x]['descr'] = remove_special_characters($config_copy['nat']['advancedoutbound']['rule'][$x]['descr']);
97
		if (isset ($config_copy['nat']['advancedoutbound']['rule'][$x]['nosync']))
98
			unset ($config_copy['nat']['advancedoutbound']['rule'][$x]);
100 99
		}
101
        if (is_array($config_copy['nat']['rule'])) {
100
	}
101
	if (is_array($config_copy['nat']['rule'])) {
102 102
		$natcnt = count($config_copy['nat']['rule']);
103
        	for ($x = 0; $x < $natcnt; $x++) {
104
                	$config_copy['nat']['rule'][$x]['descr'] = remove_special_characters($config_copy['nat']['rule'][$x]['descr']);
105
                	if (isset ($config_copy['nat']['rule'][$x]['nosync']))
106
                        	unset ($config_copy['nat']['rule'][$x]);
103
		for ($x = 0; $x < $natcnt; $x++) {
104
			$config_copy['nat']['rule'][$x]['descr'] = remove_special_characters($config_copy['nat']['rule'][$x]['descr']);
105
			if (isset ($config_copy['nat']['rule'][$x]['nosync']))
106
				unset ($config_copy['nat']['rule'][$x]);
107 107
		}
108
        }
109
        if (is_array($config_copy['filter']['rule'])) {
108
	}
109
	if (is_array($config_copy['filter']['rule'])) {
110 110
		$filtercnt = count($config_copy['filter']['rule']);
111
        	for ($x = 0; $x < $filtercnt; $x++) {
112
                	$config_copy['filter']['rule'][$x]['descr'] = remove_special_characters($config_copy['filter']['rule'][$x]['descr']);
113
                	if (isset ($config_copy['filter']['rule'][$x]['nosync']))
114
                        	unset ($config_copy['filter']['rule'][$x]);
111
		for ($x = 0; $x < $filtercnt; $x++) {
112
			$config_copy['filter']['rule'][$x]['descr'] = remove_special_characters($config_copy['filter']['rule'][$x]['descr']);
113
			if (isset ($config_copy['filter']['rule'][$x]['nosync']))
114
				unset ($config_copy['filter']['rule'][$x]);
115 115
		}
116
        }
117
        if (is_array($config_copy['aliases']['alias'])) {
116
	}
117
	if (is_array($config_copy['aliases']['alias'])) {
118 118
		$aliascnt = count($config_copy['aliases']['alias']);
119
        	for ($x = 0; $x < $aliascnt; $x++) {
120
                	$config_copy['aliases']['alias'][$x]['descr'] = remove_special_characters($config_copy['aliases']['alias'][$x]['descr']);
121
                	if (isset ($config_copy['aliases']['alias'][$x]['nosync']))
122
                        	unset ($config_copy['aliases']['alias'][$x]);
123
        	}
119
		for ($x = 0; $x < $aliascnt; $x++) {
120
			$config_copy['aliases']['alias'][$x]['descr'] = remove_special_characters($config_copy['aliases']['alias'][$x]['descr']);
121
			if (isset ($config_copy['aliases']['alias'][$x]['nosync']))
122
				unset ($config_copy['aliases']['alias'][$x]);
124 123
		}
125
        if (is_array($config_copy['dnsmasq']['hosts'])) {
124
	}
125
	if (is_array($config_copy['dnsmasq']['hosts'])) {
126 126
		$dnscnt = count($config_copy['dnsmasq']['hosts']);
127
        	for ($x = 0; $x < $dnscnt; $x++) {
128
                	$config_copy['dnsmasq']['hosts'][$x]['descr'] = remove_special_characters($config_copy['dnsmasq']['hosts'][$x]['descr']);
129
                	if (isset ($config_copy['dnsmasq']['hosts'][$x]['nosync']))
130
                        	unset ($config_copy['dnsmasq']['hosts'][$x]);
131
        	}
127
		for ($x = 0; $x < $dnscnt; $x++) {
128
			$config_copy['dnsmasq']['hosts'][$x]['descr'] = remove_special_characters($config_copy['dnsmasq']['hosts'][$x]['descr']);
129
			if (isset ($config_copy['dnsmasq']['hosts'][$x]['nosync']))
130
				unset ($config_copy['dnsmasq']['hosts'][$x]);
132 131
		}
133
        if (is_array($config_copy['virtualip']['vip'])) {
132
	}
133
	if (is_array($config_copy['virtualip']['vip'])) {
134 134
		$vipcnt = count($config_copy['virtualip']['vip']);
135
        	for ($x = 0; $x < $vipcnt; $x++) {
136
                	$config_copy['virtualip']['vip'][$x]['descr'] = remove_special_characters($config_copy['virtualip']['vip'][$x]['descr']);
137
                	if (isset ($config_copy['virtualip']['vip'][$x]['nosync']) or $config_copy['virtualip']['vip'][$x]['mode'] == "proxyarp")
138
                        	unset ($config_copy['virtualip']['vip'][$x]);
139
        	}
135
		for ($x = 0; $x < $vipcnt; $x++) {
136
			$config_copy['virtualip']['vip'][$x]['descr'] = remove_special_characters($config_copy['virtualip']['vip'][$x]['descr']);
137
			if (isset ($config_copy['virtualip']['vip'][$x]['nosync']) or $config_copy['virtualip']['vip'][$x]['mode'] == "proxyarp")
138
				unset ($config_copy['virtualip']['vip'][$x]);
140 139
		}
141
        if (is_array($config_copy['ipsec']['tunnel'])) {
140
	}
141
	if (is_array($config_copy['ipsec']['tunnel'])) {
142 142
		$ipseccnt = count($config_copy['ipsec']['tunnel']);
143
        	for ($x = 0; $x < $ipseccnt; $x++) {
144
                	$config_copy['ipsec']['tunnel'][$x]['descr'] = remove_special_characters($config_copy['ipsec']['tunnel'][$x]['descr']);
145
                	if (isset ($config_copy['ipsec']['tunnel'][$x]['nosync']))
146
                        	unset ($config_copy['ipsec']['tunnel'][$x]);
147
        	}
143
		for ($x = 0; $x < $ipseccnt; $x++) {
144
			$config_copy['ipsec']['tunnel'][$x]['descr'] = remove_special_characters($config_copy['ipsec']['tunnel'][$x]['descr']);
145
			if (isset ($config_copy['ipsec']['tunnel'][$x]['nosync']))
146
				unset ($config_copy['ipsec']['tunnel'][$x]);
148 147
		}
148
	}
149 149

  
150 150
	if (is_array($config_copy['dhcpd'])) {
151 151
		foreach($config_copy['dhcpd'] as $dhcpif => $dhcpifconf) {
......
157 157
		}
158 158
	}
159 159

  
160
        foreach ($sections as $section) {
161
                /*  we can't use array_intersect_key()
162
                 *  due to the vip 'special case'
163
                 */
160
	foreach ($sections as $section) {
161
	   /*  we can't use array_intersect_key()
162
		*  due to the vip 'special case'
163
		*/
164 164
		switch ($section) {
165 165
			case 'virtualip':
166 166
				$xml[$section] = backup_vip_config_section();
......
174 174
			default:
175 175
				$xml[$section] = $config_copy[$section];
176 176
		}
177
        }
177
	}
178 178

  
179
        $params = array(
180
                XML_RPC_encode($password),
181
                XML_RPC_encode($xml)
182
        );
179
	$params = array(
180
		XML_RPC_encode($password),
181
		XML_RPC_encode($xml)
182
	);
183 183

  
184
        $numberofruns = 0;
185
        while ($numberofruns < 2) {
186
                log_error("Beginning XMLRPC sync to {$url}:{$port}.");
187
                $msg = new XML_RPC_Message($method, $params);
188
                $cli = new XML_RPC_Client('/xmlrpc.php', $url, $port);
189
                $username = $config['system']['user'][0]['name'];
190
                $cli->setCredentials($username, $password);
191
                if($numberofruns > 1)
192
                        $cli->setDebug(1);
193
                /* send our XMLRPC message and timeout after 240 seconds */
194
                $resp = $cli->send($msg, "240");
195
				if($resp->faultCode()) {
196
					$error = "A communications error occurred while attempting communication with {$url}:{$port} (pfsense.exec_php).";
197
					log_error($error);
198
					return;	
199
				}
200
                if(!$resp) {
201
                        $error = "A communications error occured while attempting XMLRPC sync with username {$username} {$url}:{$port}.";
202
                        log_error($error);
203
                        file_notice("sync_settings", $error, "Settings Sync", "");
204
                } elseif($resp->faultCode()) {
205
                        $error = "An error code was received while attempting XMLRPC sync with username {$username} {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString();
206
                        log_error($error);
207
                        file_notice("sync_settings", $error, "Settings Sync", "");
208
                } else {
209
                        log_error("XMLRPC sync successfully completed with {$url}:{$port}.");
210
                        $numberofruns = 3;
211
                }
212
				$parsed_response =  XML_RPC_Decode($resp->value());
213
				if(!is_array($firewall_info) && trim($firewall_info) == "Authentication failed") {
214
					$error = "A authentication failure occurred while trying to access {$url}:{$port} (pfsense.exec_php).";
215
					log_error($error);
216
					$numberofruns = 5;
217
				}
218
                $numberofruns++;
219
        }
184
	$numberofruns = 0;
185
	while ($numberofruns < 2) {
186
		log_error("Beginning XMLRPC sync to {$url}:{$port}.");
187
		$msg = new XML_RPC_Message($method, $params);
188
		$cli = new XML_RPC_Client('/xmlrpc.php', $url, $port);
189
		$username = $config['system']['user'][0]['name'];
190
		$cli->setCredentials($username, $password);
191
		if($numberofruns > 1)
192
			$cli->setDebug(1);
193
		/* send our XMLRPC message and timeout after 240 seconds */
194
		$resp = $cli->send($msg, "240");
195
		if($resp->faultCode()) {
196
			$error = "A communications error occurred while attempting communication with {$url}:{$port} (pfsense.exec_php).";
197
			log_error($error);
198
			return;	
199
		}
200
		if(!$resp) {
201
			$error = "A communications error occured while attempting XMLRPC sync with username {$username} {$url}:{$port}.";
202
			log_error($error);
203
			file_notice("sync_settings", $error, "Settings Sync", "");
204
		} elseif($resp->faultCode()) {
205
			$error = "An error code was received while attempting XMLRPC sync with username {$username} {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString();
206
			log_error($error);
207
			file_notice("sync_settings", $error, "Settings Sync", "");
208
		} else {
209
			log_error("XMLRPC sync successfully completed with {$url}:{$port}.");
210
			$numberofruns = 3;
211
		}
212
		$parsed_response =  XML_RPC_Decode($resp->value());
213
		if(!is_array($firewall_info) && trim($firewall_info) == "Authentication failed") {
214
			$error = "A authentication failure occurred while trying to access {$url}:{$port} (pfsense.exec_php).";
215
			log_error($error);
216
			$numberofruns = 5;
217
		}
218
		$numberofruns++;
219
	}
220 220
}
221 221

  
222 222
global $g;
......
227 227
	update_filter_reload_status("Building CARP sync information");
228 228
	foreach($config['installedpackages']['carpsettings']['config'] as $carp) {
229 229
		if ($carp['synchronizetoip'] != "" ) {
230
			/*
231
                         * XXX: The way we're finding the port right now is really suboptimal -
232
                         *              we can't assume that the other machine is setup identically.
233
                         */
234
                         if ($config['system']['webgui']['protocol'] != "") {
235
                         	$synchronizetoip = $config['system']['webgui']['protocol'];
236
                                $synchronizetoip .= "://";
237
                         }
238
                         $port = $config['system']['webgui']['port'];
239
                         /* if port is empty lets rely on the protocol selection */
240
                         if ($port == "") {
241
                         	if ($config['system']['webgui']['protocol'] == "http")
242
                                	$port = "80";
243
                                else
244
                                	$port = "443";
245
                         }
246
                         $synchronizetoip .= $carp['synchronizetoip'];
247
                         if ($carp['synchronizerules'] != "" and is_array($config['filter']))
248
                         	$sections[] = 'filter';
249
                         if ($carp['synchronizenat'] != "" and is_array($config['nat']))
250
                         	$sections[] = 'nat';
251
                         if ($carp['synchronizealiases'] != "" and is_array($config['aliases']))
252
                         	$sections[] = 'aliases';
253
                         if ($carp['synchronizedhcpd'] != "" and is_array($config['dhcpd']))
254
                                $sections[] = 'dhcpd';
255
                         if ($carp['synchronizewol'] != "" and is_array($config['wol']))
256
                                $sections[] = 'wol';
257
                         if ($carp['synchronizetrafficshaper'] != "" and is_array($config['shaper']))
258
                                $sections[] = 'shaper';
259
                         if ($carp['synchronizestaticroutes'] != "" and is_array($config['staticroutes'])) {
260
                                $sections[] = 'staticroutes';
261
                                $sections[] = 'gateways';
262
                         }
263
                         if ($carp['synchronizevirtualip'] != "" and is_array($config['virtualip']))
264
                                $sections[] = 'virtualip';
265
                         if ($carp['synchronizelb'] != "" and is_array($config['load_balancer']))
266
                                $sections[] = 'load_balancer';
267
                         if ($carp['synchronizeipsec'] != "" and is_array($config['ipsec']))
268
                                $sections[] = 'ipsec';
269
                         if ($carp['synchronizeopenvpn'] != "" and is_array($config['openvpn'])) {
270
                                $sections[] = 'openvpn';
271
                                $mergesections[] = 'cert';
272
                                $mergesections[] = 'ca';
273
                         }
274
                         if ($carp['synchronizeusers'] != "") {
275
                                $mergesections[] = 'user';
276
                                $mergesections[] = 'group';
277
                         }
278
                         if ($carp['synchronizednsforwarder'] != "" and is_array($config['dnsmasq']))
279
                                $sections[] = 'dnsmasq';
280
                         if ($carp['synchronizeschedules'] != "" and is_array($config['schedules']))
281
                                $sections[] = 'schedules';
282
                         if (count($sections) > 0) {
283
                                update_filter_reload_status("Signaling CARP reload signal...");
284
                                carp_sync_xml($synchronizetoip, $carp['password'], $sections, $port);
285
				if (is_array($mergesections))
286
					carp_sync_xml($synchronizetoip, $carp['password'], $mergesections, $port, 'pfsense.merge_config_section');
287
                                $cli = new XML_RPC_Client('/xmlrpc.php', $synchronizetoip, $port);
288
				$params = array(
289
					XML_RPC_encode($carp['password'])
290
				);
230
		   /*
231
			* XXX: The way we're finding the port right now is really suboptimal -
232
			*              we can't assume that the other machine is setup identically.
233
			*/
234
		if ($config['system']['webgui']['protocol'] != "") {
235
			$synchronizetoip = $config['system']['webgui']['protocol'];
236
			$synchronizetoip .= "://";
237
		}
291 238

  
292
                                $msg = new XML_RPC_Message('pfsense.filter_configure', $params);
293
                                $username = $config['system']['user'][0]['name'];
294
                                $cli->setCredentials($username, $carp['password']);
295
                                $resp = $cli->send($msg, "900");
239
		/* if port is empty lets rely on the protocol selection */
240
		$port = $config['system']['webgui']['port'];
241
		if ($port == "") {
242
			if ($config['system']['webgui']['protocol'] == "http")
243
				$port = "80";
244
			else
245
				$port = "443";
246
		}
296 247

  
297
				if(!$resp) {
298
					$error = "A communications error occured while attempting Filter sync with username {$username} {$synchronizetoip}:{$port}.";
299
					log_error($error);
300
					file_notice("sync_settings", $error, "Settings Sync", "");
301
				} elseif($resp->faultCode()) {
302
					$error = "An error code was received while attempting Filter sync with username {$username} {$synchronizetoip}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString();
303
					log_error($error);
304
					file_notice("sync_settings", $error, "Settings Sync", "");
305
				} else {
306
					log_error("Filter sync successfully completed with {$synchronizetoip}:{$port}.");
307
					$numberofruns = 3;
308
				}
309
                         }
310
			 break;
311
                }
312
        }
248
		$synchronizetoip .= $carp['synchronizetoip'];
249
		if ($carp['synchronizerules'] != "" and is_array($config['filter']))
250
			$sections[] = 'filter';
251
		if ($carp['synchronizenat'] != "" and is_array($config['nat']))
252
			$sections[] = 'nat';
253
		if ($carp['synchronizealiases'] != "" and is_array($config['aliases']))
254
			$sections[] = 'aliases';
255
		if ($carp['synchronizedhcpd'] != "" and is_array($config['dhcpd']))
256
			$sections[] = 'dhcpd';
257
		if ($carp['synchronizewol'] != "" and is_array($config['wol']))
258
			$sections[] = 'wol';
259
		if ($carp['synchronizetrafficshaper'] != "" and is_array($config['shaper']))
260
			$sections[] = 'shaper';
261
		if ($carp['synchronizestaticroutes'] != "" and is_array($config['staticroutes'])) {
262
			$sections[] = 'staticroutes';
263
			$sections[] = 'gateways';
264
		}
265
		if ($carp['synchronizevirtualip'] != "" and is_array($config['virtualip']))
266
			$sections[] = 'virtualip';
267
		if ($carp['synchronizelb'] != "" and is_array($config['load_balancer']))
268
			$sections[] = 'load_balancer';
269
		if ($carp['synchronizeipsec'] != "" and is_array($config['ipsec']))
270
			$sections[] = 'ipsec';
271
		if ($carp['synchronizeopenvpn'] != "" and is_array($config['openvpn'])) {
272
			$sections[] = 'openvpn';
273
			$mergesections[] = 'cert';
274
			$mergesections[] = 'ca';
275
		}
276
		if ($carp['synchronizeusers'] != "") {
277
			$mergesections[] = 'user';
278
			$mergesections[] = 'group';
279
		} 
280
		if ($carp['synchronizednsforwarder'] != "" and is_array($config['dnsmasq']))
281
			$sections[] = 'dnsmasq';
282
		if ($carp['synchronizeschedules'] != "" and is_array($config['schedules']))
283
			$sections[] = 'schedules';
284
		if ($carp['synchronizecaptiveportal'] != "" and is_array($config['captiveportal']))
285
			$sections[] = 'captiveportal';
286
		if ($carp['synchronizecaptiveportal'] != "" and is_array($config['vouchers']))
287
			$sections[] = 'vouchers';
288
		if (count($sections) > 0) {
289
			update_filter_reload_status("Signaling CARP reload signal...");
290
			carp_sync_xml($synchronizetoip, $carp['password'], $sections, $port);
291
			if (is_array($mergesections))
292
				carp_sync_xml($synchronizetoip, $carp['password'], $mergesections, $port, 'pfsense.merge_config_section');
293
			$cli = new XML_RPC_Client('/xmlrpc.php', $synchronizetoip, $port);
294
			$params = array(
295
				XML_RPC_encode($carp['password'])
296
			);
297

  
298
			$msg = new XML_RPC_Message('pfsense.filter_configure', $params);
299
			$username = $config['system']['user'][0]['name'];
300
			$cli->setCredentials($username, $carp['password']);
301
			$resp = $cli->send($msg, "900");
302

  
303
			if(!$resp) {
304
				$error = "A communications error occured while attempting Filter sync with username {$username} {$synchronizetoip}:{$port}.";
305
				log_error($error);
306
				file_notice("sync_settings", $error, "Settings Sync", "");
307
			} elseif($resp->faultCode()) {
308
				$error = "An error code was received while attempting Filter sync with username {$username} {$synchronizetoip}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString();
309
				log_error($error);
310
				file_notice("sync_settings", $error, "Settings Sync", "");
311
			} else {
312
				log_error("Filter sync successfully completed with {$synchronizetoip}:{$port}.");
313
				$numberofruns = 3;
314
			}
315
		}
316
		break;
317
		}
318
	}
313 319
}
314 320

  
315
?>
321
?>
usr/local/pkg/carp_settings.xml
160 160
			<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>
161 161
			<type>checkbox</type>
162 162
		</field>
163
		<field>
164
			<fielddescr>Synchronize Captive Portal</fielddescr>
165
			<fieldname>synchronizecaptiveportal</fieldname>
166
			<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>
167
			<type>checkbox</type>
168
		</field>
163 169
		<field>
164 170
			<fielddescr>Synchronize to IP</fielddescr>
165 171
			<fieldname>synchronizetoip</fieldname>

Also available in: Unified diff