6 'require tools.firewall as fwtool';
7 'require tools.widgets as widgets';
9 function fmt(fmt /*, ...*/) {
10 var repl = [], wrap = false;
12 for (var i = 1; i < arguments.length; i++) {
13 if (L.dom.elem(arguments[i])) {
14 switch (arguments[i].nodeType) {
16 repl.push(arguments[i].outerHTML);
21 repl.push(arguments[i].data);
26 span.appendChild(arguments[i]);
27 repl.push(span.innerHTML);
36 repl.push(arguments[i]);
40 var rv = fmt.format.apply(fmt, repl);
41 return wrap ? E('span', rv) : rv;
44 function forward_proto_txt(s) {
46 fwtool.fmt_family(uci.get('firewall', s, 'family')),
47 fwtool.fmt_proto(uci.get('firewall', s, 'proto'),
48 uci.get('firewall', s, 'icmp_type')) || 'TCP+UDP');
51 function forward_src_txt(s) {
52 var z = fwtool.fmt_zone(uci.get('firewall', s, 'src'), _('any zone')),
53 a = fwtool.fmt_ip(uci.get('firewall', s, 'src_ip'), _('any host')),
54 p = fwtool.fmt_port(uci.get('firewall', s, 'src_port')),
55 m = fwtool.fmt_mac(uci.get('firewall', s, 'src_mac'));
58 return fmt(_('From %s in %s with source %s and %s'), a, z, p, m);
60 return fmt(_('From %s in %s with source %s'), a, z, p || m);
62 return fmt(_('From %s in %s'), a, z);
65 function forward_via_txt(s) {
66 var a = fwtool.fmt_ip(uci.get('firewall', s, 'src_dip'), _('any router IP')),
67 p = fwtool.fmt_port(uci.get('firewall', s, 'src_dport'));
70 return fmt(_('Via %s at %s'), a, p);
72 return fmt(_('Via %s'), a);
75 return L.view.extend({
76 callHostHints: rpc.declare({
87 render: function(data) {
91 m = new form.Map('firewall', _('Firewall - Port Forwards'),
92 _('Port forwarding allows remote computers on the Internet to connect to a specific computer or service within the private LAN.'));
94 s = m.section(form.GridSection, 'redirect', _('Port Forwards'));
99 s.tab('general', _('General Settings'));
100 s.tab('advanced', _('Advanced Settings'));
102 s.filter = function(section_id) {
103 return (uci.get('firewall', section_id, 'target') != 'SNAT');
106 s.sectiontitle = function(section_id) {
107 return uci.get('firewall', section_id, 'name') || _('Unnamed forward');
110 s.handleAdd = function(ev) {
111 var config_name = this.uciconfig || this.map.config,
112 section_id = uci.add(config_name, this.sectiontype);
114 uci.set(config_name, section_id, 'target', 'DNAT');
116 this.addedSection = section_id;
117 this.renderMoreOptionsModal(section_id);
120 o = s.taboption('general', form.Value, 'name', _('Name'));
121 o.placeholder = _('Unnamed forward');
124 o = s.option(form.DummyValue, '_match', _('Match'));
126 o.textvalue = function(s) {
128 forward_proto_txt(s), E('br'),
129 forward_src_txt(s), E('br'),
134 o = s.option(form.ListValue, '_dest', _('Forward to'));
136 o.textvalue = function(s) {
137 var z = fwtool.fmt_zone(uci.get('firewall', s, 'dest'), _('any zone')),
138 a = fwtool.fmt_ip(uci.get('firewall', s, 'dest_ip'), _('any host')),
139 p = fwtool.fmt_port(uci.get('firewall', s, 'dest_port')) ||
140 fwtool.fmt_port(uci.get('firewall', s, 'src_dport'));
143 return fmt(_('%s, %s in %s'), a, p, z);
145 return fmt(_('%s in %s'), a, z);
148 o = s.option(form.Flag, 'enabled', _('Enable'));
150 o.default = o.enabled;
153 o = s.taboption('general', form.Value, 'proto', _('Protocol'));
155 o.default = 'tcp udp';
156 o.value('tcp udp', 'TCP+UDP');
157 o.value('tcp', 'TCP');
158 o.value('udp', 'UDP');
159 o.value('icmp', 'ICMP');
161 o.cfgvalue = function(/* ... */) {
162 var v = this.super('cfgvalue', arguments);
163 return (v == 'tcpudp') ? 'tcp udp' : v;
166 o = s.taboption('general', widgets.ZoneSelect, 'src', _('Source zone'));
172 o = s.taboption('advanced', form.Value, 'src_mac', _('Source MAC address'),
173 _('Only match incoming traffic from these MACs.'));
176 o.datatype = 'neg(macaddr)';
177 o.placeholder = E('em', _('any'));
178 L.sortedKeys(hosts).forEach(function(mac) {
179 o.value(mac, '%s (%s)'.format(
181 hosts[mac].name || hosts[mac].ipv4 || hosts[mac].ipv6 || '?'
185 o = s.taboption('advanced', form.Value, 'src_ip', _('Source IP address'),
186 _('Only match incoming traffic from this IP or range.'));
189 o.datatype = 'neg(ipmask4)';
190 o.placeholder = E('em', _('any'));
191 L.sortedKeys(hosts, 'ipv4', 'addr').forEach(function(mac) {
192 o.value(hosts[mac].ipv4, '%s (%s)'.format(
194 hosts[mac].name || mac
198 o = s.taboption('advanced', form.Value, 'src_port', _('Source port'),
199 _('Only match incoming traffic originating from the given source port or port range on the client host'));
202 o.datatype = 'neg(portrange)';
203 o.placeholder = _('any');
204 o.depends('proto', 'tcp');
205 o.depends('proto', 'udp');
206 o.depends('proto', 'tcp udp');
207 o.depends('proto', 'tcpudp');
209 o = s.taboption('advanced', form.Value, 'src_dip', _('External IP address'),
210 _('Only match incoming traffic directed at the given IP address.'));
213 o.datatype = 'neg(ipmask4)';
214 o.placeholder = E('em', _('any'));
215 L.sortedKeys(hosts, 'ipv4', 'addr').forEach(function(mac) {
216 o.value(hosts[mac].ipv4, '%s (%s)'.format(
218 hosts[mac].name || mac
222 o = s.taboption('general', form.Value, 'src_dport', _('External port'),
223 _('Match incoming traffic directed at the given destination port or port range on this host'));
226 o.datatype = 'neg(portrange)';
227 o.depends('proto', 'tcp');
228 o.depends('proto', 'udp');
229 o.depends('proto', 'tcp udp');
230 o.depends('proto', 'tcpudp');
232 o = s.taboption('general', widgets.ZoneSelect, 'dest', _('Internal zone'));
238 o = s.taboption('general', form.Value, 'dest_ip', _('Internal IP address'),
239 _('Redirect matched incoming traffic to the specified internal host'));
242 o.datatype = 'ipmask4';
243 L.sortedKeys(hosts, 'ipv4', 'addr').forEach(function(mac) {
244 o.value(hosts[mac].ipv4, '%s (%s)'.format(
246 hosts[mac].name || mac
250 o = s.taboption('general', form.Value, 'dest_port', _('Internal port'),
251 _('Redirect matched incoming traffic to the given port on the internal host'));
254 o.placeholder = _('any');
255 o.datatype = 'portrange';
256 o.depends('proto', 'tcp');
257 o.depends('proto', 'udp');
258 o.depends('proto', 'tcp udp');
259 o.depends('proto', 'tcpudp');
261 o = s.taboption('advanced', form.Flag, 'reflection', _('Enable NAT Loopback'));
264 o.default = o.enabled;
266 o = s.taboption('advanced', form.Value, 'extra', _('Extra arguments'),
267 _('Passes additional arguments to iptables. Use with care!'));