{% let fw4 = require("fw4"); function read_state() { let state = fw4.read_state(); if (!state) { warn("Unable to read firewall state - do you need to start the firewall?\n"); exit(1); } return state; } function reload_sets() { let state = read_state(), sets = fw4.check_set_types(); for (let set in state.ipsets) { if (!set.loadfile && !length(set.entries)) continue; if (!exists(sets, set.name)) { warn(`Named set '${set.name}' does not exist - do you need to restart the firewall?\n`); continue; } else if (fw4.concat(sets[set.name]) != fw4.concat(set.types)) { warn(`Named set '${set.name}' has a different type - want '${fw4.concat(set.types)}' but is '${fw4.concat(sets[set.name])}' - do you need to restart the firewall?\n`); continue; } let first = true; let printer = (entry) => { if (first) { print(`add element inet fw4 ${set.name} {\n`); first = false; } print(` ${join(" . ", entry)},\n`); }; print(`flush set inet fw4 ${set.name}\n`); map(set.entries, printer); if (set.loadfile) fw4.parse_setfile(set, printer); if (!first) print("}\n\n"); } } function render_ruleset(use_statefile) { fw4.load(use_statefile); include("templates/ruleset.uc", { fw4, type, exists, length, include }); } function lookup_network(net) { let state = read_state(); for (let zone in state.zones) { for (let network in (zone.network || [])) { if (network.device == net) { print(zone.name, "\n"); exit(0); } } } exit(1); } function lookup_device(dev) { let state = read_state(); for (let zone in state.zones) { for (let rule in (zone.match_rules || [])) { if (dev in rule.devices_pos) { print(zone.name, "\n"); exit(0); } } } exit(1); } function lookup_zone(name, dev) { let state = read_state(); for (let zone in state.zones) { if (zone.name == name) { let devices = []; map(zone.match_rules, (r) => push(devices, ...(r.devices_pos || []))); if (dev) { if (dev in devices) { print(dev, "\n"); exit(0); } exit(1); } if (length(devices)) print(join("\n", devices), "\n"); exit(0); } } exit(1); } function run_includes() { let state = read_state(), paths = []; for (let inc in state.includes) { if (inc.type != 'script') continue; let path = replace(inc.path, "'", "'\\''"); let rc = system([ 'sh', '-c', `exec 1000>&-; config() { echo "You cannot use UCI in firewall includes!" >&2; exit 1; }; . '${path}'` ], 30000); if (rc != 0) warn(`Include '${inc.path}' failed with exit code ${rc}\n`); } } switch (getenv("ACTION")) { case "start": return render_ruleset(true); case "print": return render_ruleset(false); case "reload-sets": return reload_sets(); case "network": return lookup_network(getenv("OBJECT")); case "device": return lookup_device(getenv("OBJECT")); case "zone": return lookup_zone(getenv("OBJECT"), getenv("DEVICE")); case "includes": return run_includes(); }