Project

General

Profile

Download (8.36 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/* $Id$ */
3
/*
4
  vslb.inc
5
  Copyright (C) 2005-2008 Bill Marquette
6
  All rights reserved.
7

    
8
  Redistribution and use in source and binary forms, with or without
9
  modification, are permitted provided that the following conditions are met:
10

    
11
  1. Redistributions of source code must retain the above copyright notice,
12
  this list of conditions and the following disclaimer.
13

    
14
  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

    
18
  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

    
29
 */
30

    
31
/*
32
	pfSense_BUILDER_BINARIES:	/usr/local/sbin/relayd
33
	pfSense_MODULE:	routing
34
*/
35

    
36
/* DISABLE_PHP_LINT_CHECKING */
37

    
38
/* include all configuration functions */
39
require_once("config.inc");
40

    
41
class Monitor {
42
	private $conf = array();
43
	function __construct($config) {
44
		$this->conf = $config;
45
	}
46

    
47
	public function p() {
48
		return "check {$this->get('proto')}";
49
	}
50
	private function get($var) {
51
		return isset($this->$var) ? $this->$var : "";
52
	}
53
	protected function config($element) {
54
		return isset($this->conf[$element]) ? $this->conf[$element] : "";
55
	}
56
}
57

    
58
class TCPMonitor extends Monitor {
59
	protected $proto = 'tcp';
60
}
61

    
62
class SSLMonitor extends Monitor {
63
	protected $proto = 'ssl';
64
}
65

    
66
class ICMPMonitor extends Monitor {
67
	protected $proto = 'icmp';
68
}
69

    
70
class HTTPMonitor extends Monitor {
71
	protected $proto = 'http';
72
	function __construct($config) {
73
		parent::__construct($config);
74
	}
75
	public function p() {
76
		$method = ($this->code() != "") ? $this->code() : $this->digest();
77
		return "check {$this->proto} {$this->path()} {$this->host()} {$method}";
78
	}
79

    
80
	private function path() {
81
		return $this->config('path') != "" ? "'{$this->config('path')}'" : "";
82
	}
83

    
84
	private function host() {
85
		return $this->config('host') != "" ? "host {$this->config('host')}" : "";
86
	}
87

    
88
	private function code() {
89
		return $this->config('code') != "" ? "code {$this->config('code')}" : "";
90
	}
91

    
92
	private function digest() {
93
		return $this->config('digest') != "" ? "digest {$this->config('digest')}" : "";
94
	}
95
}
96

    
97
class HTTPSMonitor extends HTTPMonitor {
98
	protected $proto = 'https';
99
}
100

    
101
class SendMonitor extends Monitor {
102
	private $proto = 'send';
103
	function __construct($config) {
104
		parent::__construct($config);
105
	}
106
	public function p() {
107
		return "check {$this->proto} {$this->data()} expect {$this->pattern()} {$this->ssl()}";
108
	}
109

    
110

    
111
	private function data() {
112
		return $this->config('send') != "" ? "{$this->config('send')}" : "";
113
	}
114

    
115
	private function pattern() {
116
		return $this->config('expect') != "" ? "{$this->config('expect')}" : "";
117
	}
118

    
119
	private function ssl() {
120
		return $this->config('ssl') == true ? "ssl" : "";
121
	}
122
}
123

    
124
function echo_lbaction($action) {
125
  global $config;
126
  
127
  // Index actions by name
128
  $actions_a = array();
129
  for ($i=0; isset($config['load_balancer']['lbaction'][$i]); $i++)
130
		$actions_a[$config['load_balancer']['lbaction'][$i]['name']] = $config['load_balancer']['lbaction'][$i];
131

    
132
  $ret = "";
133
  $ret .=  "{$actions_a[$action]['direction']} {$actions_a[$action]['type']} {$actions_a[$action]['action']}";
134
  switch($actions_a[$action]['action']) {
135
    case 'append': {
136
      $ret .= " \"{$actions_a[$action]['options']['value']}\" to \"{$actions_a[$action]['options']['akey']}\"";
137
      break;
138
    }
139
    case 'change': {
140
      $ret .= " \"{$actions_a[$action]['options']['akey']}\" to \"{$actions_a[$action]['options']['value']}\"";
141
      break;
142
    }
143
    case 'expect': {
144
      $ret .= " \"{$actions_a[$action]['options']['value']}\" from \"{$actions_a[$action]['options']['akey']}\"";
145
      break;
146
    }
147
    case 'filter': {
148
      $ret .= " \"{$actions_a[$action]['options']['value']}\" from \"{$actions_a[$action]['options']['akey']}\"";
149
      break;
150
    }
151
    case 'hash': {
152
      $ret .= " \"{$actions_a[$action]['options']['akey']}\"";
153
      break;
154
    }
155
    case 'log': {
156
      $ret .= " \"{$actions_a[$action]['options']['akey']}\"";
157
      break;
158
    }
159
  }
160
  return $ret;
161
}
162

    
163
function relayd_configure() {
164
  global $config, $g;
165

    
166
  $vs_a = $config['load_balancer']['virtual_server'];
167
  $pool_a = $config['load_balancer']['lbpool'];
168
  $protocol_a = $config['load_balancer']['lbprotocol'];
169

    
170
  $check_a = array();
171

    
172
  foreach ((array)$config['load_balancer']['monitor_type'] as $type) {
173
    switch($type['type']) {
174
      case 'icmp': {
175
        $mon = new ICMPMonitor($type['options']);
176
	break;
177
      }
178
      case 'tcp': {
179
        $mon = new TCPMonitor($type['options']);
180
	break;
181
      }
182
      case 'http': {
183
        $mon = new HTTPMonitor($type['options']);
184
	break;
185
      }
186
      case 'https': {
187
        $mon = new HTTPSMonitor($type['options']);
188
	break;
189
      }
190
      case 'send': {
191
        $mon = new SendMonitor($type['options']);
192
	break;
193
      }
194
    }
195
    $check_a[$type['name']] = $mon->p();
196
  }
197

    
198

    
199
  $fd = fopen("{$g['varetc_path']}/relayd.conf", "w");
200

    
201
  /* reindex pools by name as we loop through the pools array */
202
  $pools = array();
203
  /* Virtual server pools */
204
  if(is_array($pool_a)) {
205
    for ($i = 0; isset($pool_a[$i]); $i++) {
206
      if(is_array($pool_a[$i]['servers'])) {
207
        $srvtxt = implode(", ", $pool_a[$i]['servers']);
208
        $conf .= "table <{$pool_a[$i]['name']}> { $srvtxt }\n";
209
        /* Index by name for easier fetching when we loop through the virtual servers */
210
        $pools[$pool_a[$i]['name']] = $pool_a[$i];
211
      }
212
    }
213
  }
214
  if(is_array($protocol_a)) {
215
    for ($i = 0; isset($protocol_a[$i]); $i++) {
216
      $proto = "{$protocol_a[$i]['type']} protocol \"{$protocol_a[$i]['name']}\" {\n";
217
      if(is_array($protocol_a[$i]['lbaction'])) {
218
        if($protocol_a[$i]['lbaction'][0] == "") {
219
          continue;
220
        }
221
        for ($a = 0; isset($protocol_a[$i]['lbaction'][$a]); $a++) {
222
          $proto .= "  " . echo_lbaction($protocol_a[$i]['lbaction'][$a]) . "\n";
223
        }
224
      }
225
      $proto .= "}\n";
226
      $conf .= $proto;
227
    }
228
  }
229
  if(is_array($vs_a)) {
230
    for ($i = 0; isset($vs_a[$i]); $i++) {
231
      switch($vs_a[$i]['mode']) {
232
        case 'redirect': {
233
          $conf .= "redirect \"{$vs_a[$i]['name']}\" {\n";
234
          $conf .= "  listen on {$vs_a[$i]['ipaddr']} port {$vs_a[$i]['port']}\n";
235
          $conf .= "  forward to <{$vs_a[$i]['pool']}> port {$pools[$vs_a[$i]['pool']]['port']} {$check_a[$pools[$vs_a[$i]['pool']]['monitor']]} timeout 1000\n";
236

    
237
          # sitedown MUST use the same port as the primary pool - sucks, but it's a relayd thing
238
          if (isset($vs_a[$i]['sitedown']) &&  $vs_a[$i]['sitedown'] != "")
239
            $conf .= "  forward to <{$vs_a[$i]['sitedown']}> port {$pools[$vs_a[$i]['pool']]['port']} {$check_a[$pools[$vs_a[$i]['pool']]['monitor']]} timeout 1000\n";
240
          $conf .= "}\n";
241
          break;
242
        }
243
        case 'relay': {
244
          $conf .= "relay \"{$vs_a[$i]['name']}\" {\n";
245
          $conf .= "  listen on {$vs_a[$i]['ipaddr']} port {$vs_a[$i]['port']}\n";
246
          $conf .= "  protocol \"{$vs_a[$i]['relay_protocol']}\"\n";
247
          $conf .= "  forward to <{$vs_a[$i]['pool']}> port {$pools[$vs_a[$i]['pool']]['port']} {$check_a[$pools[$vs_a[$i]['pool']]['monitor']]} timeout 1000\n";
248

    
249
          if (isset($vs_a[$i]['sitedown']) &&  $vs_a[$i]['sitedown'] != "")
250
            $conf .= "  forward to <{$vs_a[$i]['sitedown']}> port {$pools[$vs_a[$i]['pool']]['port']} {$check_a[$pools[$vs_a[$i]['pool']]['monitor']]} timeout 1000\n";
251
          $conf .= "}\n";
252
          break;
253
        }
254
      }
255
    }
256
  }
257
  fwrite($fd, $conf);
258
  fclose($fd);
259

    
260
  if (is_process_running('relayd: parent')) {
261
    /*
262
     * XXX: Something breaks our control connection with relayd and makes relayctl stop working
263
     * rule reloads are the current suspect
264
     * mwexec('/usr/local/bin/relayctl stop');
265
     */
266
     mwexec('pkill relayd');
267
  }
268
  if (! empty($vs_a)) {
269
    mwexec("/usr/local/sbin/relayd -f {$g['varetc_path']}/relayd.conf");
270
  }
271
}
272

    
273
?>
(42-42/46)