Project

General

Profile

Download (33.1 KB) Statistics
| Branch: | Tag: | Revision:
1 5b237745 Scott Ullrich
<?php
2
/*
3
	captiveportal.inc
4 3db19cf1 Scott Ullrich
	part of m0n0wall (http://m0n0.ch/wall)
5 36254e4a Scott Ullrich
6 0bd34ed6 Scott Ullrich
	Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>.
7 5b237745 Scott Ullrich
	All rights reserved.
8 36254e4a Scott Ullrich
9 5b237745 Scott Ullrich
	Redistribution and use in source and binary forms, with or without
10
	modification, are permitted provided that the following conditions are met:
11 36254e4a Scott Ullrich
12 5b237745 Scott Ullrich
	1. Redistributions of source code must retain the above copyright notice,
13
	   this list of conditions and the following disclaimer.
14 36254e4a Scott Ullrich
15 5b237745 Scott Ullrich
	2. Redistributions in binary form must reproduce the above copyright
16
	   notice, this list of conditions and the following disclaimer in the
17
	   documentation and/or other materials provided with the distribution.
18 36254e4a Scott Ullrich
19 5b237745 Scott Ullrich
	THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
20
	INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
21
	AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22
	AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
23
	OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24
	SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25
	INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26
	CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27
	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28
	POSSIBILITY OF SUCH DAMAGE.
29 ca83c6ea Scott Ullrich
30 9699028a Scott Ullrich
	This version of captiveportal.inc has been modified by Rob Parker
31
	<rob.parker@keycom.co.uk> to include changes for per-user bandwidth management
32
	via returned RADIUS attributes. This page has been modified to delete any
33
	added rules which may have been created by other per-user code (index.php, etc).
34
	These changes are (c) 2004 Keycom PLC.
35
*/
36 36254e4a Scott Ullrich
37 5b237745 Scott Ullrich
/* include all configuration functions */
38
require_once("functions.inc");
39 3db19cf1 Scott Ullrich
require_once("radius_authentication.inc");
40 0bd34ed6 Scott Ullrich
require_once("radius_accounting.inc");
41 856e58a6 Scott Ullrich
require_once("radius.inc");
42 0bd34ed6 Scott Ullrich
43
$lockfile = "{$g['varrun_path']}/captiveportal.lock";
44 5b237745 Scott Ullrich
45
function captiveportal_configure() {
46
	global $config, $g;
47 36254e4a Scott Ullrich
48 3db19cf1 Scott Ullrich
	if (isset($config['captiveportal']['enable']) &&
49
		(($config['captiveportal']['interface'] == "lan") ||
50
			isset($config['interfaces'][$config['captiveportal']['interface']]['enable']))) {
51 36254e4a Scott Ullrich
52 3db19cf1 Scott Ullrich
		if ($g['booting'])
53
			echo "Starting captive portal... ";
54 36254e4a Scott Ullrich
55 5b237745 Scott Ullrich
		/* kill any running mini_httpd */
56 23a0c341 Scott Ullrich
		killbypid("{$g['varrun_path']}/lighty-CaptivePortal.pid");
57 63fff79b Scott Ullrich
		killbypid("{$g['varrun_path']}/lighty-CaptivePortal-SSL.pid");
58 36254e4a Scott Ullrich
59 c6c92abf Scott Ullrich
		/* kill any running minicron */
60
		killbypid("{$g['varrun_path']}/minicron.pid");
61 36254e4a Scott Ullrich
62 3db19cf1 Scott Ullrich
		/* generate ipfw rules */
63
		$cprules = captiveportal_rules_generate();
64 36254e4a Scott Ullrich
65 3db19cf1 Scott Ullrich
		/* make sure ipfw is loaded */
66
		mwexec("/sbin/kldload ipfw");
67 36254e4a Scott Ullrich
68 5b237745 Scott Ullrich
		/* stop accounting on all clients */
69 3db19cf1 Scott Ullrich
		captiveportal_radius_stop_all();
70 5b237745 Scott Ullrich
71 0bd34ed6 Scott Ullrich
		/* initialize minicron interval value */
72
		$croninterval = $config['captiveportal']['croninterval'] ? $config['captiveportal']['croninterval'] : 60;
73
74
		/* double check if the $croninterval is numeric and at least 10 seconds. If not we set it to 60 to avoid problems */
75
		if ((!is_numeric($croninterval)) || ($croninterval < 10)) { $croninterval = 60; }
76
77 5b237745 Scott Ullrich
		/* remove old information */
78 d99f7864 Scott Ullrich
		unlink_if_exists("{$g['vardb_path']}/captiveportal.nextrule");
79
		unlink_if_exists("{$g['vardb_path']}/captiveportal.db");
80
		unlink_if_exists("{$g['vardb_path']}/captiveportal_mac.db");
81
		unlink_if_exists("{$g['vardb_path']}/captiveportal_ip.db");
82
		unlink_if_exists("{$g['vardb_path']}/captiveportal_radius.db");
83 36254e4a Scott Ullrich
84 5b237745 Scott Ullrich
		/* write portal page */
85
		if ($config['captiveportal']['page']['htmltext'])
86
			$htmltext = base64_decode($config['captiveportal']['page']['htmltext']);
87
		else {
88
			/* example/template page */
89
			$htmltext = <<<EOD
90
<html>
91
<head>
92 61b040ce Scott Ullrich
<title>pfSense captive portal</title>
93 5b237745 Scott Ullrich
</head>
94 3db19cf1 Scott Ullrich
<body>
95 a515d275 Scott Ullrich
<center>
96 61b040ce Scott Ullrich
<h2>pfSense captive portal</h2>
97 407a29ca Scott Ullrich
Welcome to the pfSense Captive Portal!  This is the default page since a custom page has not been defined.
98 14d2d21b Scott Ullrich
<p>
99 a515d275 Scott Ullrich
<form method="post" action="\$PORTAL_ACTION\$">
100
<input name="redirurl" type="hidden" value="\$PORTAL_REDIRURL\$">
101 407a29ca Scott Ullrich
<table>
102
   <tr><td>Username:</td><td><input name="auth_user" type="text"></td></tr>
103
   <tr><td>Password:</td><td><input name="auth_pass" type="password"></td></tr>
104 a515d275 Scott Ullrich
   <tr><td>&nbsp;</td></tr>
105 14d2d21b Scott Ullrich
   <tr>
106
     <td colspan="2">
107 0bd34ed6 Scott Ullrich
	<center><input name="accept" type="submit" value="Continue"></center>
108 14d2d21b Scott Ullrich
     </td>
109
   </tr>
110 407a29ca Scott Ullrich
</table>
111 a515d275 Scott Ullrich
</center>
112 407a29ca Scott Ullrich
</form>
113 5b237745 Scott Ullrich
</body>
114
</html>
115
116 0bd34ed6 Scott Ullrich
117
118 5b237745 Scott Ullrich
EOD;
119
		}
120
121
		$fd = @fopen("{$g['varetc_path']}/captiveportal.html", "w");
122
		if ($fd) {
123
			fwrite($fd, $htmltext);
124 36254e4a Scott Ullrich
			fclose($fd);
125 5b237745 Scott Ullrich
		}
126 36254e4a Scott Ullrich
127 5b237745 Scott Ullrich
		/* write error page */
128
		if ($config['captiveportal']['page']['errtext'])
129
			$errtext = base64_decode($config['captiveportal']['page']['errtext']);
130
		else {
131
			/* example page */
132
			$errtext = <<<EOD
133
<html>
134
<head>
135
<title>Authentication error</title>
136
</head>
137
<body>
138
<font color="#cc0000"><h2>Authentication error</h2></font>
139
<b>
140
Username and/or password invalid.
141
<br><br>
142
<a href="javascript:history.back()">Go back</a>
143
</b>
144
</body>
145
</html>
146
147
EOD;
148
		}
149
150
		$fd = @fopen("{$g['varetc_path']}/captiveportal-error.html", "w");
151
		if ($fd) {
152
			fwrite($fd, $errtext);
153 36254e4a Scott Ullrich
			fclose($fd);
154 5b237745 Scott Ullrich
		}
155 36254e4a Scott Ullrich
156 0bd34ed6 Scott Ullrich
		/* write elements */
157
		captiveportal_write_elements();
158 5b237745 Scott Ullrich
159 3db19cf1 Scott Ullrich
		/* load rules */
160
		mwexec("/sbin/ipfw -f delete set 1");
161
		mwexec("/sbin/ipfw -f delete set 2");
162
		mwexec("/sbin/ipfw -f delete set 3");
163 36254e4a Scott Ullrich
164 63fff79b Scott Ullrich
		/* ipfw cannot accept rules directly on stdin,
165 3db19cf1 Scott Ullrich
		   so we have to write them to a temporary file first */
166
		$fd = @fopen("{$g['tmp_path']}/ipfw.cp.rules", "w");
167
		if (!$fd) {
168
			printf("Cannot open ipfw.cp.rules in captiveportal_configure()\n");
169
			return 1;
170
		}
171 36254e4a Scott Ullrich
172 3db19cf1 Scott Ullrich
		fwrite($fd, $cprules);
173
		fclose($fd);
174 36254e4a Scott Ullrich
175 3db19cf1 Scott Ullrich
		mwexec("/sbin/ipfw {$g['tmp_path']}/ipfw.cp.rules");
176 36254e4a Scott Ullrich
177 3db19cf1 Scott Ullrich
		unlink("{$g['tmp_path']}/ipfw.cp.rules");
178 36254e4a Scott Ullrich
179 3db19cf1 Scott Ullrich
		/* filter on layer2 as well so we can check MAC addresses */
180
		mwexec("/sbin/sysctl net.link.ether.ipfw=1");
181 36254e4a Scott Ullrich
182 5b237745 Scott Ullrich
		chdir($g['captiveportal_path']);
183 36254e4a Scott Ullrich
184 9b5a1292 Scott Ullrich
		if ($config['captiveportal']['maxproc'])
185
			$maxproc = $config['captiveportal']['maxproc'];
186
		else
187
			$maxproc = 16;
188 36254e4a Scott Ullrich
189 40b9f8c0 Scott Ullrich
		if(isset($config['captiveportal']['httpslogin'])) {
190
			$cert = base64_decode($config['captiveportal']['certificate']);
191
			$key = base64_decode($config['captiveportal']['private-key']);
192 63fff79b Scott Ullrich
			/* generate lighttpd configuration */
193
			system_generate_lighty_config("{$g['varetc_path']}/lighty-CaptivePortal-SSL.conf",
194
				$cert, $key, "lighty-CaptivePortal-ssl.pid", "8001", "/usr/local/captiveportal/",
195
					"cert-portal.pem", "1", $maxproc, $use_fastcgi, true);
196 40b9f8c0 Scott Ullrich
		}
197 36254e4a Scott Ullrich
198 877ac35d Scott Ullrich
		/* generate lighttpd configuration */
199
		system_generate_lighty_config("{$g['varetc_path']}/lighty-CaptivePortal.conf",
200 63fff79b Scott Ullrich
			"", "", "lighty-CaptivePortal.pid", "8000", "/usr/local/captiveportal/",
201 556d59be Scott Ullrich
				"cert-portal.pem", "1", $maxproc, $use_fastcgi, true);
202 36254e4a Scott Ullrich
203 877ac35d Scott Ullrich
		/* attempt to start lighttpd */
204
		$res = mwexec("/usr/local/sbin/lighttpd -f {$g['varetc_path']}/lighty-CaptivePortal.conf");
205 36254e4a Scott Ullrich
206 63fff79b Scott Ullrich
		/* fire up https instance */
207
		if(isset($config['captiveportal']['httpslogin']))
208
			$res = mwexec("/usr/local/sbin/lighttpd -f {$g['varetc_path']}/lighty-CaptivePortal-SSL.conf");
209 36254e4a Scott Ullrich
210 0bd34ed6 Scott Ullrich
		/* start pruning process (interval defaults to 60 seconds) */
211
		mwexec("/usr/local/bin/minicron $croninterval {$g['varrun_path']}/minicron.pid " .
212 c6c92abf Scott Ullrich
			"/etc/rc.prunecaptiveportal");
213 36254e4a Scott Ullrich
214 5b237745 Scott Ullrich
		/* generate passthru mac database */
215 3db19cf1 Scott Ullrich
		captiveportal_passthrumac_configure();
216
		/* create allowed ip database and insert ipfw rules to make it so */
217
		captiveportal_allowedip_configure();
218 5b237745 Scott Ullrich
219 d99f7864 Scott Ullrich
		/* generate radius server database */
220
		if ($config['captiveportal']['radiusip'] && (!isset($config['captiveportal']['auth_method']) ||
221
				($config['captiveportal']['auth_method'] == "radius"))) {
222
			$radiusip = $config['captiveportal']['radiusip'];
223
			$radiusip2 = ($config['captiveportal']['radiusip2']) ? $config['captiveportal']['radiusip2'] : null;
224
225
			if ($config['captiveportal']['radiusport'])
226
				$radiusport = $config['captiveportal']['radiusport'];
227
			else
228
				$radiusport = 1812;
229
230
			if ($config['captiveportal']['radiusacctport'])
231
				$radiusacctport = $config['captiveportal']['radiusacctport'];
232
			else
233
				$radiusacctport = 1813;
234
235
			if ($config['captiveportal']['radiusport2'])
236
				$radiusport2 = $config['captiveportal']['radiusport2'];
237
			else
238
				$radiusport2 = 1812;
239
240
			$radiuskey = $config['captiveportal']['radiuskey'];
241
			$radiuskey2 = ($config['captiveportal']['radiuskey2']) ? $config['captiveportal']['radiuskey2'] : null;
242
243
			$fd = @fopen("{$g['vardb_path']}/captiveportal_radius.db", "w");
244
			if (!$fd) {
245
				printf("Error: cannot open radius DB file in captiveportal_configure().\n");
246
				return 1;
247
			} else if (isset($radiusip2, $radiuskey2)) {
248
				fwrite($fd,$radiusip . "," . $radiusport . "," . $radiusacctport . "," . $radiuskey . "\n"
249
					 . $radiusip2 . "," . $radiusport2 . "," . $radiusacctport . "," . $radiuskey2);
250
			} else {
251
				fwrite($fd,$radiusip . "," . $radiusport . "," . $radiusacctport . "," . $radiuskey);
252
			}
253
			fclose($fd);
254
		}
255 36254e4a Scott Ullrich
256 d99f7864 Scott Ullrich
		if ($g['booting'])
257
			echo "done\n";
258 36254e4a Scott Ullrich
259 5b237745 Scott Ullrich
	} else {
260 23a0c341 Scott Ullrich
		killbypid("{$g['varrun_path']}/lighty-CaptivePortal.pid");
261 c6c92abf Scott Ullrich
		killbypid("{$g['varrun_path']}/minicron.pid");
262 12ee8fe4 Scott Ullrich
263 3db19cf1 Scott Ullrich
		captiveportal_radius_stop_all();
264
265
		mwexec("/sbin/sysctl net.link.ether.ipfw=0");
266
267
		if (!isset($config['shaper']['enable'])) {
268
			/* unload ipfw */
269
			mwexec("/sbin/kldunload ipfw");
270
		} else {
271
			/* shaper is on - just remove our rules */
272
			mwexec("/sbin/ipfw -f delete set 1");
273
			mwexec("/sbin/ipfw -f delete set 2");
274
			mwexec("/sbin/ipfw -f delete set 3");
275
		}
276
	}
277 36254e4a Scott Ullrich
278 5b237745 Scott Ullrich
	return 0;
279
}
280
281 3db19cf1 Scott Ullrich
function captiveportal_rules_generate() {
282
	global $config, $g;
283 36254e4a Scott Ullrich
284 3db19cf1 Scott Ullrich
	$cpifn = $config['captiveportal']['interface'];
285
	$cpif = $config['interfaces'][$cpifn]['if'];
286
	$cpip = $config['interfaces'][$cpifn]['ipaddr'];
287
288
	/* note: the captive portal daemon inserts all pass rules for authenticated
289
	   clients as skipto 50000 rules to make traffic shaping work */
290
291
	$cprules = "";
292 181a843c Scott Ullrich
293
	/*   allow nat redirects to work  see
294
	     http://cvstrac.pfsense.com/tktview?tn=651
295
	 */
296
	$iflist = array("lan" => "LAN", "wan" => "WAN");
297 c54d236c Scott Ullrich
	$captive_portal_interface = strtoupper($cpifn);
298 36254e4a Scott Ullrich
	for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++)
