171 lines
4.9 KiB
Plaintext
171 lines
4.9 KiB
Plaintext
include_guard "port_forwarding"
|
|
|
|
template port_forwarding {
|
|
alias("_arg0") forwardings_file;
|
|
alias("_arg1") template_forward;
|
|
|
|
# Map which holds the set of current port forwardings.
|
|
# Enties are: {protocol, port_start, port_end, dest_addr}:""
|
|
value([]) map;
|
|
|
|
# Blocker which is initially down and is toggled down-up
|
|
# whenever the forwarding change.
|
|
blocker() update_blocker;
|
|
|
|
# Process manager, each forwarding has a port_forwarding__instance process.
|
|
# The process identifiers are the same as the keys in the map.
|
|
process_manager() mgr;
|
|
|
|
# Spawn a process for dealing with storage of port forwardings on disk.
|
|
spawn("port_forwarding__stored", {});
|
|
}
|
|
|
|
template port_forwarding__instance {
|
|
alias("_caller") pf;
|
|
alias("_arg0") protocol;
|
|
alias("_arg1") port_start;
|
|
alias("_arg2") port_end;
|
|
alias("_arg3") dest_addr;
|
|
|
|
log("notice", "adding port forwarding ", protocol, ":", port_start, ":", port_end, " to ", dest_addr);
|
|
log_r("notice", "removed port forwarding ", protocol, ":", port_start, ":", port_end, " to ", dest_addr);
|
|
|
|
# Do the forwarding.
|
|
call_with_caller_target(pf.template_forward, {protocol, port_start, port_end, dest_addr}, "pf._caller");
|
|
}
|
|
|
|
template port_forwarding_add {
|
|
alias(_arg0) pf;
|
|
alias("_arg1") protocol;
|
|
alias("_arg2") port_start;
|
|
alias("_arg3") port_end;
|
|
alias("_arg4") dest_addr;
|
|
|
|
var("false") succeeded;
|
|
var("") error_text;
|
|
var("true") not_finished;
|
|
backtrack_point() finished_point;
|
|
|
|
If (not_finished) {
|
|
# Check for conflicts with existing forwardings.
|
|
Foreach (pf.map.keys As entry) {
|
|
value(entry) entry;
|
|
entry->get("0") e_protocol;
|
|
entry->get("1") e_port_start;
|
|
entry->get("2") e_port_end;
|
|
|
|
val_different(protocol, e_protocol) different_protocol;
|
|
num_lesser(port_end, e_port_start) before;
|
|
num_greater(port_start, e_port_end) after;
|
|
or(different_protocol, before, after) no_conflict;
|
|
not(no_conflict) conflict;
|
|
|
|
If (conflict) {
|
|
error_text->set("Port forwarding conflicts with an existing forwarding.");
|
|
not_finished->set("false");
|
|
finished_point->go();
|
|
};
|
|
};
|
|
|
|
# Build entry key.
|
|
var({protocol, port_start, port_end, dest_addr}) key;
|
|
|
|
# Insert to map and toggle blocker.
|
|
pf.map->insert(key, "");
|
|
pf.update_blocker->downup();
|
|
|
|
# Start process.
|
|
pf.mgr->start(key, "port_forwarding__instance", {protocol, port_start, port_end, dest_addr});
|
|
|
|
succeeded->set("true");
|
|
not_finished->set("false");
|
|
finished_point->go();
|
|
};
|
|
}
|
|
|
|
template port_forwarding_remove {
|
|
alias(_arg0) pf;
|
|
alias("_arg1") protocol;
|
|
alias("_arg2") port_start;
|
|
alias("_arg3") port_end;
|
|
alias("_arg4") dest_addr;
|
|
|
|
var("false") succeeded;
|
|
var("") error_text;
|
|
var("true") not_finished;
|
|
backtrack_point() finished_point;
|
|
|
|
If (not_finished) {
|
|
# Build entry key.
|
|
var({protocol, port_start, port_end, dest_addr}) key;
|
|
|
|
# Check if the forwarding exists.
|
|
pf.map->try_get(key) entry;
|
|
not(entry.exists) does_not_exist;
|
|
If (does_not_exist) {
|
|
error_text->set("Port forwarding does not exist.");
|
|
not_finished->set("false");
|
|
finished_point->go();
|
|
};
|
|
|
|
# Stop process.
|
|
pf.mgr->stop(key);
|
|
|
|
# Remove from map and toggle blocker.
|
|
pf.map->remove(key);
|
|
pf.update_blocker->downup();
|
|
|
|
succeeded->set("true");
|
|
not_finished->set("false");
|
|
finished_point->go();
|
|
};
|
|
}
|
|
|
|
template port_forwarding__stored {
|
|
alias("_caller") pf;
|
|
|
|
# Create file if it doesn't exist.
|
|
file_stat(pf.forwardings_file) stat;
|
|
If (stat.succeeded) { print(); } Else {
|
|
file_write(pf.forwardings_file, "{}\n");
|
|
};
|
|
|
|
# Read port forwardings from file.
|
|
file_read(pf.forwardings_file) data;
|
|
from_string(data) forwardings;
|
|
|
|
# Add them.
|
|
Foreach (forwardings As fwd) {
|
|
value(fwd) fwd;
|
|
fwd->get("0") protocol;
|
|
fwd->get("1") port_start;
|
|
fwd->get("2") port_end;
|
|
fwd->get("3") dest_addr;
|
|
call("port_forwarding_add", {"_caller.pf", protocol, port_start, port_end, dest_addr});
|
|
};
|
|
|
|
# Write forwardings to file on exit.
|
|
imperative("<none>", {}, "port_forwarding__write", {}, "6000");
|
|
|
|
# Also write forwardings whenever they are changed.
|
|
pf.update_blocker->use();
|
|
call("port_forwarding__write", {});
|
|
}
|
|
|
|
template port_forwarding__write {
|
|
alias("_caller.pf") pf;
|
|
|
|
# Convert forwardings to string.
|
|
to_string(pf.map.keys) data;
|
|
concat(data, "\n") data;
|
|
|
|
# Build name of temporary file.
|
|
concat(pf.forwardings_file, ".new") temp_file;
|
|
|
|
# Write temporary file.
|
|
file_write(temp_file, data);
|
|
|
|
# Move to live file.
|
|
runonce({"/bin/mv", temp_file, pf.forwardings_file});
|
|
}
|