Project

General

Profile

Download (14.5 KB) Statistics
| Branch: | Tag: | Revision:
1 3ad6d3bb Bill Marquette
<?php
2 577c9191 Bill Marquette
/* $Id$ */
3 3ad6d3bb Bill Marquette
/*
4 17623ab5 Bill Marquette
  vslb.inc
5
  Copyright (C) 2005-2008 Bill Marquette
6
  All rights reserved.
7 3ad6d3bb Bill Marquette
8 17623ab5 Bill Marquette
  Redistribution and use in source and binary forms, with or without
9
  modification, are permitted provided that the following conditions are met:
10 3ad6d3bb Bill Marquette
11 17623ab5 Bill Marquette
  1. Redistributions of source code must retain the above copyright notice,
12
  this list of conditions and the following disclaimer.
13 3ad6d3bb Bill Marquette
14 17623ab5 Bill Marquette
  2. Redistributions in binary form must reproduce the above copyright
15
  notice, this list of conditions and the following disclaimer in the
16
  documentation and/or other materials provided with the distribution.
17 3ad6d3bb Bill Marquette
18 17623ab5 Bill Marquette
  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
19
  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
20
  AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
21
  AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
22
  OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
  POSSIBILITY OF SUCH DAMAGE.
28 3ad6d3bb Bill Marquette
29 17623ab5 Bill Marquette
 */