299
		$iflist['opt' . $i] = "OPT{$i}";
300 181a843c Scott Ullrich
	foreach ($iflist as $ifent => $ifname) {
301 d66bb68a Scott Ullrich
		if($captive_portal_interface == strtoupper($ifname))
302 181a843c Scott Ullrich
			continue;
303
		$int = convert_friendly_interface_to_real_interface_name($ifname);
304 657f3f15 Scott Ullrich
		$cprules .= "add 30 set 1 skipto 50000 all from any to any in via {$int} keep-state\n";
305 181a843c Scott Ullrich
	}
306 36254e4a Scott Ullrich
307 3db19cf1 Scott Ullrich
	/* captive portal on LAN interface? */
308
	if ($cpifn == "lan") {
309
		/* add anti-lockout rules */
310
		$cprules .= <<<EOD
311 0bd34ed6 Scott Ullrich
add 500 set 1 pass all from $cpip to any out via $cpif
312 3db19cf1 Scott Ullrich
add 501 set 1 pass all from any to $cpip in via $cpif
313
314
EOD;
315
	}
316
317
	$cprules .= <<<EOD
318
# skip to traffic shaper if not on captive portal interface
319
add 1000 set 1 skipto 50000 all from any to any not layer2 not via $cpif
320
# pass all layer2 traffic on other interfaces
321
add 1001 set 1 pass layer2 not via $cpif
322
323
# layer 2: pass ARP
324
add 1100 set 1 pass layer2 mac-type arp
325 b9d1d810 Scott Ullrich
# pfsense requires for WPA
326
add 1100 set 1 pass layer2 mac-type 0x888e
327 684c787e Scott Ullrich
328 36254e4a Scott Ullrich
# PPP Over Ethernet Discovery Stage
329 684c787e Scott Ullrich
add 1100 set 1 pass layer2 mac-type 0x8863
330
# PPP Over Ethernet Session Stage
331
add 1100 set 1 pass layer2 mac-type 0x8864
332
333 3db19cf1 Scott Ullrich
# layer 2: block anything else non-IP
334
add 1101 set 1 deny layer2 not mac-type ip
335
# layer 2: check if MAC addresses of authenticated clients are correct
336
add 1102 set 1 skipto 20000 layer2
337
338
# allow access to our DHCP server (which needs to be able to ping clients as well)
339
add 1200 set 1 pass udp from any 68 to 255.255.255.255 67 in
340
add 1201 set 1 pass udp from any 68 to $cpip 67 in
341
add 1202 set 1 pass udp from $cpip 67 to any 68 out
342
add 1203 set 1 pass icmp from $cpip to any out icmptype 8
343
add 1204 set 1 pass icmp from any to $cpip in icmptype 0
344
345
# allow access to our DNS forwarder
346
add 1300 set 1 pass udp from any to $cpip 53 in
347
add 1301 set 1 pass udp from $cpip 53 to any out
348
349
# allow access to our web server
350
add 1302 set 1 pass tcp from any to $cpip 8000 in
351
add 1303 set 1 pass tcp from $cpip 8000 to any out
352
353
EOD;
354
355
	if (isset($config['captiveportal']['httpslogin'])) {
356
		$cprules .= <<<EOD
357
add 1304 set 1 pass tcp from any to $cpip 8001 in
358
add 1305 set 1 pass tcp from $cpip 8001 to any out
359
360
EOD;
361
	}
