Feature #12945
Updated by Reid Linnemann over 2 years ago
As indicated by Viktor Gurov:
> pfSense_ipfw_*() functions have been rewritten to use shell scripts, which is slow, and can be a serious issue for the large (>1k clients) captive
> portal installations. These shell scripts should be rewritten as C functions (maybe not all):
> pfSense_pf_flush_anchor(): https://gitlab.netgate.com/pfSense/pfSense/-/blob/viktor-captive/src/etc/inc/captiveportal.inc#L1064
> pfSense_pf_get_cp_anchor_pipes(): https://gitlab.netgate.com/pfSense/pfSense/-/blob/viktor-captive/src/etc/inc/captiveportal.inc#L1116
> pfSense_pf_mod_table(): https://gitlab.netgate.com/pfSense/pfSense/-/blob/viktor-captive/src/etc/inc/captiveportal.inc#L1129
> pfSense_pf_get_table_counters(): https://gitlab.netgate.com/pfSense/pfSense/-/blob/viktor-captive/src/etc/inc/captiveportal.inc#L1764
> pfSense_pf_anchor_rules(): https://gitlab.netgate.com/pfSense/pfSense/-/blob/viktor-captive/src/etc/inc/captiveportal.inc#L3054
>
> Some of these may have been introduced into libpfctl already.
Some of this code has changed in the interim.
For reference, here is what looks to be needed:
<pre><code class="php">
/* XXX OPTIMIZE: pfSense_pf_flush_anchor($anchor, $type = 'rules/nat/ether') */
mwexec("/sbin/pfctl -a {$cpzoneprefix}_passthrumac/{$host} -F ethernet");
/* XXX OPTIMIZE: pfSense_pf_flush_anchor($anchor, $type = 'rules/nat/ether') */
mwexec("/sbin/pfctl -a {$cpzoneprefix}_{$anchor}/{$host} -F ether");
/* XXX OPTIMIZE: list($pipeup, $pipedown) = pfSense_pf_get_cp_anchor_pipes($anchor); */
$pipeup = mwexec("/sbin/pfctl -a {$cpzoneprefix}_{$anchor}/{$host} -se | cut -d' ' -f 17 | head -n1");
/* XXX OPTIMIZE: list($pipeup, $pipedown) = pfSense_pf_get_cp_anchor_pipes($anchor) */
exec("/sbin/pfctl -a {$cpzoneprefix}_{$anchor}mac/{$host} -se | awk -F'[()]' '{print $2; exit}'", $result, $retval);
/* XXX OPTIMIZE: array('output_pkts', 'output_bytes', 'input_pkts', 'input_bytes') = pfSense_pf_get_table_counters($table) */
exec("/sbin/pfctl -a {$anchor}/{$ip} -se -v 2>/dev/null | grep Bytes", $result);
/* Load rules for a host directly into pf = pfSense_pf_anchor_rules($anchor, $host, $rules) */
function captiveportal_load_pfctl($anchor, $host, $rules) {
global $g, $cpzone;
if (!empty($rules)) {
mwexec("/usr/bin/printf \"{$rules}\" | /sbin/pfctl -a {$anchor}/{$host} -f-");
} else {
log_error("CP zone ${cpzone}: {$anchor} rules are empty for {$host}");
}
}
/* Zero anchor counters = pfSense_pf_zero_anchor_counters($anchor) */
function captiveportal_anchor_zerocnt($ip, $anchor = 'auth') {
global $config, $cpzone;
$cpzoneprefix = CPPREFIX . $config['captiveportal'][$cpzone]['zoneid'];
mwexec("/sbin/pfctl -z -a {$cpzoneprefix}_{$anchor}/{$ip}");
}
</code></pre>
Rule loading will be omitted for now as it is not straightforward to expose the parser through libpfctl.