30 3ad6d3bb Bill Marquette
31 523855b0 Scott Ullrich
/*
32
	pfSense_BUILDER_BINARIES:	/usr/local/sbin/relayd
33
	pfSense_MODULE:	routing
34
*/
35
36 50d86c13 Bill Marquette
/* DISABLE_PHP_LINT_CHECKING */
37
38 3ad6d3bb Bill Marquette
/* include all configuration functions */
39
40 50d86c13 Bill Marquette
class Monitor {
41
	private $conf = array();
42
	function __construct($config) {
43
		$this->conf = $config;
44
	}
45
46
	public function p() {
47
		return "check {$this->get('proto')}";
48
	}
49
	private function get($var) {
50
		return isset($this->$var) ? $this->$var : "";
51
	}
52
	protected function config($element) {
53
		return isset($this->conf[$element]) ? $this->conf[$element] : "";
54
	}
55
}
56
57
class TCPMonitor extends Monitor {
58
	protected $proto = 'tcp';
59
}
60
61
class SSLMonitor extends Monitor {
62
	protected $proto = 'ssl';
63
}
64
65
class ICMPMonitor extends Monitor {
66
	protected $proto = 'icmp';
67
}
68
69
class HTTPMonitor extends Monitor {
70
	protected $proto = 'http';
71
	function __construct($config) {
72
		parent::__construct($config);
73
	}
74
	public function p() {
75
		$method = ($this->code() != "") ? $this->code() : $this->digest();
76
		return "check {$this->proto} {$this->path()} {$this->host()} {$method}";
77
	}
78
79
	private function path() {
80
		return $this->config('path') != "" ? "'{$this->config('path')}'" : "";
81
	}
82
83
	private function host() {
84
		return $this->config('host') != "" ? "host {$this->config('host')}" : "";
85
	}
86
87
	private function code() {
88
		return $this->config('code') != "" ? "code {$this->config('code')}" : "";
89
	}
90
91
	private function digest() {
92
		return $this->config('digest') != "" ? "digest {$this->config('digest')}" : "";
93
	}
94
}
95
96
class HTTPSMonitor extends HTTPMonitor {
97
	protected $proto = 'https';
98
}
99
100
class SendMonitor extends Monitor {
101
	private $proto = 'send';
102
	function __construct($config) {
103
		parent::__construct($config);
104
	}
105
	public function p() {
106
		return "check {$this->proto} {$this->data()} expect {$this->pattern()} {$this->ssl()}";
107
	}
108
109
110
	private function data() {
111 146a1717 jim-p
		return $this->config('send') != "" ? "\"{$this->config('send')}\"" : "\"\"";
112 50d86c13 Bill Marquette
	}
113
114
	private function pattern() {
115 146a1717 jim-p
		return $this->config('expect') != "" ? "\"{$this->config('expect')}\"" : "\"\"";
116 50d86c13 Bill Marquette
	}
117
118
	private function ssl() {
119
		return $this->config('ssl') == true ? "ssl" : "";
120
	}
121
}
122
123 0919224f Bill Marquette
function echo_lbaction($action) {
124 939b2d75 Darren Embry
	global $config;
125 0919224f Bill Marquette
  
126 939b2d75 Darren Embry
	// Index actions by name
127
	$actions_a = array();
128
	for ($i=0; isset($config['load_balancer']['lbaction'][$i]); $i++)
129 0919224f Bill Marquette
		$actions_a[$config['load_balancer']['lbaction'][$i]['name']] = $config['load_balancer']['lbaction'][$i];
130
131 939b2d75 Darren Embry
	$ret = "";
132
	$ret .=  "{$actions_a[$action]['direction']} {$actions_a[$action]['type']} {$actions_a[$action]['action']}";
133
	switch($actions_a[$action]['action']) {
134 9859b2b5 Darren Embry
	case 'append':
135 939b2d75 Darren Embry
		$ret .= " \"{$actions_a[$action]['options']['value']}\" to \"{$actions_a[$action]['options']['akey']}\"";
136
		break;
137 9859b2b5 Darren Embry
	case 'change':
138 939b2d75 Darren Embry
		$ret .= " \"{$actions_a[$action]['options']['akey']}\" to \"{$actions_a[$action]['options']['value']}\"";
139
		break;
140 9859b2b5 Darren Embry
	case 'expect':
141 939b2d75 Darren Embry
		$ret .= " \"{$actions_a[$action]['options']['value']}\" from \"{$actions_a[$action]['options']['akey']}\"";
142
		break;
143 9859b2b5 Darren Embry
	case 'filter':
144 939b2d75 Darren Embry
		$ret .= " \"{$actions_a[$action]['options']['value']}\" from \"{$actions_a[$action]['options']['akey']}\"";
145
		break;
146 9859b2b5 Darren Embry
	case 'hash':
147 939b2d75 Darren Embry
		$ret .= " \"{$actions_a[$action]['options']['akey']}\"";
148
		break;
149 9859b2b5 Darren Embry
	case 'log':
150 939b2d75 Darren Embry
		$ret .= " \"{$actions_a[$action]['options']['akey']}\"";
151
		break;
152
	}
153
	return $ret;
154 0919224f Bill Marquette
}
155 50d86c13 Bill Marquette
156 d3534235 jim-p
function relayd_configure($kill_first=false) {
157 939b2d75 Darren Embry
	global $config, $g;
158
159 d7afd900 Darren Embry
	require_once("filter.inc");
160
161 939b2d75 Darren Embry
	$vs_a = $config['load_balancer']['virtual_server'];
162
	$pool_a = $config['load_balancer']['lbpool'];
163
	$protocol_a = $config['load_balancer']['lbprotocol'];
164
	$setting = $config['load_balancer']['setting'];
165
166
	$check_a = array();
167 50d86c13 Bill Marquette
168 939b2d75 Darren Embry
	foreach ((array)$config['load_balancer']['monitor_type'] as $type) {
169
		switch($type['type']) {
170 9859b2b5 Darren Embry
		case 'icmp':
171 939b2d75 Darren Embry
			$mon = new ICMPMonitor($type['options']);
172
			break;
173 9859b2b5 Darren Embry
		case 'tcp':
174 939b2d75 Darren Embry
			$mon = new TCPMonitor($type['options']);
175
			break;
176 9859b2b5 Darren Embry
		case 'http':
177 939b2d75 Darren Embry
			$mon = new HTTPMonitor($type['options']);
178
			break;
179 9859b2b5 Darren Embry
		case 'https':
180 939b2d75 Darren Embry
			$mon = new HTTPSMonitor($type['options']);
181
			break;
182 9859b2b5 Darren Embry
		case 'send':
183 939b2d75 Darren Embry
			$mon = new SendMonitor($type['options']);
184
			break;
185
		}
186
		if($mon) {
187
			$check_a[$type['name']] = $mon->p();
188
		}
189
	}
190
	
191 206aa9fc Pierre POMES
  
192 939b2d75 Darren Embry
	$fd = fopen("{$g['varetc_path']}/relayd.conf", "w");
193
	$conf .= "log updates \n";
194
195
	/* Global timeout, interval and prefork settings
196
	   if not specified by the user:
197
	   - use a 1000 ms timeout value as in pfsense 2.0.1 and above
198
	   - leave interval and prefork empty, relayd will use its default values */
199
	
200
	if (isset($setting['timeout']) && !empty($setting['timeout'])) {
201
		$conf .= "timeout ".$setting['timeout']." \n";
202 74b7361f jim-p
	} else {
203 939b2d75 Darren Embry
		$conf .= "timeout 1000 \n";
204
	}
205
	
206
	if (isset($setting['interval']) && !empty($setting['interval'])) {
207
		$conf .= "interval ".$setting['interval']." \n";
208
	}
209
	
210
	if (isset($setting['prefork']) && !empty($setting['prefork'])) {
211
		$conf .= "prefork ".$setting['prefork']." \n";
212
	}
213
	
214
	/* reindex pools by name as we loop through the pools array */
215
	$pools = array();
216
	/* Virtual server pools */
217
	if(is_array($pool_a)) {
218
		for ($i = 0; isset($pool_a[$i]); $i++) {
219
			if(is_array($pool_a[$i]['servers'])) {
220
				if (!empty($pool_a[$i]['retry'])) {
221
					$retrytext = " retry {$pool_a[$i]['retry']}";
222
				} else {
223 0917cb21 Darren Embry
					$retrytext = "";
224 939b2d75 Darren Embry
				}
225 0917cb21 Darren Embry
				$conf .= "table <{$pool_a[$i]['name']}> {\n";
226
				foreach ($pool_a[$i]['servers'] as $server) {
227
					if (is_subnetv4($server)) {
228
						foreach (subnetv4_expand($server) as $ip) {
229
							$conf .= "\t{$ip}{$retrytext}\n";
230
						}
231
					}
232
					else {
233
						$conf .= "\t{$server}{$retrytext}\n";
234
					}
235
				}
236
				$conf .= "}\n";
237 939b2d75 Darren Embry
				/* Index by name for easier fetching when we loop through the virtual servers */
238
				$pools[$pool_a[$i]['name']] = $pool_a[$i];
239
			}
240
		}
241 74b7361f jim-p
	}
242 b6d74873 jim-p
//  if(is_array($protocol_a)) {
243
//    for ($i = 0; isset($protocol_a[$i]); $i++) {
244
//      $proto = "{$protocol_a[$i]['type']} protocol \"{$protocol_a[$i]['name']}\" {\n";
245
//      if(is_array($protocol_a[$i]['lbaction'])) {
246
//        if($protocol_a[$i]['lbaction'][0] == "") {
247
//          continue;
248
//        }
249
//        for ($a = 0; isset($protocol_a[$i]['lbaction'][$a]); $a++) {
250
//          $proto .= "  " . echo_lbaction($protocol_a[$i]['lbaction'][$a]) . "\n";
251
//        }
252
//      }
253
//      $proto .= "}\n";
254
//      $conf .= $proto;
255
//    }
256
//  }
257
258
	$conf .= "dns protocol \"dnsproto\" {\n";
259 0917cb21 Darren Embry
	$conf .= "\t" . "tcp { nodelay, sack, socket buffer 1024, backlog 1000 }\n";
260 b6d74873 jim-p
	$conf .= "}\n";
261
262 327ef8eb Warren Baker
	if(is_array($vs_a)) {
263 0130b756 Warren Baker
		for ($i = 0; isset($vs_a[$i]); $i++) {
264 01ed452e Darren Embry
			
265
			$append_port_to_name = false;
266
			if (is_alias($vs_a[$i]['port'])) {
267 d7afd900 Darren Embry
				$src_port_array = filter_expand_alias_array($vs_a[$i]['port']);
268 01ed452e Darren Embry
				$append_port_to_name = true;
269
			}
270
			else {
271
				$src_port_array = array($vs_a[$i]['port']);
272
			}
273
			if (is_alias($pools[$vs_a[$i]['pool']]['port'])) {
274 d7afd900 Darren Embry
				$dest_port_array = filter_expand_alias_array($pools[$vs_a[$i]['pool']]['port']);
275 01ed452e Darren Embry
				$append_port_to_name = true;
276
			}
277
			else {
278
				$dest_port_array = array($pools[$vs_a[$i]['pool']]['port']);
279
			}
280
281
			$append_ip_to_name = false;
282 0917cb21 Darren Embry
			if (is_subnetv4($vs_a[$i]['ipaddr'])) {
283
				$ip_list = subnetv4_expand($vs_a[$i]['ipaddr']);
284 01ed452e Darren Embry
				$append_ip_to_name = true;
285 0917cb21 Darren Embry
			}
286
			else {
287
				$ip_list = array($vs_a[$i]['ipaddr']);
288
			}
289 01ed452e Darren Embry
290 0917cb21 Darren Embry
			for ($j = 0; $j < count($ip_list); $j += 1) {
291
				$ip = $ip_list[$j];
292 01ed452e Darren Embry
				for ($k = 0; $k < count($src_port_array) && $k < count($dest_port_array); $k += 1) {
293
					$src_port  = $src_port_array[$k];
294
					$dest_port = $dest_port_array[$k];
295
296
					$name = $vs_a[$i]['name'];
297
					if ($append_ip_to_name) {
298
						$name .= "_" . $j;
299 0917cb21 Darren Embry
					}
300 01ed452e Darren Embry
					if ($append_port_to_name) {
301
						$name .= "_" . $src_port;
302 0917cb21 Darren Embry
					}
303
304 01ed452e Darren Embry
					if (($vs_a[$i]['mode'] == 'relay') || ($vs_a[$i]['relay_protocol'] == 'dns')) {
305
						$conf .= "relay \"{$name}\" {\n";
306
						$conf .= "  listen on {$ip} port {$src_port}\n";
307 0917cb21 Darren Embry
308 01ed452e Darren Embry
						if ($vs_a[$i]['relay_protocol'] == "dns") {
309
							$conf .= "  protocol \"dnsproto\"\n";
310
						} else {
311
							$conf .= "  protocol \"{$vs_a[$i]['relay_protocol']}\"\n";
312
						}
313
						$lbmode = "";
314
						if ( $pools[$vs_a[$i]['pool']]['mode'] == "loadbalance" ) {
315
							$lbmode = "mode loadbalance";
316
						}
317 0917cb21 Darren Embry
318 01ed452e Darren Embry
						$conf .= "  forward to <{$vs_a[$i]['pool']}> port {$dest_port} {$lbmode} {$check_a[$pools[$vs_a[$i]['pool']]['monitor']]} \n";
319 0917cb21 Darren Embry
320 01ed452e Darren Embry
						if (isset($vs_a[$i]['sitedown']) &&  strlen($vs_a[$i]['sitedown']) > 0)
321
							$conf .= "  forward to <{$vs_a[$i]['sitedown']}> port {$dest_port} {$lbmode} {$check_a[$pools[$vs_a[$i]['pool']]['monitor']]} \n";
322
						$conf .= "}\n";
323
					} else  {
324
						$conf .= "redirect \"{$name}\" {\n";
325
						$conf .= "  listen on {$ip} port {$src_port}\n";
326
						$conf .= "  forward to <{$vs_a[$i]['pool']}> port {$dest_port} {$check_a[$pools[$vs_a[$i]['pool']]['monitor']]} \n";
327 0917cb21 Darren Embry
328 01ed452e Darren Embry
						if (isset($config['system']['lb_use_sticky']))
329
							$conf .= "  sticky-address\n";
330
331
						/* sitedown MUST use the same port as the primary pool - sucks, but it's a relayd thing */
332
						if (isset($vs_a[$i]['sitedown']) && strlen($vs_a[$i]['sitedown']) > 0)
333
							$conf .= "  forward to <{$vs_a[$i]['sitedown']}> port {$dest_port} {$check_a[$pools[$vs_a[$i]['pool']]['monitor']]} \n";
334
335
						$conf .= "}\n";
336
					}
337 b6d74873 jim-p
				}
338 0130b756 Warren Baker
			}
339
		}
340
	}
341
	fwrite($fd, $conf);
342
	fclose($fd);
343
344
	if (is_process_running('relayd')) {
345
		if (! empty($vs_a)) {
346 d3534235 jim-p
			if ($kill_first) {
347
				mwexec('pkill relayd');
348
				mwexec("/usr/local/sbin/relayd -f {$g['varetc_path']}/relayd.conf");
349
			} else {
350
				// it's running and there is a config, just reload
351
				mwexec("/usr/local/sbin/relayctl reload");
352
			}
353 0130b756 Warren Baker
		} else {
354
			/*
355
			 * XXX: Something breaks our control connection with relayd
356
			 * and makes 'relayctl stop' not work
357
			 * rule reloads are the current suspect
358
			 * mwexec('/usr/local/sbin/relayctl stop');
359
			 *  returns "command failed"
360
			 */
361
			mwexec('pkill relayd');
362
		}
363 b1bd2119 Chris Buechler
	} else {
364 0130b756 Warren Baker
		if (! empty($vs_a)) {
365
			// not running and there is a config, start it
366
			mwexec("/usr/local/sbin/relayd -f {$g['varetc_path']}/relayd.conf");
367
		}
368 b1bd2119 Chris Buechler
	}
369 3ad6d3bb Bill Marquette
}
370
371 a776c720 jim-p
function get_lb_redirects() {
372
/*
373
# relayctl show summary
374
Id   Type      Name                      Avlblty Status
375
1    redirect  testvs2                           active
376
5    table     test2:80                          active (3 hosts up)
377
11   host      192.168.1.2               91.55%  up
378
10   host      192.168.1.3               100.00% up
379
9    host      192.168.1.4               88.73%  up
380
3    table     test:80                           active (1 hosts up)
381
7    host      192.168.1.2               66.20%  down
382
6    host      192.168.1.3               97.18%  up
383
0    redirect  testvs                            active
384
3    table     test:80                           active (1 hosts up)
385
7    host      192.168.1.2               66.20%  down
386
6    host      192.168.1.3               97.18%  up
387
4    table     testvs-sitedown:80                active (1 hosts up)
388
8    host      192.168.1.4               84.51%  up
389
# relayctl show redirects
390
Id   Type      Name                      Avlblty Status
391
1    redirect  testvs2                           active
392
0    redirect  testvs                            active
393
# relayctl show redirects
394
Id   Type      Name                      Avlblty Status
395
1    redirect  testvs2                           active
396
           total: 2 sessions
397
           last: 2/60s 2/h 2/d sessions
398
           average: 1/60s 0/h 0/d sessions
399
0    redirect  testvs                            active
400
*/
401
	$rdr_a = array();
402
	exec('/usr/local/sbin/relayctl show redirects 2>&1', $rdr_a);
403 b6d74873 jim-p
	$relay_a = array();
404
	exec('/usr/local/sbin/relayctl show relays 2>&1', $relay_a);
405 a776c720 jim-p
	$vs = array();
406 ff160984 jim-p
	$cur_entry = "";
407 a776c720 jim-p
	for ($i = 0; isset($rdr_a[$i]); $i++) {
408
		$line = $rdr_a[$i];
409
		if (preg_match("/^[0-9]+/", $line)) {
410
			$regs = array();
411
			if($x = preg_match("/^[0-9]+\s+redirect\s+([^\s]+)\s+([^\s]+)/", $line, $regs)) {
412 ff160984 jim-p
				$cur_entry = trim($regs[1]);
413 a776c720 jim-p
				$vs[trim($regs[1])] = array();
414
				$vs[trim($regs[1])]['status'] = trim($regs[2]);
415
			}
416 ff160984 jim-p
		} elseif (($x = preg_match("/^\s+total:\s(.*)\ssessions/", $line, $regs)) && !empty($cur_entry)) {
417
			$vs[$cur_entry]['total'] = trim($regs[1]);
418
		} elseif (($x = preg_match("/^\s+last:\s(.*)\ssessions/", $line, $regs)) && !empty($cur_entry)) {
419
			$vs[$cur_entry]['last'] = trim($regs[1]);
420
		} elseif (($x = preg_match("/^\s+average:(.*)\ssessions/", $line, $regs)) && !empty($cur_entry)) {
421
			$vs[$cur_entry]['average'] = trim($regs[1]);
422 a776c720 jim-p
		}
423
	}
424 ff160984 jim-p
	$cur_entry = "";
425 b6d74873 jim-p
	for ($i = 0; isset($relay_a[$i]); $i++) {
426
		$line = $relay_a[$i];
427
		if (preg_match("/^[0-9]+/", $line)) {
428
			$regs = array();
429
			if($x = preg_match("/^[0-9]+\s+relay\s+([^\s]+)\s+([^\s]+)/", $line, $regs)) {
430 ff160984 jim-p
				$cur_entry = trim($regs[1]);
431 b6d74873 jim-p
				$vs[trim($regs[1])] = array();
432
				$vs[trim($regs[1])]['status'] = trim($regs[2]);
433
			}
434 ff160984 jim-p
		} elseif (($x = preg_match("/^\s+total:\s(.*)\ssessions/", $line, $regs)) && !empty($cur_entry)) {
435
			$vs[$cur_entry]['total'] = trim($regs[1]);
436
		} elseif (($x = preg_match("/^\s+last:\s(.*)\ssessions/", $line, $regs)) && !empty($cur_entry)) {
437
			$vs[$cur_entry]['last'] = trim($regs[1]);
438
		} elseif (($x = preg_match("/^\s+average:(.*)\ssessions/", $line, $regs)) && !empty($cur_entry)) {
439
			$vs[$cur_entry]['average'] = trim($regs[1]);
440 b6d74873 jim-p
		}
441
	}
442 a776c720 jim-p
	return $vs;
443
}
444
445
function get_lb_summary() {
446
	$relayctl = array();
447
	exec('/usr/local/sbin/relayctl show summary 2>&1', $relayctl);
448
	$relay_hosts=Array();
449
	foreach( (array) $relayctl as $line) {
450 cfbfd941 smos
		$t = explode("\t", $line);
451 a776c720 jim-p
		switch (trim($t[1])) {
452
			case "table":
453
				$curpool=trim($t[2]);
454 9859b2b5 Darren Embry
				break;
455 a776c720 jim-p
			case "host":
456
				$curhost=trim($t[2]);
457
				$relay_hosts[$curpool][$curhost]['avail']=trim($t[3]);
458
				$relay_hosts[$curpool][$curhost]['state']=trim($t[4]);
459 9859b2b5 Darren Embry
				break;
460 a776c720 jim-p
		}
461
	}
462
	return $relay_hosts;
463
}
464
465 9b0ddd8c Ermal
?>