2020-03-27 09:27:18 +00:00
'use strict' ;
2020-04-09 12:39:09 +00:00
'require view' ;
'require dom' ;
'require poll' ;
2020-03-27 09:27:18 +00:00
'require fs' ;
'require ui' ;
'require uci' ;
'require form' ;
'require network' ;
'require firewall' ;
'require tools.widgets as widgets' ;
2020-05-20 08:46:25 +00:00
var isReadonlyView = ! L . hasViewPermission ( ) || null ;
2020-03-27 09:27:18 +00:00
function count _changes ( section _id ) {
var changes = ui . changes . changes , n = 0 ;
if ( ! L . isObject ( changes ) )
return n ;
if ( Array . isArray ( changes . network ) )
for ( var i = 0 ; i < changes . network . length ; i ++ )
n += ( changes . network [ i ] [ 1 ] == section _id ) ;
if ( Array . isArray ( changes . dhcp ) )
for ( var i = 0 ; i < changes . dhcp . length ; i ++ )
n += ( changes . dhcp [ i ] [ 1 ] == section _id ) ;
return n ;
}
function render _iface ( dev , alias ) {
var type = dev ? dev . getType ( ) : 'ethernet' ,
up = dev ? dev . isUp ( ) : false ;
return E ( 'span' , { class : 'cbi-tooltip-container' } , [
E ( 'img' , { 'class' : 'middle' , 'src' : L . resource ( 'icons/%s%s.png' ) . format (
alias ? 'alias' : type ,
up ? '' : '_disabled' ) } ) ,
E ( 'span' , { 'class' : 'cbi-tooltip ifacebadge large' } , [
E ( 'img' , { 'src' : L . resource ( 'icons/%s%s.png' ) . format (
type , up ? '' : '_disabled' ) } ) ,
L . itemlist ( E ( 'span' , { 'class' : 'left' } ) , [
_ ( 'Type' ) , dev ? dev . getTypeI18n ( ) : null ,
_ ( 'Device' ) , dev ? dev . getName ( ) : _ ( 'Not present' ) ,
_ ( 'Connected' ) , up ? _ ( 'yes' ) : _ ( 'no' ) ,
_ ( 'MAC' ) , dev ? dev . getMAC ( ) : null ,
_ ( 'RX' ) , dev ? '%.2mB (%d %s)' . format ( dev . getRXBytes ( ) , dev . getRXPackets ( ) , _ ( 'Pkts.' ) ) : null ,
_ ( 'TX' ) , dev ? '%.2mB (%d %s)' . format ( dev . getTXBytes ( ) , dev . getTXPackets ( ) , _ ( 'Pkts.' ) ) : null
] )
] )
] ) ;
}
function render _status ( node , ifc , with _device ) {
var desc = null , c = [ ] ;
if ( ifc . isDynamic ( ) )
desc = _ ( 'Virtual dynamic interface' ) ;
else if ( ifc . isAlias ( ) )
desc = _ ( 'Alias Interface' ) ;
else if ( ! uci . get ( 'network' , ifc . getName ( ) ) )
return L . itemlist ( node , [
null , E ( 'em' , _ ( 'Interface is marked for deletion' ) )
] ) ;
var i18n = ifc . getI18n ( ) ;
if ( i18n )
desc = desc ? '%s (%s)' . format ( desc , i18n ) : i18n ;
var changecount = with _device ? 0 : count _changes ( ifc . getName ( ) ) ,
ipaddrs = changecount ? [ ] : ifc . getIPAddrs ( ) ,
ip6addrs = changecount ? [ ] : ifc . getIP6Addrs ( ) ,
errors = ifc . getErrors ( ) ,
maindev = ifc . getL3Device ( ) || ifc . getDevice ( ) ,
macaddr = maindev ? maindev . getMAC ( ) : null ;
return L . itemlist ( node , [
2020-07-17 13:48:29 +00:00
_ ( 'Label' ) , ifc . get ( 'label' ) ,
2020-03-27 09:27:18 +00:00
_ ( 'Protocol' ) , with _device ? null : ( desc || '?' ) ,
_ ( 'Device' ) , with _device ? ( maindev ? maindev . getShortName ( ) : E ( 'em' , _ ( 'Not present' ) ) ) : null ,
_ ( 'Uptime' ) , ( ! changecount && ifc . isUp ( ) ) ? '%t' . format ( ifc . getUptime ( ) ) : null ,
_ ( 'MAC' ) , ( ! changecount && ! ifc . isDynamic ( ) && ! ifc . isAlias ( ) && macaddr ) ? macaddr : null ,
_ ( 'RX' ) , ( ! changecount && ! ifc . isDynamic ( ) && ! ifc . isAlias ( ) && maindev ) ? '%.2mB (%d %s)' . format ( maindev . getRXBytes ( ) , maindev . getRXPackets ( ) , _ ( 'Pkts.' ) ) : null ,
_ ( 'TX' ) , ( ! changecount && ! ifc . isDynamic ( ) && ! ifc . isAlias ( ) && maindev ) ? '%.2mB (%d %s)' . format ( maindev . getTXBytes ( ) , maindev . getTXPackets ( ) , _ ( 'Pkts.' ) ) : null ,
_ ( 'IPv4' ) , ipaddrs [ 0 ] ,
_ ( 'IPv4' ) , ipaddrs [ 1 ] ,
_ ( 'IPv4' ) , ipaddrs [ 2 ] ,
_ ( 'IPv4' ) , ipaddrs [ 3 ] ,
_ ( 'IPv4' ) , ipaddrs [ 4 ] ,
_ ( 'IPv6' ) , ip6addrs [ 0 ] ,
_ ( 'IPv6' ) , ip6addrs [ 1 ] ,
_ ( 'IPv6' ) , ip6addrs [ 2 ] ,
_ ( 'IPv6' ) , ip6addrs [ 3 ] ,
_ ( 'IPv6' ) , ip6addrs [ 4 ] ,
_ ( 'IPv6' ) , ip6addrs [ 5 ] ,
_ ( 'IPv6' ) , ip6addrs [ 6 ] ,
_ ( 'IPv6' ) , ip6addrs [ 7 ] ,
_ ( 'IPv6' ) , ip6addrs [ 8 ] ,
_ ( 'IPv6' ) , ip6addrs [ 9 ] ,
_ ( 'IPv6-PD' ) , changecount ? null : ifc . getIP6Prefix ( ) ,
_ ( 'Information' ) , with _device ? null : ( ifc . get ( 'auto' ) != '0' ? null : _ ( 'Not started on boot' ) ) ,
_ ( 'Error' ) , errors ? errors [ 0 ] : null ,
_ ( 'Error' ) , errors ? errors [ 1 ] : null ,
_ ( 'Error' ) , errors ? errors [ 2 ] : null ,
_ ( 'Error' ) , errors ? errors [ 3 ] : null ,
_ ( 'Error' ) , errors ? errors [ 4 ] : null ,
null , changecount ? E ( 'a' , {
href : '#' ,
click : L . bind ( ui . changes . displayChanges , ui . changes )
} , _ ( 'Interface has %d pending changes' ) . format ( changecount ) ) : null
] ) ;
}
function render _modal _status ( node , ifc ) {
var dev = ifc ? ( ifc . getDevice ( ) || ifc . getL3Device ( ) || ifc . getL3Device ( ) ) : null ;
2020-04-09 12:39:09 +00:00
dom . content ( node , [
2020-03-27 09:27:18 +00:00
E ( 'img' , {
'src' : L . resource ( 'icons/%s%s.png' ) . format ( dev ? dev . getType ( ) : 'ethernet' , ( dev && dev . isUp ( ) ) ? '' : '_disabled' ) ,
'title' : dev ? dev . getTypeI18n ( ) : _ ( 'Not present' )
} ) ,
ifc ? render _status ( E ( 'span' ) , ifc , true ) : E ( 'em' , _ ( 'Interface not present or not connected yet.' ) )
] ) ;
return node ;
}
function render _ifacebox _status ( node , ifc ) {
var dev = ifc . getL3Device ( ) || ifc . getDevice ( ) ,
subdevs = ifc . getDevices ( ) ,
c = [ render _iface ( dev , ifc . isAlias ( ) ) ] ;
if ( subdevs && subdevs . length ) {
var sifs = [ ' (' ] ;
for ( var j = 0 ; j < subdevs . length ; j ++ )
sifs . push ( render _iface ( subdevs [ j ] ) ) ;
sifs . push ( ')' ) ;
c . push ( E ( 'span' , { } , sifs ) ) ;
}
c . push ( E ( 'br' ) ) ;
c . push ( E ( 'small' , { } , ifc . isAlias ( ) ? _ ( 'Alias of "%s"' ) . format ( ifc . isAlias ( ) )
: ( dev ? dev . getName ( ) : E ( 'em' , _ ( 'Not present' ) ) ) ) ) ;
2020-04-09 12:39:09 +00:00
dom . content ( node , c ) ;
2020-03-27 09:27:18 +00:00
return firewall . getZoneByNetwork ( ifc . getName ( ) ) . then ( L . bind ( function ( zone ) {
this . style . backgroundColor = zone ? zone . getColor ( ) : '#EEEEEE' ;
this . title = zone ? _ ( 'Part of zone %q' ) . format ( zone . getName ( ) ) : _ ( 'No zone assigned' ) ;
} , node . previousElementSibling ) ) ;
}
function iface _updown ( up , id , ev , force ) {
var row = document . querySelector ( '.cbi-section-table-row[data-sid="%s"]' . format ( id ) ) ,
dsc = row . querySelector ( '[data-name="_ifacestat"] > div' ) ,
btns = row . querySelectorAll ( '.cbi-section-actions .reconnect, .cbi-section-actions .down' ) ;
btns [ + ! up ] . blur ( ) ;
btns [ + ! up ] . classList . add ( 'spinning' ) ;
btns [ 0 ] . disabled = true ;
btns [ 1 ] . disabled = true ;
if ( ! up ) {
L . resolveDefault ( fs . exec _direct ( '/usr/libexec/luci-peeraddr' ) ) . then ( function ( res ) {
var info = null ; try { info = JSON . parse ( res ) ; } catch ( e ) { }
if ( L . isObject ( info ) &&
Array . isArray ( info . inbound _interfaces ) &&
info . inbound _interfaces . filter ( function ( i ) { return i == id } ) [ 0 ] ) {
ui . showModal ( _ ( 'Confirm disconnect' ) , [
E ( 'p' , _ ( 'You appear to be currently connected to the device via the "%h" interface. Do you really want to shut down the interface?' ) . format ( id ) ) ,
E ( 'div' , { 'class' : 'right' } , [
E ( 'button' , {
'class' : 'cbi-button cbi-button-neutral' ,
'click' : function ( ev ) {
btns [ 1 ] . classList . remove ( 'spinning' ) ;
btns [ 1 ] . disabled = false ;
btns [ 0 ] . disabled = false ;
ui . hideModal ( ) ;
}
} , _ ( 'Cancel' ) ) ,
' ' ,
E ( 'button' , {
'class' : 'cbi-button cbi-button-negative important' ,
'click' : function ( ev ) {
dsc . setAttribute ( 'disconnect' , '' ) ;
2020-04-09 12:39:09 +00:00
dom . content ( dsc , E ( 'em' , _ ( 'Interface is shutting down...' ) ) ) ;
2020-03-27 09:27:18 +00:00
ui . hideModal ( ) ;
}
} , _ ( 'Disconnect' ) )
] )
] ) ;
}
else {
dsc . setAttribute ( 'disconnect' , '' ) ;
2020-04-09 12:39:09 +00:00
dom . content ( dsc , E ( 'em' , _ ( 'Interface is shutting down...' ) ) ) ;
2020-03-27 09:27:18 +00:00
}
} ) ;
}
else {
dsc . setAttribute ( up ? 'reconnect' : 'disconnect' , force ? 'force' : '' ) ;
2020-04-09 12:39:09 +00:00
dom . content ( dsc , E ( 'em' , up ? _ ( 'Interface is reconnecting...' ) : _ ( 'Interface is shutting down...' ) ) ) ;
2020-03-27 09:27:18 +00:00
}
}
function get _netmask ( s , use _cfgvalue ) {
var readfn = use _cfgvalue ? 'cfgvalue' : 'formvalue' ,
addropt = s . children . filter ( function ( o ) { return o . option == 'ipaddr' } ) [ 0 ] ,
addrvals = addropt ? L . toArray ( addropt [ readfn ] ( s . section ) ) : [ ] ,
maskopt = s . children . filter ( function ( o ) { return o . option == 'netmask' } ) [ 0 ] ,
maskval = maskopt ? maskopt [ readfn ] ( s . section ) : null ,
firstsubnet = maskval ? addrvals [ 0 ] + '/' + maskval : addrvals . filter ( function ( a ) { return a . indexOf ( '/' ) > 0 } ) [ 0 ] ;
if ( firstsubnet == null )
return null ;
var mask = firstsubnet . split ( '/' ) [ 1 ] ;
if ( ! isNaN ( mask ) )
mask = network . prefixToMask ( + mask ) ;
return mask ;
}
2020-04-09 12:39:09 +00:00
return view . extend ( {
2020-03-27 09:27:18 +00:00
poll _status : function ( map , networks ) {
var resolveZone = null ;
for ( var i = 0 ; i < networks . length ; i ++ ) {
var ifc = networks [ i ] ,
row = map . querySelector ( '.cbi-section-table-row[data-sid="%s"]' . format ( ifc . getName ( ) ) ) ;
if ( row == null )
continue ;
var dsc = row . querySelector ( '[data-name="_ifacestat"] > div' ) ,
box = row . querySelector ( '[data-name="_ifacebox"] .ifacebox-body' ) ,
btn1 = row . querySelector ( '.cbi-section-actions .reconnect' ) ,
btn2 = row . querySelector ( '.cbi-section-actions .down' ) ,
stat = document . querySelector ( '[id="%s-ifc-status"]' . format ( ifc . getName ( ) ) ) ,
resolveZone = render _ifacebox _status ( box , ifc ) ,
disabled = ifc ? ! ifc . isUp ( ) : true ,
dynamic = ifc ? ifc . isDynamic ( ) : false ;
if ( dsc . hasAttribute ( 'reconnect' ) ) {
2020-04-09 12:39:09 +00:00
dom . content ( dsc , E ( 'em' , _ ( 'Interface is starting...' ) ) ) ;
2020-03-27 09:27:18 +00:00
}
else if ( dsc . hasAttribute ( 'disconnect' ) ) {
2020-04-09 12:39:09 +00:00
dom . content ( dsc , E ( 'em' , _ ( 'Interface is stopping...' ) ) ) ;
2020-03-27 09:27:18 +00:00
}
else if ( ifc . getProtocol ( ) || uci . get ( 'network' , ifc . getName ( ) ) == null ) {
render _status ( dsc , ifc , false ) ;
}
else if ( ! ifc . getProtocol ( ) ) {
var e = map . querySelector ( '[id="cbi-network-%s"] .cbi-button-edit' . format ( ifc . getName ( ) ) ) ;
if ( e ) e . disabled = true ;
var link = L . url ( 'admin/system/opkg' ) + '?query=luci-proto' ;
2020-04-09 12:39:09 +00:00
dom . content ( dsc , [
2020-03-27 09:27:18 +00:00
E ( 'em' , _ ( 'Unsupported protocol type.' ) ) , E ( 'br' ) ,
E ( 'a' , { href : link } , _ ( 'Install protocol extensions...' ) )
] ) ;
}
else {
2020-04-09 12:39:09 +00:00
dom . content ( dsc , E ( 'em' , _ ( 'Interface not present or not connected yet.' ) ) ) ;
2020-03-27 09:27:18 +00:00
}
if ( stat ) {
var dev = ifc . getDevice ( ) ;
2020-04-09 12:39:09 +00:00
dom . content ( stat , [
2020-03-27 09:27:18 +00:00
E ( 'img' , {
'src' : L . resource ( 'icons/%s%s.png' ) . format ( dev ? dev . getType ( ) : 'ethernet' , ( dev && dev . isUp ( ) ) ? '' : '_disabled' ) ,
'title' : dev ? dev . getTypeI18n ( ) : _ ( 'Not present' )
} ) ,
render _status ( E ( 'span' ) , ifc , true )
] ) ;
}
2020-05-20 08:46:25 +00:00
btn1 . disabled = isReadonlyView || btn1 . classList . contains ( 'spinning' ) || btn2 . classList . contains ( 'spinning' ) || dynamic ;
btn2 . disabled = isReadonlyView || btn1 . classList . contains ( 'spinning' ) || btn2 . classList . contains ( 'spinning' ) || dynamic || disabled ;
2020-03-27 09:27:18 +00:00
}
return Promise . all ( [ resolveZone , network . flushCache ( ) ] ) ;
} ,
load : function ( ) {
return Promise . all ( [
network . getDSLModemType ( ) ,
uci . changes ( )
] ) ;
} ,
render : function ( data ) {
var dslModemType = data [ 0 ] ,
m , s , o ;
m = new form . Map ( 'network' ) ;
m . tabbed = true ;
m . chain ( 'dhcp' ) ;
s = m . section ( form . GridSection , 'interface' , _ ( 'Interfaces' ) ) ;
s . anonymous = true ;
s . addremove = true ;
s . addbtntitle = _ ( 'Add new interface...' ) ;
s . load = function ( ) {
return Promise . all ( [
network . getNetworks ( ) ,
firewall . getZones ( )
] ) . then ( L . bind ( function ( data ) {
this . networks = data [ 0 ] ;
this . zones = data [ 1 ] ;
} , this ) ) ;
} ;
s . tab ( 'general' , _ ( 'General Settings' ) ) ;
s . tab ( 'advanced' , _ ( 'Advanced Settings' ) ) ;
s . tab ( 'physical' , _ ( 'Physical Settings' ) ) ;
s . tab ( 'firewall' , _ ( 'Firewall Settings' ) ) ;
s . tab ( 'dhcp' , _ ( 'DHCP Server' ) ) ;
s . cfgsections = function ( ) {
return this . networks . map ( function ( n ) { return n . getName ( ) } )
. filter ( function ( n ) { return n != 'loopback' } ) ;
} ;
s . modaltitle = function ( section _id ) {
return _ ( 'Interfaces' ) + ' » ' + section _id . toUpperCase ( ) ;
} ;
s . renderRowActions = function ( section _id ) {
var tdEl = this . super ( 'renderRowActions' , [ section _id , _ ( 'Edit' ) ] ) ,
net = this . networks . filter ( function ( n ) { return n . getName ( ) == section _id } ) [ 0 ] ,
disabled = net ? ! net . isUp ( ) : true ,
dynamic = net ? net . isDynamic ( ) : false ;
2020-04-09 12:39:09 +00:00
dom . content ( tdEl . lastChild , [
2020-03-27 09:27:18 +00:00
E ( 'button' , {
'class' : 'cbi-button cbi-button-neutral reconnect' ,
'click' : iface _updown . bind ( this , true , section _id ) ,
'title' : _ ( 'Reconnect this interface' ) ,
'disabled' : dynamic ? 'disabled' : null
} , _ ( 'Restart' ) ) ,
E ( 'button' , {
'class' : 'cbi-button cbi-button-neutral down' ,
'click' : iface _updown . bind ( this , false , section _id ) ,
'title' : _ ( 'Shutdown this interface' ) ,
'disabled' : ( dynamic || disabled ) ? 'disabled' : null
} , _ ( 'Stop' ) ) ,
tdEl . lastChild . firstChild ,
tdEl . lastChild . lastChild
] ) ;
if ( ! dynamic && net && ! uci . get ( 'network' , net . getName ( ) ) ) {
tdEl . lastChild . childNodes [ 0 ] . disabled = true ;
tdEl . lastChild . childNodes [ 2 ] . disabled = true ;
tdEl . lastChild . childNodes [ 3 ] . disabled = true ;
}
return tdEl ;
} ;
s . addModalOptions = function ( s ) {
var protoval = uci . get ( 'network' , s . section , 'proto' ) ,
protoclass = protoval ? network . getProtocol ( protoval ) : null ,
2020-06-09 15:11:20 +00:00
o , ifname _single , ifname _multi , ifname _master , proto _select , proto _switch , type , stp , igmp , ss , so ;
2020-03-27 09:27:18 +00:00
if ( ! protoval )
return ;
return network . getNetwork ( s . section ) . then ( L . bind ( function ( ifc ) {
var protocols = network . getProtocols ( ) ;
protocols . sort ( function ( a , b ) {
return a . getProtocol ( ) > b . getProtocol ( ) ;
} ) ;
o = s . taboption ( 'general' , form . DummyValue , '_ifacestat_modal' , _ ( 'Status' ) ) ;
o . modalonly = true ;
o . cfgvalue = L . bind ( function ( section _id ) {
var net = this . networks . filter ( function ( n ) { return n . getName ( ) == section _id } ) [ 0 ] ;
return render _modal _status ( E ( 'div' , {
'id' : '%s-ifc-status' . format ( section _id ) ,
'class' : 'ifacebadge large'
} ) , net ) ;
} , this ) ;
o . write = function ( ) { } ;
2020-06-26 12:59:47 +00:00
o = s . taboption ( 'general' , form . Value , 'label' , _ ( 'Label' ) ) ;
o . modalonly = true ;
o . optional = true ;
2020-03-27 09:27:18 +00:00
proto _select = s . taboption ( 'general' , form . ListValue , 'proto' , _ ( 'Protocol' ) ) ;
proto _select . modalonly = true ;
proto _switch = s . taboption ( 'general' , form . Button , '_switch_proto' ) ;
proto _switch . modalonly = true ;
proto _switch . title = _ ( 'Really switch protocol?' ) ;
proto _switch . inputtitle = _ ( 'Switch protocol' ) ;
proto _switch . inputstyle = 'apply' ;
proto _switch . onclick = L . bind ( function ( ev ) {
s . map . save ( )
. then ( L . bind ( m . load , m ) )
. then ( L . bind ( m . render , m ) )
. then ( L . bind ( this . renderMoreOptionsModal , this , s . section ) ) ;
} , this ) ;
o = s . taboption ( 'general' , form . Flag , 'auto' , _ ( 'Bring up on boot' ) ) ;
o . modalonly = true ;
o . default = o . enabled ;
2020-06-09 15:11:20 +00:00
type = s . taboption ( 'physical' , form . ListValue , 'type' , _ ( 'Type' ) ) ;
type . value ( '' , _ ( 'Normal' ) ) ;
type . value ( 'bridge' , _ ( 'Bridge' ) ) ;
type . value ( 'macvlan' , _ ( 'MacVLAN' ) ) ;
2020-03-27 09:27:18 +00:00
type . write = type . remove = function ( section _id , value ) {
var protocol = network . getProtocol ( proto _select . formvalue ( section _id ) ) ,
2020-06-09 15:11:20 +00:00
ifnameopt = this . section . children . filter ( function ( o ) {
if ( value == 'bridge' )
return o . option == 'ifname_multi' ;
else if ( value == 'macvlan' )
return o . option == 'ifname_master' ;
else
return o . option == 'ifname_single' ;
} ) [ 0 ] ;
2020-03-27 09:27:18 +00:00
if ( ! protocol . isVirtual ( ) && ! this . isActive ( section _id ) )
return ;
var old _ifnames = [ ] ,
devs = ifc . getDevices ( ) || L . toArray ( ifc . getDevice ( ) ) ;
for ( var i = 0 ; i < devs . length ; i ++ )
old _ifnames . push ( devs [ i ] . getName ( ) ) ;
var new _ifnames = L . toArray ( ifnameopt . formvalue ( section _id ) ) ;
if ( ! value )
new _ifnames . length = Math . max ( new _ifnames . length , 1 ) ;
old _ifnames . sort ( ) ;
new _ifnames . sort ( ) ;
for ( var i = 0 ; i < Math . max ( old _ifnames . length , new _ifnames . length ) ; i ++ ) {
if ( old _ifnames [ i ] != new _ifnames [ i ] ) {
// backup_ifnames()
for ( var j = 0 ; j < old _ifnames . length ; j ++ )
ifc . deleteDevice ( old _ifnames [ j ] ) ;
for ( var j = 0 ; j < new _ifnames . length ; j ++ )
ifc . addDevice ( new _ifnames [ j ] ) ;
break ;
}
}
if ( value )
2020-06-09 15:11:20 +00:00
uci . set ( 'network' , section _id , 'type' , value ) ;
2020-03-27 09:27:18 +00:00
else
uci . unset ( 'network' , section _id , 'type' ) ;
} ;
stp = s . taboption ( 'physical' , form . Flag , 'stp' , _ ( 'Enable <abbr title="Spanning Tree Protocol">STP</abbr>' ) , _ ( 'Enables the Spanning Tree Protocol on this bridge' ) ) ;
igmp = s . taboption ( 'physical' , form . Flag , 'igmp_snooping' , _ ( 'Enable <abbr title="Internet Group Management Protocol">IGMP</abbr> snooping' ) , _ ( 'Enables IGMP snooping on this bridge' ) ) ;
2020-06-09 15:11:20 +00:00
ifname _master = s . taboption ( 'physical' , widgets . DeviceSelect , 'ifname_master' , _ ( 'Base interface' ) ) ;
ifname _master . nobridges = true ;
ifname _master . noaliases = true ;
ifname _master . optional = false ;
ifname _master . modalonly = true ;
ifname _master . network = ifc . getName ( ) ;
//ifname_master.write = ifname_master.remove = function() {};
ifname _master . ucioption = 'masterintf' ;
//ifname_master.cfgvalue = function(section_id) {
// return uci.get('network', section_id, 'masterintf');
//};
//ifname_master.write = function(section_id, value) {
// uci.set('network', section_id, 'masterintf', value);
//};
2020-03-27 09:27:18 +00:00
ifname _single = s . taboption ( 'physical' , widgets . DeviceSelect , 'ifname_single' , _ ( 'Interface' ) ) ;
ifname _single . nobridges = ifc . isBridge ( ) ;
ifname _single . noaliases = false ;
ifname _single . optional = false ;
ifname _single . network = ifc . getName ( ) ;
ifname _single . write = ifname _single . remove = function ( ) { } ;
ifname _multi = s . taboption ( 'physical' , widgets . DeviceSelect , 'ifname_multi' , _ ( 'Interface' ) ) ;
ifname _multi . nobridges = ifc . isBridge ( ) ;
ifname _multi . noaliases = true ;
ifname _multi . multiple = true ;
ifname _multi . optional = true ;
ifname _multi . network = ifc . getName ( ) ;
ifname _multi . display _size = 6 ;
ifname _multi . write = ifname _multi . remove = function ( ) { } ;
ifname _single . cfgvalue = ifname _multi . cfgvalue = function ( section _id ) {
var devs = ifc . getDevices ( ) || L . toArray ( ifc . getDevice ( ) ) ,
ifnames = [ ] ;
for ( var i = 0 ; i < devs . length ; i ++ )
ifnames . push ( devs [ i ] . getName ( ) ) ;
return ifnames ;
} ;
if ( L . hasSystemFeature ( 'firewall' ) ) {
2020-04-09 12:39:09 +00:00
o = s . taboption ( 'firewall' , widgets . ZoneSelect , '_zone' , _ ( 'Create / Assign firewall-zone' ) , _ ( 'Choose the firewall zone you want to assign to this interface. Select <em>unspecified</em> to remove the interface from the associated zone or fill out the <em>custom</em> field to define a new zone and attach the interface to it.' ) ) ;
2020-03-27 09:27:18 +00:00
o . network = ifc . getName ( ) ;
o . optional = true ;
o . cfgvalue = function ( section _id ) {
return firewall . getZoneByNetwork ( ifc . getName ( ) ) . then ( function ( zone ) {
return ( zone != null ? zone . getName ( ) : null ) ;
} ) ;
} ;
o . write = o . remove = function ( section _id , value ) {
return Promise . all ( [
firewall . getZoneByNetwork ( ifc . getName ( ) ) ,
( value != null ) ? firewall . getZone ( value ) : null
] ) . then ( function ( data ) {
var old _zone = data [ 0 ] ,
new _zone = data [ 1 ] ;
if ( old _zone == null && new _zone == null && ( value == null || value == '' ) )
return ;
if ( old _zone != null && new _zone != null && old _zone . getName ( ) == new _zone . getName ( ) )
return ;
if ( old _zone != null )
old _zone . deleteNetwork ( ifc . getName ( ) ) ;
if ( new _zone != null )
new _zone . addNetwork ( ifc . getName ( ) ) ;
else if ( value != null )
return firewall . addZone ( value ) . then ( function ( new _zone ) {
new _zone . addNetwork ( ifc . getName ( ) ) ;
} ) ;
} ) ;
} ;
}
for ( var i = 0 ; i < protocols . length ; i ++ ) {
proto _select . value ( protocols [ i ] . getProtocol ( ) , protocols [ i ] . getI18n ( ) ) ;
if ( protocols [ i ] . getProtocol ( ) != uci . get ( 'network' , s . section , 'proto' ) )
proto _switch . depends ( 'proto' , protocols [ i ] . getProtocol ( ) ) ;
if ( ! protocols [ i ] . isVirtual ( ) ) {
type . depends ( 'proto' , protocols [ i ] . getProtocol ( ) ) ;
stp . depends ( { type : 'bridge' , proto : protocols [ i ] . getProtocol ( ) } ) ;
igmp . depends ( { type : 'bridge' , proto : protocols [ i ] . getProtocol ( ) } ) ;
ifname _single . depends ( { type : '' , proto : protocols [ i ] . getProtocol ( ) } ) ;
2020-06-09 15:11:20 +00:00
ifname _master . depends ( { type : 'macvlan' , proto : protocols [ i ] . getProtocol ( ) } ) ;
2020-03-27 09:27:18 +00:00
ifname _multi . depends ( { type : 'bridge' , proto : protocols [ i ] . getProtocol ( ) } ) ;
}
}
2020-06-09 20:34:36 +00:00
o = s . taboption ( 'advanced' , form . ListValue , 'multipath' , _ ( 'Multipath setting' ) , _ ( 'Only one interface must be set as Master.' ) ) ;
2020-06-11 18:03:47 +00:00
o . value ( 'on' , _ ( 'Enabled' ) ) ;
o . value ( 'off' , _ ( 'Disabled' ) ) ;
2020-06-09 20:34:36 +00:00
o . value ( 'master' , _ ( 'Master' ) ) ;
o . value ( 'backup' , _ ( 'Backup' ) ) ;
2020-08-15 06:59:42 +00:00
o . default = 'off' ;
2020-06-09 20:34:36 +00:00
2020-10-19 14:20:53 +00:00
o = s . taboption ( 'advanced' , form . Value , 'addlatency' , _ ( 'Additional latency' ) ) ;
o . datatype = 'uinteger' ;
o . default = '0' ;
2020-03-27 09:27:18 +00:00
if ( L . hasSystemFeature ( 'dnsmasq' ) || L . hasSystemFeature ( 'odhcpd' ) ) {
o = s . taboption ( 'dhcp' , form . SectionValue , '_dhcp' , form . TypedSection , 'dhcp' ) ;
o . depends ( 'proto' , 'static' ) ;
ss = o . subsection ;
ss . uciconfig = 'dhcp' ;
ss . addremove = false ;
ss . anonymous = true ;
ss . tab ( 'general' , _ ( 'General Setup' ) ) ;
ss . tab ( 'advanced' , _ ( 'Advanced Settings' ) ) ;
ss . tab ( 'ipv6' , _ ( 'IPv6 Settings' ) ) ;
ss . filter = function ( section _id ) {
return ( uci . get ( 'dhcp' , section _id , 'interface' ) == ifc . getName ( ) ) ;
} ;
ss . renderSectionPlaceholder = function ( ) {
return E ( 'div' , { 'class' : 'cbi-section-create' } , [
E ( 'p' , _ ( 'No DHCP Server configured for this interface' ) + '   ' ) ,
E ( 'button' , {
'class' : 'cbi-button cbi-button-add' ,
'title' : _ ( 'Setup DHCP Server' ) ,
'click' : ui . createHandlerFn ( this , function ( section _id , ev ) {
this . map . save ( function ( ) {
uci . add ( 'dhcp' , 'dhcp' , section _id ) ;
uci . set ( 'dhcp' , section _id , 'interface' , section _id ) ;
uci . set ( 'dhcp' , section _id , 'start' , 100 ) ;
uci . set ( 'dhcp' , section _id , 'limit' , 150 ) ;
uci . set ( 'dhcp' , section _id , 'leasetime' , '12h' ) ;
} ) ;
} , ifc . getName ( ) )
} , _ ( 'Setup DHCP Server' ) )
] ) ;
} ;
ss . taboption ( 'general' , form . Flag , 'ignore' , _ ( 'Ignore interface' ) , _ ( 'Disable <abbr title="Dynamic Host Configuration Protocol">DHCP</abbr> for this interface.' ) ) ;
so = ss . taboption ( 'general' , form . Value , 'start' , _ ( 'Start' ) , _ ( 'Lowest leased address as offset from the network address.' ) ) ;
so . optional = true ;
so . datatype = 'or(uinteger,ip4addr("nomask"))' ;
so . default = '100' ;
so = ss . taboption ( 'general' , form . Value , 'limit' , _ ( 'Limit' ) , _ ( 'Maximum number of leased addresses.' ) ) ;
so . optional = true ;
so . datatype = 'uinteger' ;
so . default = '150' ;
so = ss . taboption ( 'general' , form . Value , 'leasetime' , _ ( 'Lease time' ) , _ ( 'Expiry time of leased addresses, minimum is 2 minutes (<code>2m</code>).' ) ) ;
so . optional = true ;
so . default = '12h' ;
so = ss . taboption ( 'advanced' , form . Flag , 'dynamicdhcp' , _ ( 'Dynamic <abbr title="Dynamic Host Configuration Protocol">DHCP</abbr>' ) , _ ( 'Dynamically allocate DHCP addresses for clients. If disabled, only clients having static leases will be served.' ) ) ;
so . default = so . enabled ;
ss . taboption ( 'advanced' , form . Flag , 'force' , _ ( 'Force' ) , _ ( 'Force DHCP on this network even if another server is detected.' ) ) ;
// XXX: is this actually useful?
//ss.taboption('advanced', form.Value, 'name', _('Name'), _('Define a name for this network.'));
so = ss . taboption ( 'advanced' , form . Value , 'netmask' , _ ( '<abbr title="Internet Protocol Version 4">IPv4</abbr>-Netmask' ) , _ ( 'Override the netmask sent to clients. Normally it is calculated from the subnet that is served.' ) ) ;
so . optional = true ;
so . datatype = 'ip4addr' ;
so . render = function ( option _index , section _id , in _table ) {
this . placeholder = get _netmask ( s , true ) ;
return form . Value . prototype . render . apply ( this , [ option _index , section _id , in _table ] ) ;
} ;
so . validate = function ( section _id , value ) {
var node = this . map . findElement ( 'id' , this . cbid ( section _id ) ) ;
if ( node )
node . querySelector ( 'input' ) . setAttribute ( 'placeholder' , get _netmask ( s , false ) ) ;
return form . Value . prototype . validate . apply ( this , [ section _id , value ] ) ;
} ;
ss . taboption ( 'advanced' , form . DynamicList , 'dhcp_option' , _ ( 'DHCP-Options' ) , _ ( 'Define additional DHCP options, for example "<code>6,192.168.2.1,192.168.2.2</code>" which advertises different DNS servers to clients.' ) ) ;
for ( var i = 0 ; i < ss . children . length ; i ++ )
if ( ss . children [ i ] . option != 'ignore' )
ss . children [ i ] . depends ( 'ignore' , '0' ) ;
so = ss . taboption ( 'ipv6' , form . ListValue , 'ra' , _ ( 'Router Advertisement-Service' ) ) ;
so . value ( '' , _ ( 'disabled' ) ) ;
so . value ( 'server' , _ ( 'server mode' ) ) ;
so . value ( 'relay' , _ ( 'relay mode' ) ) ;
so . value ( 'hybrid' , _ ( 'hybrid mode' ) ) ;
so = ss . taboption ( 'ipv6' , form . ListValue , 'dhcpv6' , _ ( 'DHCPv6-Service' ) ) ;
so . value ( '' , _ ( 'disabled' ) ) ;
so . value ( 'server' , _ ( 'server mode' ) ) ;
so . value ( 'relay' , _ ( 'relay mode' ) ) ;
so . value ( 'hybrid' , _ ( 'hybrid mode' ) ) ;
so = ss . taboption ( 'ipv6' , form . ListValue , 'ndp' , _ ( 'NDP-Proxy' ) ) ;
so . value ( '' , _ ( 'disabled' ) ) ;
so . value ( 'relay' , _ ( 'relay mode' ) ) ;
so . value ( 'hybrid' , _ ( 'hybrid mode' ) ) ;
so = ss . taboption ( 'ipv6' , form . Flag , 'master' , _ ( 'Master' ) , _ ( 'Set this interface as master for the dhcpv6 relay.' ) ) ;
so . depends ( 'dhcpv6' , 'relay' ) ;
so . depends ( 'dhcpv6' , 'hybrid' ) ;
so = ss . taboption ( 'ipv6' , form . ListValue , 'ra_management' , _ ( 'DHCPv6-Mode' ) , _ ( 'Default is stateless + stateful' ) ) ;
so . value ( '0' , _ ( 'stateless' ) ) ;
so . value ( '1' , _ ( 'stateless + stateful' ) ) ;
so . value ( '2' , _ ( 'stateful-only' ) ) ;
so . depends ( 'dhcpv6' , 'server' ) ;
so . depends ( 'dhcpv6' , 'hybrid' ) ;
so . default = '1' ;
so = ss . taboption ( 'ipv6' , form . Flag , 'ra_default' , _ ( 'Always announce default router' ) , _ ( 'Announce as default router even if no public prefix is available.' ) ) ;
so . depends ( 'ra' , 'server' ) ;
so . depends ( 'ra' , 'hybrid' ) ;
ss . taboption ( 'ipv6' , form . DynamicList , 'dns' , _ ( 'Announced DNS servers' ) ) ;
ss . taboption ( 'ipv6' , form . DynamicList , 'domain' , _ ( 'Announced DNS domains' ) ) ;
}
ifc . renderFormOptions ( s ) ;
for ( var i = 0 ; i < s . children . length ; i ++ ) {
o = s . children [ i ] ;
switch ( o . option ) {
case 'proto' :
case 'delegate' :
case 'auto' :
case 'type' :
case 'stp' :
case 'igmp_snooping' :
case 'ifname_single' :
case 'ifname_multi' :
2020-06-09 15:11:20 +00:00
case 'ifname_master' :
2020-03-27 09:27:18 +00:00
case '_dhcp' :
case '_zone' :
case '_switch_proto' :
case '_ifacestat_modal' :
continue ;
default :
if ( o . deps . length )
for ( var j = 0 ; j < o . deps . length ; j ++ )
o . deps [ j ] . proto = protoval ;
else
o . depends ( 'proto' , protoval ) ;
}
}
} , this ) ) ;
} ;
s . handleAdd = function ( ev ) {
var m2 = new form . Map ( 'network' ) ,
s2 = m2 . section ( form . NamedSection , '_new_' ) ,
protocols = network . getProtocols ( ) ,
2020-06-09 15:11:20 +00:00
proto , name , type , ifname _single , ifname _multi , ifname _master ;
2020-03-27 09:27:18 +00:00
protocols . sort ( function ( a , b ) {
return a . getProtocol ( ) > b . getProtocol ( ) ;
} ) ;
s2 . render = function ( ) {
return Promise . all ( [
{ } ,
this . renderUCISection ( '_new_' )
] ) . then ( this . renderContents . bind ( this ) ) ;
} ;
name = s2 . option ( form . Value , 'name' , _ ( 'Name' ) ) ;
name . rmempty = false ;
name . datatype = 'uciname' ;
name . placeholder = _ ( 'New interface name…' ) ;
name . validate = function ( section _id , value ) {
if ( uci . get ( 'network' , value ) != null )
return _ ( 'The interface name is already used' ) ;
var pr = network . getProtocol ( proto . formvalue ( section _id ) , value ) ,
ifname = pr . isVirtual ( ) ? '%s-%s' . format ( pr . getProtocol ( ) , value ) : 'br-%s' . format ( value ) ;
if ( value . length > 15 )
return _ ( 'The interface name is too long' ) ;
return true ;
} ;
proto = s2 . option ( form . ListValue , 'proto' , _ ( 'Protocol' ) ) ;
proto . validate = name . validate ;
2020-06-09 15:11:20 +00:00
type = s2 . option ( form . ListValue , 'type' , _ ( 'Interface type' ) ) ;
type . value ( '' , _ ( 'Normal' ) ) ;
type . value ( 'bridge' , _ ( 'Bridge' ) ) ;
type . value ( 'macvlan' , _ ( 'MacVLAN' ) ) ;
2020-03-27 09:27:18 +00:00
ifname _single = s2 . option ( widgets . DeviceSelect , 'ifname_single' , _ ( 'Interface' ) ) ;
ifname _single . noaliases = false ;
ifname _single . optional = false ;
2020-06-09 15:11:20 +00:00
ifname _master = s2 . option ( widgets . DeviceSelect , 'ifname_master' , _ ( 'Base interface' ) ) ;
ifname _master . noaliases = false ;
ifname _master . optional = false ;
2020-03-27 09:27:18 +00:00
ifname _multi = s2 . option ( widgets . DeviceSelect , 'ifname_multi' , _ ( 'Interface' ) ) ;
ifname _multi . nobridges = true ;
ifname _multi . noaliases = true ;
ifname _multi . multiple = true ;
ifname _multi . optional = true ;
ifname _multi . display _size = 6 ;
for ( var i = 0 ; i < protocols . length ; i ++ ) {
proto . value ( protocols [ i ] . getProtocol ( ) , protocols [ i ] . getI18n ( ) ) ;
if ( ! protocols [ i ] . isVirtual ( ) ) {
2020-06-09 15:11:20 +00:00
type . depends ( { proto : protocols [ i ] . getProtocol ( ) } ) ;
2020-03-27 09:27:18 +00:00
ifname _single . depends ( { type : '' , proto : protocols [ i ] . getProtocol ( ) } ) ;
ifname _multi . depends ( { type : 'bridge' , proto : protocols [ i ] . getProtocol ( ) } ) ;
2020-06-09 15:11:20 +00:00
ifname _master . depends ( { type : 'macvlan' , proto : protocols [ i ] . getProtocol ( ) } ) ;
2020-03-27 09:27:18 +00:00
}
}
m2 . render ( ) . then ( L . bind ( function ( nodes ) {
ui . showModal ( _ ( 'Add new interface...' ) , [
nodes ,
E ( 'div' , { 'class' : 'right' } , [
E ( 'button' , {
'class' : 'btn' ,
'click' : ui . hideModal
} , _ ( 'Cancel' ) ) , ' ' ,
E ( 'button' , {
'class' : 'cbi-button cbi-button-positive important' ,
'click' : ui . createHandlerFn ( this , function ( ev ) {
var nameval = name . isValid ( '_new_' ) ? name . formvalue ( '_new_' ) : null ,
protoval = proto . isValid ( '_new_' ) ? proto . formvalue ( '_new_' ) : null ,
protoclass = protoval ? network . getProtocol ( protoval ) : null ;
if ( nameval == null || protoval == null || nameval == '' || protoval == '' )
return ;
return protoclass . isCreateable ( nameval ) . then ( function ( checkval ) {
if ( checkval != null ) {
ui . addNotification ( null ,
E ( 'p' , _ ( 'New interface for "%s" can not be created: %s' ) . format ( protoclass . getI18n ( ) , checkval ) ) ) ;
ui . hideModal ( ) ;
return ;
}
return m . save ( function ( ) {
var section _id = uci . add ( 'network' , 'interface' , nameval ) ;
uci . set ( 'network' , section _id , 'proto' , protoval ) ;
if ( ifname _single . isActive ( '_new_' ) ) {
uci . set ( 'network' , section _id , 'ifname' , ifname _single . formvalue ( '_new_' ) ) ;
}
else if ( ifname _multi . isActive ( '_new_' ) ) {
uci . set ( 'network' , section _id , 'type' , 'bridge' ) ;
uci . set ( 'network' , section _id , 'ifname' , L . toArray ( ifname _multi . formvalue ( '_new_' ) ) . join ( ' ' ) ) ;
}
2020-06-09 15:11:20 +00:00
else if ( ifname _master . isActive ( '_new_' ) ) {
uci . set ( 'network' , section _id , 'type' , 'macvlan' ) ;
uci . set ( 'network' , section _id , 'ifname' , section _id ) ;
uci . set ( 'network' , section _id , 'masterintf' , L . toArray ( ifname _multi . formvalue ( '_new_' ) ) . join ( ' ' ) ) ;
}
2020-03-27 09:27:18 +00:00
} ) . then ( L . bind ( m . children [ 0 ] . renderMoreOptionsModal , m . children [ 0 ] , nameval ) ) ;
} ) ;
} )
} , _ ( 'Create interface' ) )
] )
] , 'cbi-modal' ) ;
nodes . querySelector ( '[id="%s"] input[type="text"]' . format ( name . cbid ( '_new_' ) ) ) . focus ( ) ;
} , this ) ) ;
} ;
s . handleRemove = function ( section _id , ev ) {
return network . deleteNetwork ( section _id ) . then ( L . bind ( function ( section _id , ev ) {
return form . GridSection . prototype . handleRemove . apply ( this , [ section _id , ev ] ) ;
} , this , section _id , ev ) ) ;
} ;
o = s . option ( form . DummyValue , '_ifacebox' ) ;
o . modalonly = false ;
o . textvalue = function ( section _id ) {
var net = this . section . networks . filter ( function ( n ) { return n . getName ( ) == section _id } ) [ 0 ] ,
zone = net ? this . section . zones . filter ( function ( z ) { return ! ! z . getNetworks ( ) . filter ( function ( n ) { return n == section _id } ) [ 0 ] } ) [ 0 ] : null ;
if ( ! net )
return ;
var node = E ( 'div' , { 'class' : 'ifacebox' } , [
E ( 'div' , {
'class' : 'ifacebox-head' ,
'style' : 'background-color:%s' . format ( zone ? zone . getColor ( ) : '#EEEEEE' ) ,
'title' : zone ? _ ( 'Part of zone %q' ) . format ( zone . getName ( ) ) : _ ( 'No zone assigned' )
} , E ( 'strong' , net . getName ( ) . toUpperCase ( ) ) ) ,
E ( 'div' , {
'class' : 'ifacebox-body' ,
'id' : '%s-ifc-devices' . format ( section _id ) ,
'data-network' : section _id
} , [
E ( 'img' , {
'src' : L . resource ( 'icons/ethernet_disabled.png' ) ,
'style' : 'width:16px; height:16px'
} ) ,
E ( 'br' ) , E ( 'small' , '?' )
] )
] ) ;
render _ifacebox _status ( node . childNodes [ 1 ] , net ) ;
return node ;
} ;
o = s . option ( form . DummyValue , '_ifacestat' ) ;
o . modalonly = false ;
o . textvalue = function ( section _id ) {
var net = this . section . networks . filter ( function ( n ) { return n . getName ( ) == section _id } ) [ 0 ] ;
if ( ! net )
return ;
var node = E ( 'div' , { 'id' : '%s-ifc-description' . format ( section _id ) } ) ;
render _status ( node , net , false ) ;
return node ;
} ;
o = s . taboption ( 'advanced' , form . Flag , 'delegate' , _ ( 'Use builtin IPv6-management' ) ) ;
o . modalonly = true ;
o . default = o . enabled ;
o = s . taboption ( 'advanced' , form . Flag , 'force_link' , _ ( 'Force link' ) , _ ( 'Set interface properties regardless of the link carrier (If set, carrier sense events do not invoke hotplug handlers).' ) ) ;
o . modalonly = true ;
o . render = function ( option _index , section _id , in _table ) {
var protoopt = this . section . children . filter ( function ( o ) { return o . option == 'proto' } ) [ 0 ] ,
protoval = protoopt ? protoopt . cfgvalue ( section _id ) : null ;
this . default = ( protoval == 'static' ) ? this . enabled : this . disabled ;
return this . super ( 'render' , [ option _index , section _id , in _table ] ) ;
} ;
s = m . section ( form . TypedSection , 'globals' , _ ( 'Global network options' ) ) ;
s . addremove = false ;
s . anonymous = true ;
o = s . option ( form . Value , 'ula_prefix' , _ ( 'IPv6 ULA-Prefix' ) ) ;
o . datatype = 'cidr6' ;
o = s . option ( form . Flag , 'packet_steering' , _ ( 'Packet Steering' ) , _ ( 'Enable packet steering across all CPUs. May help or hinder network speed.' ) ) ;
o . optional = true ;
if ( dslModemType != null ) {
s = m . section ( form . TypedSection , 'dsl' , _ ( 'DSL' ) ) ;
s . anonymous = true ;
o = s . option ( form . ListValue , 'annex' , _ ( 'Annex' ) ) ;
o . value ( 'a' , _ ( 'Annex A + L + M (all)' ) ) ;
o . value ( 'b' , _ ( 'Annex B (all)' ) ) ;
o . value ( 'j' , _ ( 'Annex J (all)' ) ) ;
o . value ( 'm' , _ ( 'Annex M (all)' ) ) ;
o . value ( 'bdmt' , _ ( 'Annex B G.992.1' ) ) ;
o . value ( 'b2' , _ ( 'Annex B G.992.3' ) ) ;
o . value ( 'b2p' , _ ( 'Annex B G.992.5' ) ) ;
o . value ( 'at1' , _ ( 'ANSI T1.413' ) ) ;
o . value ( 'admt' , _ ( 'Annex A G.992.1' ) ) ;
o . value ( 'alite' , _ ( 'Annex A G.992.2' ) ) ;
o . value ( 'a2' , _ ( 'Annex A G.992.3' ) ) ;
o . value ( 'a2p' , _ ( 'Annex A G.992.5' ) ) ;
o . value ( 'l' , _ ( 'Annex L G.992.3 POTS 1' ) ) ;
o . value ( 'm2' , _ ( 'Annex M G.992.3' ) ) ;
o . value ( 'm2p' , _ ( 'Annex M G.992.5' ) ) ;
o = s . option ( form . ListValue , 'tone' , _ ( 'Tone' ) ) ;
o . value ( '' , _ ( 'auto' ) ) ;
o . value ( 'a' , _ ( 'A43C + J43 + A43' ) ) ;
o . value ( 'av' , _ ( 'A43C + J43 + A43 + V43' ) ) ;
o . value ( 'b' , _ ( 'B43 + B43C' ) ) ;
o . value ( 'bv' , _ ( 'B43 + B43C + V43' ) ) ;
if ( dslModemType == 'vdsl' ) {
o = s . option ( form . ListValue , 'xfer_mode' , _ ( 'Encapsulation mode' ) ) ;
o . value ( '' , _ ( 'auto' ) ) ;
o . value ( 'atm' , _ ( 'ATM (Asynchronous Transfer Mode)' ) ) ;
o . value ( 'ptm' , _ ( 'PTM/EFM (Packet Transfer Mode)' ) ) ;
o = s . option ( form . ListValue , 'line_mode' , _ ( 'DSL line mode' ) ) ;
o . value ( '' , _ ( 'auto' ) ) ;
o . value ( 'adsl' , _ ( 'ADSL' ) ) ;
o . value ( 'vdsl' , _ ( 'VDSL' ) ) ;
o = s . option ( form . ListValue , 'ds_snr_offset' , _ ( 'Downstream SNR offset' ) ) ;
o . default = '0' ;
for ( var i = - 100 ; i <= 100 ; i += 5 )
o . value ( i , _ ( '%.1f dB' ) . format ( i / 10 ) ) ;
}
s . option ( form . Value , 'firmware' , _ ( 'Firmware File' ) ) ;
}
// Show ATM bridge section if we have the capabilities
if ( L . hasSystemFeature ( 'br2684ctl' ) ) {
s = m . section ( form . TypedSection , 'atm-bridge' , _ ( 'ATM Bridges' ) , _ ( 'ATM bridges expose encapsulated ethernet in AAL5 connections as virtual Linux network interfaces which can be used in conjunction with DHCP or PPP to dial into the provider network.' ) ) ;
s . addremove = true ;
s . anonymous = true ;
s . addbtntitle = _ ( 'Add ATM Bridge' ) ;
s . handleAdd = function ( ev ) {
var sections = uci . sections ( 'network' , 'atm-bridge' ) ,
max _unit = - 1 ;
for ( var i = 0 ; i < sections . length ; i ++ ) {
var unit = + sections [ i ] . unit ;
if ( ! isNaN ( unit ) && unit > max _unit )
max _unit = unit ;
}
return this . map . save ( function ( ) {
var sid = uci . add ( 'network' , 'atm-bridge' ) ;
uci . set ( 'network' , sid , 'unit' , max _unit + 1 ) ;
uci . set ( 'network' , sid , 'atmdev' , 0 ) ;
uci . set ( 'network' , sid , 'encaps' , 'llc' ) ;
uci . set ( 'network' , sid , 'payload' , 'bridged' ) ;
uci . set ( 'network' , sid , 'vci' , 35 ) ;
uci . set ( 'network' , sid , 'vpi' , 8 ) ;
} ) ;
} ;
s . tab ( 'general' , _ ( 'General Setup' ) ) ;
s . tab ( 'advanced' , _ ( 'Advanced Settings' ) ) ;
o = s . taboption ( 'general' , form . Value , 'vci' , _ ( 'ATM Virtual Channel Identifier (VCI)' ) ) ;
s . taboption ( 'general' , form . Value , 'vpi' , _ ( 'ATM Virtual Path Identifier (VPI)' ) ) ;
o = s . taboption ( 'general' , form . ListValue , 'encaps' , _ ( 'Encapsulation mode' ) ) ;
o . value ( 'llc' , _ ( 'LLC' ) ) ;
o . value ( 'vc' , _ ( 'VC-Mux' ) ) ;
s . taboption ( 'advanced' , form . Value , 'atmdev' , _ ( 'ATM device number' ) ) ;
s . taboption ( 'advanced' , form . Value , 'unit' , _ ( 'Bridge unit number' ) ) ;
o = s . taboption ( 'advanced' , form . ListValue , 'payload' , _ ( 'Forwarding mode' ) ) ;
o . value ( 'bridged' , _ ( 'bridged' ) ) ;
o . value ( 'routed' , _ ( 'routed' ) ) ;
}
return m . render ( ) . then ( L . bind ( function ( m , nodes ) {
2020-04-09 12:39:09 +00:00
poll . add ( L . bind ( function ( ) {
2020-03-27 09:27:18 +00:00
var section _ids = m . children [ 0 ] . cfgsections ( ) ,
tasks = [ ] ;
for ( var i = 0 ; i < section _ids . length ; i ++ ) {
var row = nodes . querySelector ( '.cbi-section-table-row[data-sid="%s"]' . format ( section _ids [ i ] ) ) ,
dsc = row . querySelector ( '[data-name="_ifacestat"] > div' ) ,
btn1 = row . querySelector ( '.cbi-section-actions .reconnect' ) ,
btn2 = row . querySelector ( '.cbi-section-actions .down' ) ;
if ( dsc . getAttribute ( 'reconnect' ) == '' ) {
dsc . setAttribute ( 'reconnect' , '1' ) ;
tasks . push ( fs . exec ( '/sbin/ifup' , [ section _ids [ i ] ] ) . catch ( function ( e ) {
ui . addNotification ( null , E ( 'p' , e . message ) ) ;
} ) ) ;
}
else if ( dsc . getAttribute ( 'disconnect' ) == '' ) {
dsc . setAttribute ( 'disconnect' , '1' ) ;
tasks . push ( fs . exec ( '/sbin/ifdown' , [ section _ids [ i ] ] ) . catch ( function ( e ) {
ui . addNotification ( null , E ( 'p' , e . message ) ) ;
} ) ) ;
}
else if ( dsc . getAttribute ( 'reconnect' ) == '1' ) {
dsc . removeAttribute ( 'reconnect' ) ;
btn1 . classList . remove ( 'spinning' ) ;
btn1 . disabled = false ;
}
else if ( dsc . getAttribute ( 'disconnect' ) == '1' ) {
dsc . removeAttribute ( 'disconnect' ) ;
btn2 . classList . remove ( 'spinning' ) ;
btn2 . disabled = false ;
}
}
return Promise . all ( tasks )
. then ( L . bind ( network . getNetworks , network ) )
. then ( L . bind ( this . poll _status , this , nodes ) ) ;
} , this ) , 5 ) ;
return nodes ;
} , this , m ) ) ;
}
} ) ;