362 36254e4a Scott Ullrich
363 d44bccc7 Scott Ullrich
        $cprules .= <<<EOD
364
#PPPoE Discovery Stage
365
add 1100 set 1 pass layer2 mac-type 0x8863
366
#PPPoE Session Stage
367
add 1100 set 1 pass layer2 mac-type 0x8864
368 3db19cf1 Scott Ullrich
369 d44bccc7 Scott Ullrich
EOD;
370 3db19cf1 Scott Ullrich
371 d44bccc7 Scott Ullrich
        $cprules .= <<<EOD
372
# Allow WPA
373
add 1100 set 1 pass layer2 mac-type 0x888e
374 5480497a Scott Ullrich
375 d44bccc7 Scott Ullrich
EOD;
376 9a064646 Scott Ullrich
377 5480497a Scott Ullrich
378 d44bccc7 Scott Ullrich
    $cprules .= <<<EOD
379 5480497a Scott Ullrich
380 d44bccc7 Scott Ullrich
# ... 10000-19899: rules per authenticated client go here...
381 5480497a Scott Ullrich
382 d44bccc7 Scott Ullrich
# redirect non-authenticated clients to captive portal
383
add 19902 set 1 fwd 127.0.0.1,8000 tcp from any to any 80 in
384 3db19cf1 Scott Ullrich
# let the responses from the captive portal web server back out
385 5480497a Scott Ullrich
add 19903 set 1 pass tcp from any 80 to any out
386 3db19cf1 Scott Ullrich
# block everything else
387 5480497a Scott Ullrich
add 19904 set 1 deny all from any to any
388 3db19cf1 Scott Ullrich
389
# ... 20000-29899: layer2 block rules per authenticated client go here...
390
391
# pass everything else on layer2
392
add 29900 set 1 pass all from any to any layer2
393
394
EOD;
395
396 d44bccc7 Scott Ullrich
    return $cprules;
