diff options
author | Ermal Luçi <eri@pfsense.org> | 2009-04-25 19:05:46 +0000 |
---|---|---|
committer | Ermal Luçi <eri@pfsense.org> | 2009-04-25 19:05:46 +0000 |
commit | 4e704ba37596ea3516d922bf2eca9c10ff6b2d94 (patch) | |
tree | fea201b2e81a582bd9d52c80f6220052a09134f3 /config/igmpproxy/filter.tmp | |
parent | 6352e1af802aa2d3838dbf9687a9812b630cdc99 (diff) | |
download | pfsense-packages-4e704ba37596ea3516d922bf2eca9c10ff6b2d94.tar.gz pfsense-packages-4e704ba37596ea3516d922bf2eca9c10ff6b2d94.tar.bz2 pfsense-packages-4e704ba37596ea3516d922bf2eca9c10ff6b2d94.zip |
Add igmpproxy as a package for the 1.2.x branch.
Diffstat (limited to 'config/igmpproxy/filter.tmp')
-rw-r--r-- | config/igmpproxy/filter.tmp | 3312 |
1 files changed, 3312 insertions, 0 deletions
diff --git a/config/igmpproxy/filter.tmp b/config/igmpproxy/filter.tmp new file mode 100644 index 00000000..fa79ac54 --- /dev/null +++ b/config/igmpproxy/filter.tmp @@ -0,0 +1,3312 @@ +<?php +/* $Id: filter.inc,v 1.575.2.368.2.65 2008/01/31 06:19:51 sullrich Exp $ */ +/* + filter.inc + Copyright (C) 2004-2006 Scott Ullrich + Copyright (C) 2005 Bill Marquette + Copyright (C) 2006 Peter Allgeyer + All rights reserved. + + originally part of m0n0wall (http://m0n0.ch/wall) + Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + +*/ + +/* include all configuration functions */ +require_once("functions.inc"); +require_once("pkg-utils.inc"); +require_once("notices.inc"); + +if($config['system']['shapertype'] <> "m0n0") + require_once ("shaper.inc"); + +/* holds the items that will be executed *AFTER* the filter is fully loaded */ +$after_filter_configure_run = array(); + +function filter_pflog_start() { + global $config, $g; + + if(isset($config['system']['developerspew'])) { + $mt = microtime(); + echo "filter_pflog_start() being called $mt\n"; + } + + mute_kernel_msgs(); + + $pid = `ps awwwux | grep -v "grep" | grep "tcpdump -v -l -n -e -ttt -i pflog0" | awk '{ print $2 }'`; + if(!$pid) + mwexec_bg("/usr/sbin/tcpdump -v -l -n -e -ttt -i pflog0 | logger -t pf -p local0.info"); + + unmute_kernel_msgs(); + +} + +/* reload filter async */ +function filter_configure() { + if(isset($config['system']['developerspew'])) { + $mt = microtime(); + echo "filter_configure() being called $mt\n"; + } + global $g; + + touch($g['tmp_path'] . "/filter_dirty"); +} + +/* reload filter sync */ +function filter_configure_sync() { + global $config, $g, $after_filter_configure_run; + filter_pflog_start(); + update_filter_reload_status("Initializing"); + /* invalidate interface cache */ + get_interface_arr(true); + if(isset($config['system']['developerspew'])) { + $mt = microtime(); + echo "filter_configure_sync() being called $mt\n"; + } + + /* load ipfw / dummynet early on if required */ + if($config['system']['dummynetshaper']) { + $status = intval(`kldstat | grep ipfw | wc -l | awk '{ print $1 }'`); + if($status == "0") { + mwexec("/sbin/kldload ipfw"); + mwexec("/sbin/kldload dummynet"); + } + } else { + /* check to see if any rules reference a schedule + * and if so load ipfw for later usage. + */ + foreach($config['filter']['rule'] as $rule) { + if($rule['sched']) + $time_based_rules = true; + } + if($time_based_rules == true) { + $status = intval(`kldstat | grep ipfw | wc -l | awk '{ print $1 }'`); + if($status == "0") { + mute_kernel_msgs(); + mwexec("/sbin/kldload ipfw"); + unmute_kernel_msgs(); + } + exec("/sbin/ipfw delete set 9"); + exec("/sbin/ipfw delete 2"); + exec("/sbin/ipfw delete 3"); + } + } + + $lan_if = $config['interfaces']['lan']['if']; + $wan_if = get_real_wan_interface(); + + /* generate aliases */ + if($g['booting'] == true) echo "."; + update_filter_reload_status("Creating aliases"); + $aliases = filter_generate_aliases(); + /* generate nat rules */ + if($g['booting'] == true) echo "."; + update_filter_reload_status("Generating NAT rules"); + $natrules = filter_nat_rules_generate(); + /* generate pfctl rules */ + if($g['booting'] == true) echo "."; + update_filter_reload_status("Generating filter rules"); + $pfrules = filter_rules_generate(); + + if (isset($config['shaper']['enable']) and $config['system']['shapertype'] <> "m0n0") { + /* generate altq interface setup parms */ + if($g['booting'] == true) echo "."; + update_filter_reload_status("Generating ALTQ interfaces"); + $altq_ints = filter_setup_altq_interfaces(); + /* generate altq queues */ + if($g['booting'] == true) echo "."; + update_filter_reload_status("Generating ALTQ queues"); + $altq_queues = filter_generate_altq_queues($altq_ints); + /* generate altq rules */ + if($g['booting'] == true) echo "."; + /* Setup a default rule that tags ALL packets as unshaped + * we'll match only unshaped packets in the shaper code later + * this allows the shaper to be first match + */ + $pf_altq_rules = "block in all tag unshaped label \"SHAPER: first match rule\"\n"; + update_filter_reload_status("Generating ALTQ rules"); + $pf_altq_rules .= filter_generate_pf_altq_rules(); + } + + update_filter_reload_status("Loading filter rules"); + + /* enable pf if we need to, otherwise disable */ + if (!isset ($config['system']['disablefilter'])) { + mwexec("/sbin/pfctl -e"); + } else { + mwexec("/sbin/pfctl -d"); + unlink_if_exists("{$g['tmp_path']}/filter_loading"); + update_filter_reload_status("Filter is disabled. Not loading rules."); + return; + } + + $fd = fopen("{$g['tmp_path']}/rules.debug", "w"); + $rules = $aliases . " \n"; + + update_filter_reload_status("Setting up logging information"); + + $rules .= setup_logging_interfaces(); + + if ($config['system']['optimization'] <> "") + $rules .= "set optimization {$config['system']['optimization']}\n"; + else + $rules .= "set optimization normal\n"; + + if ($config['system']['maximumstates'] <> "" && is_numeric($config['system']['maximumstates'])) { + /* User defined maximum states in Advanced menu. */ + $rules .= "set limit states {$config['system']['maximumstates']}\n"; + } + $rules .= "\n"; + + update_filter_reload_status("Setting up SCRUB information"); + /* get our wan interface? */ + $wanif = get_real_wan_interface(); + + /* disable scrub option */ + if(!isset($config['system']['disablescrub'])) { + /* set up MSS clamping */ + if ($config['interfaces']['wan']['mtu'] <> "" and is_numeric($config['interfaces']['wan']['mtu'])) + $mssclamp = "max-mss " . (intval($config['interfaces']['wan']['mtu'] - 40)); + else + if ($config['interfaces']['wan']['ipaddr'] == "pppoe") + $mssclamp = "max-mss 1452"; + else + $mssclamp = ""; + + /* configure no-df for linux nfs and others */ + if ($config['system']['scrubnodf']) + $scrubnodf = "no-df random-id"; + else + $scrubnodf = "random-id"; + $rules .= "scrub all {$scrubnodf} {$mssclamp} fragment reassemble\n"; // reassemble all directions + } else if ($config['interfaces']['wan']['mtu'] <> "" and is_numeric($config['interfaces']['wan']['mtu'])) { + $rules .= "scrub {$mssclamp}\n"; // reassemble all directions + } + + if($config['system']['shapertype'] <> "m0n0") { + $rules.= "{$altq_ints}\n"; + $rules.= "{$altq_queues}\n"; + } + $rules.= "{$natrules}\n"; + if($config['system']['shapertype'] <> "m0n0") + $rules.= "{$pf_altq_rules}\n"; + $rules.= "{$pfrules}\n"; + fwrite($fd, $rules); + fclose($fd); + + if(isset($config['system']['developerspew'])) { + $mt = microtime(); + echo "pfctl being called at $mt\n"; + } + $rules_loading = mwexec("/sbin/pfctl -o -f {$g['tmp_path']}/rules.debug"); + if(isset($config['system']['developerspew'])) { + $mt = microtime(); + echo "pfctl done at $mt\n"; + } + + /* check for a error while loading the rules file. if an error has occured + then output the contents of the error to the caller */ + if($rules_loading <> 0) { + $rules_error = exec_command("/sbin/pfctl -f {$g['tmp_path']}/rules.debug"); + $line_error = split("\:", $rules_error); + $line_number = $line_error[1]; + $rules_file = `/bin/cat {$g['tmp_path']}/rules.debug`; + $line_split = split("\n", $rules_file); + if(is_array($line_split)) + $line_error = "The line in question reads [{$line_number}]: {$line_split[$line_number-1]}"; + if($line_error and $line_number) { + file_notice("filter_load", "There were error(s) loading the rules: {$rules_error} {$line_error}", "Filter Reload", ""); + log_error("There were error(s) loading the rules: {$rules_error} - {$line_error}"); + update_filter_reload_status("There were error(s) loading the rules: {$rules_error} - {$line_error}"); + return; + } + } + + unlink_if_exists("/usr/local/pkg/pf/carp_sync_client.php"); + + /* run items scheduled for after filter configure run */ + foreach($after_filter_configure_run as $afcr) { + $fda = fopen("/tmp/commands.txt", "w"); + fwrite($fda, $afcr . "\n"); + fclose($fda); + } + if(file_exists("/tmp/commands.txt")) { + mwexec("sh /tmp/commands.txt &"); + unlink("/tmp/commands.txt"); + } + + update_filter_reload_status("Running plugins"); + + /* process packager manager custom rules */ + $files = return_dir_as_array("/usr/local/pkg/pf/"); + if($files <> "") { + foreach ($files as $file) { + if($file) { + $text = file_get_contents("/usr/local/pkg/pf/" . $file); + if($text) { + if(stristr($file, ".sh") == true) { + mwexec("/usr/local/pkg/pf/" . $file . " start"); + } else { + if(!stristr($file,"CVS")) { + if($g['booting'] == true) + echo "\t{$file}... "; + require_once("/usr/local/pkg/pf/" . $file); + } + } + } + } + } + } + update_filter_reload_status("Plugins completed."); + + system_start_ftp_helpers(); + + if($config['system']['shapertype'] == "m0n0") { + require_once ("/etc/inc/m0n0/shaper.inc"); + shaper_configure(); + } + + /* if time based rules are enabled then swap in the set */ + if($time_based_rules == true) { + tdr_install_cron(true); + tdr_install_set(); + } else { + tdr_install_cron(false); + } + + /* + we need a way to let a user run a shell cmd after each + filter_configure() call. run this xml command after + each change. + */ + if($config['system']['afterfilterchangeshellcmd'] <> "") + mwexec($config['system']['afterfilterchangeshellcmd']); + + /* sync carp entries to other firewalls */ + update_filter_reload_status("Syncing CARP data"); + carp_sync_client(); + + system_routing_configure(); + + update_filter_reload_status("Done"); + + return 0; +} + +function filter_generate_aliases() { + global $config, $g; + if(isset($config['system']['developerspew'])) { + $mt = microtime(); + echo "filter_generate_aliases() being called $mt\n"; + } + $aliases = ""; + + $i = 0; + + $lanip = find_interface_ip($config['interfaces']['lan']['if']); + $wanip = find_interface_ip(get_real_wan_interface()); + + $lan_aliases = " " . link_ip_to_carp_interface($lanip); + $wan_aliases = " " . link_ip_to_carp_interface($wanip); + + if(link_int_to_bridge_interface("lan")) + $lan_aliases .= " " . link_int_to_bridge_interface("lan"); + if(link_int_to_bridge_interface("wan")) + $wan_aliases .= " " . link_int_to_bridge_interface("wan"); + + $aliases .= "# System Aliases \n"; + $aliases .= "loopback = \"{ lo0 }\"\n"; + $aliases .= "lan = \"{ {$config['interfaces']['lan']['if']}{$lan_aliases} }\"\n"; + + if($config['interfaces']['wan']['ipaddr'] == "pppoe" or $config['interfaces']['wan']['ipaddr'] == "pptp") { + $aliases .= "ng0 = \"{ " . $config['interfaces']['wan']['if'] . " " . get_real_wan_interface() . " }\" \n"; + $aliases .= "wan = \"{ " . $config['interfaces']['wan']['if'] . "{$wan_aliases} ng0 }\"\n"; + } else { + $aliases .= "wan = \"{ " . get_real_wan_interface() . "{$wan_aliases} }\"\n"; + } + + $aliases .= "enc0 = \"{ enc0 }\"\n"; + + /* used to count netgraph interfaces */ + $counter = 0; + + /* ng ordering is VERY important here. do not alter order */ + if($config['pptpd']['mode'] == "server") { + /* build pptp alias */ + $tmp = "pptp = \"{ "; + $starting_pptp = 1; + if($config['interfaces']['wan']['ipaddr'] == "pppoe") + $starting_pptp = 1; + for($x=$starting_pptp; $x<$g["n_pptp_units"]+$starting_pptp; $x++) + $tmp .= "ng{$x} "; + $counter = $x; + $tmp .= "}\" \n"; + if($counter > 0) + $aliases .= $tmp; + } + if($config['pppoe']['mode'] == "server") { + /* build pppoe alias */ + $tmp = "pppoe = \"{ "; + $starting_pppoe = 1; + if($config['interfaces']['wan']['ipaddr'] == "pppoe") + $starting_pppoe = 1; + for($x=0; $x<$g["n_pppoe_units"]+$starting_pppoe; $x++) { + $tmp .= "ng{$counter} "; + $counter++; + } + $tmp .= "}\" \n"; + if($x > 0) + $aliases .= $tmp; + } + + $ifdescrs = array(); + for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++) { + $ifdescrs['opt' . $j] = "opt" . $j; + } + $bridgetracker = 0; + foreach ($ifdescrs as $ifdescr => $ifname) { + /* do not process tun interfaces */ + /* do process tun interfaces for openvpn compatibility */ + /* if(stristr(filter_opt_interface_to_real($ifname), "tun") == true) continue; */ + $aliases .= convert_friendly_interface_to_friendly_descr($ifname) . " = \"{ " . filter_opt_interface_to_real($ifname); + if(link_int_to_bridge_interface($ifname)) + $aliases .= " " . link_int_to_bridge_interface($ifname); + $optip = find_interface_ip($config['interfaces'][$ifname]['if']); + if($optip) { + $opt_carp_ints = link_ip_to_carp_interface($optip); + if($opt_carp_ints) + $aliases .= $opt_carp_ints; + } + $aliases .= " }\"\n"; + } + $aliases .= "# User Aliases \n"; + /* Setup pf groups */ + if (isset($config['aliases']['alias'])) { + foreach ($config['aliases']['alias'] as $alias) { + $extraalias = ""; + $ip = find_interface_ip($alias['address']); + $extraalias = " " . link_ip_to_carp_interface($ip); + $aliases .= "{$alias['name']} = \"{ {$alias['address']}{$extralias} }\"\n"; + } + } + + return $aliases; +} + +function get_vpns_list() { + global $config; + /* build list of vpns */ + $vpns = ""; + $isfirst = true; + /* ipsec */ + if ($config['ipsec']['tunnel']) { + foreach ($config['ipsec']['tunnel'] as $tunnel) { + if ($isfirst == false) + $vpns .= " "; + $vpns .= $tunnel['remote-subnet']; + $isfirst = false; + } + } + /* openvpn */ + foreach (array('client', 'server') as $type) { + $conf =& $config['installedpackages']["openvpn$type"]['config']; + if (!is_array($conf)) continue; + foreach ($conf as $tunnel) { + if ($isfirst == false) + $vpns .= " "; + $vpns .= $tunnel['remote_network']; + $isfirst = false; + } + } + /* pppoe */ + if ($config['pppoe']['remoteip']) { + if ($isfirst == false) + $vpns .= " "; + $vpns .= $config['pppoe']['remoteip'] ."/". $config['pppoe']['pppoe_subnet']; + $isfirst = false; + } + $vpns .= " "; + return $vpns; +} + +function generate_optcfg_array(& $optcfg) { + global $config; + if(isset($config['system']['developerspew'])) { + $mt = microtime(); + echo "generate_optcfg_array() being called $mt\n"; + } + + for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++) { + $oc = $config['interfaces']['opt' . $i]; + + if (isset($oc['enable']) && $oc['if']) { + $oic = array(); + $oic['if'] = $oc['if']; + + if ($oc['bridge']) { + if (!strstr($oc['bridge'], "opt") || + isset($config['interfaces'][$oc['bridge']]['enable'])) { + if (is_ipaddr($config['interfaces'][$oc['bridge']]['ipaddr'])) { + $oic['ip'] = $config['interfaces'][$oc['bridge']]['ipaddr']; + $oic['sn'] = $config['interfaces'][$oc['bridge']]['subnet']; + $oic['sa'] = gen_subnet($oic['ip'], $oic['sn']); + } + } + $oic['bridge'] = 1; + } else { + $oic['ip'] = $oc['ipaddr']; + $oic['sn'] = $oc['subnet']; + $oic['sa'] = gen_subnet($oic['ip'], $oic['sn']); + } + + $optcfg['opt' . $i] = $oic; + } + } +} + +function filter_flush_nat_table() { + global $config, $g; + if(isset($config['system']['developerspew'])) { + $mt = microtime(); + echo "filter_flush_nat_table() being called $mt\n"; + } + return mwexec("/sbin/pfctl -F nat"); +} + +function filter_flush_state_table() { + global $config, $g; + + return mwexec("/sbin/pfctl -F state"); +} + +/* Generate a 'nat on' or 'no nat on' rule for given interface */ +function filter_nat_rules_generate_if($if, $src = "any", $srcport = "", $dst = "any", $dstport = "", $natip = "", $natport = "", $nonat = false, $staticnatport = false) { + global $config; + + /* XXX: billm - any idea if this code is needed? */ + if($src == "/32" || $src{0} == "/") + return; + + /* Use interface name if IP isn't specified */ + if ($natip != "") + $tgt = "{$natip}/32"; + else + $tgt = "($if)"; + + /* Add the hard set source port (useful for ISAKMP) */ + if ($natport != "") + $tgt .= " port {$natport}"; + + /* sometimes this gets called with "" instead of a value */ + if ($src == "") + $src = "any"; + + /* Match on this source port */ + if ($srcport != "") + $src .= " port {$srcport}"; + + /* sometimes this gets called with "" instead of a value */ + if ($dst == "") + $dst = "any"; + + /* Match on this dest port */ + if ($dstport != "") + $dst .= " port {$dstport}"; + + /* Allow for negating NAT entries */ + if ($nonat) { + $nat = "no nat"; + $target = ""; + } else { + $nat = "nat"; + $target = "-> {$tgt}"; + } + + /* outgoing static-port option, hamachi, Grandstream, VOIP, etc */ + if($staticnatport) + $staticnatport_txt = " static-port"; + else + $staticnatport_txt = ""; + + $if_friendly = convert_real_interface_to_friendly_descr($if); + + /* Put all the pieces together */ + if($if_friendly) + $natrule = "{$nat} on \${$if_friendly} from {$src} to {$dst} {$target}{$staticnatport_txt}\n"; + + return $natrule; +} + +function is_one_to_one_or_server_nat_rule($iptocheck) { + global $config, $target; + if(isset($config['system']['developerspew'])) { + $mt = microtime(); + echo "is_one_to_one_or_server_nat_rule() being called $mt\n"; + } + + if($config['nat']['onetoone'] <> "") + foreach($config['nat']['onetoone'] as $onetoone) { + if(ip_in_subnet($iptocheck,$onetoone['internal']."/".$onetoone['subnet']) == true) + return true; + if($onetoone['internal'] == $target) + return true; + } + + if($config['nat']['servernat'] <> "") + foreach($config['nat']['servernat'] as $onetoone) { + $int = explode("/", $onetoone['ipaddr']); + if(ip_in_subnet($iptocheck,$onetoone['ipaddr']."/".$onetoone['subnet']) == true) + return true; + if($onetoone['ipaddr'] == $target) + return true; + } + + if($config['nat']['rule'] <> "") + foreach($config['nat']['rule'] as $onetoone) { + $int = explode("/", $onetoone['target']); + if(ip_in_subnet($iptocheck,$onetoone['target']."/".$onetoone['subnet']) == true) + return true; + if($onetoone['target'] == $target) + return true; + } + + return FALSE; +} + +function filter_nat_rules_generate() { + global $config, $g, $after_filter_configure_run; + + $wancfg = $config['interfaces']['wan']; + $lancfg = $config['interfaces']['lan']; + + $pptpdcfg = $config['pptpd']; + $pppoecfg = $config['pppoe']; + $wanif = get_real_wan_interface(); + + $lanif = $config['interfaces']['lan']['if']; + $lanip = $config['interfaces']['lan']['ipaddr']; + + $lansa = gen_subnet($lancfg['ipaddr'], $lancfg['subnet']); + + $natrules .= "nat-anchor \"pftpx/*\"\n"; + + $natrules .= "nat-anchor \"natearly/*\"\n"; + $natrules .= "nat-anchor \"natrules/*\"\n"; + + $natrules .= "# FTP proxy\n"; + $natrules .= "rdr-anchor \"pftpx/*\"\n"; + + update_filter_reload_status("Creating 1:1 rules..."); + + /* any 1:1 mappings? */ + if (is_array($config['nat']['onetoone'])) { + foreach ($config['nat']['onetoone'] as $natent) { + if (!is_numeric($natent['subnet'])) + $sn = 32; + else + $sn = $natent['subnet']; + + if (!$natent['interface'] || ($natent['interface'] == "wan")) + $natif = $wanif; + else + $natif = $config['interfaces'][$natent['interface']]['if']; + + if($natif) + $natrules .= "binat on $natif from {$natent['internal']}/{$sn} to any -> {$natent['external']}/{$sn}\n"; + } + } + + /* any 1:1 mappings? */ + if (is_array($config['nat']['onetoone'])) { + $natrules .= "\n"; + foreach ($config['nat']['onetoone'] as $natent) { + if (!is_numeric($natent['subnet'])) + $sn = 32; + else + $sn = $natent['subnet']; + + if (!$natent['interface'] || ($natent['interface'] == "wan")) + $natif = $wanif; + else + $natif = $config['interfaces'][$natent['interface']]['if']; + + if($natent['interface']) + $natrules .= "binat on $natif from {$natent['internal']}/{$sn} to any -> {$natent['external']}/{$sn}\n"; + } + } + + $natrules .= "\n# Outbound NAT rules\n"; + + /* outbound rules - advanced or standard */ + if (isset($config['nat']['advancedoutbound']['enable'])) { + /* advanced outbound rules */ + if (is_array($config['nat']['advancedoutbound']['rule'])) { + foreach ($config['nat']['advancedoutbound']['rule'] as $obent) { + + update_filter_reload_status("Creating advanced outbound rule {$obent['descr']}"); + + $src = $obent['source']['network']; + if (isset($obent['destination']['not']) && !isset($obent['destination']['any'])) + $dst = "!" . $obent['destination']['address']; + else + $dst = $obent['destination']['address']; + + + if (!$obent['interface'] || ($obent['interface'] == "wan")) + $natif = $wanif; + else + $natif = $config['interfaces'][$obent['interface']]['if']; + + $natrules .= filter_nat_rules_generate_if($natif, + $src, + $obent['sourceport'], + $dst, + $obent['dstport'], + $obent['target'], + $obent['natport'], + isset($obent['nonat']), + isset($obent['staticnatport']) + ); + } + } + } else { + /* standard outbound rules (one for each interface) */ + update_filter_reload_status("Creating outbound NAT rules"); + + $natrules .= filter_nat_rules_generate_if($wanif, + "{$lansa}/{$lancfg['subnet']}", 500, "", 500, null, 500, false); + $natrules .= filter_nat_rules_generate_if($wanif, + "{$lansa}/{$lancfg['subnet']}", 5060, "", 5060, null, 5060, false); + $natrules .= filter_nat_rules_generate_if($wanif, + "{$lansa}/{$lancfg['subnet']}"); + + $optints = array(); + generate_optcfg_array($optints); + + /* generate lan nat mappings for opts with a gateway opts */ + foreach($optints as $oc) { + $opt_interface = $oc['if']; + if (interface_has_gateway("$opt_interface")) { + $natrules .= filter_nat_rules_generate_if($opt_interface, + "{$lansa}/{$lancfg['subnet']}", 500, "", 500, null, 500, false); + $natrules .= filter_nat_rules_generate_if($opt_interface, + "{$lansa}/{$lancfg['subnet']}", 5060, "", 5060, null, 5060, false); + $natrules .= filter_nat_rules_generate_if($opt_interface, + "{$lansa}/{$lancfg['subnet']}"); + } + } + + /* optional interfaces */ + for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++) { + update_filter_reload_status("Creating outbound rules (opt{$i})"); + $optcfg = $config['interfaces']['opt' . $i]; + + if ((isset ($optcfg['enable'])) && (!$optcfg['bridge']) && (!interface_has_gateway("opt{$i}"))) { + $optsa = gen_subnet($optcfg['ipaddr'], $optcfg['subnet']); + + /* create outbound nat entries for primary wan */ + $natrules .= filter_nat_rules_generate_if($wanif, + "{$optsa}/{$optcfg['subnet']}", 500, "", 500, null, 500, false); + $natrules .= filter_nat_rules_generate_if($wanif, + "{$optsa}/{$optcfg['subnet']}", 5060, "", 5060, null, 5060, false); + $natrules .= filter_nat_rules_generate_if($wanif, + "{$optsa}/{$optcfg['subnet']}", null, "", null, null, null, isset($optcfg['nonat'])); + + /* create outbound nat entries for all opt wans */ + foreach($optints as $oc) { + $opt_interface = $oc['if']; + if (interface_has_gateway("$opt_interface")) { + $natrules .= filter_nat_rules_generate_if($opt_interface, + "{$optsa}/{$optcfg['subnet']}", 500, "", 500, null, 500, false); + $natrules .= filter_nat_rules_generate_if($opt_interface, + "{$optsa}/{$optcfg['subnet']}", 5060, "", 5060, null, 5060, false); + $natrules .= filter_nat_rules_generate_if($opt_interface, + "{$optsa}/{$optcfg['subnet']}", null, "", null, null, null, isset($optcfg['nonat'])); + } + } + } + } + + /* PPTP subnet */ + if ($pptpdcfg['mode'] == "server") { + $pptp_subnet = $g['pptp_subnet']; + if($config['pptp']['pptp_subnet'] <> "") + $pptp_subnet = $config['pptp']['pptp_subnet']; + $natrules .= filter_nat_rules_generate_if($wanif, + "{$pptpdcfg['remoteip']}/{$pptp_subnet}", 500, "", 500, null, 500, false); + $natrules .= filter_nat_rules_generate_if($wanif, + "{$pptpdcfg['remoteip']}/{$pptp_subnet}", 5060, "", 5060, null, 5060, false); + $natrules .= filter_nat_rules_generate_if($wanif, + "{$pptpdcfg['remoteip']}/{$pptp_subnet}"); + + /* generate nat mappings for opts with a gateway opts */ + foreach($optints as $oc) { + $opt_interface = $oc['if']; + if ((is_private_ip($pptpdcfg['remoteip'])) && (interface_has_gateway($opt_interface))) { + $natrules .= filter_nat_rules_generate_if($opt_interface, + "{$pptpdcfg['remoteip']}/{$pptp_subnet}", 500, "", 500, null, 500, false); + $natrules .= filter_nat_rules_generate_if($opt_interface, + "{$pptpdcfg['remoteip']}/{$pptp_subnet}", 5060, "", 5060, null, 5060, false); + $natrules .= filter_nat_rules_generate_if($opt_interface, + "{$pptpdcfg['remoteip']}/{$pptp_subnet}"); + } + } + } + + /* PPPoE subnet */ + if ($pppoecfg['mode'] == "server") { + $pppoe_subnet = $g['pppoe_subnet']; + if($config['pppoe']['pppoe_subnet'] <> "") + $pppoe_subnet = $config['pppoe']['pppoe_subnet']; + $natrules .= filter_nat_rules_generate_if($wanif, + "{$pppoecfg['remoteip']}/{$pppoe_subnet}", 500, "", 500, null, 500, false); + $natrules .= filter_nat_rules_generate_if($wanif, + "{$pppoecfg['remoteip']}/{$pppoe_subnet}", 5060, "", 5060, null, 5060, false); + $natrules .= filter_nat_rules_generate_if($wanif, + "{$pppoecfg['remoteip']}/{$pppoe_subnet}"); + + /* generate nat mappings for opts with a gateway opts */ + foreach($optints as $oc) { + $opt_interface = $oc['if']; + if ((is_private_ip($pppoecfg['remoteip'])) && (interface_has_gateway($opt_interface))) { + $natrules .= filter_nat_rules_generate_if($opt_interface, + "{$pppoecfg['remoteip']}/{$pppoe_subnet}", 500, "", 500, null, 500, false); + $natrules .= filter_nat_rules_generate_if($opt_interface, + "{$pppoecfg['remoteip']}/{$pppoe_subnet}", 5060, "", 5060, null, 5060, false); + $natrules .= filter_nat_rules_generate_if($opt_interface, + "{$pppoecfg['remoteip']}/{$pppoe_subnet}"); + } + } + } + + /* static routes */ + if (is_array($config['staticroutes']['route'])) { + foreach ($config['staticroutes']['route'] as $route) { + $netip = explode("/", $route['network']); + if ((! interface_has_gateway($route['interface'])) && (is_private_ip($netip[0]))) { + $natrules .= filter_nat_rules_generate_if($wanif, + "{$route['network']}", 500, "", 500, null, 500, false); + $natrules .= filter_nat_rules_generate_if($wanif, + "{$route['network']}", 5060, "", 5060, null, 5060, false); + $natrules .= filter_nat_rules_generate_if($wanif, + "{$route['network']}", "", null); + } + /* generate nat mapping for static routes on opts */ + foreach($optints as $oc) { + $opt_interface = $oc['if']; + if ((! interface_has_gateway($route['interface'])) && (is_private_ip($netip[0])) && (interface_has_gateway($opt_interface))) { + $natrules .= filter_nat_rules_generate_if($opt_interface, + "{$route['network']}", 500, "", 500, null, 500, false); + $natrules .= filter_nat_rules_generate_if($opt_interface, + "{$route['network']}", 5060, "", 5060, null, 5060, false); + $natrules .= filter_nat_rules_generate_if($opt_interface, + "{$route['network']}", "", null); + } + } + + } + } + + } + + $natrules .= "\n#SSH Lockout Table\n"; + $natrules .= "table <sshlockout> persist\n\n"; + + /* is SPAMD insalled? */ + if (is_package_installed("spamd") == 1) { + $natrules .= "\n# spam table \n"; + + $natrules .= "table <whitelist> persist\n"; + $natrules .= "table <blacklist> persist\n"; + $natrules .= "table <spamd> persist\n"; + if(file_exists("/var/db/whitelist.txt")) + $natrules .= "table <spamd-white> persist file \"/var/db/whitelist.txt\"\n"; + $natrules .= "rdr pass on {$wanif} proto tcp from <blacklist> to port smtp -> 127.0.0.1 port spamd\n"; + $natrules .= "rdr pass on {$wanif} proto tcp from <spamd> to port smtp -> 127.0.0.1 port spamd\n"; + $natrules .= "rdr pass on {$wanif} proto tcp from !<spamd-white> to port smtp -> 127.0.0.1 port spamd\n"; + if($config['installedpackages']['spamdsettings']['config']) + foreach($config['installedpackages']['spamdsettings']['config'] as $ss) + $nextmta = $ss['nextmta']; + if($nextmta <> "") { + $natrules .= "rdr pass on {$wanif} proto tcp from <spamd-white> to port smtp -> {$nextmta} port smtp\n"; + } + } + + /* load balancer anchor */ + $natrules .= "\n# Load balancing anchor - slbd updates\n"; + $natrules .= "rdr-anchor \"slb\"\n"; + + update_filter_reload_status("Setting up FTP helper"); + + $natrules .= "\n# FTP Proxy/helper\n"; + /* build an array of interfaces to work with */ + $iflist = array("lan" => "LAN"); + for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++) + $iflist['opt' . $i] = "opt{$i}"; + $interface_counter = 0; + $vpns_list = get_vpns_list(); + /* prevent 1:1 ips from pftpx, they will be handled by ftp-sesame */ + if($config['nat']['onetoone']) + foreach ($config['nat']['onetoone'] as $vipent) + $onetoone_list .= "{$vipent['internal']} "; + if($onetoone_list) + $natrules .= "table <onetoonelist> { $onetoone_list }\n"; + if($vpns_list) + $natrules .= "table <vpns> { $vpns_list }\n"; + /* loop through all interfaces and handle pftpx redirections */ + foreach ($iflist as $ifent => $ifname) { + $ifname_lower = convert_friendly_interface_to_friendly_descr(strtolower($ifname)); + $realif = convert_friendly_interface_to_real_interface_name(strtolower($ifname)); + $int_ip = find_interface_ip($realif); + if(isset($config['interfaces'][strtolower($ifname)]['disableftpproxy'])) { + if($g['debug']) + log_error("Filter: FTP proxy disabled for interface {$ifname} - ignoring."); + $interface_counter++; + continue; + } + if(stristr($ifname, "opt")) { + if(!isset($config['interfaces'][$ifname]['enable'])) { + continue; + } + } + /* are we in routed mode? no source nat rules and not a outside interface? */ + /* If we have advanced outbound nat we skip the FTP proxy, we use ftpsesame */ + if((isset($config['nat']['advancedoutbound']['enable'])) && (! interface_has_gateway($ifname))) { + $sourcenat = 0; + /* we are using advanced outbound nat, are we in routing mode? */ + $realif = convert_friendly_interface_to_real_interface_name($ifname); + /* if the interface address lies within a outbound NAT source network we should skip */ + if(! empty($config['nat']['advancedoutbound']['rule'])) { + foreach($config['nat']['advancedoutbound']['rule'] as $natnetwork) { + if(ip_in_subnet($int_ip, $natnetwork['source']['network'])) { + /* if the interface address is matched in the AON Rule we need the ftp proxy */ + $sourcenat++; + } + } + } + if($sourcenat == 0) { + if($g['debug']) + log_error("Filter: No AON rule matched for interface {$ifname} - not using the FTP proxy"); + $interface_counter++; + continue; + } else { + if($g['debug']) + log_error("Filter: AON Rule matched for interface {$ifname} - using FTP proxy"); + } + } + $tmp_port = 8021 + $interface_counter; + $tmp_interface = convert_friendly_interface_to_real_interface_name($ifname); + $ifname_lower = strtolower(convert_friendly_interface_to_friendly_descr($ifname)); + $vpns = get_vpns_list(); + /* if the user has defined, include the alias so that we do not redirect ftp + connections across the tunnels to pftpx */ + $int_ip = find_interface_ip($tmp_interface); + /* if interface lacks an ip, dont setup a rdr for ftp. they are most likely on a bridged interface */ + if($int_ip and $vpns_list) + if($ifname_lower) { + $natrules .= "no rdr on $tmp_interface proto tcp from any to <vpns> port 21\n"; + if($onetoone_list) + $natrules .= "no rdr on $tmp_interface proto tcp from <onetoonelist> to any port 21\n"; + } + if($ifname_lower) + $natrules .= "rdr on $tmp_interface proto tcp from any to any port 21 -> 127.0.0.1 port {$tmp_port}\n"; + $interface_counter++; + } + $natrules .= "\n"; + + /* DIAG: add ipv6 NAT, if requested */ + if (isset($config['diag']['ipv6nat']['enable']) and $config['diag']['ipv6nat']['ipaddr'] <> "") { + /* XXX: FIX ME! IPV6 */ + $natrules .= "rdr on \$wan proto ipv6 from any to any -> {$config['diag']['ipv6nat']['ipaddr']}\n"; + } + + if(file_exists("/var/etc/inetd.conf")) + mwexec("rm /var/etc/inetd.conf"); + touch("/var/etc/inetd.conf"); + + if (isset($config['nat']['rule'])) { + $natrules .= "# NAT Inbound Redirects\n"; + + if(!isset($config['system']['disablenatreflection'])) { + $inetd_fd = fopen("/var/etc/inetd.conf","w"); + /* start redirects on port 19000 of localhost */ + $starting_localhost_port = 19000; + } + + foreach ($config['nat']['rule'] as $rule) { + + update_filter_reload_status("Creating NAT rule {$rule['descr']}"); + + /* if item is an alias, expand */ + $extport = ""; + unset($extport); + if(alias_expand($rule['external-port'])) + $extport[0] = alias_expand_value($rule['external-port']); + else + $extport = explode("-", $rule['external-port']); + + /* if item is an alias, expand */ + if(alias_expand($rule['local-port'])) + $localport = ""; + else + $localport = " port {$rule['local-port']}"; + + $target = alias_expand_host($rule['target']); + + if (!$target) { + $natrules .= "# Unresolvable alias {$rule['target']}\n"; + continue; /* unresolvable alias */ + } + + # use tables for aliases in rdr + if (!is_ipaddr($target)) { + $natrules .= "table <{$rule['target']}> { $target }\n"; + $target = "<{$rule['target']}>"; + } + + if ($rule['external-address']) + if($rule['external-address'] <> "any") + $extaddr = $rule['external-address'] . "/32"; + else + $extaddr = $rule['external-address']; + else + $extaddr = get_current_wan_address($rule['interface']); + + if (!$rule['interface'] || ($rule['interface'] == "wan")) + $natif = $wanif; + else if($rule['interface'] == "\$pptp") + $natif = "pptp"; + else if($rule['interface'] == "\$pppoe") + $natif = "pppoe"; + else + $natif = $config['interfaces'][$rule['interface']]['if']; + + $lanif = $lancfg['if']; + + /* + * Expand aliases + * XXX: may want to integrate this into pf macros + */ + if(alias_expand($target)) + $target = alias_expand($target); + if(alias_expand($extaddr)) + $extaddr = alias_expand($extaddr); + + /* + * If FTP Proxy Helper is enabled and the + * operator has requested a port forward to + * a ftp server then launch a helper + */ + $dontinstallrdr = false; + if($target <> "") { + $external_address = $rule['external-address']; + if($extport[0] == "21" and !isset($config['interfaces'][strtolower($rule['interface'])]['disableftpproxy'])) { + $helpers = exec("/bin/ps awux | grep \"{$target} -b {$external_address}\" | grep -v grep"); + if(!$helpers) { + if($external_address == "") + $external_address = find_interface_ip(get_real_wan_interface()); + /* install a pftpx helper, do not set a rule. also use the delay filter configure run + * routines because if this is the first bootup the filter is not completely configured + * and thus pf is not fully running. otherwise we end up with: pftpx: pf is disabled + */ + if(isset($config['shaper']['enable'])) { + if(isset($config['ezshaper']['step5']['p2pcatchall'])) { + $shaper_queue = "-q qP2PUp "; + } else { + $upq = "q" . convert_friendly_interface_to_friendly_descr($config['ezshaper']['step2']['outside_int']); + $shaper_queue = "-q {$upq}def "; + } + } else { + $shaper_queue = ""; + } + $after_filter_configure_run[] = "/usr/local/sbin/pftpx {$shaper_queue}-f {$target} -b {$external_address} -c 21 -g 21"; + } + $dontinstallrdr = true; + } + } + + if($extaddr == "") + $dontinstallrdr = true; + + $rdr_on = convert_real_interface_to_friendly_descr($rule['interface']); + + if($dontinstallrdr == false) { + /* is rule a port range? */ + if ((!$extport[1]) || ($extport[0] == $extport[1])) { + + switch ($rule['protocol']) { + case "tcp/udp": + if($natif) { + if($rule['external-port'] <> $rule['local-port']) + $natrules .= "{$nordr}rdr on $natif proto { tcp udp } from any to {$extaddr} port { {$extport[0]} } -> {$target}{$localport}"; + else + $natrules .= "{$nordr}rdr on $natif proto { tcp udp } from any to {$extaddr} port { {$extport[0]} } -> {$target}"; + } + break; + case "udp": + case "tcp": + if($extport[0]) + if($natif) { + if($rule['external-port'] <> $rule['local-port']) + $natrules .= "rdr on $natif proto {$rule['protocol']} from any to {$extaddr} port { {$extport[0]} } -> {$target}{$localport}"; + else + $natrules .= "rdr on $natif proto {$rule['protocol']} from any to {$extaddr} port { {$extport[0]} } -> {$target}"; + } + else + if($natif) + $natrules .= "rdr on $natif proto {$rule['protocol']} from any to {$extaddr} -> {$target}{$localport}"; + break; + default: + $natrules .= "rdr on $natif proto {$rule['protocol']} from any to {$extaddr} -> {$target}"; + break; + } + } else { + switch ($rule['protocol']) { + case "tcp/udp": + if($natif) + $natrules .= "{$nordr}rdr on $natif proto { tcp udp } from any to {$extaddr} port {$extport[0]}:{$extport[1]} -> {$target}{$localport}:*"; + break; + case "udp": + case "tcp": + if($natif) + $natrules .= "{$nordr}rdr on $natif proto {$rule['protocol']} from any to {$extaddr} port {$extport[0]}:{$extport[1]} -> {$target}{$localport}:*"; + break; + default: + if($natif) + $natrules .= "{$nordr}rdr on $natif proto {$rule['protocol']} from any to {$extaddr} -> {$target}"; + } + } + } + + /* does this rule redirect back to a internal host? + * if so, add some extra goo to help this work. + */ + $rule_friendly_if = convert_friendly_interface_to_real_interface_name($rule['interface']); + $rule_interface_ip = find_interface_ip($rule_friendly_if); + $rule_interface_subnet = $config['interfaces'][$rule['interface']]['subnet']; + $rule_subnet = gen_subnet($rule_interface_ip, $rule_interface_subnet); + if($rule['external-address'] == "any" and $rule['interface'] == "lan") { + $natrules .= "\n"; + if($rule_friendly_if) + $natrules .= "no nat on {$rule_friendly_if} proto tcp from {$rule_friendly_if} to {$rule_subnet}/{$rule_interface_subnet}\n"; + if($rule_friendly_if) + $natrules .= "nat on {$rule_friendly_if} proto tcp from {$rule_subnet}/{$rule_interface_subnet} to {$target} port {$extport[0]} -> {$rule_friendly_if}\n"; + } + + if(!isset($config['system']['disablenatreflection'])) { + + update_filter_reload_status("Setting up reflection"); + + $natrules .= "\n# Reflection redirects\n"; + foreach ($iflist as $ifent => $ifname) { + + /* do not process interfaces with gateways*/ + if($config['interfaces'][$ifname]['gateway'] <> "") + continue; + + /* do not process interfaces that will end up with gateways */ + if($config['interfaces'][$ifname]['ipaddr'] == "dhcp" or + $config['interfaces'][$ifname]['ipaddr'] == "bigpond" or + $config['interfaces'][$ifname]['ipaddr'] == "pppoe" or + $config['interfaces'][$ifname]['ipaddr'] == "pptp") + continue; + + $ifname_real = convert_friendly_interface_to_real_interface_name($ifname); + + if($extport[1]) + $range_end = ($extport[1]); + else + $range_end = ($extport[0]); + + $range_end++; + + if($rule['local-port']) + $lrange_start = $rule['local-port']; + + if($range_end - $extport[0] > 500) { + $range_end = $extport[0]+1; + log_error("Not installing nat reflection rules for a port range > 500"); + } else { + /* only install reflection rules for < 19991 items */ + if($starting_localhost_port < 19991) { + $loc_pt = $lrange_start; + for($x=$extport[0]; $x<$range_end; $x++) { + + $xxx = $x; + + /* do not install reflection rules for FTP. This simply + * opens up pandoras box. + */ + if($xxx == "21") + continue; + + update_filter_reload_status("Creating reflection rule for {$rule['descr']}..."); + + $ifname_real = convert_friendly_interface_to_friendly_descr(strtolower($ifname)); + + if($config['system']['reflectiontimeout']) + $reflectiontimeout = $config['system']['reflectiontimeout']; + else + $reflectiontimeout = "2000"; + + switch($rule['protocol']) { + + case "tcp/udp": + $protocol = "{ tcp udp }"; + $toadd_array = array(); + if(is_alias($loc_pt)) { + $loc_pt_translated = alias_expand_value($loc_pt); + if(stristr($loc_pt_translated, " ")) { + /* XXX: we should deal with multiple ports */ + $loc_pt_translated_split = split(" ", $loc_pt_translated); + foreach($loc_pt_translated_split as $lpts) + $toadd_array[] = $lpts; + } else { + $toadd_array[] = $loc_pt_translated; + } + } else { + $loc_pt_translated = $loc_pt; + $toadd_array[] = $loc_pt_translated; + } + foreach($toadd_array as $tda){ + fwrite($inetd_fd, "{$starting_localhost_port}\tstream\ttcp/udp\tnowait/0\tnobody\t/usr/bin/nc nc -u -w {$reflectiontimeout} {$target} {$tda}\n"); + if($ifname_real) + $natrules .= "rdr on \${$ifname_real} proto tcp from any to {$extaddr} port { {$xxx} } -> 127.0.0.1 port {$starting_localhost_port}\n"; + $starting_localhost_port++; + fwrite($inetd_fd, "{$starting_localhost_port}\tstream\ttcp/udp\tnowait/0\tnobody\t/usr/bin/nc nc -w {$reflectiontimeout} {$target} {$tda}\n"); + if($ifname_real) + $natrules .= "rdr on \${$ifname_real} proto udp from any to {$extaddr} port { {$xxx} } -> 127.0.0.1 port {$starting_localhost_port}\n"; + $xxx++; + $starting_localhost_port++; + } + break; + case "tcp": + case "udp": + $protocol = $rule['protocol']; + $toadd_array = array(); + if(is_alias($loc_pt)) { + $loc_pt_translated = alias_expand_value($loc_pt); + if(stristr($loc_pt_translated, " ")) { + /* XXX: we should deal with multiple ports */ + $loc_pt_translated_split = split(" ", $loc_pt_translated); + foreach($loc_pt_translated_split as $lpts) + $toadd_array[] = $lpts; + } else { + $toadd_array[] = $loc_pt_translated; + } + } else { + $loc_pt_translated = $loc_pt; + $toadd_array[] = $loc_pt_translated; + } + foreach($toadd_array as $tda){ + if($protocol == "udp") + $dash_u = "-u "; + else + $dash_u = ""; + if($config['system']['reflectiontimeout']) + $reflectiontimeout = $config['system']['reflectiontimeout']; + else + $reflectiontimeout = "20"; + fwrite($inetd_fd, "{$starting_localhost_port}\tstream\t{$protocol}\tnowait/0\tnobody\t/usr/bin/nc nc {$dash_u}-w {$reflectiontimeout} {$target} {$tda}\n"); + if($ifname_real) + $natrules .= "rdr on \${$ifname_real} proto {$protocol} from any to {$extaddr} port { {$xxx} } -> 127.0.0.1 port {$starting_localhost_port}\n"; + $xxx++; + $starting_localhost_port++; + } + break; + default: + break; + } + $loc_pt++; + if($starting_localhost_port > 19990) { + log_error("Not installing nat reflection rules. Maximum 1,000 reached."); + $x = $range_end+1; + } + } + } + } + + } + + } + + $natrules .= "\n"; + } + + if(!isset($config['system']['disablenatreflection'])) { + fclose($inetd_fd); + $helpers = trim(exec("/bin/ps ax | /usr/bin/grep inetd | /usr/bin/grep -v grep | /usr/bin/grep 127")); + if(!$helpers) + mwexec("/usr/sbin/inetd -wW -R 0 -a 127.0.0.1 /var/etc/inetd.conf"); + else + mwexec("/usr/bin/killall -HUP inetd"); + + } + } + + if ($pptpdcfg['mode'] && $pptpdcfg['mode'] != "off") { + + if ($pptpdcfg['mode'] == "server") + $pptpdtarget = "127.0.0.1"; + else if ($pptpdcfg['mode'] == "redir") + $pptpdtarget = $pptpdcfg['redir']; + + if ($pptpdcfg['mode'] == "redir") { + + $natrules .= <<<EOD + +# PPTP +rdr on \$wan proto gre from any to any -> $pptpdtarget +rdr on \$wan proto tcp from any to any port 1723 -> $pptpdtarget + +EOD; + } + } + + if (is_package_installed('squid') && file_exists('/usr/local/pkg/squid.inc')) { + require_once('squid.inc'); + $natrules .= squid_generate_rules('nat'); + } + + if (is_package_installed('clamav') && file_exists('/usr/local/pkg/clamav.inc')) { + require_once('clamav.inc'); + $natrules .= clamav_generate_rules('nat'); + } + + if (is_package_installed('frickin') && file_exists('/usr/local/pkg/frickin.inc')) { + require_once ('frickin.inc'); + $natrules .= frickin_generate_rules('nat'); + } + + if (is_package_installed('siproxd') && file_exists('/usr/local/pkg/sipproxd.inc')) { + require_once('sipproxd.inc'); + $natrules .= siproxd_generate_rules('nat'); + } + + $natrules .= process_carp_nat_rules(); + + $natrules .= "# IMSpector rdr anchor\n"; + $natrules .= "rdr-anchor \"imspector\"\n"; + + $natrules .= "# UPnPd rdr anchor\n"; + $natrules .= "rdr-anchor \"miniupnpd\"\n"; + + return $natrules; +} + +function run_command_return_string($cmd) { + global $config; + if(isset($config['system']['developerspew'])) { + $mt = microtime(); + echo "generate_user_filter_rule() being called $mt\n"; + } + + $fd = popen($cmd, "r"); + while(!feof($fd)) { + $tmp .= fread($fd,49); + } + fclose($fd); + return $tmp; +} + +function generate_user_filter_rule_arr($rule, $ngcounter) { + global $config; + update_filter_reload_status("Creating filter rules {$rule['descr']} ..."); + if(isset($config['system']['developerspew'])) { + $mt = microtime(); + echo "generate_user_filter_rule() being called $mt\n"; + } + $ret = array(); + $line = generate_user_filter_rule($rule, $ngcounter); + $ret['rule'] = $line; + $ret['interface'] = $rule['interface']; + if ($line[0] != '#') { + if($rule['descr'] != "" and $line != "") + $ret['descr'] = "label \"USER_RULE: " . str_replace('"', '', $rule['descr']) . "\""; + else + $ret['descr'] = "label \"USER_RULE\""; + } + $ret['ackq'] = get_ack_queue($rule['interface']); + + return $ret; +} + +function generate_user_filter_rule($rule, $ngcounter) { + global $config, $g; + global $table_cache; + global $schedule_enabled; + + if($config['schedules']) { + foreach($config['schedules']['schedule'] as $sched) { + $schedule_enabled = true; + break; + } + } + + if(isset($config['system']['developerspew'])) { + $mt = microtime(); + echo "generate_user_filter_rule() being called $mt\n"; + } + + /* Setup cache array if not already existing */ + if (!isset($table_cache)) { + if ($g['debug']) + echo "Creating table cache\n"; + $table_cache = array(); + } + + update_filter_reload_status("Creating filter rules {$rule['descr']} ..."); + + $wancfg = $config['interfaces']['wan']; + $lancfg = $config['interfaces']['lan']; + $pptpdcfg = $config['pptpd']; + $pppoecfg = $config['pppoe']; + + $lanif = $lancfg['if']; + $wanif = get_real_wan_interface(); + + $lanip = $lancfg['ipaddr']; + $lansa = gen_subnet($lancfg['ipaddr'], $lancfg['subnet']); + $lansn = $lancfg['subnet']; + + $int = ""; + + $optcfg = array(); + generate_optcfg_array($optcfg); + + $curwanip = get_current_wan_address(); + + /* don't include disabled rules */ + if (isset($rule['disabled'])) { + return "# rule " . $rule['descr'] . " disabled "; + } + + $pptpdcfg = $config['pptpd']; + $pppoecfg = $config['pppoe']; + + if ($pptpdcfg['mode'] == "server") { + $pptpip = $pptpdcfg['localip']; + $pptpsa = $pptpdcfg['remoteip']; + $pptpsn = $g['pptp_subnet']; + if($config['pptp']['pptp_subnet'] <> "") + $pptpsn = $config['pptp']['pptp_subnet']; + } + + if ($pppoecfg['mode'] == "server") { + $pppoeip = $pppoecfg['localip']; + $pppoesa = $pppoecfg['remoteip']; + $pppoesn = $g['pppoe_subnet']; + if($config['pppoe']['pppoe_subnet'] <> "") + $pppoesn = $config['pppoe']['pppoe_subnet']; + } + + /* does the rule deal with a PPTP interface? */ + if ($rule['interface'] == "pptp") { + if ($pptpdcfg['mode'] != "server") + return ""; + $nif = $g['n_pptp_units']; + if($config['pptp']['n_pptp_units'] <> "") + $nif = $config['pptp']['n_pptp_units']; + $ispptp = true; + } else if($rule['interface'] == "pppoe") { + if ($pppoecfg['mode'] != "server") { + return " # Error creating pppoe rule"; + } + $nif = $g['n_pppoe_units']; + if($config['pppoe']['n_pppoe_units'] <> "") + $nif = $config['pppoe']['n_pppoe_units']; + $ispppoe = true; + } else if(!isset($rule['interface'])) { + return '# Interface empty for rule: '.$rule['descr']; + } else { + + /* Check to see if the interface is opt and in our opt list */ + if (strstr($rule['interface'], "opt")) { + if (!array_key_exists($rule['interface'], $optcfg)) { + $item = ""; + foreach($optcfg as $oc) $item .= $oc['if']; + return "# {$real_int} {$item} {$rule['interface']} array key does not exist for " . $rule['descr']; + } + } + + $nif = 1; + $ispptp = false; + $ispppoe = false; + } + + if ($pptpdcfg['mode'] != "server") { + if (($rule['source']['network'] == "pptp") || + ($rule['destination']['network'] == "pptp")) { + return "# source network or destination network == pptp on " . $rule['descr']; + } + } + + if ($rule['source']['network'] && strstr($rule['source']['network'], "opt")) { + if (!array_key_exists($rule['source']['network'], $optcfg)) { + $optmatch = ""; + if(preg_match("/opt([0-999])/", $rule['source']['network'], $optmatch)) { + $real_opt_int = convert_friendly_interface_to_real_interface_name("opt" . $optmatch[1]); + $opt_ip = find_interface_ip($real_opt_int); + if(!$opt_ip) + return "# unresolvable optarray $real_opt_int - $optmatch[0] - $opt_ip"; + } else { + return "# {$rule['source']['network']} !array_key_exists source network " . $rule['descr']; + } + } + } + if ($rule['destination']['network'] && strstr($rule['destination']['network'], "opt")) { + if (!array_key_exists($rule['destination']['network'], $optcfg)) { + if(preg_match("/opt([0-999])/", $rule['destination']['network'], $optmatch)) { + $real_opt_int = convert_friendly_interface_to_real_interface_name("opt" . $optmatch[1]); + $opt_ip = find_interface_ip($real_opt_int); + if(!$opt_ip) + return "# unresolvable oparray $real_opt_int - $optmatch[0] - $opt_ip"; + } else { + return "# {$item} {$rule['destination']['network']} !array_key_exists dest network " . $rule['descr']; + } + } + } + + /* check for unresolvable aliases */ + if ($rule['source']['address'] && !alias_expand($rule['source']['address'])) { + file_notice("Filter_Reload", "# unresolvable source aliases {$rule['descr']}"); + return "# unresolvable source aliases {$rule['descr']}"; + } + if ($rule['destination']['address'] && !alias_expand($rule['destination']['address'])) { + file_notice("Filter_Reload", "# unresolvable dest aliases {$rule['descr']}"); + return "# unresolvable dest aliases {$rule['descr']}"; + } + + $ifdescrs = array(); + for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++) + $ifdescrs[] = "opt" . $i; + + update_filter_reload_status("Setting up pass/block rules"); + + for ($iif = 0; $iif < $nif; $iif++) { + + $type = $rule['type']; + + + if ($type != "pass" && $type != "block" && $type != "reject") { + /* default (for older rules) is pass */ + $type = "pass"; + } + + if ($type == "reject") { + /* special reject packet */ + if ($rule['protocol'] == "tcp") { + $aline['type'] = "block return-rst"; + } else if ($rule['protocol'] == "udp") { + $aline['type'] = "block return-icmp"; + } else if ($rule['protocol'] == "tcp/udp") { + $aline['type'] = "block return"; + } else { + $aline['type'] = "block"; + } + } else { + $aline['type'] = $type; + } + + /* ensure the direction is in */ + $aline['direction'] = " in "; + + if (isset($rule['log'])) + $aline['log'] = "log "; + + $aline['quick'] = "quick "; + + if ($ispptp) { + $aline['interface'] = "on \$pptp "; + } else if ($ispppoe) { + $aline['interface'] = "on \$pppoe "; + } else { + // translate wan, man, lan, opt to real interface. + $interface = $rule['interface']; + $temp = filter_get_opt_interface_descr($interface); + if($temp <> "") $interface = $temp; + if(isset($rule['destination']['address'])) { + $canadd = 0; // XXX: billm - eh? this is a nice little noop + /* because pf will not allow a interface for proxyARP + type traffic lets check if its in use and if so leave + off the interface */ + if(is_one_to_one_or_server_nat_rule($rule['destination']['address'])) + $canadd = 0; + } + if($canadd == 0) + $aline['interface'] = "on \$" . convert_real_interface_to_friendly_descr($rule['interface']) . " "; + } + + + /* set the gateway interface */ + $ri = filter_translate_type_to_real_interface($rule['interface']); + + update_filter_reload_status("Setting up pass/block rules {$rule['descr']}"); + + /* + * check to see if /tmp/{${ri}_router exists. This file + * is created by dhclient for 2nd wan interfaces, etc. + * else get gateway from the interface config + */ + if(file_exists("{$g['tmp_path']}/{$ri}_router")) { + $rg = file_get_contents("{$g['tmp_path']}/{$ri}_router"); + $rg = rtrim($rg); + } elseif ($config['interfaces'][$rule['interface']]['gateway'] <> "") { + $rg = $config['interfaces'][$rule['interface']]['gateway']; + } + + /* do not process reply-to for gateway'd rules */ + if(($rule['gateway'] == "") and ($ri != "") and ($rg != "") and (stristr($rule['interface'],"opt") == true)) { + $aline['reply'] = "reply-to (" . $ri . " " . $rg . ") "; + } + + /* if user has selected a custom gateway, lets work with it */ + if($rule['gateway'] <> "") { + $foundlb = 0; + $routeto = " route-to { "; + if(is_array($config['load_balancer']['lbpool'])) { + foreach($config['load_balancer']['lbpool'] as $lb) { + update_filter_reload_status("Creating load balancing item..."); + if($lb['name'] == $rule['gateway']) { + $gateway = $rule['gateway']; + /* + * is $gateway a interface name? + * if so, lets find out the gateway address + * from /tmp/router_bleh.router + */ + if(in_array($gateway, $ifdescrs)==true) { + if(is_file("{$g['tmp_path']}/{$gateway}_router")) { + $return_gateway = file_get_contents("{$g['tmp_path']}/{$gateway}_router"); + } else { + log_error("Could not find {$g['tmp_path']}/{$gateway}_router. Needed for dhcp gateway information"); + continue; + } + } + /* if /tmp/$lbname.pool exists then read in our gateway hints from slbd */ + if(file_exists("{$g['tmp_path']}/{$lb['name']}.pool")) { + $lbs_tmp = split("\n", file_get_contents("{$g['tmp_path']}/{$lb['name']}.pool")); + $lbs = array(); + /* process the entire file to prevent empty lines */ + foreach($lbs_tmp as $lb_tmp) { + if(is_ipaddr($lb_tmp)) { + $lbs[] = $lb_tmp; + } + } + $lbs_count = count($lbs); + if($g['debug']) + log_error("We found $lbs_count valid entries in status file {$g['tmp_path']}/{$lb['name']}.pool"); + + if(count($lbs) == 0) { + if($g['debug']) + log_error("There are no servers found in the status file, using XML config settings!"); + foreach ($lb['servers'] as $lbsvr) { + $lbsvr_split = split("\|", $lbsvr); + $lbs[] = $lbsvr_split[1]; + } + } + } else { + if($g['debug']) + log_error("There is no server status file, using XML config settings!"); + $lbs = array(); + foreach ($lb['servers'] as $lbsvr) { + $lbsvr_split = split("\|", $lbsvr); + $lbs[] = $lbsvr_split[1]; + } + } + /* If we want failover we only return the first (top) server from the list + * and work our way down from there. This way we order the failover order. + */ + if($lb['behaviour'] == "failover") { + $firstsrv = $lbs[0]; + $lbs = array("$firstsrv"); + } + + /* create server/gateway gateway/monitor array */ + $l = 0; + $lbconfig = array(); + foreach ($lb['servers'] as $lbsvr) { + $lbsvr_split=split("\|", $lbsvr); + $lbconfig['gateway'][$l] = $lbsvr_split[0]; + $lbconfig['monitor'][$l] = $lbsvr_split[1]; + $l++; + } + $lbconfig_count = count($lbconfig['gateway']); + + $l = 0; + while($l < $lbconfig_count) { + /* iterate through $lbs and setup items accordingly */ + foreach($lbs as $server) { + if ($server == "") + continue; + unset($gateway, $int); + if ($lbconfig['monitor'][$l] == $server) { + /* determine interface gateway */ + if(is_ipaddr($lbconfig['gateway'][$l])) { + $int = guess_interface_from_ip($lbconfig['gateway'][$l]); + $gateway = $lbconfig['gateway'][$l]; + log_error("SLBD pool {$lb['name']} is old style. Please recreate."); + } else if(interface_has_gateway($lbconfig['gateway'][$l])) { + $int = convert_friendly_interface_to_real_interface_name($lbconfig['gateway'][$l]); + $gateway = get_interface_gateway($lbconfig['gateway'][$l]); + } + if(($int <> "") && ($gateway <> "")) { + if($g['debug']) + log_error("Setting up route with {$lbconfig['gateway'][$l]} om $int for monitor {$lbconfig['monitor'][$l]} on gateway $gateway"); + if($foundlb == 1) + $routeto .= ", "; + $routeto .= "( {$int} {$gateway} ) "; + $foundlb = 1; + } + /* we have a match, go forth and try the next LB item so we don't setup multiples incorrectly */ + $l++; + continue; + } + } + $l++; + } + /* If we want failover just use route-to else round-robin */ + if($lb['behaviour'] == "failover") { + $routeto .= "} "; + } else { + $routeto .= "} round-robin "; + if(isset($config['system']['lb_use_sticky'])) + $routeto .= " sticky-address "; + } + } + } + /* Add the load balanced gateways */ + if ($foundlb == 1) + $aline['route'] = $routeto; + } + /* we're not using load balancing, just setup gateway */ + if($foundlb == 0) { + $gateway = $rule['gateway']; + /* + * is $gateway a interface name? + * if so, lets find out the gateway address + * from /tmp/router_bleh.router + */ + if(in_array($gateway, $ifdescrs)==true) { + $int=filter_opt_interface_to_real($gateway); + if(is_file("{$g['tmp_path']}/{$int}_router")) { + $gatewayip = file_get_contents("{$g['tmp_path']}/{$int}_router"); + $gatewayip = rtrim($gatewayip); + if (is_ipaddr($gatewayip)) { + $aline['route'] = " route-to ( {$int} {$gatewayip} ) "; + } + } else { + log_error("Could not find {$g['tmp_path']}/{$int}_router. Needed for dhcp gateway information"); + continue; + } + } else { + /* user picked a real gateway ip */ + if(is_ipaddr($rule['gateway'])) { + $gatewayip = $rule['gateway']; + $int = guess_interface_from_ip($gatewayip); + $aline['route'] = " route-to ( " . guess_interface_from_ip($rule['gateway']) . " {$rule['gateway']} ) "; + } + } + } + } + + if (isset($rule['protocol'])) { + if($rule['protocol'] == "tcp/udp") + $aline['prot'] = "proto { tcp udp } "; + elseif($rule['protocol'] == "icmp") + $aline['prot'] = "inet proto icmp "; + else + $aline['prot'] = "proto {$rule['protocol']} "; + } else { + if($rule['source']['port'] <> "" || $rule['destination']['port'] <> "") { + $aline['prot'] = "proto tcp "; + } + } + + update_filter_reload_status("Creating rule {$rule['descr']}"); + + /* source address */ + if (isset($rule['source']['any'])) { + $src = "any"; + } else if ($rule['source']['network']) { + + if (strstr($rule['source']['network'], "opt")) { + $src = $optcfg[$rule['source']['network']]['sa'] . "/" . + $optcfg[$rule['source']['network']]['sn']; + if (isset($rule['source']['not'])) $src = " !{$src}"; + /* check for opt$NUMip here */ + $matches = ""; + if (preg_match("/opt([0-9999])ip/", $rule['source']['network'], $matches)) { + $optnum = $matches[1]; + $real_int = convert_friendly_interface_to_real_interface_name("opt{$optnum}"); + $src = find_interface_ip($real_int); + } + } else { + switch ($rule['source']['network']) { + case 'wanip': + $src = $curwanip; + break; + case 'lanip': + $src = $lanip; + break; + case 'lan': + $src = "{$lansa}/{$lansn}"; + break; + case 'pptp': + $src = "{$pptpsa}/{$pptpsn}"; + break; + case 'pppoe': + $src = "{$pppoesa}/{$pppoesn}"; + break; + } + if (isset($rule['source']['not'])) $src = "!{$src}"; + } + } else if ($rule['source']['address']) { + $expsrc = alias_expand($rule['source']['address']); + + if (isset($rule['source']['not'])) + $not = "!"; + else + $not = ""; + + if (stristr($expsrc, "$")) { + if($not) { + $src = "{"; + foreach(preg_split("/[\s]+/", alias_expand_value($rule['source']['address'])) as $item) { + if($item != "") { + $src .= " {$not}{$item}"; + } + } + /* added support for tables */ + $src .= " 0/0 }"; + $src_table = "<not" . $rule['source']['address'] . ">"; + } + else { + $src = "{ {$not} " . alias_expand_value($rule['source']['address']) . " } "; + $src_table = "<" . $rule['source']['address'] . ">"; + } + + /* support for tables */ + $src_table_line = "table $src_table {$src}\n"; + $src = $src_table; + } + else + $src = "{ {$not} {$expsrc} }"; + } + + if (!$src || ($src == "/")) { + return "# at the break!"; + } + + $aline['src'] = "from $src "; + + if (in_array($rule['protocol'], array("tcp","udp","tcp/udp"))) { + + if ($rule['source']['port']) { + $srcport = explode("-", $rule['source']['port']); + if(alias_expand($srcport[0])) + $srcporta = alias_expand($srcport[0]); + else + $srcporta = $srcport[0]; + if ((!$srcport[1]) || ($srcport[0] == $srcport[1])) { + if(alias_expand($srcport[0])) + $aline['srcport'] = "port {$srcporta} "; + else + $aline['srcport'] = "port = {$srcporta} "; + } else if (($srcport[0] == 1) && ($srcport[1] == 65535)) { + /* no need for a port statement here */ + } else if ($srcport[1] == 65535) { + $aline['srcport'] = "port >= {$srcport[0]} "; + } else if ($srcport[0] == 1) { + $aline['srcport']= "port <= {$srcport[1]} "; + } else { + $srcport[0]--; + $srcport[1]++; + $aline['srcport'] = "port {$srcport[0]} >< {$srcport[1]} "; + } + } + /* OS signatures */ + if (($rule['protocol'] == "tcp") && ($rule['os'] <> "")) + $aline['os'] = "os {$rule['os']} "; + + } + + /* destination address */ + if (isset($rule['destination']['any'])) { + $dst = "any"; + } else if ($rule['destination']['network']) { + + if (strstr($rule['destination']['network'], "opt")) { + $dst = $optcfg[$rule['destination']['network']]['sa'] . "/" . + $optcfg[$rule['destination']['network']]['sn']; + /* check for opt$NUMip here */ + $matches = ""; + if (preg_match("/opt([0-9999])ip/", $rule['destination']['network'], $matches)) { + $optnum = $matches[1]; + $real_int = convert_friendly_interface_to_real_interface_name("opt{$optnum}"); + $dst = find_interface_ip($real_int); + } + if (isset($rule['destination']['not'])) $dst = " !{$dst}"; + } else { + switch ($rule['destination']['network']) { + case 'wanip': + $dst = $curwanip; + break; + case 'lanip': + $dst = $lanip; + break; + case 'lan': + $dst = "{$lansa}/{$lansn}"; + break; + case 'pptp': + $dst = "{$pptpsa}/{$pptpsn}"; + break; + case 'pppoe': + $dst = "{$ppoesa}/{$pppoesn}"; + break; + } + if (isset($rule['destination']['not'])) $dst = " !{$dst}"; + } + } else if ($rule['destination']['address']) { + $expdst = alias_expand($rule['destination']['address']); + + if (isset($rule['destination']['not'])) + $not = "!"; + else + $not = ""; + + if (stristr($expdst, "$")) { + if($not) { + $dst = "{"; + foreach(preg_split("/[\s]+/", alias_expand_value($rule['destination']['address'])) as $item) { + if($item != "") { + $dst .= " {$not}{$item}"; + } + } + /* added support for tables */ + $dst .= " 0/0 }"; + $dst_table = "<not" . $rule['destination']['address'] . ">"; + } + else { + $dst = "{ {$not} " . alias_expand_value($rule['destination']['address']) . " } "; + $dst_table = "<" . $rule['destination']['address'] . ">"; + } + + /* support for tables */ + $dst_table_line = "table $dst_table {$dst}\n"; + $dst = $dst_table; + } + else + $dst = "{ {$not} {$expdst} }"; + } + + if (!$dst || ($dst == "/")) { + return "# returning at dst $dst == \"/\""; + } + + $aline['dst'] = "to $dst "; + + if (in_array($rule['protocol'], array("tcp","udp","tcp/udp"))) { + + if ($rule['destination']['port']) { + $dstport = explode("-", $rule['destination']['port']); + if(alias_expand($dstport[0])) + $dstporta = alias_expand($dstport[0]); + else + $dstporta = $dstport[0]; + if ((!$dstport[1]) || ($dstport[0] == $dstport[1])) { + if(alias_expand($dstport[0])) + $aline['dstport'] = "port {$dstporta} "; + else + $aline['dstport'] = "port = {$dstporta} "; + } else if (($dstport[0] == 1) && ($dstport[1] == 65535)) { + /* no need for a port statement here */ + } else if ($dstport[1] == 65535) { + $aline['dstport'] = "port >= {$dstport[0]} "; + } else if ($dstport[0] == 1) { + $aline['dstport'] = "port <= {$dstport[1]} "; + } else { + $dstport[0]--; + $dstport[1]++; + $aline['dstport'] = "port {$dstport[0]} >< {$dstport[1]} "; + } + } + } + + if (($rule['protocol'] == "icmp") && $rule['icmptype']) { + $aline['icmp-type'] = "icmp-type {$rule['icmptype']} "; + } + + if ($type == "pass") { + if (isset($rule['allowopts'])) + $aline['allowopts'] = " allow-opts "; + if( isset($rule['source-track']) or isset($rule['max-src-nodes']) or isset($rule['max-src-states']) ) + if($rule['protocol'] == "tcp") + $aline['flags'] = "flags S/SA "; + /* + # keep state + works with TCP, UDP, and ICMP. + # modulate state + works only with TCP. pfSense will generate strong Initial Sequence Numbers (ISNs) + for packets matching this rule. + # synproxy state + proxies incoming TCP connections to help protect servers from spoofed TCP SYN floods. + This option includes the functionality of keep state and modulate state combined. + # none + do not use state mechanisms to keep track. this is only useful if your doing advanced + queueing in certain situations. please check the faq. + */ + $noadvoptions = false; + if(isset($rule['statetype']) && $rule['statetype'] <> "") { + switch($rule['statetype']) { + case "none": + $noadvoptions = true; + break; + case "modulate state": + case "synproxy state": + if($rule['protocol'] == "tcp") + $aline['flags'] = "{$rule['statetype']} "; + break; + default: + $aline['flags'] = "{$rule['statetype']} "; + } + } else { + $aline['flags'] = "keep state "; + } + if($noadvoptions == false) + if( isset($rule['source-track']) and $rule['source-track'] <> "" or + isset($rule['max-src-nodes']) and $rule['max-src-nodes'] <> "" or + isset($rule['max-src-conn-rate']) and $rule['max-src-conn-rate'] <> "" or + isset($rule['max-src-conn-rates']) and $rule['max-src-conn-rates'] <> "" or + isset($rule['max-src-states']) and $rule['max-src-states'] <> "" or + isset($rule['statetimeout']) and $rule['statetimeout'] <> "") { + $aline['flags'] .= "( "; + if(isset($rule['source-track']) and $rule['source-track'] <> "") + $aline['flags'] .= "source-track rule "; + if(isset($rule['max-src-nodes']) and $rule['max-src-nodes'] <> "") + $aline['flags'] .= "max-src-nodes " . $rule['max-src-nodes'] . " "; + if(isset($rule['max-src-states']) and $rule['max-src-states'] <> "") + $aline['flags'] .= "max-src-states " . $rule['max-src-states'] . " "; + if(isset($rule['statetimeout']) and $rule['statetimeout'] <> "") + $aline['flags'] .= "tcp.established " . $rule['statetimeout'] . " "; + if(isset($rule['max-src-conn-rate']) and $rule['max-src-conn-rate'] <> "" + and isset($rule['max-src-conn-rates']) and $rule['max-src-conn-rates'] <> "") { + $aline['flags'] .= "max-src-conn-rate " . $rule['max-src-conn-rate'] . " "; + $aline['flags'] .= "/" . $rule['max-src-conn-rates'] . ", overload <virusprot> flush global "; + } + $aline['flags'] .= " ) "; + } + } + if ($type == "reject" && $rule['protocol'] == "tcp") { + /* special reject packet */ + $aline['flags'] .= "flags S/SA "; + } + } + + /* cache entries */ + if (isset($src_table)) + if (isset($table_cache[$src_table])) { + if ($g['debug']) + echo "{$src_table} found in cache\n"; + } else { + if ($g['debug']) + echo "{$src_table} NOT found in cache...adding\n"; + $table_cache[$src_table] = $src_table_line; + } + if (isset($dst_table)) + if (isset($table_cache[$dst_table])) { + if ($g['debug']) + echo "{$dst_table} found in cache\n"; + } else { + if ($g['debug']) + echo "{$dst_table} NOT found in cache...adding\n"; + $table_cache[$dst_table] = $dst_table_line; + } + + /* exception(s) to a user rules can go here. */ + /* rules with a gateway or pool should create another rule for routing to local networks or vpns */ + /* we only trigger this for a rule with the destination of any and without a gateway */ + if (($aline['route'] <> "") && ($aline['type'] == "pass") && ($dst == "any") && (! interface_has_gateway($aline['interface']))) { + /* negate VPN/PPTP/PPPoE networks for load balancer rules */ + $vpns = " to <vpns> "; + $line .= $aline['type'] . $aline['direction'] . $aline['log'] . $aline['quick'] . $aline['interface'] . $aline['prot'] . + $aline['src'] . $aline['srcport'] . $aline['os'] . $vpns . $aline['dstport']. + $aline['icmp-type'] . $aline['allowopts'] . $aline['flags'] . + " label \"NEGATE_ROUTE: Negate policy route for local network(s)\"\n"; + } + + /* piece together the actual user rule */ + $line .= $aline['type'] . $aline['direction'] . $aline['log'] . $aline['quick'] . $aline['interface'] . $aline['reply'] . + $aline['route'] . $aline['prot'] . $aline['src'] . $aline['srcport'] . $aline['os'] . $aline['dst'] . + $aline['dstport'] . $aline['icmp-type'] . $aline['allowopts'] . $aline['flags']; + + /* is a time based rule schedule attached? */ + if($rule['sched']) { + if($config['schedules']) { + foreach($config['schedules']['schedule'] as $sched) { + if($sched['name'] == $rule['sched']) + $schedule_xml_block = $sched; + $schedule_enabled = true; + } + } + if($schedule_xml_block) + $status = get_time_based_rule_status($schedule_xml_block); + if($status) { + if($g['debug']) + log_error("[TDR DEBUG] status true -- rule type '$type'"); + if($type == "block") { + // active deny rules should deny + $ipfw_rule = tdr_create_ipfw_rule($rule, "deny"); + tdr_install_rule($ipfw_rule); + } else { + // active allow rules should allow + $ipfw_rule = tdr_create_ipfw_rule($rule, "allow"); + tdr_install_rule($ipfw_rule); + } + return "$line"; + } else { + /* rule is turned off, if type == pass, deny traffic until + * active else allow traffic until active + */ + if($type == "pass") { + // inactive pass rules should deny + $ipfw_rule = tdr_create_ipfw_rule($rule, "deny"); + tdr_install_rule($ipfw_rule); + } else { + // inactive block rules should skipto + $ipfw_rule = tdr_create_ipfw_rule($rule, "skipto"); + tdr_install_rule($ipfw_rule); + } + return "# $line"; + } + } else { + if($schedule_enabled) { + // no schedule allow rules should simply allow + $ipfw_rule = tdr_create_ipfw_rule($rule, "allow"); + tdr_install_rule($ipfw_rule); + } + return $line; + } +} + +function filter_rules_generate() { + global $config, $g, $table_cache; + + update_filter_reload_status("Creating default rules"); + + if(isset($config['system']['developerspew'])) { + $mt = microtime(); + echo "filter_rules_generate() being called $mt\n"; + } + + $wancfg = $config['interfaces']['wan']; + $lancfg = $config['interfaces']['lan']; + $pptpdcfg = $config['pptpd']; + $pppoecfg = $config['pppoe']; + + $lanif = $lancfg['if']; + $wanif = get_real_wan_interface(); + + $lanip = $lancfg['ipaddr']; + $lansa = gen_subnet($lancfg['ipaddr'], $lancfg['subnet']); + $lansn = $lancfg['subnet']; + + $wanip = find_interface_ip(get_real_wan_interface()); + + if($lansa) + $lansa_sn_combo = "{$lansa}/{$lansn}"; + else + $lansa_sn_combo = "192.168.1.1/32"; + + /* optional interfaces */ + $optcfg = array(); + generate_optcfg_array($optcfg); + + if (is_package_installed('squid') && file_exists('/usr/local/pkg/squid.inc')) { + require_once('squid.inc'); + $ipfrules .= squid_generate_rules('filter'); + } + + if (is_package_installed('clamav') && file_exists('/usr/local/pkg/clamav.inc')) { + require_once('clamav.inc'); + $ipfrules .= clamav_generate_rules('filter'); + } + + if (is_package_installed('clamav') && file_exists('/usr/local/pkg/clamav.inc')) { + require_once('clamav.inc'); + $ipfrules .= clamav_generate_rules('filter'); + } + + if (is_package_installed('frickin') && file_exists('/usr/local/pkg/frickin.inc')) { + require_once ('frickin.inc'); + $ipfrules .= frickin_generate_rules('filter'); + } + + if (is_package_installed('siproxd') && file_exists('/usr/local/pkg/sipproxd.inc')) { + require_once('sipproxd.inc'); + $ipfrules .= siproxd_generate_rules('filter'); + } + + /* if captive portal is enabled, ensure that access to this port + * is allowed on a locked down interface + */ + if (isset($config['captiveportal']['enable'])) { + $cp_interface = $config['captiveportal']['interface']; + $cp_interface_real = convert_friendly_interface_to_real_interface_name($cp_interface); + $cp_interface_ip = find_interface_ip($cp_interface_real); + if($cp_interface_ip and $cp_interface_real) + $ipfrules .= "pass in quick on {$cp_interface_real} proto tcp from any to {$cp_interface_ip} port { 8000 8001 } keep state\n"; + } + + /* ftp-sesame */ + $ipfrules .= "anchor \"ftpsesame/*\" \n"; + + # BEGIN OF firewall rules + $ipfrules .= "anchor \"firewallrules\"\n"; + + if ($pptpdcfg['mode'] == "server") { + $pptpip = $pptpdcfg['localip']; + $pptpsa = $pptpdcfg['remoteip']; + $pptpsn = $g['pptp_subnet']; + if($config['pptp']['pptp_subnet'] <> "") + $pptpsn = $config['pptp']['pptp_subnet']; + } + + if ($pppoecfg['mode'] == "server") { + $pppoeip = $pppoecfg['localip']; + $pppoesa = $pppoecfg['remoteip']; + $pppoesn = $g['pppoe_subnet']; + if($config['pppoe']['pppoe_subnet'] <> "") + $pppoesn = $config['pppoe']['pppoe_subnet']; + } + + /* default block logging? */ + if (!isset($config['syslog']['nologdefaultblock'])) + $log = "log"; + else + $log = ""; + + $ipfrules .= <<<EOD + +# We use the mighty pf, we cannot be fooled. +block quick proto { tcp, udp } from any port = 0 to any +block quick proto { tcp, udp } from any to any port = 0 + +# snort2c +table <snort2c> persist +block quick from <snort2c> to any label "Block snort2c hosts" +block quick from any to <snort2c> label "Block snort2c hosts" + +# loopback +anchor "loopback" +pass in quick on \$loopback all label "pass loopback" +pass out quick on \$loopback all label "pass loopback" + +# package manager early specific hook +anchor "packageearly" + + +# carp +anchor "carp" + +EOD; + +if($wanip) + $ipfrules .= <<<EOD + +# permit wan interface to ping out (ping_hosts.sh) +pass quick proto icmp from {$wanip} to any keep state + +EOD; + + $ipfrules .= <<<EOD + +# NAT Reflection rules + +EOD; + + if (isset($config['nat']['rule'])) { + $natrules .= "# NAT Inbound Redirects\n"; + + if(!isset($config['system']['disablenatreflection'])) { + //$fd = fopen("/var/etc/inetd.conf","w"); + /* start redirects on port 19000 of localhost */ + $starting_localhost_port = 18999; + } + + foreach ($config['nat']['rule'] as $rule) { + + update_filter_reload_status("Creating NAT rule {$rule['descr']}"); + + /* if item is an alias, expand */ + if(alias_expand($rule['external-port'])) + $extport[0] = alias_expand_value($rule['external-port']); + else + $extport = explode("-", $rule['external-port']); + + /* if item is an alias, expand */ + if(alias_expand($rule['local-port'])) + $localport = ""; + else + $localport = " port {$rule['local-port']}"; + + $target = alias_expand_host($rule['target']); + + if (!$target) + continue; /* unresolvable alias */ + + if ($rule['external-address']) + if($rule['external-address'] <> "any") + $extaddr = $rule['external-address'] . "/32"; + else + $extaddr = $rule['external-address']; + else + $extaddr = get_current_wan_address($rule['interface']); + + if (!$rule['interface'] || ($rule['interface'] == "wan")) + $natif = $wanif; + else if($rule['interface'] == "\$pptp") + $natif = "pptp"; + else if($rule['interface'] == "\$pppoe") + $natif = "pppoe"; + else + $natif = $config['interfaces'][$rule['interface']]['if']; + + $lanif = $lancfg['if']; + + /* + * Expand aliases + * XXX: may want to integrate this into pf macros + */ + if(alias_expand($target)) + $target = alias_expand($target); + if(alias_expand($extaddr)) + $extaddr = alias_expand($extaddr); + + if(!isset($config['system']['disablenatreflection'])) { + + /* if list */ + $iflist = array("lan" => "LAN"); + for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++) + $iflist['opt' . $i] = "opt{$i}"; + + foreach ($iflist as $ifent => $ifname) { + + /* do not process interfaces with gateways*/ + if($config['interfaces'][$ifname]['gateway'] <> "") + continue; + + /* do not process interfaces that will end up with gateways */ + if($config['interfaces'][$ifname]['ipaddr'] == "dhcp" or + $config['interfaces'][$ifname]['ipaddr'] == "bigpond" or + $config['interfaces'][$ifname]['ipaddr'] == "pppoe" or + $config['interfaces'][$ifname]['ipaddr'] == "pptp") + + continue; + + $ifname_real = convert_friendly_interface_to_real_interface_name($ifname); + + if($extport[1]) + $range_end = ($extport[1]); + else + $range_end = ($extport[0]); + + $range_end++; + + if($rule['local-port']) + $lrange_start = $rule['local-port']; + + if($range_end - $extport[0] > 500) { + $range_end = $extport[0]+1; + log_error("Not installing nat reflection rules for a port range > 500"); + } else { + /* only install reflection rules for < 19991 items */ + if($starting_localhost_port < 19991) { + $loc_pt = $lrange_start; + for($x=$extport[0]; $x<$range_end; $x++) { + + $starting_localhost_port++; + $ifname_real = convert_friendly_interface_to_friendly_descr(strtolower($ifname)); + + switch($rule['protocol']) { + case "tcp/udp": + $protocol = "{ tcp udp }"; + $ipfrules .= "pass in quick on \${$ifname_real} inet proto tcp from any to \$loopback port {$starting_localhost_port} keep state label \"NAT REFLECT: Allow traffic to localhost\"\n"; + $starting_localhost_port++; + $ipfrules .= "pass in quick on \${$ifname_real} inet proto udp from any to \$loopback port {$starting_localhost_port} keep state label \"NAT REFLECT: Allow traffic to localhost\"\n"; + break; + case "tcp": + case "udp": + $protocol = $rule['protocol']; + $ipfrules .= "pass in quick on \${$ifname_real} inet proto {$rule['protocol']} from any to \$loopback port {$starting_localhost_port} keep state label \"NAT REFLECT: Allow traffic to localhost\"\n"; + break; + default: + break; + } + $loc_pt++; + if($starting_localhost_port > 19990) { + log_error("Not installing nat reflection rules. Maximum 1,000 reached."); + $x = $range_end+1; + } + } + } + } + } + + } + } + } + + $ipfrules .= <<<EOD + +# allow access to DHCP server on LAN +anchor "dhcpserverlan" +pass in quick on \$lan proto udp from any port = 68 to 255.255.255.255 port = 67 label "allow access to DHCP server on LAN" +pass in quick on \$lan proto udp from any port = 68 to $lanip port = 67 label "allow access to DHCP server on LAN" +pass out quick on \$lan proto udp from $lanip port = 67 to any port = 68 label "allow access to DHCP server on LAN" + +EOD; + + /* allow access to DHCP server on optional interfaces */ + foreach ($optcfg as $on => $oc) { + if ($config[interfaces][$on][ipaddr] == "dhcp" ) { + $friendly_on = filter_get_opt_interface_descr($on); + $ipfrules .= <<<EOD + +# Not installing DHCP server firewall rules for $friendly_on which is configured for DHCP. + +EOD; + } elseif (isset($config['dhcpd'][$on]['enable']) && (!$oc['bridge']) || + ($oc['bridge'] && isset($config['dhcpd'][$oc['bridge']]['enable']))) { + + $friendly_on = filter_get_opt_interface_descr($on); + + $ipfrules .= <<<EOD + +# allow access to DHCP server on {$on} +anchor "dhcpserver{$friendly_on}" +pass in quick on \${$friendly_on} proto udp from any port = 68 to 255.255.255.255 port = 67 label "allow access to DHCP server" +pass in quick on \${$friendly_on} proto udp from any port = 68 to {$oc['ip']} port = 67 label "allow access to DHCP server" +pass out quick on \${$friendly_on} proto udp from {$oc['ip']} port = 67 to any port = 68 label "allow access to DHCP server" + +EOD; + } + } + + /* pass traffic between statically routed subnets and the subnet on the + interface in question to avoid problems with complicated routing + topologies */ + $sa = ""; + if (isset($config['filter']['bypassstaticroutes']) && is_array($config['staticroutes']['route']) && count($config['staticroutes']['route'])) { + foreach ($config['staticroutes']['route'] as $route) { + unset($sa); + $friendly_int = convert_friendly_interface_to_friendly_descr($route['interface']); + if ($route['interface'] == "lan") { + $sa = $lansa; + $sn = $lansn; + $if = $lanif; + $friendly_int = "lan"; + } else if (strstr($route['interface'], "opt")) { + $oc = $optcfg[$route['interface']]; + if ($oc['ip']) { + $sa = $oc['sa']; + $sn = $oc['sn']; + $if = $oc['if']; + } + } + + if ($sa) { + $ipfrules .= <<<EOD +anchor "staticrouted" +pass in quick on \${$friendly_int} from {$sa}/{$sn} to {$route['network']} label "pass traffic between statically routed subnets" +pass in quick on \${$friendly_int} from {$route['network']} to {$sa}/{$sn} label "pass traffic between statically routed subnets" +pass out quick on \${$friendly_int} from {$sa}/{$sn} to {$route['network']} label "pass traffic between statically routed subnets" +pass out quick on \${$friendly_int} from {$route['network']} to {$sa}/{$sn} label "pass traffic between statically routed subnets" + +EOD; + } + } + } + + /* install wan spoof check rule if lan address exists */ + if($lansa) { + if(!isset($config['interfaces']['wan']['spoofmac'])) { + $ipfrules .= <<<EOD + +# WAN spoof check +anchor "wanspoof" +block in $log quick on \$wan from $lansa/$lansn to any label "WAN spoof check" + +EOD; + + } + } + + foreach ($optcfg as $oc) { + if (!$oc['bridge']) + if($oc['sa'] <> "") + if(isset($oc['enable'])) + $ipfrules .= "block in $log quick on \$wan from {$oc['sa']}/{$oc['sn']} to any label \"interface spoof check\"\n"; + } + + /* allow PPTP traffic if PPTP client is enabled on WAN */ + if ($wancfg['ipaddr'] == "pptp") { + $ipfrules .= <<<EOD + +# allow PPTP client +anchor "pptpclient" +pass in quick on \$wan proto gre from any to any modulate state label "allow PPTP client" +pass in quick on \$wan proto gre from any to any modulate state label "allow PPTP client" +pass in quick on \$wan proto tcp from any port = 1723 to any flags S/SA modulate state label "allow PPTP client" +pass in quick on \$wan proto tcp from any to any port = 1723 flags S/SA modulate state label "allow PPTP client" + +EOD; + } + + if ($wancfg['ipaddr'] == "dhcp") { + + $ipfrules .= <<<EOD + +# allow our DHCP client out to the WAN +anchor "wandhcp" +pass out quick on \$wan proto udp from any port = 68 to any port = 67 label "allow dhcp client out wan" + +EOD; + } + +if($config['interfaces']['lan']['bridge'] <> "wan" and $config['interfaces']['wan']['bridge'] <> "lan") + $ipfrules .= "block in $log quick on \$wan proto udp from any port = 67 to {$lansa_sn_combo} port = 68 label \"block dhcp client out wan\"\n"; + + $ipfrules .= <<<EOD + +pass in quick on \$wan proto udp from any port = 67 to any port = 68 label "allow dhcp client out wan" + +# LAN/OPT spoof check (needs to be after DHCP because of broadcast addresses) + +EOD; + + /* LAN spoof check */ + $lanbridge = false; + foreach($config['interfaces'] as $int) + if($int['bridge'] == "lan") + $lanbridge = true; + if(!$lanbridge) + $ipfrules .= filter_rules_spoofcheck_generate('lan', $lanif, $lansa, $lansn, $log); + $wanbridge = false; + foreach($config['interfaces'] as $int) + if($int['bridge'] == "wan") + $lanbridge = true; + if($config['interfaces']['lan']['bridge'] == "wan") + $wanbridge = true; + + /* OPT spoof check */ + foreach ($optcfg as $on => $oc) { + $isbridged = false; + foreach ($optcfg as $on2 => $oc2) { + if ($oc2['bridge'] && $oc2['bridge'] == $on) { + $isbridged = true; + break; + } + } + if ($oc['ip'] && !(($oc['bridge'] || $isbridged) && isset($config['bridge']['filteringbridge']))) + $ipfrules .= filter_rules_spoofcheck_generate($on, $oc['if'], $oc['sa'], $oc['sn'], $log); + } + + $ipfrules .= "\nanchor \"spoofing\"\n"; + + /* block private networks on WAN? */ + if (isset($config['interfaces']['wan']['blockpriv'])) { + if($wanbridge == false) { + $ipfrules .= <<<EOD + +# block anything from private networks on WAN interface +anchor "spoofing" +antispoof for \$wan +block in $log quick on \$wan from 10.0.0.0/8 to any label "block private networks from wan block 10/8" +block in $log quick on \$wan from 127.0.0.0/8 to any label "block private networks from wan block 127/8" +block in $log quick on \$wan from 172.16.0.0/12 to any label "block private networks from wan block 172.16/12" +block in $log quick on \$wan from 192.168.0.0/16 to any label "block private networks from wan block 192.168/16" + +EOD; + + } + } + + /* + * Support for allow limiting of TCP connections by establishment rate + * Useful for protecting against sudden outburts, etc. + */ + $ipfrules .= <<<EODF +# Support for allow limiting of TCP connections by establishment rate +anchor "limitingesr" +table <virusprot> +block in quick from <virusprot> to any label "virusprot overload table" + +EODF; + + /* block bogon networks on WAN */ + /* http://www.cymru.com/Documents/bogon-bn-nonagg.txt */ + /* file is automatically in cron every 3000 minutes */ + if (isset($config['interfaces']['wan']['blockbogons'])) { + $ipfrules .= <<<EOD + +# block bogon networks +# http://www.cymru.com/Documents/bogon-bn-nonagg.txt +anchor "wanbogons" +table <bogons> persist file "/etc/bogons" +block in $log quick on \$wan from <bogons> to any label "block bogon networks from wan" + +EOD; + } + +if (!isset($config['shaper']['enable']) && !is_array($config['shaper']['queue']) and $config['system']['shapertype'] <> "m0n0") { + + $ipfrules .= <<<EOD + +# let out anything from the firewall host itself and decrypted IPsec traffic +pass out quick on \$lan proto icmp keep state label "let out anything from firewall host itself" +pass out quick on \$wan proto icmp keep state label "let out anything from firewall host itself" +pass out quick on $wanif all keep state label "let out anything from firewall host itself" + +EOD; + +} + + $ipfrules .= create_firewall_outgoing_rules_to_itself(); + + /* group heads for optional interfaces */ + foreach ($optcfg as $on => $oc) { + $ipfrules .= <<<EOD + + +# let out anything from the firewall host itself and decrypted IPsec traffic +pass out quick on {$oc['if']} proto icmp keep state label "let out anything from firewall host itself" +pass out quick on {$oc['if']} all keep state label "let out anything from firewall host itself" + +EOD; + + } + + if($config['interfaces']['wan']['ipaddr'] == "pppoe") + $ipfrules .= <<<EOD +# permit wan interface to ping out (ping_hosts.sh) +pass out quick on ng0 proto icmp keep state label "let out anything from firewall host itself" + +EOD; + + if (!isset($config['system']['webgui']['noantilockout'])) { + + if($lansa and $lansn) { + + $ipfrules .= <<<EOD + +# make sure the user cannot lock himself out of the webGUI or SSH +anchor "anti-lockout" +pass in quick on $lanif from any to $lanip keep state label "anti-lockout web rule" + +EOD; + } + } + + /* PPTPd enabled? */ + if ($pptpdcfg['mode'] && ($pptpdcfg['mode'] != "off")) { + + if ($pptpdcfg['mode'] == "server") + $pptpdtarget = get_current_wan_address(); + else + $pptpdtarget = $pptpdcfg['redir']; + + if($pptpdtarget) { + $ipfrules .= <<<EOD + +# PPTPd rules +anchor "pptp" +pass in quick on \$wan proto gre from any to $pptpdtarget keep state label "allow gre pptpd" +pass in quick on \$wan proto tcp from any to $pptpdtarget port = 1723 modulate state label "allow pptpd {$pptpdtarget}" + +EOD; + + } else { + /* this shouldnt ever happen but instead of breaking the clients ruleset + * log an error. + */ + log_error("ERROR! PPTP enabled but could not resolve the \$pptpdtarget"); + } + } + + /* BigPond client enabled? */ + if ($wancfg['ipaddr'] == "bigpond") { + + $ipfrules .= <<<EOD + +# BigPond heartbeat rules +anchor "bigpond" +pass in quick proto udp from any to any port = 5050 keep state label "BigPond heartbeat" + +# package manager late specific hook +anchor "packagelate" + + + +EOD; + } + + $ipfrules .= "\n# SSH lockout\n"; + $ipfrules .= "block in log proto tcp from <sshlockout> to any port 22 label \"sshlockout\"\n\n"; + + $ipfrules .= "anchor \"ftpproxy\"\n"; + $ipfrules .= "anchor \"pftpx/*\"\n"; + + $ipfrules .= process_carp_rules(); + + if (isset($config['filter']['rule'])) { + /* Pre-cache all our rules so we only have to generate them once */ + $rule_arr = array(); + foreach ($config['filter']['rule'] as $rule) { + update_filter_reload_status("Pre-caching {$rule['descr']}..."); + $line = ""; + if (!isset($rule['disabled'])) { + if ($rule['interface'] == "pptp") { + /* we have a pptp rule but its turned off, ignore */ + if(!$config['pptpd']['mode'] == "server") + continue; + $n_pptp_units = $g['n_pptp_units']; + if($config['pptp']['n_pptp_units'] <> "") + $nif = $config['pptp']['n_pptp_units']; + /* + * now that PPTP server are user rules, detect + * that user is setting the pptp server rule + * and setup for all netgraph interfaces + */ + $rule_arr[] = generate_user_filter_rule_arr($rule, 0); + } else if($rule['interface'] == "pppoe") { + if(!$config['pppoe']['mode'] == "server") + continue; + $n_pppoe_units = $g['n_pppoe_units']; + if($config['pppoe']['n_pppoe_units'] <> "") + $nif = $config['pppoe']['n_pppoe_units']; + /* + * now that pppoe server are user rules, detect + * that user is setting the pppoe server rule + * and setup for all netgraph interfaces + */ + $rule_arr[] = generate_user_filter_rule_arr($rule, 0); + } else { + $rule_arr[] = generate_user_filter_rule_arr($rule, 0); + } + } + } + + $ipfrules .= "\n# User-defined aliases follow\n"; + /* tables for aliases */ + foreach($table_cache as $table) { + $ipfrules .= $table; + } + + /* Shaper rules */ + if (isset($config['shaper']['enable']) && is_array($config['shaper']['queue']) && isset($config['filter']['rule']) and $config['system']['shapertype'] <> "m0n0") { + + $ipfrules .= "\n# Anchors for rules that might be matched by queues\n"; + + /* This is ugly, but we generate one anchor per queue */ + foreach ($config['shaper']['queue'] as $queue) { + update_filter_reload_status("Creating filter anchor for {$queue['name']} ..."); + /* Add anchor to rules */ + $ipfrules .= "anchor {$queue['name']} tagged {$queue['name']}\n"; + $ipfrules .= "load anchor {$queue['name']} from \"{$g['tmp_path']}/{$queue['name']}.rules\"\n"; + /* Create rules for anchors */ + $fd = fopen("{$g['tmp_path']}/{$queue['name']}.rules", "w"); + /* aliases don't recurse to anchors */ + $line = filter_generate_aliases(); + fwrite($fd, $line); + foreach($rule_arr as $rule) { + if($rule['ackq'] != "") + $line = "{$rule['rule']} queue ({$queue['name']}, {$rule['ackq']}) {$rule['descr']}\n"; + else + $line = "{$rule['rule']} queue {$queue['name']} {$rule['descr']}\n"; + fwrite($fd, $line); + } + fclose($fd); + } + } + + $ipfrules .= "\n# User-defined rules follow\n"; + /* Generate user rule lines */ + foreach($rule_arr as $rule) { + $line = ""; + if (!isset($rule['disabled'])) { + $line = $rule['rule']; + if($line <> "") { + /* Add default queue if we're using the shaper */ + if (isset($config['shaper']['enable']) && is_array($config['shaper']['queue']) and $config['system']['shapertype'] <> "m0n0") { + $defq = find_default_queue($rule['interface']); + $ackq = $rule['ackq']; + if (($defq != "") and ($ackq != "")) + $line .= " queue ({$defq}, {$ackq}) "; + } + /* label */ + $line .= " {$rule['descr']}"; + } + } + $line .= "\n"; + $ipfrules .= $line; + } + } + + update_filter_reload_status("Creating carp rules..."); + + $ipfrules .= "\n# VPN Rules\n"; + $lan_ip = $config['interfaces']['lan']['ipaddr']; + $lan_subnet = $config['interfaces']['lan']['subnet']; + $wanif = get_real_wan_interface(); + $wan_ip = find_interface_ip($wanif); + if($wan_ip) { + $internal_subnet = gen_subnet($lan_ip, $lan_subnet) . "/" . $config['interfaces']['lan']['subnet']; + /* Is IP Compression enabled? */ + if(isset($config['ipsec']['ipcomp'])) + exec("/sbin/sysctl net.inet.ipcomp.ipcomp_enable=1"); + else + exec("/sbin/sysctl net.inet.ipcomp.ipcomp_enable=0"); + + /* build an interface collection */ + $ifdescrs = array ("wan"); + for ($j = 1; isset ($config['interfaces']['opt' . $j]); $j++) { + if(isset($config['interfaces']['opt' . $j]['enable'])) + $ifdescrs['opt' . $j] = filter_get_opt_interface_descr("opt" . $j); + } + + if(is_array($config['ipsec']['tunnel']) && isset($config['ipsec']['enable'])) { + foreach ($config['ipsec']['tunnel'] as $tunnel) { + if(isset($tunnel['disabled'])) + continue; + update_filter_reload_status("Creating IPSEC tunnel items {$tunnel['descr']}..."); + /* if tunnel is disabled, lets skip to next item */ + $ipsec_ips = array(get_current_wan_address($tunnel['interface'])); + /* is this a dynamic dns hostname? */ + $remote_gateway = gethostbyname($tunnel['remote-gateway']); + if($remote_gateway == "") + $remote_gateway = $tunnel['remote-gateway']; + /* do not add items with blank remote_gateway */ + if(!$remote_gateway) { + $ipfrules .= "# ERROR! Remote gateway not found on {$tunnel['remote-gateway']}\n"; + continue; + } + $local_subnet = return_vpn_subnet($tunnel['local-subnet']); + foreach($ifdescrs as $iface) { + foreach($ipsec_ips as $interface_ip) { + if($iface == "wan") + $interface_ip = find_interface_ip(get_real_wan_interface()); + else + $interface_ip = find_interface_ip(convert_friendly_interface_to_real_interface_name($iface)); + if(!$interface_ip) + continue; + if(!$remote_gateway) + continue; + $ipfrules .= "pass out quick on \${$iface} proto udp from any to {$remote_gateway} port = 500 keep state label \"IPSEC: {$tunnel['descr']} - outbound isakmp\"\n"; + $ipfrules .= "pass in quick on \${$iface} proto udp from {$remote_gateway} to any port = 500 keep state label \"IPSEC: {$tunnel['descr']} - inbound isakmp\"\n"; + if ($tunnel['p2']['protocol'] == 'esp') { + $ipfrules .= "pass out quick on \${$iface} proto esp from any to {$remote_gateway} keep state label \"IPSEC: {$tunnel['descr']} - outbound esp proto\"\n"; + $ipfrules .= "pass in quick on \${$iface} proto esp from {$remote_gateway} to any keep state label \"IPSEC: {$tunnel['descr']} - inbound esp proto\"\n"; + } + if ($tunnel['p2']['protocol'] == 'ah') { + $ipfrules .= "pass out quick on \${$iface} proto ah from any to {$remote_gateway} keep state label \"IPSEC: {$tunnel['descr']} - outbound ah proto\"\n"; + $ipfrules .= "pass in quick on \${$iface} proto ah from {$remote_gateway} to any keep state label \"IPSEC: {$tunnel['descr']} - inbound ah proto\"\n"; + } + } + } + } + } + + /* is mobile ipsec enabled? if so lets allow some pretty + * loose rules to allow mobile clients to phone in. + */ + $ipseccfg = $config['ipsec']; + if (isset($ipseccfg['mobileclients']['enable'])) { + foreach($ifdescrs as $iface) { + $ipfrules .= "pass in quick on \${$iface} proto udp from any to any port = 500 keep state label \"IPSEC: Mobile - inbound isakmp\"\n"; + $ipfrules .= "pass in quick on \${$iface} proto esp from any to any keep state label \"IPSEC: Mobile - inbound esp proto\"\n"; + $ipfrules .= "pass in quick on \${$iface} proto ah from any to any keep state label \"IPSEC: Mobile - inbound ah proto\"\n"; + } + } + } + $ipfrules .= <<<EOD + +pass in quick on $lanif inet proto tcp from any to \$loopback port 8021 keep state label "FTP PROXY: Allow traffic to localhost" +pass in quick on $lanif inet proto tcp from any to \$loopback port 21 keep state label "FTP PROXY: Allow traffic to localhost" +pass in quick on $wanif inet proto tcp from port 20 to ($wanif) port > 49000 flags S/SA keep state label "FTP PROXY: PASV mode data connection" + +EOD; + + if(!isset($config['system']['disableftpproxy'])) { + + $ipfrules .= "# enable ftp-proxy\n"; + + $optcfg = array(); + generate_optcfg_array($optcfg); + $ftp_counter = "8022"; + foreach($optcfg as $oc) { + if(!isset($oc['gateway']) && $oc['if'] <> "") { + $ipfrules .= "pass in quick on " . $oc['if'] . " inet proto tcp from any to \$loopback port {$ftp_counter} keep state label \"FTP PROXY: Allow traffic to localhost\"\n"; + $ipfrules .= "pass in quick on " . $oc['if'] . " inet proto tcp from any to \$loopback port 21 keep state label \"FTP PROXY: Allow traffic to localhost\"\n"; + } + $ftp_counter++; + } + + if(isset($config['system']['rfc959workaround'])) { + $ipfrules .= <<<EODEOD + +# Fix sites that violate RFC 959 which specifies that the data connection +# be sourced from the command port - 1 (typically port 20) +# This workaround doesn't expose us to any extra risk as we'll still only allow +# connections to the firewall on a port that ftp-proxy is listening on +pass in quick on $wanif inet proto tcp from any to ($wanif) port > 49000 flags S/SA keep state label "FTP PROXY: RFC959 violation workaround" + +EODEOD; + + $optcfg = array(); + generate_optcfg_array($optcfg); + foreach($optcfg as $oc) { + if($oc['gateway'] <> "") + $ipfrules .= "pass in quick on {$oc['if']} inet proto tcp from any to ({$oc['if']}) port > 49000 flags S/SA keep state label \"FTP PROXY: RFC959 violation workaround\" \n"; + } + } + } + + $ipfrules .= <<<EOD + +# IMSpector +anchor "imspector" + +# uPnPd +anchor "miniupnpd" + +#--------------------------------------------------------------------------- +# default rules (just to be sure) +#--------------------------------------------------------------------------- +block in $log quick all label "Default block all just to be sure." +block out $log quick all label "Default block all just to be sure." + +EOD; + + return $ipfrules; +} + +function filter_rules_spoofcheck_generate($ifname, $if, $sa, $sn, $log) { + + global $g, $config; + + if(isset($config['system']['developerspew'])) { + $mt = microtime(); + echo "filter_rules_spoofcheck_generate() being called $mt\n"; + } + + $ipfrules = "antispoof for {$if}\n"; + + return $ipfrules; + +} + +function setup_logging_interfaces() { + global $config; + if(isset($config['system']['developerspew'])) { + $mt = microtime(); + echo "setup_logging_interfaces() being called $mt\n"; + } + $rules = ""; + $i = 0; + $ifdescrs = array('wan', 'lan'); + for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++) { + $ifdescrs['opt' . $j] = "opt" . $j; + } + foreach ($ifdescrs as $ifdescr => $ifname) { + /* do not work with tun interfaces */ + if(stristr(filter_translate_type_to_real_interface($ifname), "tun") == true) continue; + $int = filter_translate_type_to_real_interface($ifname); + $rules .= "set loginterface {$int}\n"; + } + return $rules; +} + +function create_firewall_outgoing_rules_to_itself() { + global $config, $g; + + if(isset($config['system']['developerspew'])) { + $mt = microtime(); + echo "create_firewall_outgoing_rules_to_itself() being called $mt\n"; + } + + $i = 0; + $rule .= "# pass traffic from firewall -> out\n"; + $rule .= "anchor \"firewallout\"\n"; + $ifdescrs = array('wan', 'lan'); + for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++) + $ifdescrs['opt' . $j] = "opt" . $j; + + /* go through primary and optional interfaces */ + foreach ($ifdescrs as $ifdescr => $ifname) { + $return_gateway = $config['interfaces'][$ifname]['gateway']; + $ints = array(); + $int = filter_translate_type_to_real_interface($ifname); + /* if the interface is pppoe, set the ng0 interface */ + update_filter_reload_status("Creating IPSEC tunnel items {$tunnel['descr']}..."); + $ip = find_interface_ip($int); + if ($config['interfaces'][$ifname]['ipaddr'] == "pppoe") + $int = " { " . filter_translate_type_to_real_interface($ifname) . " ng0 } "; + if (isset($config['shaper']['enable']) && is_array($config['shaper']['queue']) and $config['system']['shapertype'] <> "m0n0") { + $ackq = get_ack_queue($ifname); + $defq = find_default_queue($ifname); + /* Handle all tagged packets */ + foreach ($config['shaper']['queue'] as $queue) { + if(!filter_is_queue_being_used_on_interface($queue['name'], $ifname, 'out')) + continue; + if ($ackq == "" || $defq == "") { + /* Shaper must not be enabled on this interface */ + $q = ""; + } else { + $q = "queue ({$queue['name']}, {$ackq})"; + } + $rule .="pass out quick on {$int} all keep state tagged {$queue['name']} {$q} label \"let out anything from firewall host itself\"\n"; + } + /* Handle untagged packets */ + if ($ackq == "" || $defq == "") { + /* Shaper must not be enabled on this interface */ + $q = ""; + } else { + $q = "queue ({$defq}, {$ackq})"; + } + $rule .="pass out quick on {$int} all keep state {$q} label \"let out anything from firewall host itself\"\n"; + } else { + /* first add a rule for the real interface, then for ng0 */ + $rule .="pass out quick on {$int} all keep state label \"let out anything from firewall host itself\"\n"; + } + } + + update_filter_reload_status("Setting up bridging items"); + /* is bridging turned on? */ + for($x=0; $x<10; $x++) { + if(does_interface_exist("bridge{$x}") == true) + $rule .="pass out quick on bridge{$x} all keep state label \"let out anything from firewall host itself\"\n"; + } + + update_filter_reload_status("Setting up pptp items"); + if($config['pptpd']['mode'] == "server") + $rule .="pass out quick on \$pptp all keep state label \"let out anything from firewall host itself pptp\"\n"; + + update_filter_reload_status("Setting up pppoe items"); + if($config['pppoe']['mode'] == "server") + $rule .="pass out quick on \$pppoe all keep state label \"let out anything from firewall host itself pppoe\"\n"; + + update_filter_reload_status("Setting up gif tunnels"); + /* setup outgoing gif tunnels */ + $number_of_gifs = find_last_gif_device(); + $number_of_gifs++; + for($x=0; $x<$number_of_gifs; $x++) { + if(does_interface_exist("gif{$x}") == true) + $rule .="pass out quick on gif{$x} all keep state label \"let out anything from firewall host itself ipsec gif\"\n"; + } + + update_filter_reload_status("Setting up tun interfaces (openvpn)"); + /* openvpn tun interfaces. check for 100. */ + for($x=0; $x<100; $x++) { + if(does_interface_exist("tun{$x}") == true) { + $rule .="pass out quick on tun{$x} all keep state label \"let out anything from firewall host itself openvpn\"\n"; + $friendlytunif = convert_real_interface_to_friendly_interface_name("tun{$x}"); + /* If the interface has a gateway we do not add a pass in rule. */ + /* Some people use a TUN tunnel with public IP as a Multiwan interface */ + if(interface_has_gateway("tun{$x}")) { + $rule .= "# Not adding default pass in rule for interface $friendlytunif - tun{$x} with a gateway!"; + } else { + $rule .="pass in quick on tun{$x} all keep state label \"let out anything from firewall host itself openvpn\"\n"; + } + } + } + for($x=0; $x<100; $x++) { + if(does_interface_exist("tap{$x}") == true) { + $rule .="pass out quick on tap{$x} all keep state label \"let out anything from firewall host itself openvpn\"\n"; + $friendlytapif = convert_real_interface_to_friendly_interface_name("tap{$x}"); + /* If the interface has a gateway we do not add a pass in rule. */ + /* Some people use a TAP tunnel with public IP as a Multiwan interface */ + if(interface_has_gateway("tap{$x}")) { + $rule .= "# Not adding default pass in rule for interface $friendlytapif - tap{$x} with a gateway!"; + } else { + $rule .="pass in quick on tap{$x} all keep state label \"let out anything from firewall host itself openvpn\"\n"; + } + } + } + + /* permit internal ipsec outbound traffic */ + $rule .="pass out quick on \$enc0 keep state label \"IPSEC internal host to host\""; + + return $rule; +} + +function process_carp_nat_rules() { + global $g, $config; + + update_filter_reload_status("Creating CARP NAT rules"); + + $wan_interface = get_real_wan_interface(); + + if(isset($config['system']['developerspew'])) { + $mt = microtime(); + echo "process_carp_nat_rules() being called $mt\n"; + } + $lines = ""; + if($config['installedpackages']['carp']['config'] != "") + foreach($config['installedpackages']['carp']['config'] as $carp) { + $ip = $carp['ipaddress']; + if($ip <> "any") { + $ipnet = "any"; + } else { + $int = find_ip_interface($ip); + $carp_int = find_carp_interface($ip); + } + if($int != false and $int != $wan_interface) { + $ipnet = convert_ip_to_network_format($ip, $carp['netmask']); + if($int) + $lines .= "nat on {$int} inet from {$ipnet} to any -> ({$carp_int}) \n"; + } + } + return $lines; +} + +function process_carp_rules() { + global $g, $config; + if(isset($config['system']['developerspew'])) { + $mt = microtime(); + echo "process_carp_rules() being called $mt\n"; + } + $lines = ""; + /* return if there are no carp configured items */ + if($config['installedpackages']['carpsettings']['config'] <> "" or + $config['virtualip']['vip'] <> "") { + $lines .= "pass quick proto carp\n"; + $lines .= "pass quick proto pfsync"; + } + return $lines; +} + +function remove_special_characters($string) { + $match_array = ""; + preg_match_all("/[a-zA-Z0-9\_\-]+/",$string,$match_array); + $string = ""; + foreach($match_array[0] as $ma) { + if($string <> "") + $string .= " "; + $string .= $ma; + } + return $string; +} + +function carp_sync_xml($url, $password, $sections, $port = 80, $method = 'pfsense.restore_config_section') { + global $config, $g; + + if($g['booting']) + return; + + update_filter_reload_status("Syncing CARP data to {$url}"); + + /* make a copy of config */ + $config_copy = $config; + + /* strip out nosync items */ + for ($x = 0; $x < count($config_copy['nat']['advancedoutbound']['rule']); $x++) { + if (isset ($config_copy['nat']['advancedoutbound']['rule'][$x]['nosync'])) + unset ($config_copy['nat']['advancedoutbound']['rule'][$x]); + $config_copy['nat']['advancedoutbound']['rule'][$x]['descr'] = remove_special_characters($config_copy['nat']['advancedoutbound']['rule'][$x]['descr']); + } + for ($x = 0; $x < count($config_copy['nat']['rule']); $x++) { + if (isset ($config_copy['nat']['rule'][$x]['nosync'])) + unset ($config_copy['nat']['rule'][$x]); + $config_copy['nat']['rule'][$x]['descr'] = remove_special_characters($config_copy['nat']['rule'][$x]['descr']); + } + for ($x = 0; $x < count($config_copy['filter']['rule']); $x++) { + if (isset ($config_copy['filter']['rule'][$x]['nosync'])) + unset ($config_copy['filter']['rule'][$x]); + $config_copy['filter']['rule'][$x]['descr'] = remove_special_characters($config_copy['filter']['rule'][$x]['descr']); + } + for ($x = 0; $x < count($config_copy['aliases']['alias']); $x++) { + if (isset ($config_copy['aliases']['alias'][$x]['nosync'])) + unset ($config_copy['aliases']['alias'][$x]); + $config_copy['aliases']['alias'][$x]['descr'] = remove_special_characters($config_copy['aliases']['alias'][$x]['descr']); + } + for ($x = 0; $x < count($config_copy['dnsmasq']['hosts']); $x++) { + if (isset ($config_copy['dnsmasq']['hosts'][$x]['nosync'])) + unset ($config_copy['dnsmasq']['hosts'][$x]); + $config_copy['dnsmasq']['hosts'][$x]['descr'] = remove_special_characters($config_copy['dnsmasq']['hosts'][$x]['descr']); + } + for ($x = 0; $x < count($config_copy['virtualip']['vip']); $x++) { + if (isset ($config_copy['virtualip']['vip'][$x]['nosync']) or $config_copy['virtualip']['vip'][$x]['mode'] == "proxyarp") + unset ($config_copy['virtualip']['vip'][$x]); + $config_copy['virtualip']['vip'][$x]['descr'] = remove_special_characters($config_copy['virtualip']['vip'][$x]['descr']); + } + for ($x = 0; $x < count($config_copy['ipsec']['tunnel']); $x++) { + if (isset ($config_copy['ipsec']['tunnel'][$x]['nosync'])) + unset ($config_copy['ipsec']['tunnel'][$x]); + $config_copy['ipsec']['tunnel'][$x]['descr'] = remove_special_characters($config_copy['ipsec']['tunnel'][$x]['descr']); + } + + foreach($sections as $section) { + /* we can't use array_intersect_key() + due to the vip 'special case' */ + if($section != 'virtualip') { + $xml[$section] = $config_copy[$section]; + } else { + $xml[$section] = backup_vip_config_section(); + } + } + + $params = array( + XML_RPC_encode($password), + XML_RPC_encode($xml) + ); + + log_error("Beginning XMLRPC sync to {$url}:{$port}."); + $msg = new XML_RPC_Message($method, $params); + $cli = new XML_RPC_Client('/xmlrpc.php', $url, $port); + $cli->setCredentials('admin', $password); + if($g['debug']) $cli->setDebug(1); + /* send our XMLRPC message and timeout after 240 seconds */ + $resp = $cli->send($msg, "240"); + if(!$resp) { + $error = "A communications error occured while attempting XMLRPC sync with username admin {$url}:{$port}."; + log_error($error); + file_notice("sync_settings", $error, "Settings Sync", ""); + } elseif($resp->faultCode()) { + $error = "An error code was received while attempting XMLRPC sync with username admin {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString(); + log_error($error); + file_notice("sync_settings", $error, "Settings Sync", ""); + } else { + log_error("XMLRPC sync successfully completed with {$url}:{$port}."); + } +} + +function carp_sync_client() { + + global $config, $g; + + update_filter_reload_status("Building CARP sync information"); + + if($g['booting']) + return; + + if(is_array($config['installedpackages']['carpsettings']['config'])) { + foreach($config['installedpackages']['carpsettings']['config'] as $carp) { + if($carp['synchronizetoip'] != "" ) { + /* + * XXX: The way we're finding the port right now is really suboptimal - + * we can't assume that the other machine is setup identically. + */ + if($config['system']['webgui']['protocol'] != "") { + $synchronizetoip = $config['system']['webgui']['protocol']; + $synchronizetoip .= "://"; + } + $port = $config['system']['webgui']['port']; + /* if port is empty lets rely on the protocol selection */ + if($port == "") { + if($config['system']['webgui']['protocol'] == "http") { + $port = "80"; + } else { + $port = "443"; + } + } + $synchronizetoip .= $carp['synchronizetoip']; + if($carp['synchronizerules'] != "" and is_array($config['filter'])) { + $sections[] = 'filter'; + } + if($carp['synchronizenat'] != "" and is_array($config['nat'])) { + $sections[] = 'nat'; + } + if($carp['synchronizealiases'] != "" and is_array($config['aliases'])) { + $sections[] = 'aliases'; + } + if($carp['synchronizedhcpd'] != "" and is_array($config['dhcpd'])) { + $sections[] = 'dhcpd'; + } + if($carp['synchronizewol'] != "" and is_array($config['wol'])) { + $sections[] = 'wol'; + } + if($carp['synchronizetrafficshaper'] != "" and is_array($config['shaper'])) { + $sections[] = 'shaper'; + } + if($carp['synchronizestaticroutes'] != "" and is_array($config['staticroutes'])) { + $sections[] = 'staticroutes'; + } + if($carp['synchronizevirtualip'] != "" and is_array($config['virtualip'])) { + $sections[] = 'virtualip'; + } + if($carp['synchronizelb'] != "" and is_array($config['load_balancer'])) { + $sections[] = 'load_balancer'; + } + if($carp['synchronizeipsec'] != "" and is_array($config['ipsec'])) { + $sections[] = 'ipsec'; + } + if($carp['synchronizednsforwarder'] != "" and is_array($config['dnsmasq'])) { + $sections[] = 'dnsmasq'; + } + if($carp['synchronizeschedules'] != "" and is_array($config['schedules'])) { + $sections[] = 'schedules'; + } + if(count($sections) > 0) { + update_filter_reload_status("Signaling CARP reload signal..."); + carp_sync_xml($synchronizetoip, $carp['password'], $sections, $port); + $cli = new XML_RPC_Client('/xmlrpc.php', $synchronizetoip, $port); + $msg = new XML_RPC_Message('pfsense.filter_configure', array(new XML_RPC_Value($carp['password'], 'string'))); + $cli->setCredentials('admin', $carp['password']); + $cli->send($msg, "900"); + /* signal a carp reload */ + $msg = new XML_RPC_Message('pfsense.interfaces_carp_configure'); + $cli->send($msg, "900"); + } + } + } + } + +} + +function return_vpn_subnet($adr) { + global $config; + if(isset($config['system']['developerspew'])) { + $mt = microtime(); + echo "return_vpn_subnet() being called $mt\n"; + } + + if ($adr['address']) { + list($padr, $pmask) = explode("/", $adr['address']); + if (is_null($pmask)) + return "{$padr}/32"; + return "{$padr}/{$pmask}"; + } + + /* XXX: do not return wan, lan, etc */ + if(strstr($adr['network'], "wan") or strstr($adr['network'], "lan") or strstr($adr['network'], "opt")) + return convert_ip_to_network_format($config['interfaces'][$adr['network']]['ipaddr'], + $config['interfaces'][$adr['network']]['subnet']); + + /* fallback - error */ + return " # error - {$adr['network']} "; + +} + +?> |