diff options
Diffstat (limited to 'etc')
-rw-r--r-- | etc/inc/captiveportal.inc | 641 | ||||
-rw-r--r-- | etc/inc/gwlb.inc | 4 | ||||
-rw-r--r-- | etc/inc/interfaces.inc | 27 | ||||
-rw-r--r-- | etc/inc/openvpn.inc | 4 | ||||
-rw-r--r-- | etc/inc/services.inc | 10 | ||||
-rw-r--r-- | etc/inc/shaper.inc | 2 | ||||
-rw-r--r-- | etc/inc/voucher.inc | 12 | ||||
-rwxr-xr-x | etc/rc.bootup | 6 | ||||
-rwxr-xr-x | etc/rc.linkup | 47 |
9 files changed, 380 insertions, 373 deletions
diff --git a/etc/inc/captiveportal.inc b/etc/inc/captiveportal.inc index f6f6bcd..23ac756 100644 --- a/etc/inc/captiveportal.inc +++ b/etc/inc/captiveportal.inc @@ -104,8 +104,9 @@ EOD; if(isset($config['voucher'][$cpzone]['enable'])) { $htmltext .= <<<EOD - <tr><td> + <tr><td align="right"> Enter Voucher Code: + </td><td> <input name="auth_voucher" type="text" style="border:1px dashed;" size="22"> </td></tr> @@ -155,9 +156,9 @@ function captiveportal_load_modules() { /* make sure ipfw is not on pfil hooks */ mwexec("/sbin/sysctl net.inet.ip.pfil.inbound=\"pf\" net.inet6.ip6.pfil.inbound=\"pf\"" . " net.inet.ip.pfil.outbound=\"pf\" net.inet6.ip6.pfil.outbound=\"pf\""); + /* Activate layer2 filtering */ + mwexec("/sbin/sysctl net.link.ether.ipfw=1 net.inet.ip.fw.one_pass=1"); } - /* Activate layer2 filtering */ - mwexec("/sbin/sysctl net.link.ether.ipfw=1"); /* Always load dummynet now that even allowed ip and mac passthrough use it. */ if (!is_module_loaded("dummynet.ko")) { @@ -198,30 +199,20 @@ function captiveportal_configure_zone($cpcfg) { if (isset($cpcfg['enable'])) { - if ($g['booting']) + if ($g['booting']) { echo "Starting captive portal({$cpcfg['zone']})... "; - else - captiveportal_syslog("Restarting captive portal({$cpcfg['zone']})."); - /* kill any running mini_httpd */ - killbypid("{$g['varrun_path']}/lighty-{$cpzone}-CaptivePortal.pid"); - killbypid("{$g['varrun_path']}/lighty-{$cpzone}-CaptivePortal-SSL.pid"); + /* remove old information */ + unlink_if_exists("{$g['vardb_path']}/captiveportal{$cpzone}.db"); + } else + captiveportal_syslog("Reconfiguring captive portal({$cpcfg['zone']})."); - /* remove old information */ - unlink_if_exists("{$g['vardb_path']}/captiveportal_{$cpzone}.db"); - unlink_if_exists("{$g['vardb_path']}/captiveportal_mac_{$cpzone}.db"); - unlink_if_exists("{$g['vardb_path']}/captiveportal_ip_{$cpzone}.db"); - unlink_if_exists("{$g['vardb_path']}/captiveportal_radius_{$cpzone}.db"); - - /* setup new database in case someone tries to access the status -> captive portal page */ - touch("{$g['vardb_path']}/captiveportal_{$cpzone}.db"); + /* init ipfw rules */ + captiveportal_init_rules(true); /* kill any running minicron */ killbypid("{$g['varrun_path']}/cp_prunedb_{$cpzone}.pid"); - /* init ipfw rules */ - captiveportal_init_rules(true); - /* initialize minicron interval value */ $croninterval = $cpcfg['croninterval'] ? $cpcfg['croninterval'] : 60; @@ -335,6 +326,10 @@ EOD; /* write elements */ captiveportal_write_elements(); + /* kill any running mini_httpd */ + killbypid("{$g['varrun_path']}/lighty-{$cpzone}-CaptivePortal.pid"); + killbypid("{$g['varrun_path']}/lighty-{$cpzone}-CaptivePortal-SSL.pid"); + /* start up the webserving daemon */ captiveportal_init_webgui_zone($cpcfg); @@ -347,6 +342,7 @@ EOD; "/etc/rc.prunecaptiveportal {$cpzone}"); /* generate radius server database */ + unlink_if_exists("{$g['vardb_path']}/captiveportal_radius_{$cpzone}.db"); captiveportal_init_radius_servers(); if ($g['booting']) @@ -360,9 +356,7 @@ EOD; @unlink("{$g['varetc_path']}/captiveportal-{$cpzone}-error.html"); @unlink("{$g['varetc_path']}/captiveportal-{$cpzone}-logout.html"); /* remove old information */ - unlink_if_exists("{$g['vardb_path']}/captiveportal_{$cpzone}.db"); - unlink_if_exists("{$g['vardb_path']}/captiveportal_mac_{$cpzone}.db"); - unlink_if_exists("{$g['vardb_path']}/captiveportal_ip_{$cpzone}.db"); + unlink_if_exists("{$g['vardb_path']}/captiveportal{$cpzone}.db"); unlink_if_exists("{$g['vardb_path']}/captiveportal_radius_{$cpzone}.db"); captiveportal_radius_stop_all(); @@ -429,14 +423,14 @@ function captiveportal_init_webgui_zone($cpcfg) { $listenporthttps = $cpcfg['listenporthttps'] ? $cpcfg['listenporthttps'] : ($cpcfg['zoneid'] + 1); system_generate_lighty_config("{$g['varetc_path']}/lighty-{$cpzone}-CaptivePortal-SSL.conf", $crt, $key, $ca, "lighty-{$cpzone}-CaptivePortal-SSL.pid", $listenporthttps, "/usr/local/captiveportal", - "cert-portal.pem", "ca-portal.pem", "1", $use_fastcgi, $cpzone); + "cert-{$cpzone}-portal.pem", "ca-{$cpzone}-portal.pem", "1", $use_fastcgi, $cpzone); } /* generate lighttpd configuration */ $listenporthttp = $cpcfg['listenporthttp'] ? $cpcfg['listenporthttp'] : $cpcfg['zoneid']; system_generate_lighty_config("{$g['varetc_path']}/lighty-{$cpzone}-CaptivePortal.conf", "", "", "", "lighty-{$cpzone}-CaptivePortal.pid", $listenporthttp, "/usr/local/captiveportal", - "cert-portal.pem", "ca-portal.pem", "1", $use_fastcgi, $cpzone); + "", "", "1", $use_fastcgi, $cpzone); /* attempt to start lighttpd */ $res = mwexec("/usr/local/sbin/lighttpd -f {$g['varetc_path']}/lighty-{$cpzone}-CaptivePortal.conf"); @@ -491,9 +485,6 @@ function captiveportal_init_rules($reinit = false) { if ($reinit == false) $captiveportallck = lock("captiveportal{$cpzone}"); - /* init dummynet/ipfw rules number database */ - captiveportal_init_ipfw_ruleno(); - $cprules = "add 65291 allow pfsync from any to any\n"; $cprules .= "add 65292 allow carp from any to any\n"; @@ -531,21 +522,9 @@ EOD; $cprules .= "add {$rulenum} pass icmp from any to {$ips} in icmptype 8 \n"; $rulenum++; /* Allowed ips */ - $cprules .= "add {$rulenum} allow ip from table(3) to any in\n"; - $rulenum++; - $cprules .= "add {$rulenum} allow ip from any to table(4) out\n"; - $rulenum++; - $cprules .= "add {$rulenum} pipe tablearg ip from table(5) to any in\n"; - $rulenum++; - $cprules .= "add {$rulenum} pipe tablearg ip from any to table(6) out\n"; + $cprules .= "add {$rulenum} pipe tablearg ip from table(3) to any in\n"; $rulenum++; - $cprules .= "add {$rulenum} allow ip from any to table(7) in\n"; - $rulenum++; - $cprules .= "add {$rulenum} allow ip from table(8) to any out\n"; - $rulenum++; - $cprules .= "add {$rulenum} pipe tablearg ip from any to table(9) in\n"; - $rulenum++; - $cprules .= "add {$rulenum} pipe tablearg ip from table(10) to any out\n"; + $cprules .= "add {$rulenum} pipe tablearg ip from any to table(4) out\n"; $rulenum++; /* Authenticated users rules. */ @@ -559,7 +538,7 @@ EOD; $config['captiveportal'][$cpzone]['listenporthttp'] : $config['captiveportal'][$cpzone]['zoneid']; - if (isset($cpcfg['httpslogin'])) { + if (isset($config['captiveportal'][$cpzone]['httpslogin'])) { $listenporthttps = $listenporthttp + 1; $cprules .= "add 65531 fwd 127.0.0.1,{$listenporthttps} tcp from any to any dst-port 443 in\n"; } @@ -586,21 +565,7 @@ EOD; $cprules .= captiveportal_allowedhostname_configure(); /* load rules */ - if ($reinit == true) - $cprules = "table all flush\nflush\n{$cprules}"; - else { - $tmprules = "table 3 flush\n"; - $tmprules .= "table 4 flush\n"; - $tmprules .= "table 5 flush\n"; - $tmprules .= "table 6 flush\n"; - $tmprules .= "table 7 flush\n"; - $tmprules .= "table 8 flush\n"; - $tmprules .= "table 9 flush\n"; - $tmprules .= "table 10 flush\n"; - $tmprules .= "flush\n"; - $cprules = "{$tmprules}\n{$cprules}"; - } - + $cprules = "flush\n{$cprules}"; file_put_contents("{$g['tmp_path']}/ipfw_{$cpzone}.cp.rules", $cprules); captiveportal_ipfw_set_context($cpzone); mwexec("/sbin/ipfw -q {$g['tmp_path']}/ipfw_{$cpzone}.cp.rules", true); @@ -609,11 +574,6 @@ EOD; if ($reinit == false) unlock($captiveportallck); - - /* activate ipfw(4) so CP can work */ - mwexec("/sbin/sysctl net.link.ether.ipfw=1"); - /* Make sure not re-entrancy is allowed in ipfw(4) */ - mwexec("/sbin/sysctl net.inet.ip.fw.one_pass=1"); } /* @@ -647,7 +607,8 @@ function captiveportal_prune_old() { $radiussrvs = captiveportal_get_radius_servers(); - /* read database */ + /* Read database */ + /* NOTE: while this can be simplified in non radius case keep as is for now */ $cpdb = captiveportal_read_db(); /* @@ -788,7 +749,7 @@ function captiveportal_prune_old() { /* write database */ if (!empty($unsetindexes)) - captiveportal_write_db($cpdb, false, $unsetindexes); + captiveportal_remove_entries($unsetindexes); } function captiveportal_prune_old_automac() { @@ -803,12 +764,19 @@ function captiveportal_prune_old_automac() { if (isset($tmpvoucherdb[$emac['username']])) { $temac = $config['captiveportal'][$cpzone]['passthrumac'][$tmpvoucherdb[$emac['username']]]; $ruleno = captiveportal_get_ipfw_passthru_ruleno($temac['mac']); + $pipeno = captiveportal_get_dn_passthru_ruleno($temac['mac']); if ($ruleno) { - captiveportal_free_ipfw_ruleno($ruleno, true); + captiveportal_free_ipfw_ruleno($ruleno); $macrules .= "delete {$ruleno}"; ++$ruleno; $macrules .= "delete {$ruleno}"; } + if ($pipeno) { + captiveportal_free_dn_ruleno($pipeno); + $macrules .= "pipe delete {$pipeno}\n"; + ++$pipeno; + $macrules .= "pipe delete {$pipeno}\n"; + } $writecfg = true; captiveportal_logportalauth($temac['username'], $temac['mac'], $temac['ip'], "DUPLICATE {$temac['username']} LOGIN - TERMINATING OLD SESSION"); unset($config['captiveportal'][$cpzone]['passthrumac'][$tmpvoucherdb[$emac['username']]]); @@ -816,12 +784,19 @@ function captiveportal_prune_old_automac() { $tmpvoucherdb[$emac['username']] = $eid; if (voucher_auth($emac['username']) <= 0) { $ruleno = captiveportal_get_ipfw_passthru_ruleno($emac['mac']); + $pipeno = captiveportal_get_dn_passthru_ruleno($emac['mac']); if ($ruleno) { - captiveportal_free_ipfw_ruleno($ruleno, true); + captiveportal_free_ipfw_ruleno($ruleno); $macrules .= "delete {$ruleno}"; ++$ruleno; $macrules .= "delete {$ruleno}"; } + if ($pipeno) { + captiveportal_free_dn_ruleno($pipeno); + $macrules .= "pipe delete {$pipeno}\n"; + ++$pipeno; + $macrules .= "pipe delete {$pipeno}\n"; + } $writecfg = true; captiveportal_logportalauth($emac['username'], $emac['mac'], $emac['ip'], "EXPIRED {$emac['username']} LOGIN - TERMINATING SESSION"); unset($config['captiveportal'][$cpzone]['passthrumac'][$eid]); @@ -860,9 +835,9 @@ function captiveportal_disconnect($dbent, $radiusservers,$term_cause = 1,$stop_t if (is_ipaddr($dbent[2])) { captiveportal_ipfw_set_context($cpzone); - /* Delete client's ip entry from tables 3 and 4. */ - pfSense_ipfw_Tableaction($cpzone, 1, IP_FW_TABLE_DEL, $dbent[2]); - pfSense_ipfw_Tableaction($cpzone, 2, IP_FW_TABLE_DEL, $dbent[2]); + /* Delete client's ip entry from tables 1 and 2. */ + pfSense_ipfw_Tableaction($cpzone, IP_FW_TABLE_DEL, 1, $dbent[2]); + pfSense_ipfw_Tableaction($cpzone, IP_FW_TABLE_DEL, 2, $dbent[2]); /* XXX: Redundant?! Ensure all pf(4) states are killed. */ pfSense_kill_states($dbent[2]); pfSense_kill_srcstates($dbent[2]); @@ -873,11 +848,11 @@ function captiveportal_disconnect($dbent, $radiusservers,$term_cause = 1,$stop_t * We could get an error if the pipe doesn't exist but everything should still be fine */ if (!empty($dbent[1])) { - pfSense_pipe_action("pipe delete " . ($dbent[1]+20000)); - pfSense_pipe_action("pipe delete " . ($dbent[1]+20001)); + pfSense_pipe_action("pipe delete {$dbent[1]}"); + pfSense_pipe_action("pipe delete " . ($dbent[1]+1)); /* Release the ruleno so it can be reallocated to new clients. */ - captiveportal_free_ipfw_ruleno($dbent[1]); + captiveportal_free_dn_ruleno($dbent[1]); } // XMLRPC Call over to the master Voucher node @@ -893,25 +868,23 @@ function captiveportal_disconnect($dbent, $radiusservers,$term_cause = 1,$stop_t /* remove a single client by sessionid */ function captiveportal_disconnect_client($sessionid, $term_cause = 1, $logoutReason = "LOGOUT") { - global $g, $config, $cpzone; + global $g, $config; $radiusservers = captiveportal_get_radius_servers(); - $unsetindex = array(); /* read database */ - $cpdb = captiveportal_read_db(); + $cpentry = captiveportal_read_db("WHERE sessionid = '{$sessionid}'"); /* find entry */ - if (isset($cpdb[$sessionid])) { - $cpentry = $cpdb[$sessionid]; - /* write database */ - $unsetindex[] = $sessionid; - captiveportal_write_db($cpdb, false, $unsetindex); + if (!empty($cpentry)) { + captiveportal_write_db("DELETE FROM captiveportal WHERE sessionid = '{$sessionid}'"); + if (empty($cpentry[10])) $cpentry[10] = 'first'; captiveportal_disconnect($cpentry, $radiusservers[$cpentry[10]], $term_cause); captiveportal_logportalauth($cpentry[4], $cpentry[3], $cpentry[2], "DISCONNECT"); - } + unset($cpentry); + } } /* send RADIUS acct stop for all current clients */ @@ -942,27 +915,21 @@ function captiveportal_radius_stop_all() { } function captiveportal_passthrumac_configure_entry($macent) { - $rules = ""; - $enBwup = isset($macent['bw_up']); - $enBwdown = isset($macent['bw_down']); - $actionup = "allow"; - $actiondown = "allow"; + + $bwUp = empty($macent['bw_up']) ? 0 : $macent['bw_up']; + $bwDown = empty($macent['bw_down']) ? 0 : $macent['bw_down']; $ruleno = captiveportal_get_next_ipfw_ruleno(); + $pipeno = captiveportal_get_next_dn_ruleno(); - if ($enBwup) { - $bw_up = $ruleno + 20000; - $rules .= "pipe {$bw_up} config bw {$macent['bw_up']}Kbit/s queue 100\n"; - $actionup = "pipe {$bw_up}"; - } - if ($enBwdown) { - $bw_down = $ruleno + 20001; - $rules .= "pipe {$bw_down} config bw {$macent['bw_down']}Kbit/s queue 100\n"; - $actiondown = "pipe {$bw_down}"; - } - $rules .= "add {$ruleno} {$actiondown} ip from any to any MAC {$macent['mac']} any\n"; + $rules = ""; + $pipeup = $pipeno; + $rules .= "pipe {$pipeup} config bw {$bwUp}Kbit/s queue 100 buckets 16\n"; + $pipedown = $pipeno + 1; + $rules .= "pipe {$pipedown} config bw {$bwDown}Kbit/s queue 100 buckets 16\n"; + $rules .= "add {$ruleno} pipe {$pipeup} ip from any to any MAC {$macent['mac']} any\n"; $ruleno++; - $rules .= "add {$ruleno} {$actionup} ip from any to any MAC any {$macent['mac']}\n"; + $rules .= "add {$ruleno} pipe {$pipedown} ip from any to any MAC any {$macent['mac']}\n"; return $rules; } @@ -998,9 +965,8 @@ function captiveportal_passthrumac_findbyname($username) { /* * table (3=IN)/(4=OUT) hold allowed ip's without bw limits - * table (5=IN)/(6=OUT) hold allowed ip's with bw limit. */ -function captiveportal_allowedip_configure_entry($ipent) { +function captiveportal_allowedip_configure_entry($ipent, $ishostname = false) { /* This function can deal with hostname or ipaddress */ if($ipent['ip']) @@ -1009,107 +975,56 @@ function captiveportal_allowedip_configure_entry($ipent) { /* Instead of copying this entire function for something * easy such as hostname vs ip address add this check */ - if($ipent['hostname']) { + if(!empty($ipent['hostname'])) { $ipaddress = gethostbyname($ipent['hostname']); if(!is_ipaddr($ipaddress)) return; } $rules = ""; - $enBwup = intval($ipent['bw_up']); - $enBwdown = intval($ipent['bw_down']); - $bw_up = ""; - $bw_down = ""; - $tablein = array(); - $tableout = array(); - - $ruleno = captiveportal_get_next_ipfw_ruleno(); - - if ($ipent['dir'] == "from") { - if ($enBwup) - $tablein[] = 5; - else - $tablein[] = 3; - if ($enBwdown) - $tableout[] = 6; - else - $tableout[] = 4; - } else if ($ipent['dir'] == "to") { - if ($enBwup) - $tablein[] = 9; - else - $tablein[] = 7; - if ($enBwdown) - $tableout[] = 10; - else - $tableout[] = 8; - } else if ($ipent['dir'] == "both") { - if ($enBwup) { - $tablein[] = 5; - $tablein[] = 9; - } else { - $tablein[] = 3; - $tablein[] = 7; - } - if ($enBwdown) { - $tableout[] = 6; - $tableout[] = 10; - } else { - $tableout[] = 4; - $tableout[] = 8; - } - } - if ($enBwup) { - $bw_up = $ruleno + 20000; - $rules .= "pipe {$bw_up} config bw {$ipent['bw_up']}Kbit/s queue 100\n"; + $cp_filterdns_conf = ""; + $enBwup = empty($ipent['bw_up']) ? 0 : intval($ipent['bw_up']); + $enBwdown = empty($ipent['bw_down']) ? 0 : intval($ipent['bw_down']); + + $pipeno = captiveportal_get_next_dn_ruleno(); + $rules .= "pipe {$pipeno} config bw {$ipent['bw_up']}Kbit/s queue 100 buckets 16\n"; + $pipedown = $pipeno + 1; + $rules .= "pipe {$pipedown} config bw {$ipent['bw_down']}Kbit/s queue 100 buckets 16\n"; + if ($ishostname === true) { + $cp_filterdns_conf .= "ipfw {$ipent['hostname']} 3 pipe {$pipeno}\n"; + $cp_filterdns_conf .= "ipfw {$ipent['hostname']} 4 pipe {$pipedown}\n"; } $subnet = ""; if (!empty($ipent['sn'])) $subnet = "/{$ipent['sn']}"; - foreach ($tablein as $table) - $rules .= "table {$table} add {$ipaddress}{$subnet} {$bw_up}\n"; - if ($enBwdown) { - $bw_down = $ruleno + 20001; - $rules .= "pipe {$bw_down} config bw {$ipent['bw_down']}Kbit/s queue 100\n"; - } - foreach ($tableout as $table) - $rules .= "table {$table} add {$ipaddress}{$subnet} {$bw_down}\n"; - - return $rules; -} + $rules .= "table 3 add {$ipaddress}{$subnet} {$pipeno}\n"; + $rules .= "table 4 add {$ipaddress}{$subnet} {$pipedown}\n"; -/* - Adds a dnsfilter entry and watches for hostname changes. - A change results in reloading the ruleset. -*/ -function setup_dnsfilter_entries() { - global $g, $config, $cpzone; - - $cp_filterdns_filename = "{$g['varetc_path']}/filterdns-{$cpzone}-captiveportal.conf"; - $cp_filterdns_conf = ""; - if (is_array($config['captiveportal'][$cpzone]['allowedhostname'])) { - foreach ($config['captiveportal'][$cpzone]['allowedhostname'] as $hostnameent) { - $cp_filterdns_conf .= "ipfw {$hostnameent['hostname']} 3\n"; - $cp_filterdns_conf .= "ipfw {$hostnameent['hostname']} 4\n"; - $cp_filterdns_conf .= "ipfw {$hostnameent['hostname']} 7\n"; - $cp_filterdns_conf .= "ipfw {$hostnameent['hostname']} 8\n"; - } - } - file_put_contents($cp_filterdns_filename, $cp_filterdns_conf); - unset($cp_filterdns_conf); - killbypid("{$g['tmp_path']}/filterdns-{$cpzone}-cpah.pid"); - mwexec("/usr/local/sbin/filterdns -p {$g['tmp_path']}/filterdns-{$cpzone}-cpah.pid -i 300 -c {$cp_filterdns_filename} -y {$cpzone} -d 1"); + if ($ishostname === true) + return array($rules, $cp_filterdns_conf); + else + return $rules; } function captiveportal_allowedhostname_configure() { global $config, $g, $cpzone; - $rules = "\n# captiveportal_allowedhostname_configure()\n"; - setup_dnsfilter_entries(); + $rules = ""; if (is_array($config['captiveportal'][$cpzone]['allowedhostname'])) { - foreach ($config['captiveportal'][$cpzone]['allowedhostname'] as $hostnameent) - $rules .= captiveportal_allowedip_configure_entry($hostnameent); + $rules = "\n# captiveportal_allowedhostname_configure()\n"; + $cp_filterdns_conf = ""; + foreach ($config['captiveportal'][$cpzone]['allowedhostname'] as $hostnameent) { + $tmprules = captiveportal_allowedip_configure_entry($hostnameent, true); + $rules .= $tmprules[0]; + $cp_filterdns_conf .= $tmprules[1]; + } + $cp_filterdns_filename = "{$g['varetc_path']}/filterdns-{$cpzone}-captiveportal.conf"; + @file_put_contents($cp_filterdns_filename, $cp_filterdns_conf); + unset($cp_filterdns_conf); + killbypid("{$g['tmp_path']}/filterdns-{$cpzone}-cpah.pid"); + mwexec("/usr/local/sbin/filterdns -p {$g['tmp_path']}/filterdns-{$cpzone}-cpah.pid -i 300 -c {$cp_filterdns_filename} -y {$cpzone} -d 1"); } + return $rules; } @@ -1129,15 +1044,11 @@ function captiveportal_allowedip_configure() { function captiveportal_get_last_activity($ip) { global $cpzone; - $ipfwoutput = ""; - captiveportal_ipfw_set_context($cpzone); - exec("/sbin/ipfw table 1 entrystats {$ip} 2>/dev/null", $ipfwoutput); + $ipfwoutput = pfSense_ipfw_getTablestats($cpzone, 1, $ip); /* Reading only from one of the tables is enough of approximation. */ - if ($ipfwoutput[0]) { - $ri = explode(" ", $ipfwoutput[0]); - if ($ri[4]) - return $ri[4]; + if (is_array($ipfwoutput)) { + return $ipfwoutput['timestamp']; } return 0; @@ -1262,10 +1173,10 @@ function captiveportal_syslog($message) { function radius($username,$password,$clientip,$clientmac,$type, $radiusctx = null) { global $g, $config; - $ruleno = captiveportal_get_next_ipfw_ruleno(); + $pipeno = captiveportal_get_next_dn_ruleno(); /* If the pool is empty, return appropriate message and fail authentication */ - if (is_null($ruleno)) { + if (is_null($pipeno)) { $auth_list = array(); $auth_list['auth_val'] = 1; $auth_list['error'] = "System reached maximum login capacity"; @@ -1282,7 +1193,7 @@ function radius($username,$password,$clientip,$clientmac,$type, $radiusctx = nul $radiusservers[$radiusctx], $clientip, $clientmac, - $ruleno); + $pipeno); if ($auth_list['auth_val'] == 2) { captiveportal_logportalauth($username,$clientmac,$clientip,$type); @@ -1291,69 +1202,92 @@ function radius($username,$password,$clientip,$clientmac,$type, $radiusctx = nul $username, $password, $auth_list, - $ruleno, + $pipeno, $radiusctx); } return $auth_list; } -/* read captive portal DB into array */ -function captiveportal_read_db($locked = false, $index = 5 /* sessionid by default */) { +function captiveportal_opendb() { global $g, $cpzone; - $cpdb = array(); - - if ($locked == false) - $cpdblck = lock("captiveportaldb{$cpzone}"); - $fd = @fopen("{$g['vardb_path']}/captiveportal_{$cpzone}.db", "r"); - if ($fd) { - while (!feof($fd)) { - $line = trim(fgets($fd)); - if ($line) { - $cpe = explode(",", $line); - /* Hash by session id */ - $cpdb[$cpe[$index]] = $cpe; - } - } - fclose($fd); + if (file_exists("{$g['vardb_path']}/captiveportal{$cpzone}.db")) + $DB = @sqlite_open("{$g['vardb_path']}/captiveportal{$cpzone}.db"); + else { + $errormsg = ""; + $DB = @sqlite_open("{$g['vardb_path']}/captiveportal{$cpzone}.db"); + if (@sqlite_exec($DB, "CREATE TABLE captiveportal (allow_time INTEGER, ruleno INTEGER, ip TEXT, mac TEXT, username TEXT, sessionid TEXT, bpassword TEXT, session_timeout INTEGER, idle_timeout INTEGER, session_terminate_time INTEGER) ", $errormsg)) { + @sqlite_exec($DB, "CREATE UNIQUE INDEX idx_active ON captiveportal (sessionid, username)"); + @sqlite_exec($DB, "CREATE INDEX user ON captiveportal (username)"); + @sqlite_exec($DB, "CREATE INDEX ip ON captiveportal (ip)"); + @sqlite_exec($DB, "CREATE INDEX starttime ON captiveportal (allow_time)"); + @sqlite_exec($DB, "CREATE INDEX serviceid ON captiveportal (serviceid)"); + } else + captiveportal_syslog("Error during table {$cpzone} creation. Error message: {$errormsg}"); } - if ($locked == false) - unlock($cpdblck); - return $cpdb; + + return $DB; } -/* write captive portal DB */ -function captiveportal_write_db($cpdb, $locked = false, $remove = false) { - global $g, $cpzone; +/* read captive portal DB into array */ +function captiveportal_read_db($query = "") { - if ($locked == false) - $cpdblck = lock("captiveportaldb{$cpzone}", LOCK_EX); - - if (is_array($remove)) { - if (!empty($remove)) { - $cpdb = captiveportal_read_db(true); - foreach ($remove as $key) { - if (is_array($key)) - log_error("Captive portal Array passed as unset index: " . print_r($key, true)); - else - unset($cpdb[$key]); - } - } else { - if ($locked == false) - unlock($cpdblck); - return; //This makes sure no record removal calls + $DB = captiveportal_opendb(); + if ($DB) { + sqlite_exec($DB, "BEGIN"); + if (empty($query)) + $cpdb = @sqlite_array_query($DB, "SELECT * FROM captiveportal {$query}", SQLITE_NUM); + else { + $response = @sqlite_unbuffered_query($DB, "SELECT * FROM captiveportal", SQLITE_NUM); + $cpdb = @sqlite_fetch_all($response, SQLITE_NUM); } + sqlite_exec($DB, "END"); + @sqlite_close($DB); } - $fd = @fopen("{$g['vardb_path']}/captiveportal_{$cpzone}.db", "w"); - if ($fd) { - foreach ($cpdb as $cpent) { - fwrite($fd, join(",", $cpent) . "\n"); - } - fclose($fd); + if (!$cpdb) + $cpdb = array(); + + return $cpdb; +} + +function captiveportal_remove_entries($remove) { + + if (!is_array($remove) || empty($remove)) + return; + + $query = "DELETE FROM captiveportal WHERE sessiondid in ("; + foreach($remove as $idx => $rid) { + $query .= "'{$unindex}'"; + if ($idx < (count($remove) - 1)) + $query .= ","; } - if ($locked == false) - unlock($cpdblck); + $query .= ")"; + captiveportal_write_db($query); +} + +/* write captive portal DB */ +function captiveportal_write_db($queries) { + global $g; + + if (is_array($queries)) + $query = implode(";", $queries); + else + $query = $queries; + + $DB = captiveportal_opendb(); + if ($DB) { + $error_msg = ""; + sqlite_exec($DB, "BEGIN TRANSACTION"); + $result = @sqlite_exec($DB, $query, $error_msg); + if (!$result) + captiveportal_syslog("Trying to modify DB returned error: {$error_msg}"); + else + sqlite_exec($DB, "END TRANSACTION"); + @sqlite_close($DB); + return $result; + } else + return true; } function captiveportal_write_elements() { @@ -1394,12 +1328,68 @@ function captiveportal_write_elements() { return 0; } -function captiveportal_init_ipfw_ruleno($rulenos_start = 2000, $rulenos_range_max = 49899) { - global $g, $cpzone; +function captiveportal_get_next_dn_ruleno($rulenos_start = 2000, $rulenos_range_max = 64500) { + global $config, $g; - @unlink("{$g['vardb_path']}/captiveportal_{$cpzone}.rules"); - $rules = array_pad(array(), $rulenos_range_max - $rulenos_start, false); - file_put_contents("{$g['vardb_path']}/captiveportal_{$cpzone}.rules", serialize($rules)); + $cpruleslck = lock("captiveportalrulesdn", LOCK_EX); + $ruleno = 0; + if (file_exists("{$g['vardb_path']}/captiveportaldn.rules")) { + $rules = unserialize(file_get_contents("{$g['vardb_path']}/captiveportaldn.rules")); + for ($ridx = $rulenos_start; $ridx < $rulenos_range_max; $ridx++) { + if ($rules[$ridx]) { + $ridx++; + continue; + } + $ruleno = $ridx; + $rules[$ridx] = "used"; + $rules[++$ridx] = "used"; + break; + } + } else { + $rules = array_pad(array(), $rulenos_range_max, false); + $rules[$rulenos_start] = "used"; + $rules[++$rulenos_start] = "used"; + $ruleno = $rulenos_start; + } + file_put_contents("{$g['vardb_path']}/captiveportaldn.rules", serialize($rules)); + unlock($cpruleslck); + + return $ruleno; +} + +function captiveportal_free_dn_ruleno($ruleno) { + global $config, $g; + + $cpruleslck = lock("captiveportalrulesdn", LOCK_EX); + if (file_exists("{$g['vardb_path']}/captiveportal_{$cpzone}.rules")) { + $rules = unserialize(file_get_contents("{$g['vardb_path']}/captiveportaldn.rules")); + $rules[$ruleno] = false; + $rules[++$ruleno] = false; + file_put_contents("{$g['vardb_path']}/captiveportaldn.rules", serialize($rules)); + } + unlock($cpruleslck); +} + +function captiveportal_get_dn_passthru_ruleno($value) { + global $config, $g, $cpzone; + + $cpcfg = $config['captiveportal'][$cpzone]; + if(!isset($cpcfg['enable'])) + return NULL; + + $cpruleslck = lock("captiveportalrulesdn", LOCK_EX); + if (file_exists("{$g['vardb_path']}/captiveportaldn.rules")) { + $rules = unserialize(file_get_contents("{$g['vardb_path']}/captiveportaldn.rules")); + captiveportal_ipfw_set_context($cpzone); + $ruleno = intval(`/sbin/ipfw show | /usr/bin/grep {$value} | /usr/bin/grep -v grep | /usr/bin/cut -d " " -f 5 | /usr/bin/head -n 1`); + if ($rules[$ruleno]) { + unlock($cpruleslck); + return $ruleno; + } + } + + unlock($cpruleslck); + return NULL; } /* @@ -1407,7 +1397,7 @@ function captiveportal_init_ipfw_ruleno($rulenos_start = 2000, $rulenos_range_ma * within the range specified based on the actual logged on users * */ -function captiveportal_get_next_ipfw_ruleno($rulenos_start = 2000, $rulenos_range_max = 49899) { +function captiveportal_get_next_ipfw_ruleno($rulenos_start = 2, $rulenos_range_max = 64500) { global $config, $g, $cpzone; $cpcfg = $config['captiveportal'][$cpzone]; @@ -1433,8 +1423,9 @@ function captiveportal_get_next_ipfw_ruleno($rulenos_start = 2000, $rulenos_rang break; } } else { - $rules = array_pad(array(), $rulenos_range_max - $rulenos_start, false); - $rules[2] = "used"; + $rules = array_pad(array(), $rulenos_range_max, false); + $rules[$rulenos_start] = "used"; + $rules[++$rulenos_start] = "used"; $ruleno = 2; } file_put_contents("{$g['vardb_path']}/captiveportal_{$cpzone}.rules", serialize($rules)); @@ -1442,7 +1433,7 @@ function captiveportal_get_next_ipfw_ruleno($rulenos_start = 2000, $rulenos_rang return $ruleno; } -function captiveportal_free_ipfw_ruleno($ruleno, $usedbw = false) { +function captiveportal_free_ipfw_ruleno($ruleno) { global $config, $g, $cpzone; $cpcfg = $config['captiveportal'][$cpzone]; @@ -1496,28 +1487,20 @@ function getVolume($ip) { global $cpzone; $volume = array(); - // Initialize vars properly, since we don't want NULL vars $volume['input_pkts'] = $volume['input_bytes'] = $volume['output_pkts'] = $volume['output_bytes'] = 0 ; - // Ingress - $ipfwin = ""; - $ipfwout = ""; - $matchesin = ""; - $matchesout = ""; captiveportal_ipfw_set_context($cpzone); - exec("/sbin/ipfw table 1 entrystats {$ip}", $ipfwin); - if ($ipfwin[0]) { - $ipfwin = explode(" ", $ipfwin[0]); - $volume['input_pkts'] = $ipfwin[2]; - $volume['input_bytes'] = $ipfwin[3]; + $ipfw = pfSense_ipfw_getTablestats($cpzone, 1, $ip); + if (is_array($ipfw)) { + $volume['input_pkts'] = $ipfw['packets']; + $volume['input_bytes'] = $ipfw['bytes']; } - exec("/sbin/ipfw table 2 entrystats {$ip}", $ipfwout); - if ($ipfwout[0]) { - $ipfwout = explode(" ", $ipfwout[0]); - $volume['output_pkts'] = $ipfwout[2]; - $volume['output_bytes'] = $ipfwout[3]; + $ipfw = pfSense_ipfw_getTablestats($cpzone, 2, $ip); + if (is_array($ipfw)) { + $volume['output_pkts'] = $ipfw['packets']; + $volume['output_bytes'] = $ipfw['bytes']; } return $volume; @@ -1625,10 +1608,14 @@ function portal_reply_page($redirurl, $type = null, $message = null, $clientmac } else { $httpport = $cpcfg['listenporthttp'] ? $cpcfg['listenporthttp'] : $cpcfg['zoneid']; $ifip = portal_ip_from_client_ip($clientip); - if (!$ifip) + if (!$ifip) { $ourhostname = $config['system']['hostname'] . ":{$httpport}"; - else - $ourhostname = "{$ifip}:{$httpport}"; + } else { + if (is_ipaddrv6($ifip)) + $ourhostname = "[{$ifip}]:{$httpport}"; + else + $ourhostname = "{$ifip}:{$httpport}"; + } $htmltext = str_replace("\$PORTAL_ACTION\$", "http://{$ourhostname}/", $htmltext); $htmltext = str_replace("#PORTAL_ACTION#", "http://{$ourhostname}/", $htmltext); } @@ -1676,45 +1663,28 @@ function captiveportal_reapply_attributes($cpentry, $attributes) { $dwfaultbw_down = isset($config['captiveportal'][$cpzone]['bwdefaultdn']) ? $config['captiveportal'][$cpzone]['bwdefaultdn'] : 0; $bw_up = isset($attributes['bw_up']) ? round(intval($attributes['bw_up'])/1000, 2) : $dwfaultbw_up; $bw_down = isset($attributes['bw_down']) ? round(intval($attributes['bw_down'])/1000, 2) : $dwfaultbw_down; - $bw_up_pipeno = $cpentry[1]+20000; - $bw_down_pipeno = $cpentry[1]+20001; + $bw_up_pipeno = $cpentry[1]; + $bw_down_pipeno = $cpentry[1]+1; - pfSense_pipe_action("pipe {$bw_up_pipeno} config bw {$bw_up}Kbit/s queue 100"); - pfSense_pipe_action("pipe {$bw_down_pipeno} config bw {$bw_down}Kbit/s queue 100"); + pfSense_pipe_action("pipe {$bw_up_pipeno} config bw {$bw_up}Kbit/s queue 100 buckets 16"); + pfSense_pipe_action("pipe {$bw_down_pipeno} config bw {$bw_down}Kbit/s queue 100 buckets 16"); //captiveportal_logportalauth($cpentry[4], $cpentry[3], $cpentry[2], "RADIUS_BANDWIDTH_REAPPLY", "{$bw_up}/{$bw_down}"); - unset($bw_up_pipeno, $bw_Down_pipeno, $bw_up, $bw_down); + unset($bw_up_pipeno, $bw_down_pipeno, $bw_up, $bw_down); } -function portal_allow($clientip,$clientmac,$username,$password = null, $attributes = null, $ruleno = null, $radiusctx = null) { - +function portal_allow($clientip,$clientmac,$username,$password = null, $attributes = null, $pipeno = null, $radiusctx = null) { global $redirurl, $g, $config, $type, $passthrumac, $_POST, $cpzone; - /* See if a ruleno is passed, if not start sessions because this means there isn't one atm */ - if ($ruleno == null) - $ruleno = captiveportal_get_next_ipfw_ruleno(); - - /* if the pool is empty, return appropriate message and exit */ - if (is_null($ruleno)) { - portal_reply_page($redirurl, "error", "System reached maximum login capacity"); - log_error("WARNING! Captive portal has reached maximum login capacity"); - exit; - } - // Ensure we create an array if we are missing attributes if (!is_array($attributes)) $attributes = array(); - $radiusservers = captiveportal_get_radius_servers(); + unset($sessionid); /* Do not allow concurrent login execution. */ $cpdblck = lock("captiveportaldb{$cpzone}", LOCK_EX); - unset($sessionid); - - /* read in client database */ - $cpdb = captiveportal_read_db(true); - if ($attributes['voucher']) $remaining_time = $attributes['session_timeout']; @@ -1729,12 +1699,19 @@ function portal_allow($clientip,$clientmac,$username,$password = null, $attribut if ($macent['mac'] == $mac['mac']) { $macrules = ""; $ruleno = captiveportal_get_ipfw_passthru_ruleno($mac['mac']); + $pipeno = captiveportal_get_dn_passthru_ruleno($mac['mac']); if ($ruleno) { - captiveportal_free_ipfw_ruleno($ruleno, true); + captiveportal_free_ipfw_ruleno($ruleno); $macrules .= "delete {$ruleno}\n"; ++$ruleno; $macrules .= "delete {$ruleno}\n"; } + if ($pipeno) { + captiveportal_free_dn_ruleno($pipeno); + $macrules .= "pipe delete {$pipeno}\n"; + ++$pipeno; + $macrules .= "pipe delete {$pipeno}\n"; + } unset($config['captiveportal'][$cpzone]['passthrumac'][$idx]); $mac['mac'] = $clientmac; $config['captiveportal'][$cpzone]['passthrumac'][] = $mac; @@ -1751,17 +1728,27 @@ function portal_allow($clientip,$clientmac,$username,$password = null, $attribut portal_reply_page($redirurl, "error", "Username: {$username} is already authenticated using another MAC address.", $clientmac, $clientip, $username, $password); unlock($cpdblck); - exit; + return; } } } } + /* read in client database */ + $query = "WHERE ip = '{$clientip}'"; + $tmpusername = strtolower($username); + if (isset($config['captiveportal']['noconcurrentlogins'])) + $query .= " OR (username != 'unauthenticated' AND lower(username) = '{$tmpusername}')"; + $cpdb = captiveportal_read_db($query); + /* Snapshot the timestamp */ $allow_time = time(); + $radiusservers = captiveportal_get_radius_servers(); + $unsetindexes = array(); if (is_null($radiusctx)) $radiusctx = 'first'; - foreach ($cpdb as $sid => $cpentry) { + + foreach ($cpdb as $cpentry) { if (empty($cpentry[10])) $cpentry[10] = 'first'; /* on the same ip */ @@ -1770,7 +1757,7 @@ function portal_allow($clientip,$clientmac,$username,$password = null, $attribut captiveportal_logportalauth($cpentry[4],$cpentry[3],$cpentry[2],"CONCURRENT LOGIN - REUSING OLD SESSION"); else captiveportal_logportalauth($cpentry[4],$cpentry[3],$cpentry[2],"CONCURRENT LOGIN - REUSING IP {$cpentry[2]} WITH DIFFERENT MAC ADDRESS {$cpentry[3]}"); - $sessionid = $sid; + $sessionid = $cpentry[5]; break; } elseif (($attributes['voucher']) && ($username != 'unauthenticated') && ($cpentry[4] == $username)) { @@ -1783,7 +1770,7 @@ function portal_allow($clientip,$clientmac,$username,$password = null, $attribut /* This user was already logged in so we disconnect the old one */ captiveportal_disconnect($cpentry,$radiusservers[$cpentry[10]],13); captiveportal_logportalauth($cpentry[4],$cpentry[3],$cpentry[2],"CONCURRENT LOGIN - TERMINATING OLD SESSION"); - unset($cpdb[$sid]); + $unsetindexes[] = $cpentry[5]; break; } elseif ((isset($config['captiveportal'][$cpzone]['noconcurrentlogins'])) && ($username != 'unauthenticated')) { @@ -1792,12 +1779,15 @@ function portal_allow($clientip,$clientmac,$username,$password = null, $attribut /* This user was already logged in so we disconnect the old one */ captiveportal_disconnect($cpentry,$radiusservers[$cpentry[10]],13); captiveportal_logportalauth($cpentry[4],$cpentry[3],$cpentry[2],"CONCURRENT LOGIN - TERMINATING OLD SESSION"); - unset($cpdb[$sid]); + $unsetindexes[] = $cpentry[5]; break; } } } + if (!empty($unsetindexes)) + captiveportal_remove_entries($unsetindexes); + if ($attributes['voucher'] && $remaining_time <= 0) return 0; // voucher already used and no time left @@ -1806,11 +1796,6 @@ function portal_allow($clientip,$clientmac,$username,$password = null, $attribut $tod = gettimeofday(); $sessionid = substr(md5(mt_rand() . $tod['sec'] . $tod['usec'] . $clientip . $clientmac), 0, 16); - $dwfaultbw_up = isset($config['captiveportal'][$cpzone]['bwdefaultup']) ? $config['captiveportal'][$cpzone]['bwdefaultup'] : 0; - $dwfaultbw_down = isset($config['captiveportal'][$cpzone]['bwdefaultdn']) ? $config['captiveportal'][$cpzone]['bwdefaultdn'] : 0; - $bw_up = isset($attributes['bw_up']) ? round(intval($attributes['bw_up'])/1000, 2) : $dwfaultbw_up; - $bw_down = isset($attributes['bw_down']) ? round(intval($attributes['bw_down'])/1000, 2) : $dwfaultbw_down; - if ($passthrumac) { $mac = array(); $mac['mac'] = $clientmac; @@ -1835,37 +1820,57 @@ function portal_allow($clientip,$clientmac,$username,$password = null, $attribut mwexec("/sbin/ipfw -q {$g['tmp_path']}/macentry_{$cpzone}.rules.tmp"); $writecfg = true; } else { - $bw_up_pipeno = $ruleno + 20000; - $bw_down_pipeno = $ruleno + 20001; + /* See if a pipeno is passed, if not start sessions because this means there isn't one atm */ + if (is_null($pipeno)) + $pipeno = captiveportal_get_next_dn_ruleno(); + + /* if the pool is empty, return appropriate message and exit */ + if (is_null($pipeno)) { + portal_reply_page($redirurl, "error", "System reached maximum login capacity"); + log_error("WARNING! Captive portal has reached maximum login capacity"); + unlock($cpdblck); + return; + } + + $dwfaultbw_up = isset($config['captiveportal'][$cpzone]['bwdefaultup']) ? $config['captiveportal'][$cpzone]['bwdefaultup'] : 0; + $dwfaultbw_down = isset($config['captiveportal'][$cpzone]['bwdefaultdn']) ? $config['captiveportal'][$cpzone]['bwdefaultdn'] : 0; + $bw_up = isset($attributes['bw_up']) ? round(intval($attributes['bw_up'])/1000, 2) : $dwfaultbw_up; + $bw_down = isset($attributes['bw_down']) ? round(intval($attributes['bw_down'])/1000, 2) : $dwfaultbw_down; + + $bw_up_pipeno = $pipeno; + $bw_down_pipeno = $pipeno + 1; //$bw_up /= 1000; // Scale to Kbit/s - pfSense_pipe_action("pipe {$bw_up_pipeno} config bw {$bw_up}Kbit/s queue 100"); - pfSense_pipe_action("pipe {$bw_down_pipeno} config bw {$bw_down}Kbit/s queue 100"); + pfSense_pipe_action("pipe {$bw_up_pipeno} config bw {$bw_up}Kbit/s queue 100 buckets 16"); + pfSense_pipe_action("pipe {$bw_down_pipeno} config bw {$bw_down}Kbit/s queue 100 buckets 16"); captiveportal_ipfw_set_context($cpzone); if (!isset($config['captiveportal'][$cpzone]['nomacfilter'])) - pfSense_ipfw_Tableaction($cpzone, 1, IP_FW_TABLE_ADD, $clientip, 32, $clientmac, $bw_up_pipeno); + pfSense_ipfw_Tableaction($cpzone, IP_FW_TABLE_ADD, 1, $clientip, 32, $clientmac, $bw_up_pipeno); else - pfSense_ipfw_Tableaction($cpzone, 1, IP_FW_TABLE_ADD, $clientip, 32, NULL, $bw_up_pipeno); + pfSense_ipfw_Tableaction($cpzone, IP_FW_TABLE_ADD, 1, $clientip, 32, NULL, $bw_up_pipeno); if (!isset($config['captiveportal'][$cpzone]['nomacfilter'])) - pfSense_ipfw_Tableaction("", 2, IP_FW_TABLE_ADD, $clientip, 32, $clientmac, $bw_down_pipeno); + pfSense_ipfw_Tableaction("", IP_FW_TABLE_ADD, 2, $clientip, 32, $clientmac, $bw_down_pipeno); else - pfSense_ipfw_Tableaction("", 2, IP_FW_TABLE_ADD, $clientip, 32, NULL, $bw_down_pipeno); + pfSense_ipfw_Tableaction("", IP_FW_TABLE_ADD, 2, $clientip, 32, NULL, $bw_down_pipeno); if ($attributes['voucher']) $attributes['session_timeout'] = $remaining_time; /* encode password in Base64 just in case it contains commas */ $bpassword = base64_encode($password); - $cpdb[] = array($allow_time, $ruleno, $clientip, $clientmac, $username, $sessionid, $bpassword, + $cpdb[] = array($allow_time, $pipeno, $clientip, $clientmac, $username, $sessionid, $bpassword, $attributes['session_timeout'], $attributes['idle_timeout'], $attributes['session_terminate_time'], $radiusctx); + $insertquery = "INSERT INTO captiveportal (allow_time, ruleno, ip, mac, username, sessionid, bpassword, session_timeout, idle_timeout, session_terminate_time) "; + $insertquery .= " VALUES ({$allow_time}, {$ruleno}, '{$clientip}', '{$clientmac}', '{$username}', '{$sessionid}', '{$bpassword}',"; + $insertquery .= "{$attributes['session_timeout']}, {$attributes['idle_timeout']}, {$attributes['session_terminate_time']})"; - /* rewrite information to database */ - captiveportal_write_db($cpdb, true); + /* store information to database */ + captiveportal_write_db($insertquery); unlock($cpdblck); if (isset($config['captiveportal'][$cpzone]['radacct_enable']) && !empty($radiusservers[$radiusctx])) { - $acct_val = RADIUS_ACCOUNTING_START($ruleno, + $acct_val = RADIUS_ACCOUNTING_START($pipeno, $username, $sessionid, $radiusservers[$radiusctx], $clientip, $clientmac); if ($acct_val == 1) captiveportal_logportalauth($username,$clientmac,$clientip,$type,"RADIUS ACCOUNTING FAILED"); @@ -1892,7 +1897,7 @@ function portal_allow($clientip,$clientmac,$username,$password = null, $attribut $config['captiveportal'][$cpzone]['listenporthttps'] ? $config['captiveportal'][$cpzone]['listenporthttps'] : ($config['captiveportal'][$cpzone]['zoneid'] + 1); - $logouturl = "https://{$config['captiveportal']['httpsname']}:{$httpsport}/"; + $logouturl = "https://{$config['captiveportal'][$cpzone]['httpsname']}:{$httpsport}/"; } else { $ifip = portal_ip_from_client_ip($clientip); $httpport = diff --git a/etc/inc/gwlb.inc b/etc/inc/gwlb.inc index 173a185..3dc7e2b 100644 --- a/etc/inc/gwlb.inc +++ b/etc/inc/gwlb.inc @@ -522,7 +522,7 @@ function return_gateways_array($disabled = false, $localhost = false) { $ctype = strtoupper($ifcfg['ipaddr']); break; default: - if (substr($ifcfg['if'], 0, 5) == "ovpnc") + if (substr($ifcfg['if'], 0, 4) == "ovpn") $ctype = "VPNv4"; break; } @@ -588,7 +588,7 @@ function return_gateways_array($disabled = false, $localhost = false) { $ctype = strtoupper($ifcfg['ipaddrv6']); break; default: - if (substr($ifcfg['if'], 0, 5) == "ovpnc") + if (substr($ifcfg['if'], 0, 4) == "ovpn") $ctype = "VPNv6"; break; } diff --git a/etc/inc/interfaces.inc b/etc/inc/interfaces.inc index 75058ff..3b6d6c5 100644 --- a/etc/inc/interfaces.inc +++ b/etc/inc/interfaces.inc @@ -834,13 +834,19 @@ function interface_gif_configure(&$gif, $gifkey = "") { return -1; $realif = get_real_interface($gif['if']); + $ipaddr = $gif['ipaddr']; - if(is_ipaddrv4($gif['remote-addr'])) { - $realifip = get_interface_ip($gif['if']); + if (is_ipaddrv4($gif['remote-addr'])) { + if (is_ipaddrv4($ipaddr)) + $realifip = $ipaddr; + else + $realifip = get_interface_ip($gif['if']); $realifgw = get_interface_gateway($gif['if']); - } - if(is_ipaddrv6($gif['remote-addr'])) { - $realifip = get_interface_ipv6($gif['if']); + } else if (is_ipaddrv6($gif['remote-addr'])) { + if (is_ipaddrv6($ipaddr)) + $realifip = $ipaddr; + else + $realifip = get_interface_ipv6($gif['if']); $realifgw = get_interface_gatewayv6($gif['if']); } /* make sure the parent interface is up */ @@ -1022,7 +1028,8 @@ function interfaces_configure() { services_dnsmasq_configure(); /* reload captive portal */ - captiveportal_init_rules(); + if (function_exists('captiveportal_init_rules')) + captiveportal_init_rules(); } return 0; @@ -3155,6 +3162,7 @@ function interface_6rd_configure($interface = "wan") { /* stf approach only works when embedding the entire 32 bits of the v4 */ mwexec("/sbin/ifconfig stf0 create"); + pfSense_interface_flags("stf0", IFF_LINK2); mwexec("/sbin/ifconfig stf0 inet6 {$rd6prefix}/{$rd6prefixlen}"); log_error("Created 6rd interface stf0 {$rd6prefix}/{$rd6prefixlen}"); @@ -3250,6 +3258,7 @@ function interface_6to4_configure($interface = "wan"){ /* setup the stf interface */ mwexec("/sbin/ifconfig stf0 destroy"); mwexec("/sbin/ifconfig stf0 create"); + pfSense_interface_flags("stf0", IFF_LINK2); mwexec("/sbin/ifconfig stf0 inet6 {$stflanpr} prefixlen 16"); log_error("Set IPv6 address inet6 {$stflanpr} prefixlen 16 for stf0, route {$stfbrgw}"); @@ -4286,7 +4295,7 @@ function get_interfaces_with_gateway() { $ints[$ifdescr] = $ifdescr; break; default: - if (substr($ifname['if'], 0, 5) == "ovpnc" || + if (substr($ifname['if'], 0, 4) == "ovpn" || !empty($ifname['gateway'])) $ints[$ifdescr] = $ifdescr; break; @@ -4310,7 +4319,7 @@ function interface_has_gateway($friendly) { return true; break; default: - if (substr($ifname['if'], 0, 5) == "ovpnc") + if (substr($ifname['if'], 0, 4) == "ovpn") return true; if (!empty($ifname['gateway'])) return true; @@ -4339,7 +4348,7 @@ function interface_has_gatewayv6($friendly) { return true; break; default: - if (substr($ifname['if'], 0, 5) == "ovpnc") + if (substr($ifname['if'], 0, 4) == "ovpn") return true; if (!empty($ifname['gatewayv6'])) return true; diff --git a/etc/inc/openvpn.inc b/etc/inc/openvpn.inc index 7ffd65c..df34539 100644 --- a/etc/inc/openvpn.inc +++ b/etc/inc/openvpn.inc @@ -315,7 +315,7 @@ function openvpn_reconfigure($mode, $settings) { $devname = "ovpnc{$vpnid}"; /* is our device already configured */ - if (mwexec("/sbin/ifconfig {$devname}")) { + if (mwexec("/sbin/ifconfig {$devname}", true)) { /* create the tap device if required */ if (!file_exists("/dev/{$tunname}")) @@ -525,7 +525,6 @@ function openvpn_reconfigure($mode, $settings) { if ($settings['local_network']) { list($ip, $mask) = explode('/', $settings['local_network']); $mask = gen_subnet_mask($mask); - $conf .= "push \"route remote_host 255.255.255.255 net_gateway\"\n"; $conf .= "push \"route $ip $mask\"\n"; } if ($settings['local_networkv6']) { @@ -616,7 +615,6 @@ function openvpn_reconfigure($mode, $settings) { if ((substr($settings['mode'], 0, 3) == "p2p") && is_subnet($settings['remote_network'])) { list($ip, $mask) = explode('/', $settings['remote_network']); $mask = gen_subnet_mask($mask); - $conf .= "route remote_host 255.255.255.255 net_gateway\n"; $conf .= "route $ip $mask\n"; } // Add a remote network route if set, and only for p2p modes. diff --git a/etc/inc/services.inc b/etc/inc/services.inc index d5c6b3a..4e6a532 100644 --- a/etc/inc/services.inc +++ b/etc/inc/services.inc @@ -6,7 +6,7 @@ originally part of m0n0wall (http://m0n0.ch/wall) Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>. - Copyright (C) 2010 Ermal Lu�i + Copyright (C) 2010 Ermal Luci All rights reserved. Redistribution and use in source and binary forms, with or without @@ -1493,15 +1493,9 @@ function services_dyndns_configure($int = "") { echo gettext("Starting DynDNS clients..."); foreach ($dyndnscfg as $dyndns) { - $failovergroup = interface_gateway_group_member($int); - if (!empty($int) && $int == $dyndns['interface']) { + if ((empty($int)) || ($int == $dyndns['interface']) || (is_array($gwgroups[$dyndns['interface']]))) { services_dyndns_configure_client($dyndns); sleep(1); - } elseif (is_array($gwgroups[$dyndns['interface']])){ - services_dyndns_configure_client($dyndns); - sleep(1); - } else { - continue; } } diff --git a/etc/inc/shaper.inc b/etc/inc/shaper.inc index 1635df1..835214b 100644 --- a/etc/inc/shaper.inc +++ b/etc/inc/shaper.inc @@ -3421,8 +3421,8 @@ class dnqueue_class extends dummynet_class { default: break; } - $pfq_rule .= "\n"; } + $pfq_rule .= "\n"; return $pfq_rule; } diff --git a/etc/inc/voucher.inc b/etc/inc/voucher.inc index 3a8c0bc..3356a1a 100644 --- a/etc/inc/voucher.inc +++ b/etc/inc/voucher.inc @@ -215,8 +215,6 @@ function voucher_expire($voucher_received) { // split into an array. Useful for multiple vouchers given $a_vouchers_received = preg_split("/[\t\n\r ]+/s", $voucher_received); $active_dirty = false; - - $cpdb = captiveportal_read_db(false, 4); /* Indexed by Voucher */ $unsetindexes[] = array(); // go through all received vouchers, check their valid and extract @@ -250,11 +248,10 @@ function voucher_expire($voucher_received) { captiveportal_syslog("{$voucher} ({$roll}/{$nr}) forced to expire"); /* Check if this voucher has any active sessions */ - if (isset($cpdb[$voucher])) { - $cpentry = $cpdb[$voucher]; + $cpentry = captiveportal_read_db("WHERE username = '{$voucher}'"); + if (!empty($cpentry)) { captiveportal_disconnect($cpentry,null,13); captiveportal_logportalauth($cpentry[4],$cpentry[3],$cpentry[2],"FORCLY TERMINATING VOUCHER {$voucher} SESSION"); - unset($cpdb[$voucher]); $unsetindexes[] = $cpentry[5]; } } else @@ -289,7 +286,7 @@ function voucher_expire($voucher_received) { /* Write database */ if (!empty($unsetindexes)) - captiveportal_write_db($cpdb, false, $unsetindexes); + captiveportal_remove_entries($unsetindexes); return true; } @@ -673,6 +670,9 @@ function voucher_save_db_to_config_zone() { if (!isset($config['voucher'][$cpzone]['enable'])) return; // no vouchers or don't want to save DB's + if (!is_array($config['voucher'][$cpzone]['roll'])) + return; + $voucherlck = lock("voucher{$cpzone}", LOCK_EX); // walk all active rolls and save runtime DB's to flash diff --git a/etc/rc.bootup b/etc/rc.bootup index b8bf0e3..8af6ceb 100755 --- a/etc/rc.bootup +++ b/etc/rc.bootup @@ -313,6 +313,9 @@ system_routing_configure(); /* enable routing */ system_routing_enable(); +/* start dnsmasq service */ +services_dnsmasq_configure(); + /* Do an initial time sync */ echo "Starting NTP time client..."; /* At bootup this will just write the config, ntpd will launch from ntpdate_sync_once.sh */ @@ -329,9 +332,6 @@ system_console_configure(); /* start DHCP service */ services_dhcpd_configure(); -/* start dnsmasq service */ -services_dnsmasq_configure(); - /* start dhcpleases dhpcp hosts leases program */ system_dhcpleases_configure(); diff --git a/etc/rc.linkup b/etc/rc.linkup index 23d7c9b..217fe65 100755 --- a/etc/rc.linkup +++ b/etc/rc.linkup @@ -39,9 +39,14 @@ require_once("interfaces.inc"); function handle_argument_group($iface, $argument2) { global $config; + if (!is_array($config['interfaces'][$iface])) + return; + $ipaddr = $config['interfaces'][$iface]['ipaddr']; - if (is_ipaddr($ipaddr) || empty($ipaddr)) { - log_error("Hotplug event detected for {$iface} but ignoring since interface is configured with static IP ({$ipaddr})"); + $ip6addr = $config['interfaces'][$iface]['ipaddrv6']; + if ((!empty($ipaddr) && is_ipaddrv4($ipaddr)) || (empty($ipaddr) && empty($ip6addr)) || (!empty($ip6addr) && is_ipaddrv6($ip6addr))) { + $friendly = convert_friendly_interface_to_friendly_descr($iface); + log_error("Hotplug event detected for {$friendly}({$iface}) but ignoring since interface is configured with static IP ({$ipaddr} {$ip6addr})"); interfaces_staticarp_configure($iface); $iface = get_real_interface($iface); interfaces_bring_up($iface); @@ -75,28 +80,24 @@ global $g; if (file_exists("{$g['varrun_path']}/booting")) { /* ignore all linkup events */ } else { - foreach($_SERVER['argv'] as $argv) { - switch($argv) { - case "start": - $action = "start"; - break; - case "stop": - $action = "stop"; - break; - case "/etc/rc.linkup": - break; - default: - $interface = convert_real_interface_to_friendly_interface_name($argv); - if($interface == "") { - unset($interface); - } - break; - } - if(($action) && ($interface)) { - handle_argument_group($interface, $action); - unset ($action, $interface); - } + if ($argc < 3) { + log_error("HOTPLUG event: The number of required parameters not passed!"); + exit; + } + $action = $argv[1]; + switch($action) { + case "start": + case "stop": + break; + default: + log_error("HOTPLUG event: The action parameter passed is wrong($action) only start/stop/up/down are allowed!"); + exit; + /* NOTREACHED */ + break; } + $interface = convert_real_interface_to_friendly_interface_name($argv[2]); + if (!empty($interface)) + handle_argument_group($interface, $action); } ?> |