397 3db19cf1 Scott Ullrich
}
398
399 5b237745 Scott Ullrich
/* remove clients that have been around for longer than the specified amount of time */
400 36254e4a Scott Ullrich
/* db file structure:
401 0bd34ed6 Scott Ullrich
timestamp,ipfw_rule_no,clientip,clientmac,username,sessionid,password,session_timeout,idle_timeout,session_terminate_time */
402
403 3db19cf1 Scott Ullrich
/* (password is in Base64 and only saved when reauthentication is enabled) */
404 5b237745 Scott Ullrich
function captiveportal_prune_old() {
405 0bd34ed6 Scott Ullrich
406 23c4f978 Scott Ullrich
    global $g, $config;
407
408
    /* check for expired entries */
409
    if ($config['captiveportal']['timeout'])
410
        $timeout = $config['captiveportal']['timeout'] * 60;
411
    else
412
        $timeout = 0;
413
414
    if ($config['captiveportal']['idletimeout'])
415
        $idletimeout = $config['captiveportal']['idletimeout'] * 60;
416
    else
417
        $idletimeout = 0;
418
419
    if (!$timeout && !$idletimeout && !isset($config['captiveportal']['reauthenticate']) && !isset($config['captiveportal']['radiussession_timeout']))
420
        return;
421
422
    captiveportal_lock();
423
424
    /* read database */
425
    $cpdb = captiveportal_read_db();
426
427
    $radiusservers = captiveportal_get_radius_servers();
428
429
    for ($i = 0; $i < count($cpdb); $i++) {
430
431
        $timedout = false;
432
        $term_cause = 1;
433
434
        /* hard timeout? */
435
        if ($timeout) {
436
            if ((time() - $cpdb[$i][0]) >= $timeout) {
437
                $timedout = true;
438
                $term_cause = 5; // Session-Timeout
439
            }
440
        }
441
442
        /* Session-Terminate-Time */
443
        if (!$timedout && !empty($cpdb[$i][9])) {
444
            if (time() >= $cpdb[$i][9]) {
445
                $timedout = true;
446
                $term_cause = 5; // Session-Timeout
447
            }
448
        }
449
450
        /* check if the radius idle_timeout attribute has been set and if its set change the idletimeout to this value */
451
        $idletimeout = (is_numeric($cpdb[$i][8])) ? $cpdb[$i][8] : $idletimeout;
452
        /* if an idle timeout is specified, get last activity timestamp from ipfw */
453
        if (!$timedout && $idletimeout) {
454
            $lastact = captiveportal_get_last_activity($cpdb[$i][1]);
455
            if ($lastact && ((time() - $lastact) >= $idletimeout)) {
456
                $timedout = true;
457
                $term_cause = 4; // Idle-Timeout
458
                $stop_time = $lastact; // Entry added to comply with WISPr
459
            }
460
        }
461
462
        /* if radius session_timeout is enabled and the session_timeout is not null, then check if the user should be logged out */
463
        if (!$timedout && isset($config['captiveportal']['radiussession_timeout']) && !empty($cpdb[$i][7])) {
464
            if (time() >= ($cpdb[$i][0] + $cpdb[$i][7])) {
465
                $timedout = true;
466
                $term_cause = 5; // Session-Timeout
467
            }
468
        }
469
470
        if ($timedout) {
471
            captiveportal_disconnect($cpdb[$i], $radiusservers,$term_cause,$stop_time);
472
            captiveportal_logportalauth($cpdb[$i][4], $cpdb[$i][3], $cpdb[$i][2], "TIMEOUT");
473
            unset($cpdb[$i]);
474
        }
475
476
        /* do periodic RADIUS reauthentication? */
477
        if (!$timedout && isset($config['captiveportal']['reauthenticate']) &&
478
            ($radiusservers !== false)) {
479
480
            if (isset($config['captiveportal']['radacct_enable'])) {
481
                if ($config['captiveportal']['reauthenticateacct'] == "stopstart") {
482
                    /* stop and restart accounting */
483
                    RADIUS_ACCOUNTING_STOP($cpdb[$i][1], // ruleno
484
                                           $cpdb[$i][4], // username
485
                                           $cpdb[$i][5], // sessionid
486
                                           $cpdb[$i][0], // start time
487
                                           $radiusservers[0]['ipaddr'],
488
                                           $radiusservers[0]['acctport'],
489
                                           $radiusservers[0]['key'],
490
                                           $cpdb[$i][2], // clientip
491
                                           $cpdb[$i][3], // clientmac
492
                                           10); // NAS Request
493
                    exec("/sbin/ipfw zero {$cpdb[$i][1]}");
494
                    RADIUS_ACCOUNTING_START($cpdb[$i][1], // ruleno
495
                                            $cpdb[$i][4], // username
496
                                            $cpdb[$i][5], // sessionid
497
                                            $radiusservers[0]['ipaddr'],
498
                                            $radiusservers[0]['acctport'],
499
                                            $radiusservers[0]['key'],
500
                                            $cpdb[$i][2], // clientip
501
                                            $cpdb[$i][3]); // clientmac
502
                } else if ($config['captiveportal']['reauthenticateacct'] == "interimupdate") {
503
                    RADIUS_ACCOUNTING_STOP($cpdb[$i][1], // ruleno
504
                                           $cpdb[$i][4], // username
505
                                           $cpdb[$i][5], // sessionid
506
                                           $cpdb[$i][0], // start time
507
                                           $radiusservers[0]['ipaddr'],
508
                                           $radiusservers[0]['acctport'],
509
                                           $radiusservers[0]['key'],
510
                                           $cpdb[$i][2], // clientip
511
                                           $cpdb[$i][3], // clientmac
512
                                           10, // NAS Request
513
                                           true); // Interim Updates
514
                }
515
            }
516
517
            /* check this user against RADIUS again */
518
            $auth_list = RADIUS_AUTHENTICATION($cpdb[$i][4], // username
519
                                          base64_decode($cpdb[$i][6]), // password
520
                                            $radiusservers,
521
                                          $cpdb[$i][2], // clientip
522
                                          $cpdb[$i][3], // clientmac
523
                                          $cpdb[$i][1]); // ruleno
524
525
            if ($auth_list['auth_val'] == 3) {
526
                captiveportal_disconnect($cpdb[$i], $radiusservers, 17);
527
                captiveportal_logportalauth($cpdb[$i][4], $cpdb[$i][3], $cpdb[$i][2], "RADIUS_DISCONNECT", $auth_list['reply_message']);
528
                unset($cpdb[$i]);
529
            }
530
        }
531
    }
532
533
    /* write database */
534
    captiveportal_write_db($cpdb);
535
536
    captiveportal_unlock();
537 5b237745 Scott Ullrich
}
538
539 3db19cf1 Scott Ullrich
/* remove a single client according to the DB entry */
540 0bd34ed6 Scott Ullrich
function captiveportal_disconnect($dbent, $radiusservers,$term_cause = 1,$stop_time = null) {
541 36254e4a Scott Ullrich
542 d99f7864 Scott Ullrich
	global $g, $config;
543
544
	$stop_time = (empty($stop_time)) ? time() : $stop_time;
545
546
	/* this client needs to be deleted - remove ipfw rules */
547
	if (isset($config['captiveportal']['radacct_enable']) && isset($radiusservers[0])) {
548
		RADIUS_ACCOUNTING_STOP($dbent[1], // ruleno
549
							   $dbent[4], // username
550
							   $dbent[5], // sessionid
551
							   $dbent[0], // start time
552
							   $radiusservers[0]['ipaddr'],
553
							   $radiusservers[0]['acctport'],
554
							   $radiusservers[0]['key'],
555
							   $dbent[2], // clientip
556
							   $dbent[3], // clientmac
557
							   $term_cause, // Acct-Terminate-Cause
558
							   false,
559
							   $stop_time);
560
	}
561
562
	mwexec("/sbin/ipfw delete " . $dbent[1] . " " . ($dbent[1]+10000));
563
564 d44bccc7 Scott Ullrich
    /* We need to delete +40500 and +45500 as well...
565
     * these are the pipe numbers we use to control traffic shaping for each logged in user via captive portal
566
     * We could get an error if the pipe doesn't exist but everything should still be fine
567
     */
568
    if (isset($config['captiveportal']['peruserbw'])) {
569
        mwexec("/sbin/ipfw pipe " . ($dbent[1]+40500) . " delete");
570
        mwexec("/sbin/ipfw pipe " . ($dbent[1]+45500) . " delete");
571
    }
572 7a7abeba Scott Ullrich
573 d44bccc7 Scott Ullrich
	/* pfSense: ensure all pf states are killed (pfSense) */
574 7a7abeba Scott Ullrich
	mwexec("pfctl -k {$dbent[2]}");
575
576 3db19cf1 Scott Ullrich
}
577 12ee8fe4 Scott Ullrich
578 3db19cf1 Scott Ullrich
/* remove a single client by ipfw rule number */
579 0bd34ed6 Scott Ullrich
function captiveportal_disconnect_client($id,$term_cause = 1) {
580 36254e4a Scott Ullrich
581 d99f7864 Scott Ullrich
	global $g, $config;
582 36254e4a Scott Ullrich
583 d99f7864 Scott Ullrich
	captiveportal_lock();
584 36254e4a Scott Ullrich
585 d99f7864 Scott Ullrich
	/* read database */
586
	$cpdb = captiveportal_read_db();
587
	$radiusservers = captiveportal_get_radius_servers();
588
589
	/* find entry */
590
	for ($i = 0; $i < count($cpdb); $i++) {
591
		if ($cpdb[$i][1] == $id) {
592
			captiveportal_disconnect($cpdb[$i], $radiusservers, $term_cause);
593
			captiveportal_logportalauth($cpdb[$i][4], $cpdb[$i][3], $cpdb[$i][2], "DISCONNECT");
594
			unset($cpdb[$i]);
595
			break;
596
		}
597
	}
598 36254e4a Scott Ullrich
599 d99f7864 Scott Ullrich
	/* write database */
600
	captiveportal_write_db($cpdb);
601 36254e4a Scott Ullrich
602 d99f7864 Scott Ullrich
	captiveportal_unlock();
603 5b237745 Scott Ullrich
}
604
605
/* send RADIUS acct stop for all current clients */
606
function captiveportal_radius_stop_all() {
607 d99f7864 Scott Ullrich
	global $g, $config;
608
609
	if (!isset($config['captiveportal']['radacct_enable']))
610
		return;
611
612
	captiveportal_lock();
613
	$cpdb = captiveportal_read_db();
614
615
	$radiusservers = captiveportal_get_radius_servers();
616
617
	if (isset($radiusservers[0])) {
618
		for ($i = 0; $i < count($cpdb); $i++) {
619
			RADIUS_ACCOUNTING_STOP($cpdb[$i][1], // ruleno
620
								   $cpdb[$i][4], // username
621
								   $cpdb[$i][5], // sessionid
622
								   $cpdb[$i][0], // start time
623
								   $radiusservers[0]['ipaddr'],
624
								   $radiusservers[0]['acctport'],
625
								   $radiusservers[0]['key'],
626
								   $cpdb[$i][2], // clientip
627
								   $cpdb[$i][3], // clientmac
628
								   7); // Admin Reboot
629
		}
630
	}
631
	captiveportal_unlock();
632 5b237745 Scott Ullrich
}
633
634
function captiveportal_passthrumac_configure() {
635
	global $config, $g;
636 36254e4a Scott Ullrich
637 3db19cf1 Scott Ullrich
	captiveportal_lock();
638 36254e4a Scott Ullrich
639 5b237745 Scott Ullrich
	/* clear out passthru macs, if necessary */
640 3db19cf1 Scott Ullrich
	unlink_if_exists("{$g['vardb_path']}/captiveportal_mac.db");
641 36254e4a Scott Ullrich
642 5b237745 Scott Ullrich
	if (is_array($config['captiveportal']['passthrumac'])) {
643 36254e4a Scott Ullrich
644 5b237745 Scott Ullrich
		$fd = @fopen("{$g['vardb_path']}/captiveportal_mac.db", "w");
645
		if (!$fd) {
646
			printf("Error: cannot open passthru mac DB file in captiveportal_passthrumac_configure().\n");
647 3db19cf1 Scott Ullrich
			captiveportal_unlock();
648 36254e4a Scott Ullrich
			return 1;
649 5b237745 Scott Ullrich
		}
650 36254e4a Scott Ullrich
651 5b237745 Scott Ullrich
		foreach ($config['captiveportal']['passthrumac'] as $macent) {
652
			/* record passthru mac so it can be recognized and let thru */
653
			fwrite($fd, $macent['mac'] . "\n");
654
		}
655 36254e4a Scott Ullrich
656
		fclose($fd);
657 5b237745 Scott Ullrich
	}
658 0bd34ed6 Scott Ullrich
659 d44bccc7 Scott Ullrich
	/*    pfSense:
660
	 * 	  pass through mac entries should always exist.  the reason
661 1de584c9 Scott Ullrich
	 *    for this is because we do not have native mac address filtering
662 d44bccc7 Scott Ullrich
	 *    mechanisms.  this allows us to filter by mac address easily
663 1de584c9 Scott Ullrich
	 *    and get around this limitation.   I consider this a bug in
664 d44bccc7 Scott Ullrich
	 *    m0n0wall and pfSense as m0n0wall does not have native mac
665
	 *    filtering mechanisms as well. -Scott Ullrich
666
	 */
667 1de584c9 Scott Ullrich
	if (is_array($config['captiveportal']['passthrumac'])) {
668
		mwexec("/sbin/ipfw delete 50");
669
		foreach($config['captiveportal']['passthrumac'] as $ptm) {
670
			/* create the pass through mac entry */
671 12249cad Scott Ullrich
			//system("echo /sbin/ipfw add 50 skipto 65535 ip from any to any MAC {$ptm['mac']} any > /tmp/cp");
672 5d61b44e Scott Ullrich
			mwexec("/sbin/ipfw add 50 skipto 29900 ip from any to any MAC {$ptm['mac']} any keep-state");
673
			mwexec("/sbin/ipfw add 50 skipto 29900 ip from any to any MAC any {$ptm['mac']} keep-state");
674 1de584c9 Scott Ullrich
		}
675
	}
676 0bd34ed6 Scott Ullrich
677 3db19cf1 Scott Ullrich
	captiveportal_unlock();
678 36254e4a Scott Ullrich
679 5b237745 Scott Ullrich
	return 0;
680
}
681
682
function captiveportal_allowedip_configure() {
683
	global $config, $g;
684 36254e4a Scott Ullrich
685 3db19cf1 Scott Ullrich
	captiveportal_lock();
686 5b237745 Scott Ullrich
687
	/* clear out existing allowed ips, if necessary */
688
	if (file_exists("{$g['vardb_path']}/captiveportal_ip.db")) {
689
		$fd = @fopen("{$g['vardb_path']}/captiveportal_ip.db", "r");
690
		if ($fd) {
691
			while (!feof($fd)) {
692
				$line = trim(fgets($fd));
693 3db19cf1 Scott Ullrich
				if ($line) {
694 5b237745 Scott Ullrich
					list($ip,$rule) = explode(",",$line);
695 3db19cf1 Scott Ullrich
					mwexec("/sbin/ipfw delete $rule");
696 36254e4a Scott Ullrich
				}
697 5b237745 Scott Ullrich
			}
698
		}
699 3db19cf1 Scott Ullrich
		fclose($fd);
700 5b237745 Scott Ullrich
		unlink("{$g['vardb_path']}/captiveportal_ip.db");
701
	}
702
703 3db19cf1 Scott Ullrich
	/* get next ipfw rule number */
704
	if (file_exists("{$g['vardb_path']}/captiveportal.nextrule"))
705
		$ruleno = trim(file_get_contents("{$g['vardb_path']}/captiveportal.nextrule"));
706
	if (!$ruleno)
707
		$ruleno = 10000;	/* first rule number */
708 36254e4a Scott Ullrich
709 5b237745 Scott Ullrich
	if (is_array($config['captiveportal']['allowedip'])) {
710 36254e4a Scott Ullrich
711 5b237745 Scott Ullrich
		$fd = @fopen("{$g['vardb_path']}/captiveportal_ip.db", "w");
712
		if (!$fd) {
713
			printf("Error: cannot open allowed ip DB file in captiveportal_allowedip_configure().\n");
714 3db19cf1 Scott Ullrich
			captiveportal_unlock();
715 36254e4a Scott Ullrich
			return 1;
716 5b237745 Scott Ullrich
		}
717 36254e4a Scott Ullrich
718 5b237745 Scott Ullrich
		foreach ($config['captiveportal']['allowedip'] as $ipent) {
719 d44bccc7 Scott Ullrich
            /* get next ipfw rule number */
720
            $ruleno = captiveportal_get_next_ipfw_ruleno();
721 36254e4a Scott Ullrich
722 d44bccc7 Scott Ullrich
            /* if the pool is empty, return apprioriate message and fail */
723
            if (is_null($ruleno)) {
724
                printf("Error: system reached maximum login capacity, no free FW rulenos in captiveportal_allowedip_configure().\n");
725
                fclose($fd);
726
                captiveportal_unlock();
727
                return 1;
728
            }
729 36254e4a Scott Ullrich
730 d44bccc7 Scott Ullrich
            /* record allowed ip so it can be recognized and removed later */
731
            fwrite($fd, $ipent['ip'] . "," . $ruleno ."\n");
732 36254e4a Scott Ullrich
733 d44bccc7 Scott Ullrich
            /* insert ipfw rule to allow ip thru */
734
            if ($ipent['dir'] == "from") {
735
                mwexec("/sbin/ipfw add $ruleno set 2 skipto 50000 ip from " . $ipent['ip'] . " to any in");
736
                mwexec("/sbin/ipfw add $ruleno set 2 skipto 50000 ip from any to " . $ipent['ip'] . " out");
737
            } else {
738
                mwexec("/sbin/ipfw add $ruleno set 2 skipto 50000 ip from any to " . $ipent['ip'] . " in");
739
                mwexec("/sbin/ipfw add $ruleno set 2 skipto 50000 ip from " . $ipent['ip'] . " to any out");
740
            }
741 36254e4a Scott Ullrich
742 d44bccc7 Scott Ullrich
        }
743 5b237745 Scott Ullrich
744 d44bccc7 Scott Ullrich
        fclose($fd);
745
    }
746 36254e4a Scott Ullrich
747 d44bccc7 Scott Ullrich
    captiveportal_unlock();
748
    return 0;
749 5b237745 Scott Ullrich
}
750
751 3db19cf1 Scott Ullrich
/* get last activity timestamp given ipfw rule number */
752
function captiveportal_get_last_activity($ruleno) {
753 36254e4a Scott Ullrich
754 d99f7864 Scott Ullrich
	$ipfwoutput = "";
755 36254e4a Scott Ullrich
756 d99f7864 Scott Ullrich
	exec("/sbin/ipfw -T list {$ruleno} 2>/dev/null", $ipfwoutput);
757
758
	/* in */
759
	if ($ipfwoutput[0]) {
760
		$ri = explode(" ", $ipfwoutput[0]);
761
		if ($ri[1])
762
			return $ri[1];
763
	}
764 36254e4a Scott Ullrich
765 d99f7864 Scott Ullrich
	return 0;
766 5b237745 Scott Ullrich
}
767
768
/* read RADIUS servers into array */
769
function captiveportal_get_radius_servers() {
770 0bd34ed6 Scott Ullrich
771
        global $g;
772
773
        if (file_exists("{$g['vardb_path']}/captiveportal_radius.db")) {
774
                $fd = @fopen("{$g['vardb_path']}/captiveportal_radius.db","r");
775
                if ($fd) {
776
                        $radiusservers = array();
777
                        while (!feof($fd)) {
778
                                $line = trim(fgets($fd));
779
                                if ($line) {
780
                                        $radsrv = array();
781
                                        list($radsrv['ipaddr'],$radsrv['port'],$radsrv['acctport'],$radsrv['key']) = explode(",",$line);
782
                                        $radiusservers[] = $radsrv;
783
                                }
784
                        }
785
                        fclose($fd);
786
787
                        return $radiusservers;
788
                }
789
        }
790
791
        return false;
792 5b237745 Scott Ullrich
}
793
794
/* lock captive portal information, decide that the lock file is stale after
795
   10 seconds */
