summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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