BadVPN – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | include_guard "port_forwarding" |
2 | |||
3 | template port_forwarding { |
||
4 | alias("_arg0") forwardings_file; |
||
5 | alias("_arg1") template_forward; |
||
6 | |||
7 | # Map which holds the set of current port forwardings. |
||
8 | # Enties are: {protocol, port_start, port_end, dest_addr}:"" |
||
9 | value([]) map; |
||
10 | |||
11 | # Blocker which is initially down and is toggled down-up |
||
12 | # whenever the forwarding change. |
||
13 | blocker() update_blocker; |
||
14 | |||
15 | # Process manager, each forwarding has a port_forwarding__instance process. |
||
16 | # The process identifiers are the same as the keys in the map. |
||
17 | process_manager() mgr; |
||
18 | |||
19 | # Spawn a process for dealing with storage of port forwardings on disk. |
||
20 | spawn("port_forwarding__stored", {}); |
||
21 | } |
||
22 | |||
23 | template port_forwarding__instance { |
||
24 | alias("_caller") pf; |
||
25 | alias("_arg0") protocol; |
||
26 | alias("_arg1") port_start; |
||
27 | alias("_arg2") port_end; |
||
28 | alias("_arg3") dest_addr; |
||
29 | |||
30 | log("notice", "adding port forwarding ", protocol, ":", port_start, ":", port_end, " to ", dest_addr); |
||
31 | log_r("notice", "removed port forwarding ", protocol, ":", port_start, ":", port_end, " to ", dest_addr); |
||
32 | |||
33 | # Do the forwarding. |
||
34 | call_with_caller_target(pf.template_forward, {protocol, port_start, port_end, dest_addr}, "pf._caller"); |
||
35 | } |
||
36 | |||
37 | template port_forwarding_add { |
||
38 | alias(_arg0) pf; |
||
39 | alias("_arg1") protocol; |
||
40 | alias("_arg2") port_start; |
||
41 | alias("_arg3") port_end; |
||
42 | alias("_arg4") dest_addr; |
||
43 | |||
44 | var("false") succeeded; |
||
45 | var("") error_text; |
||
46 | var("true") not_finished; |
||
47 | backtrack_point() finished_point; |
||
48 | |||
49 | If (not_finished) { |
||
50 | # Check for conflicts with existing forwardings. |
||
51 | Foreach (pf.map.keys As entry) { |
||
52 | value(entry) entry; |
||
53 | entry->get("0") e_protocol; |
||
54 | entry->get("1") e_port_start; |
||
55 | entry->get("2") e_port_end; |
||
56 | |||
57 | val_different(protocol, e_protocol) different_protocol; |
||
58 | num_lesser(port_end, e_port_start) before; |
||
59 | num_greater(port_start, e_port_end) after; |
||
60 | or(different_protocol, before, after) no_conflict; |
||
61 | not(no_conflict) conflict; |
||
62 | |||
63 | If (conflict) { |
||
64 | error_text->set("Port forwarding conflicts with an existing forwarding."); |
||
65 | not_finished->set("false"); |
||
66 | finished_point->go(); |
||
67 | }; |
||
68 | }; |
||
69 | |||
70 | # Build entry key. |
||
71 | var({protocol, port_start, port_end, dest_addr}) key; |
||
72 | |||
73 | # Insert to map and toggle blocker. |
||
74 | pf.map->insert(key, ""); |
||
75 | pf.update_blocker->downup(); |
||
76 | |||
77 | # Start process. |
||
78 | pf.mgr->start(key, "port_forwarding__instance", {protocol, port_start, port_end, dest_addr}); |
||
79 | |||
80 | succeeded->set("true"); |
||
81 | not_finished->set("false"); |
||
82 | finished_point->go(); |
||
83 | }; |
||
84 | } |
||
85 | |||
86 | template port_forwarding_remove { |
||
87 | alias(_arg0) pf; |
||
88 | alias("_arg1") protocol; |
||
89 | alias("_arg2") port_start; |
||
90 | alias("_arg3") port_end; |
||
91 | alias("_arg4") dest_addr; |
||
92 | |||
93 | var("false") succeeded; |
||
94 | var("") error_text; |
||
95 | var("true") not_finished; |
||
96 | backtrack_point() finished_point; |
||
97 | |||
98 | If (not_finished) { |
||
99 | # Build entry key. |
||
100 | var({protocol, port_start, port_end, dest_addr}) key; |
||
101 | |||
102 | # Check if the forwarding exists. |
||
103 | pf.map->try_get(key) entry; |
||
104 | not(entry.exists) does_not_exist; |
||
105 | If (does_not_exist) { |
||
106 | error_text->set("Port forwarding does not exist."); |
||
107 | not_finished->set("false"); |
||
108 | finished_point->go(); |
||
109 | }; |
||
110 | |||
111 | # Stop process. |
||
112 | pf.mgr->stop(key); |
||
113 | |||
114 | # Remove from map and toggle blocker. |
||
115 | pf.map->remove(key); |
||
116 | pf.update_blocker->downup(); |
||
117 | |||
118 | succeeded->set("true"); |
||
119 | not_finished->set("false"); |
||
120 | finished_point->go(); |
||
121 | }; |
||
122 | } |
||
123 | |||
124 | template port_forwarding__stored { |
||
125 | alias("_caller") pf; |
||
126 | |||
127 | # Create file if it doesn't exist. |
||
128 | file_stat(pf.forwardings_file) stat; |
||
129 | If (stat.succeeded) { print(); } Else { |
||
130 | file_write(pf.forwardings_file, "{}\n"); |
||
131 | }; |
||
132 | |||
133 | # Read port forwardings from file. |
||
134 | file_read(pf.forwardings_file) data; |
||
135 | from_string(data) forwardings; |
||
136 | |||
137 | # Add them. |
||
138 | Foreach (forwardings As fwd) { |
||
139 | value(fwd) fwd; |
||
140 | fwd->get("0") protocol; |
||
141 | fwd->get("1") port_start; |
||
142 | fwd->get("2") port_end; |
||
143 | fwd->get("3") dest_addr; |
||
144 | call("port_forwarding_add", {"_caller.pf", protocol, port_start, port_end, dest_addr}); |
||
145 | }; |
||
146 | |||
147 | # Write forwardings to file on exit. |
||
148 | imperative("<none>", {}, "port_forwarding__write", {}, "6000"); |
||
149 | |||
150 | # Also write forwardings whenever they are changed. |
||
151 | pf.update_blocker->use(); |
||
152 | call("port_forwarding__write", {}); |
||
153 | } |
||
154 | |||
155 | template port_forwarding__write { |
||
156 | alias("_caller.pf") pf; |
||
157 | |||
158 | # Convert forwardings to string. |
||
159 | to_string(pf.map.keys) data; |
||
160 | concat(data, "\n") data; |
||
161 | |||
162 | # Build name of temporary file. |
||
163 | concat(pf.forwardings_file, ".new") temp_file; |
||
164 | |||
165 | # Write temporary file. |
||
166 | file_write(temp_file, data); |
||
167 | |||
168 | # Move to live file. |
||
169 | runonce({"/bin/mv", temp_file, pf.forwardings_file}); |
||
170 | } |