796
function captiveportal_lock() {
797 0bd34ed6 Scott Ullrich
798
        global $lockfile;
799
800
        $n = 0;
801
        while ($n < 10) {
802
                /* open the lock file in append mode to avoid race condition */
803
                if ($fd = @fopen($lockfile, "x")) {
804
                        /* succeeded */
805
                        fclose($fd);
806
                        return;
807
                } else {
808
                        /* file locked, wait and try again */
809
                        sleep(1);
810
                        $n++;
811
                }
812
        }
813 5b237745 Scott Ullrich
}
814
815 0bd34ed6 Scott Ullrich
/* unlock captive portal information file */
816 5b237745 Scott Ullrich
function captiveportal_unlock() {
817 0bd34ed6 Scott Ullrich
818
        global $lockfile;
819
820
        if (file_exists($lockfile))
821
                unlink($lockfile);
822 5b237745 Scott Ullrich
}
823
824 3db19cf1 Scott Ullrich
/* log successful captive portal authentication to syslog */
825
/* part of this code from php.net */
826 0bd34ed6 Scott Ullrich
function captiveportal_logportalauth($user,$mac,$ip,$status, $message = null) {
827 d99f7864 Scott Ullrich
	define_syslog_variables();
828
	$message = trim($message);
829
	openlog("logportalauth", LOG_PID, LOG_LOCAL4);
830
	// Log it
831
	if (!$message)
832
	syslog(LOG_INFO, "$status: $user, $mac, $ip");
833
	else
834
	syslog(LOG_INFO, "$status: $user, $mac, $ip, $message");
835
	closelog();
836 3db19cf1 Scott Ullrich
}
837
838 0bd34ed6 Scott Ullrich
function radius($username,$password,$clientip,$clientmac,$type) {
839 d44bccc7 Scott Ullrich
    global $g, $config;
840 d99f7864 Scott Ullrich
841 d44bccc7 Scott Ullrich
    /* Start locking from the beginning of an authentication session */
842
    captiveportal_lock();
843 0bd34ed6 Scott Ullrich
844 d44bccc7 Scott Ullrich
    $ruleno = captiveportal_get_next_ipfw_ruleno();
845
846
    /* if the pool is empty, return apprioriate message and fail authentication */
847
    if (is_null($ruleno)) {
848
        $auth_list = array();
849
        $auth_list['auth_val'] = 1;
850
        $auth_list['error'] = "System reached maximum login capacity";
851
        captiveportal_unlock();
852
        return $auth_list;
853
    }
854
855
    $radiusservers = captiveportal_get_radius_servers();
856
857
    $auth_list = RADIUS_AUTHENTICATION($username,
858
                    $password,
859
                    $radiusservers,
860
                    $clientip,
861
                    $clientmac,
862
                    $ruleno);
863
864
    if ($auth_list['auth_val'] == 2) {
865
        captiveportal_logportalauth($username,$clientmac,$clientip,$type);
866
        $sessionid = portal_allow($clientip,
867
                    $clientmac,
868
                    $username,
869
                    $password,
870
                    $auth_list,
871
                    $ruleno);
872
    }
873
    else {
874
        captiveportal_unlock();
875
    }
876
877
    return $auth_list;
878 0bd34ed6 Scott Ullrich
879
}
880
881
/* read captive portal DB into array */
882
function captiveportal_read_db() {
883
884
        global $g;
885
886
        $cpdb = array();
887
        $fd = @fopen("{$g['vardb_path']}/captiveportal.db", "r");
888
        if ($fd) {
889
                while (!feof($fd)) {
890
                        $line = trim(fgets($fd));
891
                        if ($line) {
892
                                $cpdb[] = explode(",", $line);
893
                        }
894
                }
895
                fclose($fd);
896
        }
897
        return $cpdb;
898
}
899
900
/* write captive portal DB */
901
function captiveportal_write_db($cpdb) {
902 d44bccc7 Scott Ullrich
                 
903 0bd34ed6 Scott Ullrich
        global $g;
904 d44bccc7 Scott Ullrich
                
905 0bd34ed6 Scott Ullrich
        $fd = @fopen("{$g['vardb_path']}/captiveportal.db", "w");
906 d44bccc7 Scott Ullrich
        if ($fd) { 
907 0bd34ed6 Scott Ullrich
                foreach ($cpdb as $cpent) {
908
                        fwrite($fd, join(",", $cpent) . "\n");
909 d44bccc7 Scott Ullrich
                }       
910 0bd34ed6 Scott Ullrich
                fclose($fd);
911 d44bccc7 Scott Ullrich
        }       
912 0bd34ed6 Scott Ullrich
}
913
914
function captiveportal_write_elements() {
915 d44bccc7 Scott Ullrich
    global $g, $config;
916
    
917
    /* delete any existing elements */
918
    if (is_dir($g['captiveportal_element_path'])) {
919
        $dh = opendir($g['captiveportal_element_path']);
920
        while (($file = readdir($dh)) !== false) {
921
            if ($file != "." && $file != "..")
922
                unlink($g['captiveportal_element_path'] . "/" . $file);
923
        }
924
        closedir($dh);
925
    } else {
926
        mkdir($g['captiveportal_element_path']);
927
    }
928
    
929
    if (is_array($config['captiveportal']['element'])) {
930
    
931
        foreach ($config['captiveportal']['element'] as $data) {
932
            $fd = @fopen($g['captiveportal_element_path'] . '/' . $data['name'], "wb");
933
            if (!$fd) {
934
                printf("Error: cannot open '{$data['name']}' in captiveportal_write_elements().\n");
935
                return 1;
936
            }
937
            $decoded = base64_decode($data['content']);
938
            fwrite($fd,$decoded);
939
            fclose($fd);
940
        }
941
    }
942
    
943
    return 0;
944 0bd34ed6 Scott Ullrich
}
945
946 920cafaf Scott Ullrich
/*
947
 * This function will calculate the lowest free firewall ruleno
948
 * within the range specified based on the actual installed rules
949
 *
950
 */
