summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorErmal <eri@pfsense.org>2010-04-20 00:39:16 +0000
committerErmal <eri@pfsense.org>2010-04-20 00:40:02 +0000
commit6ce61a8fd6423e5b7cd851ebbfab3486523db9b6 (patch)
tree64dbac1a32815d2de8f3181e3bc52f81c8fcbd9b
parentc443bb14cb89462e8f19f8e60527b970f3344bfb (diff)
downloadpfsense-6ce61a8fd6423e5b7cd851ebbfab3486523db9b6.zip
pfsense-6ce61a8fd6423e5b7cd851ebbfab3486523db9b6.tar.gz
Add a new option which allows the admin user to configure CP so that it automatically enters an MAC passthru entry. The MAC is taken from login details and has to be removed manually. Also do improvements on rules handling and pipes. Add some optmizations. Teach the GUI/backend on ip/mac passthrough to configure a bw limit for this entries.
-rw-r--r--etc/inc/captiveportal.inc289
-rwxr-xr-xusr/local/captiveportal/index.php78
-rwxr-xr-xusr/local/www/services_captiveportal.php13
-rwxr-xr-xusr/local/www/services_captiveportal_ip.php5
-rwxr-xr-xusr/local/www/services_captiveportal_ip_edit.php38
-rwxr-xr-xusr/local/www/services_captiveportal_mac.php14
-rwxr-xr-xusr/local/www/services_captiveportal_mac_edit.php27
7 files changed, 312 insertions, 152 deletions
diff --git a/etc/inc/captiveportal.inc b/etc/inc/captiveportal.inc
index 33d1b75..c7095d6 100644
--- a/etc/inc/captiveportal.inc
+++ b/etc/inc/captiveportal.inc
@@ -102,6 +102,16 @@ function captiveportal_configure() {
killbypid("{$g['varrun_path']}/lighty-CaptivePortal.pid");
killbypid("{$g['varrun_path']}/lighty-CaptivePortal-SSL.pid");
+ /* remove old information */
+ unlink_if_exists("{$g['vardb_path']}/captiveportal.db");
+ unlink_if_exists("{$g['vardb_path']}/captiveportal_mac.db");
+ unlink_if_exists("{$g['vardb_path']}/captiveportal_ip.db");
+ unlink_if_exists("{$g['vardb_path']}/captiveportal_radius.db");
+ mwexec("/sbin/ipfw table all flush");
+
+ /* setup new database in case someone tries to access the status -> captive portal page */
+ touch("{$g['vardb_path']}/captiveportal.db");
+
/* kill any running minicron */
killbypid("{$g['varrun_path']}/minicron.pid");
@@ -112,7 +122,14 @@ function captiveportal_configure() {
mwexec("/sbin/kldload dummynet");
/* generate ipfw rules */
+ captiveportal_init_ipfw_ruleno();
$cprules = captiveportal_rules_generate($cpinterface, $cpips);
+ $cprules .= "\n";
+ /* generate passthru mac database */
+ $cprules .= captiveportal_passthrumac_configure(true);
+ $cprules .= "\n";
+ /* allowed ipfw rules to make allowed ip work */
+ $cprules .= captiveportal_allowedip_configure();
/* stop accounting on all clients */
captiveportal_radius_stop_all(true);
@@ -123,17 +140,6 @@ function captiveportal_configure() {
/* double check if the $croninterval is numeric and at least 10 seconds. If not we set it to 60 to avoid problems */
if ((!is_numeric($croninterval)) || ($croninterval < 10)) { $croninterval = 60; }
- /* remove old information */
- unlink_if_exists("{$g['vardb_path']}/captiveportal.nextrule");
- unlink_if_exists("{$g['vardb_path']}/captiveportal.db");
- unlink_if_exists("{$g['vardb_path']}/captiveportal_mac.db");
- unlink_if_exists("{$g['vardb_path']}/captiveportal_ip.db");
- unlink_if_exists("{$g['vardb_path']}/captiveportal_radius.db");
- mwexec("/sbin/ipfw table all flush");
-
- /* setup new database in case someone tries to access the status -> captive portal page */
- touch("{$g['vardb_path']}/captiveportal.db");
-
/* write portal page */
if ($config['captiveportal']['page']['htmltext'])
$htmltext = base64_decode($config['captiveportal']['page']['htmltext']);
@@ -210,7 +216,7 @@ EOD;
captiveportal_write_elements();
/* load rules */
- mwexec("/sbin/ipfw -f delete set 1");
+ mwexec("/sbin/ipfw -q flush");
/* ipfw cannot accept rules directly on stdin,
so we have to write them to a temporary file first */
@@ -225,7 +231,7 @@ EOD;
mwexec("/sbin/ipfw {$g['tmp_path']}/ipfw.cp.rules");
- unlink("{$g['tmp_path']}/ipfw.cp.rules");
+ @unlink("{$g['tmp_path']}/ipfw.cp.rules");
/* filter on layer2 as well so we can check MAC addresses */
mwexec("/sbin/sysctl net.link.ether.ipfw=1");
@@ -268,11 +274,6 @@ EOD;
mwexec("/usr/local/bin/minicron $croninterval {$g['varrun_path']}/minicron.pid " .
"/etc/rc.prunecaptiveportal");
- /* generate passthru mac database */
- captiveportal_passthrumac_configure(true);
- /* allowed ipfw rules to make allowed ip work */
- captiveportal_allowedip_configure();
-
/* generate radius server database */
if ($config['captiveportal']['radiusip'] && (!isset($config['captiveportal']['auth_method']) ||
($config['captiveportal']['auth_method'] == "radius"))) {
@@ -346,36 +347,30 @@ EOD;
function captiveportal_rules_generate($cpif, &$cpiparray) {
global $config, $g;
- $cpifn = $config['captiveportal']['interface'];
- $lanip = get_interface_ip("lan");
-
- /* note: the captive portal daemon inserts all pass rules for authenticated
- clients as skipto 50000 rules to make traffic shaping work */
-
- $cprules = "add 500 set 1 allow pfsync from any to any\n";
- $cprules .= "add 500 set 1 allow carp from any to any\n";
+ $cprules = "add 65301 set 1 allow pfsync from any to any\n";
+ $cprules .= "add 65302 set 1 allow carp from any to any\n";
$cprules .= <<<EOD
-add 1000 set 1 skipto 1150 all from any to any not layer2
+# add 65305 set 1 skipto 65534 all from any to any not layer2
# layer 2: pass ARP
-add 1100 set 1 pass layer2 mac-type arp
+add 65310 set 1 pass layer2 mac-type arp
# pfsense requires for WPA
-add 1100 set 1 pass layer2 mac-type 0x888e
-add 1100 set 1 pass layer2 mac-type 0x88c7
+add 65311 set 1 pass layer2 mac-type 0x888e
+add 65312 set 1 pass layer2 mac-type 0x88c7
# PPP Over Ethernet Discovery Stage
-add 1100 set 1 pass layer2 mac-type 0x8863
+add 65313 set 1 pass layer2 mac-type 0x8863
# PPP Over Ethernet Session Stage
-add 1100 set 1 pass layer2 mac-type 0x8864
+add 65314 set 1 pass layer2 mac-type 0x8864
# Allow WPA
-add 1100 set 1 pass layer2 mac-type 0x888e
+add 65315 set 1 pass layer2 mac-type 0x888e
# layer 2: block anything else non-IP
-add 1101 set 1 deny layer2 not mac-type ip
+add 65316 set 1 deny layer2 not mac-type ip
EOD;
- $rulenum = 1150;
+ $rulenum = 65320;
$ips = "255.255.255.255 ";
foreach ($cpiparray as $cpip)
$ips .= "or {$cpip} ";
@@ -420,30 +415,27 @@ EOD;
$rulenum++;
if (isset($config['captiveportal']['peruserbw'])) {
- $cprules .= "add {$rulenum} set 1 pipe tablearg ip from table(3) to any in\n";
+ $cprules .= "add {$rulenum} set 1 pipe tablearg ip from table(1) to any in\n";
$rulenum++;
- $cprules .= "add {$rulenum} set 1 pipe tablearg ip from any to table(4) out\n";
+ $cprules .= "add {$rulenum} set 1 pipe tablearg ip from any to table(2) out\n";
$rulenum++;
} else {
- $cprules .= "add {$rulenum} set 1 skipto 50000 ip from table(3) to any in\n";
+ $cprules .= "add {$rulenum} set 1 allow ip from table(1) to any in\n";
$rulenum++;
- $cprules .= "add {$rulenum} set 1 skipto 50000 ip from any to table(4) out\n";
+ $cprules .= "add {$rulenum} set 1 allow ip from any to table(2) out\n";
$rulenum++;
}
$cprules .= <<<EOD
# redirect non-authenticated clients to captive portal
-add 1990 set 1 fwd 127.0.0.1,8000 tcp from any to any in
+add 65531 set 1 fwd 127.0.0.1,8000 tcp from any to any in
# let the responses from the captive portal web server back out
-add 1991 set 1 pass tcp from any to any out
+add 65532 set 1 pass tcp from any to any out
# block everything else
-add 1992 set 1 deny all from any to any
-
-# ... 2000-49899: layer2 block rules per authenticated client go here...
-
+add 65533 set 1 deny all from any to any
# pass everything else on layer2
-add 49900 set 1 pass all from any to any layer2
+add 65534 set 1 pass all from any to any layer2
EOD;
@@ -566,8 +558,8 @@ function captiveportal_prune_old() {
$cpdb[$i][2], // clientip
$cpdb[$i][3], // clientmac
10); // NAS Request
- exec("/sbin/ipfw table 3 entryzerostats {$cpdb[$i][2]}");
- exec("/sbin/ipfw table 4 entryzerostats {$cpdb[$i][2]}");
+ exec("/sbin/ipfw table 1 entryzerostats {$cpdb[$i][2]}");
+ exec("/sbin/ipfw table 2 entryzerostats {$cpdb[$i][2]}");
RADIUS_ACCOUNTING_START($cpdb[$i][1], // ruleno
$cpdb[$i][4], // username
$cpdb[$i][5], // sessionid
@@ -633,8 +625,10 @@ function captiveportal_disconnect($dbent, $radiusservers,$term_cause = 1,$stop_t
$stop_time);
}
/* Delete client's ip entry from tables 3 and 4. */
- mwexec("/sbin/ipfw table 3 delete {$dbent[2]}");
- mwexec("/sbin/ipfw table 4 delete {$dbent[2]}");
+ mwexec("/sbin/ipfw table 1 delete {$dbent[2]}");
+ mwexec("/sbin/ipfw table 2 delete {$dbent[2]}");
+ /* Release the ruleno so it can be reallocated to new clients. */
+ captiveportal_free_ipfw_ruleno($dbent[1]);
/*
* These are the pipe numbers we use to control traffic shaping for each logged in user via captive portal
@@ -645,7 +639,7 @@ function captiveportal_disconnect($dbent, $radiusservers,$term_cause = 1,$stop_t
mwexec("/sbin/ipfw pipe " . ($dbent[1]+20001) . " delete");
}
- /* Ensure all pf(4) states are killed. */
+ /* XXX: Redundant?! Ensure all pf(4) states are killed. */
mwexec("pfctl -k {$dbent[2]}");
mwexec("pfctl -K {$dbent[2]}");
@@ -664,7 +658,8 @@ function captiveportal_disconnect_client($id,$term_cause = 1) {
/* find entry */
$tmpindex = 0;
- for ($i = 0; $i < count($cpdb); $i++) {
+ $cpdbcount = count($cpdb);
+ for ($i = 0; $i < $cpdbcount; $i++) {
if ($cpdb[$i][1] == $id) {
captiveportal_disconnect($cpdb[$i], $radiusservers, $term_cause);
captiveportal_logportalauth($cpdb[$i][4], $cpdb[$i][3], $cpdb[$i][2], "DISCONNECT");
@@ -717,6 +712,7 @@ function captiveportal_passthrumac_configure($lock = false) {
/* clear out passthru macs, if necessary */
unlink_if_exists("{$g['vardb_path']}/captiveportal_mac.db");
+ $rules = "";
if (is_array($config['captiveportal']['passthrumac'])) {
$fd = @fopen("{$g['vardb_path']}/captiveportal_mac.db", "w");
@@ -726,69 +722,85 @@ function captiveportal_passthrumac_configure($lock = false) {
return 1;
}
+ $peruserbw = isset($config['captiveportal']['peruserbw']);
+ $macdb = "";
foreach ($config['captiveportal']['passthrumac'] as $macent) {
- /* record passthru mac so it can be recognized and let thru */
- fwrite($fd, $macent['mac'] . "\n");
+ $ruleno = captiveportal_get_next_ipfw_ruleno();
+
+ $macdb .= $macent['mac'] . "\n";
+
+ /* pfSense:
+ * pass through mac entries should always exist. the reason
+ * for this is because we do not have native mac address filtering
+ * mechanisms. this allows us to filter by mac address easily
+ * and get around this limitation. I consider this a bug in
+ * m0n0wall and pfSense as m0n0wall does not have native mac
+ * filtering mechanisms as well. -Scott Ullrich
+ *
+ * Add rules for traffic shaping.
+ * This assumes that net.inet.ip.fw.one_pass: 1 is set.
+ */
+
+ $actionup = "allow";
+ $actiondown = "allow";
+ if ($peruserbw) {
+ $bw_up = isset($macent['bw_up']) ? trim($macent['bw_up']) : $config['captiveportal']['bwdefaultup'];
+ $bw_down = isset($macent['bw_down']) ? trim($macent['bw_down']) : $config['captiveportal']['bwdefaultdn'];
+ if (!empty($bw_up) && is_numeric($bw_up)) {
+ $bw_up_pipeno = $ruleno + 20000;
+ $rules .= "pipe {$bw_up_pipeno} config bw {$bw_up}Kbit/s queue 100\n";
+ $actionup = "pipe {$bw_up_pipeno}";
+ }
+ if (!empty($bw_down) && is_numeric($bw_down)) {
+ $bw_down_pipeno = $ruleno + 20001;
+ $rules .= "pipe {$bw_down_pipeno} config bw {$bw_down}Kbit/s queue 100\n";
+ $actiondown = "pipe {$bw_down_pipeno}";
+ }
+ }
+ $rules .= "add {$ruleno} {$actionup} ip from any to any MAC {$macent['mac']} any\n";
+ $ruleno++;
+ $rules .= "add {$ruleno} {$actiondown} ip from any to any MAC any {$macent['mac']}\n";
}
-
+ /* record passthru MACs so can be recognized and let thru */
+ fwrite($fd, $macdb);
fclose($fd);
}
- /* pfSense:
- * pass through mac entries should always exist. the reason
- * for this is because we do not have native mac address filtering
- * mechanisms. this allows us to filter by mac address easily
- * and get around this limitation. I consider this a bug in
- * m0n0wall and pfSense as m0n0wall does not have native mac
- * filtering mechanisms as well. -Scott Ullrich
- */
- if (is_array($config['captiveportal']['passthrumac'])) {
- mwexec("/sbin/ipfw delete 50");
- foreach($config['captiveportal']['passthrumac'] as $ptm) {
- /* create the pass through mac entry */
- //system("echo /sbin/ipfw add 50 skipto 65535 ip from any to any MAC {$ptm['mac']} any > /tmp/cp");
- mwexec("/sbin/ipfw add 50 skipto 49900 ip from any to any MAC {$ptm['mac']} any keep-state");
- mwexec("/sbin/ipfw add 50 skipto 49900 ip from any to any MAC any {$ptm['mac']} keep-state");
- }
- }
-
if (!$lock)
unlock($captiveportallck);
- return 0;
+ return $rules;
}
function captiveportal_allowedip_configure() {
global $config, $g;
- /* clear out existing allowed ips, if necessary */
- mwexec("/sbin/ipfw table 1 flush");
- mwexec("/sbin/ipfw table 2 flush");
-
+ $rules = "";
if (is_array($config['captiveportal']['allowedip'])) {
- $tableone = false;
- $tabletwo = false;
+ $peruserbw = isset($config['captiveportal']['peruserbw']);
foreach ($config['captiveportal']['allowedip'] as $ipent) {
+ $ruleno = captiveportal_get_next_ipfw_ruleno();
+ $bw_up = "";
+ $bw_down = "";
+ if ($peruserbw) {
+ $bwup = isset($ipent['bw_up']) ? trim($ipent['bw_up']) : $config['captiveportal']['bwdefaultup'];
+ $bwdown = isset($ipent['bw_down']) ? trim($ipent['bw_down']) : $config['captiveportal']['bwdefaultdn'];
+ if (!empty($bwup) && is_numeric($bwup)) {
+ $bw_up = $ruleno + 20000;
+ $rules .= "pipe {$bw_up} config bw {$bw_up}Kbit/s queue 100\n";
+ }
+ if (!empty($bwdown) && is_numeric($bwdown)) {
+ $bw_down = $ruleno + 20001;
+ $rules .= "pipe {$bw_down} config bw {$bw_down}Kbit/s queue 100\n";
+ }
+ }
/* insert address in ipfw table */
- if ($ipent['dir'] == "from") {
- mwexec("/sbin/ipfw table 1 add {$ipent['ip']}");
- $tableone = true;
- } else {
- mwexec("/sbin/ipfw table 2 add {$ipent['ip']}");
- $tabletwo = true;
- }
- }
- if ($tableone == true) {
- mwexec("/sbin/ipfw add 1890 set 1 skipto 50000 ip from table\(1\) to any in");
- mwexec("/sbin/ipfw add 1891 set 1 skipto 50000 ip from any to table\(1\) out");
- }
- if ($tabletwo == true) {
- mwexec("/sbin/ipfw add 1892 set 1 skipto 50000 ip from any to table\(2\) in");
- mwexec("/sbin/ipfw add 1893 set 1 skipto 50000 ip from table\(2\) to any out");
+ $rules .= "table 1 add {$ipent['ip']} ${bw_up}\n";
+ $rules .= "table 2 add {$ipent['ip']} ${bw_down}\n";
}
}
- return 0;
+ return $rules;
}
/* get last activity timestamp given client IP address */
@@ -796,7 +808,7 @@ function captiveportal_get_last_activity($ip) {
$ipfwoutput = "";
- exec("/sbin/ipfw table 3 entrystats {$ip} 2>/dev/null", $ipfwoutput);
+ exec("/sbin/ipfw table 1 entrystats {$ip} 2>/dev/null", $ipfwoutput);
/* Reading only from one of the tables is enough of approximation. */
if ($ipfwoutput[0]) {
$ri = explode(" ", $ipfwoutput[0]);
@@ -974,6 +986,14 @@ function captiveportal_write_elements() {
return 0;
}
+function captiveportal_init_ipfw_ruleno($rulenos_start = 2000, $rulenos_range_max = 49899) {
+ global $g;
+
+ @unlink("{$g['vardb_path']}/captiveportal.rules");
+ $rules = array_pad(array(), $rulenos_range_max - $rulenos_start, false);
+ file_put_contents("{$g['vardb_path']}/captiveportal.rules", serialize($rules));
+}
+
/*
* This function will calculate the lowest free firewall ruleno
* within the range specified based on the actual logged on users
@@ -981,26 +1001,67 @@ function captiveportal_write_elements() {
*/
function captiveportal_get_next_ipfw_ruleno($rulenos_start = 2000, $rulenos_range_max = 49899) {
global $config, $g;
+
if(!isset($config['captiveportal']['enable']))
return NULL;
+
$ruleno = 0;
- if (file_exists("{$g['vardb_path']}/captiveportal.nextrule"))
- $ruleno = intval(file_get_contents("{$g['vardb_path']}/captiveportal.nextrule"));
- else
- $ruleno = 1;
- if ($ruleno > 0 && (($rulenos_start + $ruleno) < $rulenos_range_max)) {
- /*
- * This allows our traffic shaping pipes to be the in pipe the same as ruleno
- * and the out pipe ruleno + 1. This removes limitation that where present in
- * previous version of the peruserbw.
- */
+ if (file_exists("{$g['vardb_path']}/captiveportal.rules")) {
+ $rules = unserialize(file_get_contents("{$g['vardb_path']}/captiveportal.rules"));
+ for ($ridx = 2; $ridx < ($rulenos_range_max - $rulenos_start); $ridx++) {
+ if ($rules[$ridx]) {
+ /*
+ * This allows our traffic shaping pipes to be the in pipe the same as ruleno
+ * and the out pipe ruleno + 1. This removes limitation that where present in
+ * previous version of the peruserbw.
+ */
+ if (isset($config['captiveportal']['peruserbw']))
+ $ridx++;
+ continue;
+ }
+ $ruleno = $ridx;
+ $rules[$ridx] = "used";
+ if (isset($config['captiveportal']['peruserbw']))
+ $rules[++$ridx] = "used";
+ break;
+ }
+ } else {
+ $rules = array_pad(array(), $rulenos_range_max - $rulenos_start, false);
+ $rules[2] = "used";
+ $ruleno = 2;
+ }
+ file_put_contents("{$g['vardb_path']}/captiveportal.rules", serialize($rules));
+ return $ruleno;
+}
+
+function captiveportal_free_ipfw_ruleno($ruleno) {
+ global $config, $g;
+
+ if(!isset($config['captiveportal']['enable']))
+ return NULL;
+
+ if (file_exists("{$g['vardb_path']}/captiveportal.rules")) {
+ $rules = unserialize(file_get_contents("{$g['vardb_path']}/captiveportal.rules"));
+ $rules[$ruleno] = false;
if (isset($config['captiveportal']['peruserbw']))
- $ruleno += 2;
- else
- $ruleno++;
- file_put_contents("{$g['vardb_path']}/captiveportal.nextrule", $ruleno);
- return $rulenos_start + $ruleno;
+ $rules[++$ruleno] = false;
+ file_put_contents("{$g['vardb_path']}/captiveportal.rules", serialize($rules));
}
+}
+
+function captiveportal_get_ipfw_ruleno_byvalue($value) {
+ global $config, $g;
+
+ if(!isset($config['captiveportal']['enable']))
+ return NULL;
+
+ if (file_exists("{$g['vardb_path']}/captiveportal.rules")) {
+ $rules = unserialize(file_get_contents("{$g['vardb_path']}/captiveportal.rules"));
+ $ruleno = intval(`/sbin/ipfw show | /usr/bin/grep 00:0c:29:88:77:80 | /usr/bin/grep -v grep | /usr/bin/cut -d " " -f 1 | /usr/bin/head -n 1`);
+ if ($rules[$ruleno])
+ return $ruleno;
+ }
+
return NULL;
}
@@ -1027,14 +1088,14 @@ function getVolume($ip) {
$ipfwout = "";
$matchesin = "";
$matchesout = "";
- exec("/sbin/ipfw table 3 entrystats {$ip}", $ipfwin);
+ exec("/sbin/ipfw table 1 entrystats {$ip}", $ipfwin);
if ($ipfwin[0]) {
$ipfwin = split(" ", $ipfwin[0]);
$volume['input_pkts'] = $ipfwin[2];
$volume['input_bytes'] = $ipfwin[3];
}
- exec("/sbin/ipfw table 4 entrystats {$ip}", $ipfwout);
+ exec("/sbin/ipfw table 2 entrystats {$ip}", $ipfwout);
if ($ipfwout[0]) {
$ipfwout = split(" ", $ipfwout[0]);
$volume['output_pkts'] = $ipfwout[2];
diff --git a/usr/local/captiveportal/index.php b/usr/local/captiveportal/index.php
index 0011f0b..c2f886c 100755
--- a/usr/local/captiveportal/index.php
+++ b/usr/local/captiveportal/index.php
@@ -117,11 +117,13 @@ setTimeout('window.close();',5000) ;
</HTML>
EOD;
-/* The $macfilter can be removed safely since we first check if the $clientmac is present, if not we fail */
+/* NOTE: This is not needed now that CP works only at layer2.
+ * The $macfilter can be removed safely since we first check if the $clientmac is present, if not we fail
} else if ($clientmac && portal_mac_fixed($clientmac)) {
- /* punch hole in ipfw for pass thru mac addresses */
+ // punch hole in ipfw for pass thru mac addresses
portal_allow($clientip, $clientmac, "unauthenticated");
exit;
+*/
} else if ($clientmac && $radmac_enable && portal_mac_radius($clientmac,$clientip)) {
/* radius functions handle everything so we exit here since we're done */
@@ -307,6 +309,7 @@ function portal_allow($clientip,$clientmac,$username,$password = null, $attribut
return 0; // voucher already used and no time left
}
+ $writecfg = false;
if (!isset($sessionid)) {
/* generate unique session ID */
@@ -314,40 +317,69 @@ function portal_allow($clientip,$clientmac,$username,$password = null, $attribut
$sessionid = substr(md5(mt_rand() . $tod['sec'] . $tod['usec'] . $clientip . $clientmac), 0, 16);
/* Add rules for traffic shaping
- * We don't need to add extra l3 allow rules since traffic will pass due to the following kernel option
+ * We don't need to add extra rules since traffic will pass due to the following kernel option
* net.inet.ip.fw.one_pass: 1
*/
$peruserbw = isset($config['captiveportal']['peruserbw']);
-
+ $passthrumacadd = isset($config['captiveportal']['passthrumacadd']);
+
$bw_up = isset($attributes['bw_up']) ? trim($attributes['bw_up']) : $config['captiveportal']['bwdefaultup'];
$bw_down = isset($attributes['bw_down']) ? trim($attributes['bw_down']) : $config['captiveportal']['bwdefaultdn'];
+ if ($passthrumacadd) {
+ $mac = array();
+ $mac['mac'] = $clientmac;
+ if (!empty($bw_up))
+ $mac['bw_up'] = $bw_up;
+ if (!empty($bw_down))
+ $mac['bw_down'] = $bw_down;
+ if (!is_array($config['captiveportal']['passthrumac']))
+ $config['captiveportal']['passthrumac'] = array();
+ $config['captiveportal']['passthrumac'][] = $mac;
+ $writecfg = true;
+ }
+
if ($peruserbw && !empty($bw_up) && is_numeric($bw_up)) {
$bw_up_pipeno = $ruleno + 20000;
- mwexec("/sbin/ipfw pipe $bw_up_pipeno config bw {$bw_up}Kbit/s queue 100");
-
- if (!isset($config['captiveportal']['nomacfilter']))
- mwexec("/sbin/ipfw table 3 add {$clientip} mac {$clientmac} {$bw_up_pipeno}");
+ //$bw_up /= 1000; // Scale to Kbit/s
+ mwexec("/sbin/ipfw pipe {$bw_up_pipeno} config bw {$bw_up}Kbit/s queue 100");
+ mwexec("echo 'pipe {$bw_up_pipeno} config bw {$bw_up}Kbit/s queue 100' > /tmp/testing");
+
+ if ($passthrumacadd) {
+ mwexec("/sbin/ipfw add {$ruleno} pipe {$bw_up_pipeno} ip from any to any MAC {$clientmac} any");
+ } else if (!isset($config['captiveportal']['nomacfilter']))
+ mwexec("/sbin/ipfw table 1 add {$clientip} mac {$clientmac} {$bw_up_pipeno}");
else
- mwexec("/sbin/ipfw table 3 add {$clientip} {$bw_up_pipeno}");
+ mwexec("/sbin/ipfw table 1 add {$clientip} {$bw_up_pipeno}");
} else {
- if (!isset($config['captiveportal']['nomacfilter']))
- mwexec("/sbin/ipfw table 3 add {$clientip} mac {$clientmac}");
+ if ($passthrumacadd) {
+ mwexec("/sbin/ipfw add {$ruleno} allow ip from any to any MAC {$clientmac} any");
+ } else if (!isset($config['captiveportal']['nomacfilter']))
+ mwexec("/sbin/ipfw table 1 add {$clientip} mac {$clientmac}");
else
- mwexec("/sbin/ipfw table 3 add {$clientip}");
+ mwexec("/sbin/ipfw table 1 add {$clientip}");
}
if ($peruserbw && !empty($bw_down) && is_numeric($bw_down)) {
$bw_down_pipeno = $ruleno + 20001;
- mwexec("/sbin/ipfw pipe $bw_down_pipeno config bw {$bw_down}Kbit/s queue 100");
- if (!isset($config['captiveportal']['nomacfilter']))
- mwexec("/sbin/ipfw table 4 add {$clientip} mac {$clientmac} {$bw_down_pipeno}");
+ //$bw_down /= 1000; // Scale to Kbit/s
+ mwexec("/sbin/ipfw pipe {$bw_down_pipeno} config bw {$bw_down}Kbit/s queue 100");
+ mwexec("echo 'pipe {$bw_down_pipeno} config bw {$bw_down}Kbit/s queue 100' > /tmp/testing");
+
+ if ($passthrumacadd) {
+ $ruledown = $ruleno + 1;
+ mwexec("/sbin/ipfw add {$ruledown} pipe {$bw_down_pipeno} ip from any to any MAC any {$clientmac}");
+ } else if (!isset($config['captiveportal']['nomacfilter']))
+ mwexec("/sbin/ipfw table 2 add {$clientip} mac {$clientmac} {$bw_down_pipeno}");
else
- mwexec("/sbin/ipfw table 4 add {$clientip} {$bw_down_pipeno}");
+ mwexec("/sbin/ipfw table 2 add {$clientip} {$bw_down_pipeno}");
} else {
- if (!isset($config['captiveportal']['nomacfilter']))
- mwexec("/sbin/ipfw table 4 add {$clientip} mac {$clientmac}");
+ if ($passthrumacadd) {
+ $ruledown = $ruleno + 1;
+ mwexec("/sbin/ipfw add {$ruleno} allow ip from any to any MAC {$clientmac} any");
+ } else if (!isset($config['captiveportal']['nomacfilter']))
+ mwexec("/sbin/ipfw table 2 add {$clientip} mac {$clientmac}");
else
- mwexec("/sbin/ipfw table 4 add {$clientip}");
+ mwexec("/sbin/ipfw table 2 add {$clientip}");
}
if ($attributes['voucher'])
@@ -379,6 +411,9 @@ function portal_allow($clientip,$clientmac,$username,$password = null, $attribut
if ($captiveshouldunlock == true)
unlock($cplock);
+ if ($writecfg == true)
+ write_config();
+
/* redirect user to desired destination */
if ($url_redirection)
$my_redirurl = $url_redirection;
@@ -387,7 +422,7 @@ function portal_allow($clientip,$clientmac,$username,$password = null, $attribut
else
$my_redirurl = $redirurl;
- if(isset($config['captiveportal']['logoutwin_enable'])) {
+ if(isset($config['captiveportal']['logoutwin_enable']) && !isset($config['captiveportal']['passthrumacadd'])) {
if (isset($config['captiveportal']['httpslogin']))
$logouturl = "https://{$config['captiveportal']['httpsname']}:8001/";
@@ -456,7 +491,8 @@ function disconnect_client($sessionid, $logoutReason = "LOGOUT", $term_cause = 1
$radiusservers = captiveportal_get_radius_servers();
/* find entry */
- for ($i = 0; $i < count($cpdb); $i++) {
+ $dbcount = count($cpdb);
+ for ($i = 0; $i < $dbcount; $i++) {
if ($cpdb[$i][5] == $sessionid) {
captiveportal_disconnect($cpdb[$i],$radiusservers, $term_cause);
captiveportal_logportalauth($cpdb[$i][4],$cpdb[$i][3],$cpdb[$i][2],$logoutReason);
diff --git a/usr/local/www/services_captiveportal.php b/usr/local/www/services_captiveportal.php
index b79a5ac..99a943f 100755
--- a/usr/local/www/services_captiveportal.php
+++ b/usr/local/www/services_captiveportal.php
@@ -92,6 +92,7 @@ $pconfig['radiuskey'] = $config['captiveportal']['radiuskey'];
$pconfig['radiuskey2'] = $config['captiveportal']['radiuskey2'];
$pconfig['radiusvendor'] = $config['captiveportal']['radiusvendor'];
$pconfig['radiussession_timeout'] = isset($config['captiveportal']['radiussession_timeout']);
+$pconfig['passthrumacadd'] = isset($config['captiveportal']['passthrumacadd']);
$pconfig['radmac_format'] = $config['captiveportal']['radmac_format'];
if ($_POST) {
@@ -192,7 +193,8 @@ if ($_POST) {
$config['captiveportal']['radiuskey2'] = $_POST['radiuskey2'];
$config['captiveportal']['radiusvendor'] = $_POST['radiusvendor'] ? $_POST['radiusvendor'] : false;
$config['captiveportal']['radiussession_timeout'] = $_POST['radiussession_timeout'] ? true : false;
- $config['captiveportal']['radmac_format'] = $_POST['radmac_format'] ? $_POST['radmac_format'] : false;
+ $config['captiveportal']['passthrumacadd'] = $_POST['passthrumacadd'] ? true : false;
+ $config['captiveportal']['radmac_format'] = $_POST['radmac_format'] ? $_POST['radmac_format'] : false;
/* file upload? */
if (is_uploaded_file($_FILES['htmlfile']['tmp_name']))
@@ -362,6 +364,15 @@ to access after they've authenticated.</td>
If this is enabled, RADIUS MAC authentication cannot be used.</td>
</tr>
<tr>
+ <td valign="top" class="vncell">MAC passthrough</td>
+ <td class="vtable">
+ <input name="passthrumacadd" type="checkbox" class="formfld" id="passthrumacadd" value="yes" <?php if ($pconfig['passthrumacadd']) echo "checked"; ?>>
+ <strong>MAC passthrough authentication</strong><br>
+ If this option is set, after a user is authenticated a mac passthrough entry will be added.
+ To remove the passthrough MAC entry you either have to log in and remove it manually from the MAC passthrough tab or send a POST to remove it from some other system.
+ If this is enabled, RADIUS MAC authentication cannot be used. Also, the logout window will not be shown.</td>
+ </tr>
+ <tr>
<td valign="top" class="vncell">Per-user bandwidth restriction</td>
<td class="vtable">
<input name="peruserbw" type="checkbox" class="formfld" id="peruserbw" value="yes" <?php if ($pconfig['peruserbw']) echo "checked"; ?>>
diff --git a/usr/local/www/services_captiveportal_ip.php b/usr/local/www/services_captiveportal_ip.php
index 60d2792..1da30a1 100755
--- a/usr/local/www/services_captiveportal_ip.php
+++ b/usr/local/www/services_captiveportal_ip.php
@@ -54,10 +54,11 @@ $a_allowedips = &$config['captiveportal']['allowedip'] ;
if ($_GET['act'] == "del") {
if ($a_allowedips[$_GET['id']]) {
$ipent = $a_allowedips[$_GET['id']];
- if ($ipent['dir'] == "from")
+
+ if (isset($config['captiveportal']['enable'])) {
mwexec("/sbin/ipfw table 1 delete " . $ipent['ip']);
- else
mwexec("/sbin/ipfw table 2 delete " . $ipent['ip']);
+ }
unset($a_allowedips[$_GET['id']]);
write_config();
diff --git a/usr/local/www/services_captiveportal_ip_edit.php b/usr/local/www/services_captiveportal_ip_edit.php
index 93628ba..4e1b661 100755
--- a/usr/local/www/services_captiveportal_ip_edit.php
+++ b/usr/local/www/services_captiveportal_ip_edit.php
@@ -67,8 +67,9 @@ if (isset($_POST['id']))
if (isset($id) && $a_allowedips[$id]) {
$pconfig['ip'] = $a_allowedips[$id]['ip'];
+ $pconfig['bw_up'] = $a_allowedips[$id]['bw_up'];
+ $pconfig['bw_down'] = $a_allowedips[$id]['bw_down'];
$pconfig['descr'] = $a_allowedips[$id]['descr'];
- $pconfig['dir'] = $a_allowedips[$id]['dir'];
}
if ($_POST) {
@@ -85,6 +86,10 @@ if ($_POST) {
if (($_POST['ip'] && !is_ipaddr($_POST['ip']))) {
$input_errors[] = "A valid IP address must be specified. [".$_POST['ip']."]";
}
+ if ($_POST['bw_up'] && !is_numeric($_POST['bw_up']))
+ $input_errors[] = "Upload speed needs to be an integer";
+ if ($_POST['bw_down'] && !is_numeric($_POST['bw_down']))
+ $input_errors[] = "Download speed needs to be an integer";
foreach ($a_allowedips as $ipent) {
if (isset($id) && ($a_allowedips[$id]) && ($a_allowedips[$id] === $ipent))
@@ -100,8 +105,10 @@ if ($_POST) {
$ip = array();
$ip['ip'] = $_POST['ip'];
$ip['descr'] = $_POST['descr'];
- $ip['dir'] = $_POST['dir'];
-
+ if ($_POST['bw_up'])
+ $ip['bw_up'] = $_POST['bw_up'];
+ if ($_POST['bw_down'])
+ $ip['bw_down'] = $_POST['bw_down'];
if (isset($id) && $a_allowedips[$id])
$a_allowedips[$id] = $ip;
else
@@ -111,10 +118,7 @@ if ($_POST) {
write_config();
if (isset($config['captiveportal']['enable'])) {
- if ($ip['dir'] == "from")
- mwexec("/sbin/ipfw table 1 add " . $ip['ip']);
- else
- mwexec("/sbin/ipfw table 2 add " . $ip['ip']);
+ mwexec("/sbin/ipfw table 1 add " . $ip['ip']);
}
header("Location: services_captiveportal_ip.php");
@@ -130,7 +134,8 @@ include("head.inc");
<?php if ($input_errors) print_input_errors($input_errors); ?>
<form action="services_captiveportal_ip_edit.php" method="post" name="iform" id="iform">
<table width="100%" border="0" cellpadding="6" cellspacing="0">
- <tr>
+<?php if (false): ?>
+ <tr>
<td width="22%" valign="top" class="vncellreq">Direction</td>
<td width="78%" class="vtable">
<select name="dir" class="formselect">
@@ -146,20 +151,33 @@ include("head.inc");
<span class="vexpl">Use <em>From</em> to always allow an IP address through the captive portal (without authentication).
Use <em>To</em> to allow access from all clients (even non-authenticated ones) behind the portal to this IP address.</span></td>
</tr>
- <tr>
+<?php endif; ?>
+ <tr>
<td width="22%" valign="top" class="vncellreq">IP address</td>
<td width="78%" class="vtable">
<?=$mandfldhtml;?><input name="ip" type="text" class="formfld unknown" id="ip" size="17" value="<?=htmlspecialchars($pconfig['ip']);?>">
<br>
<span class="vexpl">IP address</span></td>
</tr>
- <tr>
+ <tr>
<td width="22%" valign="top" class="vncell">Description</td>
<td width="78%" class="vtable">
<input name="descr" type="text" class="formfld unknown" id="descr" size="40" value="<?=htmlspecialchars($pconfig['descr']);?>">
<br> <span class="vexpl">You may enter a description here
for your reference (not parsed).</span></td>
</tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Bandwidth up</td>
+ <td width="78%" class="vtable">
+ <input name="bw_up" type="text" class="formfld unknown" id="bw_up" size="10" value="<?=htmlspecialchars($pconfig['bw_up']);?>">
+ <br> <span class="vexpl">Enter a upload limit to be enforced on this mac-address in Kbit/s</span></td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Bandwidth down</td>
+ <td width="78%" class="vtable">
+ <input name="bw_down" type="text" class="formfld unknown" id="bw_down" size="10" value="<?=htmlspecialchars($pconfig['bw_down']);?>">
+ <br> <span class="vexpl">Enter a download limit to be enforced on this mac-address in Kbit/s</span></td>
+ </tr>
<tr>
<td width="22%" valign="top">&nbsp;</td>
<td width="78%">
diff --git a/usr/local/www/services_captiveportal_mac.php b/usr/local/www/services_captiveportal_mac.php
index 5080c0c..ca900bf 100755
--- a/usr/local/www/services_captiveportal_mac.php
+++ b/usr/local/www/services_captiveportal_mac.php
@@ -50,6 +50,7 @@ if (!is_array($config['captiveportal']['passthrumac']))
$a_passthrumacs = &$config['captiveportal']['passthrumac'] ;
+
if ($_POST) {
$pconfig = $_POST;
@@ -57,7 +58,9 @@ if ($_POST) {
if ($_POST['apply']) {
$retval = 0;
- $retval = captiveportal_passthrumac_configure();
+ $rules = captiveportal_passthrumac_configure();
+ file_put_contents("{$g['tmp_path']}/passthru.mac", $rules);
+ mwexec("/sbin/ipfw {$g['tmp_path']}/passthru.mac");
$savemsg = get_std_save_message($retval);
if ($retval == 0)
@@ -67,10 +70,17 @@ if ($_POST) {
if ($_GET['act'] == "del") {
if ($a_passthrumacs[$_GET['id']]) {
+ $ruleno = captiveportal_get_ipfw_ruleno_byvalue($a_passthrumacs[$_GET['id']]['mac']);
+ if ($ruleno) {
+ mwexec("/sbin/ipfw delete {$ruleno}");
+ captiveportal_free_ipfw_ruleno($ruleno);
+ $ruleno++;
+ mwexec("/sbin/ipfw delete {$ruleno}");
+ }
unset($a_passthrumacs[$_GET['id']]);
write_config();
- mark_subsystem_dirty('passthrumac');
header("Location: services_captiveportal_mac.php");
+ //mark_subsystem_dirty('passthrumac');
exit;
}
}
diff --git a/usr/local/www/services_captiveportal_mac_edit.php b/usr/local/www/services_captiveportal_mac_edit.php
index 9123303..f618d47 100755
--- a/usr/local/www/services_captiveportal_mac_edit.php
+++ b/usr/local/www/services_captiveportal_mac_edit.php
@@ -66,6 +66,8 @@ if (isset($_POST['id']))
if (isset($id) && $a_passthrumacs[$id]) {
$pconfig['mac'] = $a_passthrumacs[$id]['mac'];
+ $pconfig['bw_up'] = $a_passthrumacs[$id]['bw_up'];
+ $pconfig['bw_down'] = $a_passthrumacs[$id]['bw_down'];
$pconfig['descr'] = $a_passthrumacs[$id]['descr'];
}
@@ -85,6 +87,10 @@ if ($_POST) {
if (($_POST['mac'] && !is_macaddr($_POST['mac']))) {
$input_errors[] = "A valid MAC address must be specified. [".$_POST['mac']."]";
}
+ if ($_POST['bw_up'] && !is_numeric($_POST['bw_up']))
+ $input_errors[] = "Upload speed needs to be an integer";
+ if ($_POST['bw_down'] && !is_numeric($_POST['bw_down']))
+ $input_errors[] = "Download speed needs to be an integer";
foreach ($a_passthrumacs as $macent) {
if (isset($id) && ($a_passthrumacs[$id]) && ($a_passthrumacs[$id] === $macent))
@@ -99,6 +105,11 @@ if ($_POST) {
if (!$input_errors) {
$mac = array();
$mac['mac'] = $_POST['mac'];
+ if ($_POST['bw_up'])
+ $mac['bw_up'] = $_POST['bw_up'];
+ if ($_POST['bw_down'])
+ $mac['bw_down'] = $_POST['bw_down'];
+
$mac['descr'] = $_POST['descr'];
if (isset($id) && $a_passthrumacs[$id])
@@ -109,7 +120,7 @@ if ($_POST) {
write_config();
- mark_subsystem_dirty('passthrumac');
+ //mark_subsystem_dirty('passthrumac');
header("Location: services_captiveportal_mac.php");
exit;
@@ -129,13 +140,25 @@ include("head.inc");
<br>
<span class="vexpl">MAC address (6 hex octets separated by colons)</span></td>
</tr>
- <tr>
+ <tr>
<td width="22%" valign="top" class="vncell">Description</td>
<td width="78%" class="vtable">
<input name="descr" type="text" class="formfld unknown" id="descr" size="40" value="<?=htmlspecialchars($pconfig['descr']);?>">
<br> <span class="vexpl">You may enter a description here
for your reference (not parsed).</span></td>
</tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Bandwidth up</td>
+ <td width="78%" class="vtable">
+ <input name="bw_up" type="text" class="formfld unknown" id="bw_up" size="10" value="<?=htmlspecialchars($pconfig['bw_up']);?>">
+ <br> <span class="vexpl">Enter a upload limit to be enforced on this mac-address in Kbit/s</span></td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell">Bandwidth down</td>
+ <td width="78%" class="vtable">
+ <input name="bw_down" type="text" class="formfld unknown" id="bw_down" size="10" value="<?=htmlspecialchars($pconfig['bw_down']);?>">
+ <br> <span class="vexpl">Enter a download limit to be enforced on this mac-address in Kbit/s</span></td>
+ </tr>
<tr>
<td width="22%" valign="top">&nbsp;</td>
<td width="78%">
OpenPOWER on IntegriCloud