e983035b3d0a04c951dcd565859f689883d2b680
7 'require tools.prng as random';
11 'hopopt', 0, 'HOPOPT',
15 'ipencap', 4, 'IP-ENCAP',
23 'xns-idp', 22, 'XNS-IDP',
25 'iso-tp4', 29, 'ISO-TP4',
29 'idpr-cmtp', 38, 'IDPR-CMTP',
31 'ipv6-route', 43, 'IPv6-Route',
32 'ipv6-frag', 44, 'IPv6-Frag',
36 'esp', 50, 'IPSEC-ESP',
39 'ipv6-icmp', 58, 'IPv6-ICMP',
40 'ipv6-nonxt', 59, 'IPv6-NoNxt',
41 'ipv6-opts', 60, 'IPv6-Opts',
42 'rspf', 73, 'RSPF', 'CPHB',
45 'ospf', 89, 'OSPFIGP',
48 'etherip', 97, 'ETHERIP',
51 'ipcomp', 108, 'IPCOMP',
57 'mobility-header', 135, 'Mobility-Header',
58 'udplite', 136, 'UDPLite',
59 'mpls-in-ip', 137, 'MPLS-in-IP',
60 'manet', 138, 'MANET',
62 'shim6', 140, 'Shim6',
67 function lookupProto(x
) {
68 if (x
== null || x
== '')
71 var s
= String(x
).toLowerCase();
73 for (var i
= 0; i
< protocols
.length
; i
+= 3)
74 if (s
== protocols
[i
] || s
== protocols
[i
+1])
75 return [ protocols
[i
+1], protocols
[i
+2] ];
81 return L
.Class
.extend({
82 fmt_neg: function(x
) {
84 v
= (typeof(x
) == 'string') ? x
.replace(/^ *! */, '') : '';
86 L
.dom
.append(rv
, (v
!= '' && v
!= x
) ? [ _('not') + ' ', v
] : [ '', x
]);
90 fmt_mac: function(x
) {
91 var rv
= E([]), l
= L
.toArray(x
);
96 L
.dom
.append(rv
, [ _('MAC') + ' ' ]);
98 for (var i
= 0; i
< l
.length
; i
++) {
99 var n
= this.fmt_neg(l
[i
]);
100 L
.dom
.append(rv
, (i
> 0) ? [ ', ', n
] : n
);
103 if (rv
.childNodes
.length
> 2)
104 rv
.firstChild
.data
= _('MACs') + ' ';
109 fmt_port: function(x
, d
) {
110 var rv
= E([]), l
= L
.toArray(x
);
114 L
.dom
.append(rv
, E('var', {}, d
));
121 L
.dom
.append(rv
, [ _('port') + ' ' ]);
123 for (var i
= 0; i
< l
.length
; i
++) {
124 var n
= this.fmt_neg(l
[i
]),
125 m
= n
.lastChild
.data
.match(/^(\d+)\D+(\d+)$/);
128 L
.dom
.append(rv
, [ ', ' ]);
131 rv
.firstChild
.data
= _('ports') + ' ';
132 L
.dom
.append(rv
, E('var', [ n
.firstChild
, m
[1], '-', m
[2] ]));
135 L
.dom
.append(rv
, E('var', {}, n
));
139 if (rv
.childNodes
.length
> 2)
140 rv
.firstChild
.data
= _('ports') + ' ';
145 fmt_ip: function(x
, d
) {
146 var rv
= E([]), l
= L
.toArray(x
);
150 L
.dom
.append(rv
, E('var', {}, d
));
157 L
.dom
.append(rv
, [ _('IP') + ' ' ]);
159 for (var i
= 0; i
< l
.length
; i
++) {
160 var n
= this.fmt_neg(l
[i
]),
161 m
= n
.lastChild
.data
.match(/^(\S+)\/(\d+\.\S+)$/);
164 L
.dom
.append(rv
, [ ', ' ]);
167 rv
.firstChild
.data
= _('IP range') + ' ';
168 else if (n
.lastChild
.data
.match(/^[a-zA-Z0-9_]+$/))
169 rv
.firstChild
.data
= _('Network') + ' ';
171 L
.dom
.append(rv
, E('var', {}, n
));
174 if (rv
.childNodes
.length
> 2)
175 rv
.firstChild
.data
= _('IPs') + ' ';
180 fmt_zone: function(x
, d
) {
182 return E('var', _('any zone'));
183 else if (x
!= null && x
!= '')
184 return E('var', {}, [ x
]);
185 else if (d
!= null && d
!= '')
186 return E('var', {}, d
);
191 fmt_icmp_type: function(x
) {
192 var rv
= E([]), l
= L
.toArray(x
);
197 L
.dom
.append(rv
, [ _('type') + ' ' ]);
199 for (var i
= 0; i
< l
.length
; i
++) {
200 var n
= this.fmt_neg(l
[i
]);
203 L
.dom
.append(rv
, [ ', ' ]);
205 L
.dom
.append(rv
, E('var', {}, n
));
208 if (rv
.childNodes
.length
> 2)
209 rv
.firstChild
.data
= _('types') + ' ';
214 fmt_family: function(family
) {
215 if (family
== 'ipv4')
217 else if (family
== 'ipv6')
220 return _('IPv4 and IPv6');
223 fmt_proto: function(x
, icmp_types
) {
224 var rv
= E([]), l
= L
.toArray(x
);
229 var t
= this.fmt_icmp_type(icmp_types
);
231 for (var i
= 0; i
< l
.length
; i
++) {
232 var n
= this.fmt_neg(l
[i
]),
233 p
= lookupProto(n
.lastChild
.data
);
235 if (n
.lastChild
.data
== 'all')
239 L
.dom
.append(rv
, [ ', ' ]);
241 if (t
&& (p
[0] == 1 || p
[0] == 58))
242 L
.dom
.append(rv
, [ _('%s%s with %s').format(n
.firstChild
.data
, p
[1], ''), t
]);
244 L
.dom
.append(rv
, [ n
.firstChild
.data
, p
[1] ]);
250 fmt_limit: function(limit
, burst
) {
251 if (limit
== null || limit
== '')
254 var m
= String(limit
).match(/^(\d+)\/(\w+)$/),
255 u
= m
[2] || 'second',
256 l
= +(m
[1] || limit
),
262 else if (u
.match(/^m/))
264 else if (u
.match(/^h/))
266 else if (u
.match(/^d/))
269 if (!isNaN(b
) && b
> 0)
271 _('<var>%d</var> pkts. per <var>%s</var>, burst <var>%d</var> pkts.').format(l
, u
, b
) +
275 _('<var>%d</var> pkts. per <var>%s</var>').format(l
, u
) +
280 fmt_target: function(x
, src
, dest
) {
281 if (src
== null || src
== '') {
283 return _('Accept output');
284 else if (x
== 'REJECT')
285 return _('Refuse output');
286 else if (x
== 'NOTRACK')
287 return _('Do not track output');
288 else /* if (x == 'DROP') */
289 return _('Discard output');
291 else if (dest
!= null && dest
!= '') {
293 return _('Accept forward');
294 else if (x
== 'REJECT')
295 return _('Refuse forward');
296 else if (x
== 'NOTRACK')
297 return _('Do not track forward');
298 else /* if (x == 'DROP') */
299 return _('Discard forward');
303 return _('Accept input');
304 else if (x
== 'REJECT' )
305 return _('Refuse input');
306 else if (x
== 'NOTRACK')
307 return _('Do not track input');
308 else /* if (x == 'DROP') */
309 return _('Discard input');
313 addDSCPOption: function(s
, is_target
) {
314 var o
= s
.taboption(is_target
? 'general' : 'advanced', form
.Value
, is_target
? 'set_dscp' : 'dscp',
315 is_target
? _('DSCP mark') : _('Match DSCP'),
316 is_target
? _('Apply the given DSCP class or value to established connections.') : _('Matches traffic carrying the specified DSCP marking.'));
319 o
.rmempty
= !is_target
;
320 o
.placeholder
= _('any');
323 o
.depends('target', 'DSCP');
347 o
.validate = function(section_id
, value
) {
349 return is_target
? _('DSCP mark required') : true;
352 value
= String(value
).replace(/^!\s*/, '');
354 var m
= value
.match(/^(?:CS[0-7]|BE|AF[1234][123]|EF|(0x[0-9a-f]{1,2}|[0-9]{1,2}))$/);
356 if (!m
|| (m
[1] != null && +m
[1] > 0x3f))
357 return _('Invalid DSCP mark');
365 addMarkOption: function(s
, is_target
) {
366 var o
= s
.taboption(is_target
? 'general' : 'advanced', form
.Value
,
367 (is_target
> 1) ? 'set_xmark' : (is_target
? 'set_mark' : 'mark'),
368 (is_target
> 1) ? _('XOR mark') : (is_target
? _('Set mark') : _('Match mark')),
369 (is_target
> 1) ? _('Apply a bitwise XOR of the given value and the existing mark value on established connections. Format is value[/mask]. If a mask is specified then those bits set in the mask are zeroed out.') :
370 (is_target
? _('Set the given mark value on established connections. Format is value[/mask]. If a mask is specified then only those bits set in the mask are modified.') :
371 _('Matches a specific firewall mark or a range of different marks.')));
377 o
.depends('target', 'MARK_XOR');
379 o
.depends('target', 'MARK_SET');
381 o
.validate = function(section_id
, value
) {
383 return is_target
? _('Valid firewall mark required') : true;
386 value
= String(value
).replace(/^!\s*/, '');
388 var m
= value
.match(/^(0x[0-9a-f]{1,8}|[0-9]{1,10})(?:\/(0x[0-9a-f]{1,8}|[0-9]{1,10}))?$/i);
390 if (!m
|| +m
[1] > 0xffffffff || (m
[2] != null && +m
[2] > 0xffffffff))
391 return _('Expecting: %s').format(_('valid firewall mark'));
399 addLimitOption: function(s
) {
400 var o
= s
.taboption('advanced', form
.Value
, 'limit',
402 _('Limits traffic matching to the specified rate.'));
406 o
.placeholder
= _('unlimited');
407 o
.value('10/second');
408 o
.value('60/minute');
411 o
.validate = function(section_id
, value
) {
415 var m
= String(value
).toLowerCase().match(/^(?:0x[0-9a-f]{1,8}|[0-9]{1,10})\/([a-z]+)$/),
416 u
= ['second', 'minute', 'hour', 'day'],
420 for (i
= 0; i
< u
.length
; i
++)
421 if (u
[i
].indexOf(m
[1]) == 0)
424 if (!m
|| i
>= u
.length
)
425 return _('Invalid limit value');
433 addLimitBurstOption: function(s
) {
434 var o
= s
.taboption('advanced', form
.Value
, 'limit_burst',
436 _('Maximum initial number of packets to match: this number gets recharged by one every time the limit specified above is not reached, up to this number.'));
441 o
.datatype
= 'uinteger';
442 o
.depends({ limit
: null, '!reverse': true });