2019-06-13 13:23:26 +00:00
'use strict' ;
2020-04-03 08:00:06 +00:00
'require baseclass' ;
'require dom' ;
2019-06-13 13:23:26 +00:00
'require ui' ;
'require uci' ;
'require form' ;
'require network' ;
'require firewall' ;
'require tools.prng as random' ;
var protocols = [
'ip' , 0 , 'IP' ,
'hopopt' , 0 , 'HOPOPT' ,
'icmp' , 1 , 'ICMP' ,
'igmp' , 2 , 'IGMP' ,
'ggp' , 3 , 'GGP' ,
'ipencap' , 4 , 'IP-ENCAP' ,
'st' , 5 , 'ST' ,
'tcp' , 6 , 'TCP' ,
'egp' , 8 , 'EGP' ,
'igp' , 9 , 'IGP' ,
'pup' , 12 , 'PUP' ,
'udp' , 17 , 'UDP' ,
'hmp' , 20 , 'HMP' ,
'xns-idp' , 22 , 'XNS-IDP' ,
'rdp' , 27 , 'RDP' ,
'iso-tp4' , 29 , 'ISO-TP4' ,
'dccp' , 33 , 'DCCP' ,
'xtp' , 36 , 'XTP' ,
'ddp' , 37 , 'DDP' ,
'idpr-cmtp' , 38 , 'IDPR-CMTP' ,
'ipv6' , 41 , 'IPv6' ,
'ipv6-route' , 43 , 'IPv6-Route' ,
'ipv6-frag' , 44 , 'IPv6-Frag' ,
'idrp' , 45 , 'IDRP' ,
'rsvp' , 46 , 'RSVP' ,
'gre' , 47 , 'GRE' ,
'esp' , 50 , 'IPSEC-ESP' ,
'ah' , 51 , 'IPSEC-AH' ,
'skip' , 57 , 'SKIP' ,
2020-01-19 15:08:47 +00:00
'icmpv6' , 58 , 'IPv6-ICMP' ,
2019-06-13 13:23:26 +00:00
'ipv6-icmp' , 58 , 'IPv6-ICMP' ,
'ipv6-nonxt' , 59 , 'IPv6-NoNxt' ,
'ipv6-opts' , 60 , 'IPv6-Opts' ,
2020-01-19 15:08:47 +00:00
'rspf' , 73 , 'RSPF' ,
'rspf' , 73 , 'CPHB' ,
2019-06-13 13:23:26 +00:00
'vmtp' , 81 , 'VMTP' ,
'eigrp' , 88 , 'EIGRP' ,
'ospf' , 89 , 'OSPFIGP' ,
'ax.25' , 93 , 'AX.25' ,
'ipip' , 94 , 'IPIP' ,
'etherip' , 97 , 'ETHERIP' ,
'encap' , 98 , 'ENCAP' ,
'pim' , 103 , 'PIM' ,
'ipcomp' , 108 , 'IPCOMP' ,
'vrrp' , 112 , 'VRRP' ,
'l2tp' , 115 , 'L2TP' ,
'isis' , 124 , 'ISIS' ,
'sctp' , 132 , 'SCTP' ,
'fc' , 133 , 'FC' ,
2020-01-19 15:08:47 +00:00
'mh' , 135 , 'Mobility-Header' ,
'ipv6-mh' , 135 , 'Mobility-Header' ,
2019-06-13 13:23:26 +00:00
'mobility-header' , 135 , 'Mobility-Header' ,
'udplite' , 136 , 'UDPLite' ,
'mpls-in-ip' , 137 , 'MPLS-in-IP' ,
'manet' , 138 , 'MANET' ,
'hip' , 139 , 'HIP' ,
'shim6' , 140 , 'Shim6' ,
'wesp' , 141 , 'WESP' ,
'rohc' , 142 , 'ROHC' ,
] ;
function lookupProto ( x ) {
2020-03-04 19:21:23 +00:00
if ( x == null || x === '' )
2019-06-13 13:23:26 +00:00
return null ;
var s = String ( x ) . toLowerCase ( ) ;
for ( var i = 0 ; i < protocols . length ; i += 3 )
if ( s == protocols [ i ] || s == protocols [ i + 1 ] )
2020-01-19 15:08:47 +00:00
return [ protocols [ i + 1 ] , protocols [ i + 2 ] , protocols [ i ] ] ;
2019-06-13 13:23:26 +00:00
2020-01-19 15:08:47 +00:00
return [ - 1 , x , x ] ;
2019-06-13 13:23:26 +00:00
}
2020-04-03 08:00:06 +00:00
return baseclass . extend ( {
2020-01-19 15:08:47 +00:00
fmt : function ( fmtstr , args , values ) {
var repl = [ ] ,
wrap = false ,
tokens = [ ] ;
if ( values == null ) {
values = [ ] ;
wrap = true ;
2019-06-13 13:23:26 +00:00
}
2020-01-19 15:08:47 +00:00
var get = function ( args , key ) {
var names = key . trim ( ) . split ( /\./ ) ,
obj = args ,
ctx = obj ;
2019-06-13 13:23:26 +00:00
2020-01-19 15:08:47 +00:00
for ( var i = 0 ; i < names . length ; i ++ ) {
if ( ! L . isObject ( obj ) )
return null ;
2019-06-13 13:23:26 +00:00
2020-01-19 15:08:47 +00:00
ctx = obj ;
obj = obj [ names [ i ] ] ;
2019-06-13 13:23:26 +00:00
}
2020-01-19 15:08:47 +00:00
if ( typeof ( obj ) == 'function' )
return obj . call ( ctx ) ;
2019-06-13 13:23:26 +00:00
2020-01-19 15:08:47 +00:00
return obj ;
} ;
2019-06-13 13:23:26 +00:00
2020-01-19 15:08:47 +00:00
var isset = function ( val ) {
2020-04-03 08:00:06 +00:00
if ( L . isObject ( val ) && ! dom . elem ( val ) ) {
2020-01-19 15:08:47 +00:00
for ( var k in val )
if ( val . hasOwnProperty ( k ) )
return true ;
2019-06-13 13:23:26 +00:00
2020-01-19 15:08:47 +00:00
return false ;
}
else if ( Array . isArray ( val ) ) {
return ( val . length > 0 ) ;
2019-06-13 13:23:26 +00:00
}
else {
2020-01-19 15:08:47 +00:00
return ( val !== null && val !== undefined && val !== '' && val !== false ) ;
2019-06-13 13:23:26 +00:00
}
2020-01-19 15:08:47 +00:00
} ;
2019-06-13 13:23:26 +00:00
2020-01-19 15:08:47 +00:00
var parse = function ( tokens , text ) {
2020-04-03 08:00:06 +00:00
if ( dom . elem ( text ) ) {
2020-01-19 15:08:47 +00:00
tokens . push ( '<span data-fmt-placeholder="%d"></span>' . format ( values . length ) ) ;
values . push ( text ) ;
2019-06-13 13:23:26 +00:00
}
2020-01-19 15:08:47 +00:00
else {
tokens . push ( String ( text ) . replace ( /\\(.)/g , '$1' ) ) ;
}
} ;
2019-06-13 13:23:26 +00:00
2020-01-19 15:08:47 +00:00
for ( var i = 0 , last = 0 ; i <= fmtstr . length ; i ++ ) {
if ( fmtstr . charAt ( i ) == '%' && fmtstr . charAt ( i + 1 ) == '{' ) {
if ( i > last )
parse ( tokens , fmtstr . substring ( last , i ) ) ;
var j = i + 1 , nest = 0 ;
var subexpr = [ ] ;
for ( var off = j + 1 , esc = false ; j <= fmtstr . length ; j ++ ) {
var ch = fmtstr . charAt ( j ) ;
if ( esc ) {
esc = false ;
}
else if ( ch == '\\' ) {
esc = true ;
}
else if ( ch == '{' ) {
nest ++ ;
}
else if ( ch == '}' ) {
if ( -- nest == 0 ) {
subexpr . push ( fmtstr . substring ( off , j ) ) ;
break ;
}
}
else if ( ch == '?' || ch == ':' || ch == '#' ) {
if ( nest == 1 ) {
subexpr . push ( fmtstr . substring ( off , j ) ) ;
subexpr . push ( ch ) ;
off = j + 1 ;
}
}
}
var varname = subexpr [ 0 ] . trim ( ) ,
op1 = ( subexpr [ 1 ] != null ) ? subexpr [ 1 ] : '?' ,
if _set = ( subexpr [ 2 ] != null && subexpr [ 2 ] != '' ) ? subexpr [ 2 ] : '%{' + varname + '}' ,
op2 = ( subexpr [ 3 ] != null ) ? subexpr [ 3 ] : ':' ,
if _unset = ( subexpr [ 4 ] != null ) ? subexpr [ 4 ] : '' ;
/* Invalid expression */
if ( nest != 0 || subexpr . length > 5 || varname == '' ) {
return fmtstr ;
}
/* enumeration */
else if ( op1 == '#' && subexpr . length == 3 ) {
var items = L . toArray ( get ( args , varname ) ) ;
for ( var k = 0 ; k < items . length ; k ++ ) {
tokens . push . apply ( tokens , this . fmt ( if _set , Object . assign ( { } , args , {
first : k == 0 ,
next : k > 0 ,
last : ( k + 1 ) == items . length ,
item : items [ k ]
} ) , values ) ) ;
}
}
/* ternary expression */
else if ( op1 == '?' && op2 == ':' && ( subexpr . length == 1 || subexpr . length == 3 || subexpr . length == 5 ) ) {
var val = get ( args , varname ) ;
if ( subexpr . length == 1 )
parse ( tokens , isset ( val ) ? val : '' ) ;
else if ( isset ( val ) )
tokens . push . apply ( tokens , this . fmt ( if _set , args , values ) ) ;
else
tokens . push . apply ( tokens , this . fmt ( if _unset , args , values ) ) ;
}
/* unrecognized command */
else {
return fmtstr ;
}
last = j + 1 ;
i = j ;
}
else if ( i >= fmtstr . length ) {
if ( i > last )
parse ( tokens , fmtstr . substring ( last , i ) ) ;
}
2019-06-13 13:23:26 +00:00
}
2020-01-19 15:08:47 +00:00
if ( wrap ) {
var node = E ( 'span' , { } , tokens . join ( '' ) ) ,
repl = node . querySelectorAll ( 'span[data-fmt-placeholder]' ) ;
2019-06-13 13:23:26 +00:00
2020-01-19 15:08:47 +00:00
for ( var i = 0 ; i < repl . length ; i ++ )
repl [ i ] . parentNode . replaceChild ( values [ repl [ i ] . getAttribute ( 'data-fmt-placeholder' ) ] , repl [ i ] ) ;
2019-06-13 13:23:26 +00:00
2020-01-19 15:08:47 +00:00
return node ;
2019-06-13 13:23:26 +00:00
}
2020-01-19 15:08:47 +00:00
else {
return tokens ;
2019-06-13 13:23:26 +00:00
}
2019-07-17 16:19:45 +00:00
} ,
2020-01-19 15:08:47 +00:00
map _invert : function ( v , fn ) {
return L . toArray ( v ) . map ( function ( v ) {
v = String ( v ) ;
2019-06-13 13:23:26 +00:00
2020-01-19 15:08:47 +00:00
if ( fn != null && typeof ( v [ fn ] ) == 'function' )
v = v [ fn ] . call ( v ) ;
2019-06-13 13:23:26 +00:00
2020-01-19 15:08:47 +00:00
return {
ival : v ,
inv : v . charAt ( 0 ) == '!' ,
val : v . replace ( /^!\s*/ , '' )
} ;
} ) ;
2019-06-13 13:23:26 +00:00
} ,
2020-01-19 15:08:47 +00:00
lookupProto : lookupProto ,
2020-01-16 21:13:34 +00:00
addDSCPOption : function ( s , is _target ) {
var o = s . taboption ( is _target ? 'general' : 'advanced' , form . Value , is _target ? 'set_dscp' : 'dscp' ,
is _target ? _ ( 'DSCP mark' ) : _ ( 'Match DSCP' ) ,
is _target ? _ ( 'Apply the given DSCP class or value to established connections.' ) : _ ( 'Matches traffic carrying the specified DSCP marking.' ) ) ;
o . modalonly = true ;
o . rmempty = ! is _target ;
o . placeholder = _ ( 'any' ) ;
if ( is _target )
o . depends ( 'target' , 'DSCP' ) ;
o . value ( 'CS0' ) ;
o . value ( 'CS1' ) ;
o . value ( 'CS2' ) ;
o . value ( 'CS3' ) ;
o . value ( 'CS4' ) ;
o . value ( 'CS5' ) ;
o . value ( 'CS6' ) ;
o . value ( 'CS7' ) ;
o . value ( 'BE' ) ;
o . value ( 'AF11' ) ;
o . value ( 'AF12' ) ;
o . value ( 'AF13' ) ;
o . value ( 'AF21' ) ;
o . value ( 'AF22' ) ;
o . value ( 'AF23' ) ;
o . value ( 'AF31' ) ;
o . value ( 'AF32' ) ;
o . value ( 'AF33' ) ;
o . value ( 'AF41' ) ;
o . value ( 'AF42' ) ;
o . value ( 'AF43' ) ;
o . value ( 'EF' ) ;
o . validate = function ( section _id , value ) {
if ( value == '' )
return is _target ? _ ( 'DSCP mark required' ) : true ;
if ( ! is _target )
value = String ( value ) . replace ( /^!\s*/ , '' ) ;
var m = value . match ( /^(?:CS[0-7]|BE|AF[1234][123]|EF|(0x[0-9a-f]{1,2}|[0-9]{1,2}))$/ ) ;
if ( ! m || ( m [ 1 ] != null && + m [ 1 ] > 0x3f ) )
return _ ( 'Invalid DSCP mark' ) ;
return true ;
} ;
return o ;
} ,
addMarkOption : function ( s , is _target ) {
var o = s . taboption ( is _target ? 'general' : 'advanced' , form . Value ,
( is _target > 1 ) ? 'set_xmark' : ( is _target ? 'set_mark' : 'mark' ) ,
( is _target > 1 ) ? _ ( 'XOR mark' ) : ( is _target ? _ ( 'Set mark' ) : _ ( 'Match mark' ) ) ,
( 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.' ) :
( 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.' ) :
_ ( 'Matches a specific firewall mark or a range of different marks.' ) ) ) ;
o . modalonly = true ;
o . rmempty = true ;
if ( is _target > 1 )
o . depends ( 'target' , 'MARK_XOR' ) ;
else if ( is _target )
o . depends ( 'target' , 'MARK_SET' ) ;
o . validate = function ( section _id , value ) {
if ( value == '' )
return is _target ? _ ( 'Valid firewall mark required' ) : true ;
if ( ! is _target )
value = String ( value ) . replace ( /^!\s*/ , '' ) ;
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 ) ;
if ( ! m || + m [ 1 ] > 0xffffffff || ( m [ 2 ] != null && + m [ 2 ] > 0xffffffff ) )
return _ ( 'Expecting: %s' ) . format ( _ ( 'valid firewall mark' ) ) ;
return true ;
} ;
return o ;
} ,
addLimitOption : function ( s ) {
var o = s . taboption ( 'advanced' , form . Value , 'limit' ,
_ ( 'Limit matching' ) ,
_ ( 'Limits traffic matching to the specified rate.' ) ) ;
o . modalonly = true ;
o . rmempty = true ;
o . placeholder = _ ( 'unlimited' ) ;
o . value ( '10/second' ) ;
o . value ( '60/minute' ) ;
o . value ( '3/hour' ) ;
o . value ( '500/day' ) ;
o . validate = function ( section _id , value ) {
if ( value == '' )
return true ;
var m = String ( value ) . toLowerCase ( ) . match ( /^(?:0x[0-9a-f]{1,8}|[0-9]{1,10})\/([a-z]+)$/ ) ,
u = [ 'second' , 'minute' , 'hour' , 'day' ] ,
i = 0 ;
if ( m )
for ( i = 0 ; i < u . length ; i ++ )
if ( u [ i ] . indexOf ( m [ 1 ] ) == 0 )
break ;
if ( ! m || i >= u . length )
return _ ( 'Invalid limit value' ) ;
return true ;
} ;
return o ;
} ,
addLimitBurstOption : function ( s ) {
var o = s . taboption ( 'advanced' , form . Value , 'limit_burst' ,
_ ( 'Limit burst' ) ,
_ ( '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.' ) ) ;
o . modalonly = true ;
o . rmempty = true ;
o . placeholder = '5' ;
o . datatype = 'uinteger' ;
o . depends ( { limit : null , '!reverse' : true } ) ;
return o ;
2020-01-19 15:08:47 +00:00
} ,
transformHostHints : function ( family , hosts ) {
var choice _values = [ ] , choice _labels = { } ;
if ( ! family || family == 'ipv4' ) {
L . sortedKeys ( hosts , 'ipv4' , 'addr' ) . forEach ( function ( mac ) {
var val = hosts [ mac ] . ipv4 ,
txt = hosts [ mac ] . name || mac ;
choice _values . push ( val ) ;
choice _labels [ val ] = E ( [ ] , [ val , ' (' , E ( 'strong' , { } , [ txt ] ) , ')' ] ) ;
} ) ;
}
if ( ! family || family == 'ipv6' ) {
L . sortedKeys ( hosts , 'ipv6' , 'addr' ) . forEach ( function ( mac ) {
var val = hosts [ mac ] . ipv6 ,
txt = hosts [ mac ] . name || mac ;
choice _values . push ( val ) ;
choice _labels [ val ] = E ( [ ] , [ val , ' (' , E ( 'strong' , { } , [ txt ] ) , ')' ] ) ;
} ) ;
}
return [ choice _values , choice _labels ] ;
} ,
updateHostHints : function ( map , section _id , option , family , hosts ) {
var opt = map . lookupOption ( option , section _id ) [ 0 ] . getUIElement ( section _id ) ,
choices = this . transformHostHints ( family , hosts ) ;
opt . clearChoices ( ) ;
opt . addChoices ( choices [ 0 ] , choices [ 1 ] ) ;
} ,
2021-02-19 10:29:14 +00:00
CBIDynamicMultiValueList : form . DynamicList . extend ( {
renderWidget : function ( /* ... */ ) {
var dl = form . DynamicList . prototype . renderWidget . apply ( this , arguments ) ,
inst = dom . findClassInstance ( dl ) ;
inst . addItem = function ( dl , value , text , flash ) {
var values = L . toArray ( value ) ;
for ( var i = 0 ; i < values . length ; i ++ )
ui . DynamicList . prototype . addItem . call ( this , dl , values [ i ] , null , true ) ;
} ;
return dl ;
}
} ) ,
2020-01-19 15:08:47 +00:00
addIPOption : function ( s , tab , name , label , description , family , hosts , multiple ) {
2021-02-19 10:29:14 +00:00
var o = s . taboption ( tab , multiple ? this . CBIDynamicMultiValueList : form . Value , name , label , description ) ;
2020-01-19 15:08:47 +00:00
o . modalonly = true ;
2021-03-01 14:18:25 +00:00
o . datatype = 'list(neg(ipmask("true")))' ;
2020-01-19 15:08:47 +00:00
o . placeholder = multiple ? _ ( '-- add IP --' ) : _ ( 'any' ) ;
if ( family != null ) {
var choices = this . transformHostHints ( family , hosts ) ;
for ( var i = 0 ; i < choices [ 0 ] . length ; i ++ )
o . value ( choices [ 0 ] [ i ] , choices [ 1 ] [ choices [ 0 ] [ i ] ] ) ;
}
/* force combobox rendering */
o . transformChoices = function ( ) {
return this . super ( 'transformChoices' , [ ] ) || { } ;
} ;
return o ;
} ,
addLocalIPOption : function ( s , tab , name , label , description , devices ) {
var o = s . taboption ( tab , form . Value , name , label , description ) ;
o . modalonly = true ;
o . datatype = 'ip4addr("nomask")' ;
o . placeholder = _ ( 'any' ) ;
L . sortedKeys ( devices , 'name' ) . forEach ( function ( dev ) {
var ip4addrs = devices [ dev ] . ipaddrs ;
if ( ! L . isObject ( devices [ dev ] . flags ) || ! Array . isArray ( ip4addrs ) || devices [ dev ] . flags . loopback )
return ;
for ( var i = 0 ; i < ip4addrs . length ; i ++ ) {
if ( ! L . isObject ( ip4addrs [ i ] ) || ! ip4addrs [ i ] . address )
continue ;
o . value ( ip4addrs [ i ] . address , E ( [ ] , [
ip4addrs [ i ] . address , ' (' , E ( 'strong' , { } , [ dev ] ) , ')'
] ) ) ;
}
} ) ;
return o ;
} ,
addMACOption : function ( s , tab , name , label , description , hosts ) {
2021-02-19 10:29:14 +00:00
var o = s . taboption ( tab , this . CBIDynamicMultiValueList , name , label , description ) ;
2020-01-19 15:08:47 +00:00
o . modalonly = true ;
o . datatype = 'list(macaddr)' ;
o . placeholder = _ ( '-- add MAC --' ) ;
L . sortedKeys ( hosts ) . forEach ( function ( mac ) {
o . value ( mac , E ( [ ] , [ mac , ' (' , E ( 'strong' , { } , [
hosts [ mac ] . name || hosts [ mac ] . ipv4 || hosts [ mac ] . ipv6 || '?'
] ) , ')' ] ) ) ;
} ) ;
return o ;
} ,
CBIProtocolSelect : form . MultiValue . extend ( {
_ _name _ _ : 'CBI.ProtocolSelect' ,
addChoice : function ( value , label ) {
if ( ! Array . isArray ( this . keylist ) || this . keylist . indexOf ( value ) == - 1 )
this . value ( value , label ) ;
} ,
load : function ( section _id ) {
var cfgvalue = L . toArray ( this . super ( 'load' , [ section _id ] ) || this . default ) . sort ( ) ;
[ 'all' , 'tcp' , 'udp' , 'icmp' ] . concat ( cfgvalue ) . forEach ( L . bind ( function ( value ) {
switch ( value ) {
case 'all' :
case 'any' :
case '*' :
this . addChoice ( 'all' , _ ( 'Any' ) ) ;
break ;
case 'tcpudp' :
this . addChoice ( 'tcp' , 'TCP' ) ;
this . addChoice ( 'udp' , 'UDP' ) ;
break ;
default :
var m = value . match ( /^(0x[0-9a-f]{1,2}|[0-9]{1,3})$/ ) ,
p = lookupProto ( m ? + m [ 1 ] : value ) ;
this . addChoice ( p [ 2 ] , p [ 1 ] ) ;
break ;
}
} , this ) ) ;
2020-12-11 12:22:38 +00:00
if ( cfgvalue == '*' || cfgvalue == 'any' || cfgvalue == 'all' )
cfgvalue = 'all' ;
2020-01-19 15:08:47 +00:00
return cfgvalue ;
} ,
renderWidget : function ( section _id , option _index , cfgvalue ) {
var value = ( cfgvalue != null ) ? cfgvalue : this . default ,
choices = this . transformChoices ( ) ;
var widget = new ui . Dropdown ( L . toArray ( value ) , choices , {
id : this . cbid ( section _id ) ,
sort : this . keylist ,
multiple : true ,
optional : false ,
display _items : 10 ,
dropdown _items : - 1 ,
create : true ,
2020-04-13 15:36:16 +00:00
disabled : ( this . readonly != null ) ? this . readonly : this . map . readonly ,
2020-01-19 15:08:47 +00:00
validate : function ( value ) {
var v = L . toArray ( value ) ;
for ( var i = 0 ; i < v . length ; i ++ ) {
if ( v [ i ] == 'all' )
continue ;
var m = v [ i ] . match ( /^(0x[0-9a-f]{1,2}|[0-9]{1,3})$/ ) ;
if ( m ? ( + m [ 1 ] > 255 ) : ( lookupProto ( v [ i ] ) [ 0 ] == - 1 ) )
return _ ( 'Unrecognized protocol' ) ;
}
return true ;
}
} ) ;
widget . createChoiceElement = function ( sb , value ) {
var m = value . match ( /^(0x[0-9a-f]{1,2}|[0-9]{1,3})$/ ) ,
p = lookupProto ( lookupProto ( m ? + m [ 1 ] : value ) [ 0 ] ) ;
return ui . Dropdown . prototype . createChoiceElement . call ( this , sb , p [ 2 ] , p [ 1 ] ) ;
} ;
widget . createItems = function ( sb , value ) {
var values = L . toArray ( value ) . map ( function ( value ) {
var m = value . match ( /^(0x[0-9a-f]{1,2}|[0-9]{1,3})$/ ) ,
p = lookupProto ( m ? + m [ 1 ] : value ) ;
return ( p [ 0 ] > - 1 ) ? p [ 2 ] : value ;
} ) ;
return ui . Dropdown . prototype . createItems . call ( this , sb , values . join ( ' ' ) ) ;
} ;
widget . toggleItem = function ( sb , li ) {
var value = li . getAttribute ( 'data-value' ) ,
toggleFn = ui . Dropdown . prototype . toggleItem ;
toggleFn . call ( this , sb , li ) ;
if ( value == 'all' ) {
var items = li . parentNode . querySelectorAll ( 'li[data-value]' ) ;
for ( var j = 0 ; j < items . length ; j ++ )
if ( items [ j ] !== li )
toggleFn . call ( this , sb , items [ j ] , false ) ;
}
else {
toggleFn . call ( this , sb , li . parentNode . querySelector ( 'li[data-value="all"]' ) , false ) ;
}
} ;
return widget . render ( ) ;
}
2020-01-19 18:37:28 +00:00
} ) ,
checkLegacySNAT : function ( ) {
var redirects = uci . sections ( 'firewall' , 'redirect' ) ;
for ( var i = 0 ; i < redirects . length ; i ++ )
if ( ( redirects [ i ] [ 'target' ] || '' ) . toLowerCase ( ) == 'snat' )
return true ;
return false ;
} ,
handleMigration : function ( ev ) {
var redirects = uci . sections ( 'firewall' , 'redirect' ) ,
tasks = [ ] ;
var mapping = {
dest : 'src' ,
reflection : null ,
reflection _src : null ,
src _dip : 'snat_ip' ,
src _dport : 'snat_port' ,
src : null
} ;
for ( var i = 0 ; i < redirects . length ; i ++ ) {
if ( ( redirects [ i ] [ 'target' ] || '' ) . toLowerCase ( ) != 'snat' )
continue ;
var sid = uci . add ( 'firewall' , 'nat' ) ;
for ( var opt in redirects [ i ] ) {
if ( opt . charAt ( 0 ) == '.' )
continue ;
if ( mapping [ opt ] === null )
continue ;
uci . set ( 'firewall' , sid , mapping [ opt ] || opt , redirects [ i ] [ opt ] ) ;
}
uci . remove ( 'firewall' , redirects [ i ] [ '.name' ] ) ;
}
return uci . save ( )
. then ( L . bind ( ui . changes . init , ui . changes ) )
. then ( L . bind ( ui . changes . apply , ui . changes ) ) ;
} ,
renderMigration : function ( ) {
ui . showModal ( _ ( 'Firewall configuration migration' ) , [
E ( 'p' , _ ( 'The existing firewall configuration needs to be changed for LuCI to function properly.' ) ) ,
E ( 'p' , _ ( 'Upon pressing "Continue", "redirect" sections with target "SNAT" will be converted to "nat" sections and the firewall will be restarted to apply the updated configuration.' ) ) ,
E ( 'div' , { 'class' : 'right' } ,
E ( 'button' , {
'class' : 'btn cbi-button-action important' ,
'click' : ui . createHandlerFn ( this , 'handleMigration' )
} , _ ( 'Continue' ) ) )
] ) ;
} ,
2019-06-13 13:23:26 +00:00
} ) ;