951
952
function captiveportal_get_next_ipfw_ruleno($rulenos_start = 10000, $rulenos_range_max = 9899) {
953
954 84e5047d Scott Ullrich
	$fwrules = "";
955
	$matches = "";
956 920cafaf Scott Ullrich
	exec("/sbin/ipfw show", $fwrules);
957
	foreach ($fwrules as $fwrule) {
958
		preg_match("/^(\d+)\s+/", $fwrule, $matches);
959
		$rulenos_used[] = $matches[1];
960
	}
961
	$rulenos_used = array_unique($rulenos_used);
962
	$rulenos_range = count($rulenos_used);
963
	if ($rulenos_range > $rulenos_range_max) {
964
		return NULL;
965
	}
966
	$rulenos_pool = range($rulenos_start, ($rulenos_start + $rulenos_range));
967
	$rulenos_free = array_diff($rulenos_pool, $rulenos_used);
968
	$ruleno = array_shift($rulenos_free);
969
970
	return $ruleno;
971
}
972
973 360d815d Scott Ullrich
/**
974
 * This function will calculate the traffic produced by a client
975
 * based on its firewall rule
976
 *
977
 * Point of view: NAS
978
 *
979
 * Input means: from the client
980
 * Output means: to the client
981
 *
982
 */
983
984
function getVolume($ruleno) {
985
986
    $volume = array();
987
988
    // Initialize vars properly, since we don't want NULL vars
989
    $volume['input_pkts'] = $volume['input_bytes'] = $volume['output_pkts'] = $volume['output_bytes'] = 0 ;
990
991
    // Ingress
992 84e5047d Scott Ullrich
    $ipfw = "";
993
    $matches = "";
994 360d815d Scott Ullrich
    exec("/sbin/ipfw show {$ruleno}", $ipfw);
995
    preg_match("/(\d+)\s+(\d+)\s+(\d+)\s+.*/", $ipfw[0], $matches);
996
    $volume['input_pkts'] = $matches[2];
997
    $volume['input_bytes'] = $matches[3];
998
999
    // Flush internal buffer
1000
    unset($matches);
1001
1002
    // Outgress
1003
    preg_match("/(\d+)\s+(\d+)\s+(\d+)\s+.*/", $ipfw[1], $matches);
1004
    $volume['output_pkts'] = $matches[2];
1005
    $volume['output_bytes'] = $matches[3];
1006
1007
    return $volume;
1008
}
1009
1010 856e58a6 Scott Ullrich
/**
1011
 * Get the NAS-Identifier
1012
 *
1013
 * We will use our local hostname to make up the nas_id
1014
 */
1015
function getNasID()
1016
{
1017 84e5047d Scott Ullrich
    $nasId = "";
1018 856e58a6 Scott Ullrich
    exec("/bin/hostname", $nasId);
1019
    if(!$nasId[0])
1020
        $nasId[0] = "pfSense";
1021
    return $nasId[0];
1022
}
1023
1024
/**
1025
 * Get the NAS-IP-Address based on the current wan address
1026
 *
1027
 * Use functions in interfaces.inc to find this out
1028
 *
1029
 */
1030
1031
function getNasIP()
1032
{
1033
    $nasIp = get_current_wan_address();
1034
    if(!$nasIp)
1035
        $nasIp = "0.0.0.0";
1036
    return $nasIp;
1037
}
1038
1039 36254e4a Scott Ullrich
?>