8 var callNetworkInterfaceDump
= rpc
.declare({
9 object
: 'network.interface',
11 expect
: { interface: [] }
14 function applyMask(addr
, mask
, v6
) {
15 var words
= v6
? validation
.parseIPv6(addr
) : validation
.parseIPv4(addr
);
16 var bword
= v6
? 0xffff : 0xff;
17 var bwlen
= v6
? 16 : 8;
19 if (!words
|| mask
< 0 || mask
> (v6
? 128 : 32))
22 for (var i
= 0; i
< words
.length
; i
++) {
23 var b
= Math
.min(mask
, bwlen
);
24 words
[i
] &= (bword
<< (bwlen
- b
)) & bword
;
28 return String
.prototype.format
.apply(
29 v6
? '%x:%x:%x:%x:%x:%x:%x:%x' : '%d.%d.%d.%d', words
);
35 callNetworkInterfaceDump(),
36 L
.resolveDefault(fs
.exec('/sbin/ip', [ '-4', 'neigh', 'show' ]), {}),
37 L
.resolveDefault(fs
.exec('/sbin/ip', [ '-4', 'route', 'show', 'table', 'all' ]), {}),
38 L
.resolveDefault(fs
.exec('/sbin/ip', [ '-4', 'rule', 'show' ]), {}),
39 L
.resolveDefault(fs
.exec('/sbin/ip', [ '-6', 'neigh', 'show' ]), {}),
40 L
.resolveDefault(fs
.exec('/sbin/ip', [ '-6', 'route', 'show', 'table', 'all' ]), {}),
41 L
.resolveDefault(fs
.exec('/sbin/ip', [ '-6', 'rule', 'show' ]), {})
45 getNetworkByDevice(networks
, dev
, addr
, mask
, v6
) {
46 var addr_arrays
= [ 'ipv4-address', 'ipv6-address', 'ipv6-prefix', 'ipv6-prefix-assignment', 'route' ],
47 matching_iface
= null,
50 for (var i
= 0; i
< networks
.length
; i
++) {
51 if (!L
.isObject(networks
[i
]))
54 if (networks
[i
].l3_device
!= dev
&& networks
[i
].device
!= dev
)
57 for (var j
= 0; j
< addr_arrays
.length
; j
++) {
58 var addr_list
= networks
[i
][addr_arrays
[j
]];
60 if (!Array
.isArray(addr_list
) || addr_list
.length
== 0)
63 for (var k
= 0; k
< addr_list
.length
; k
++) {
64 var cmp_addr
= addr_list
[k
].address
|| addr_list
[k
].target
,
65 cmp_mask
= addr_list
[k
].mask
;
70 var addr1
= applyMask(cmp_addr
, cmp_mask
, v6
),
71 addr2
= applyMask(addr
, cmp_mask
, v6
);
73 if (addr1
!= addr2
|| mask
< cmp_mask
)
76 if (cmp_mask
> matching_prefix
) {
77 matching_iface
= networks
[i
].interface;
78 matching_prefix
= cmp_mask
;
84 return matching_iface
;
87 parseNeigh: function(s
, networks
, v6
) {
88 var lines
= s
.trim().split(/\n/),
91 for (var i
= 0; i
< lines
.length
; i
++) {
92 var m
= lines
[i
].match(/^([0-9a-f:.]+) (.+) (\S+) *$/),
93 addr
= m
? m
[1] : null,
94 flags
= m
? m
[2].trim().split(/\s+/) : [],
95 state
= (m
? m
[3] : null) || 'FAILED';
97 if (!addr
|| state
== 'FAILED' || addr
.match(/^fe[89a-f][0-9a-f]:/))
100 for (var j
= 0; j
< flags
.length
; j
+= 2)
101 flags
[flags
[j
]] = flags
[j
+ 1];
106 var net
= this.getNetworkByDevice(networks
, flags
.dev
, addr
, v6
? 128 : 32, v6
);
110 flags
.lladdr
.toUpperCase(),
111 E('span', { 'class': 'ifacebadge' }, [ net
? net
: '(%s)'.format(flags
.dev
) ])
118 parseRoute: function(s
, networks
, v6
) {
119 var lines
= s
.trim().split(/\n/),
122 for (var i
= 0; i
< lines
.length
; i
++) {
123 var m
= lines
[i
].match(/^(?:([a-z_]+|\d+) )?(default|[0-9a-f:.\/]+) (.+)$/),
124 type
= (m
? m
[1] : null) || 'unicast',
125 dest
= m
? (m
[2] == 'default' ? (v6
? '::/0' : '0.0.0.0/0') : m
[2]) : null,
126 flags
= m
? m
[3].trim().split(/\s+/) : [];
128 if (!dest
|| type
!= 'unicast' || dest
== 'fe80::/64' || dest
== 'ff00::/8')
131 for (var j
= 0; j
< flags
.length
; j
+= 2)
132 flags
[flags
[j
]] = flags
[j
+ 1];
134 var addr
= dest
.split('/'),
135 bits
= (addr
[1] != null) ? +addr
[1] : (v6
? 128 : 32),
136 net
= this.getNetworkByDevice(networks
, flags
.dev
, addr
[0], bits
, v6
);
139 E('span', { 'class': 'ifacebadge' }, [ net
? net
: '(%s)'.format(flags
.dev
) ]),
141 (v6
? flags
.from : flags
.via
) || '-',
142 String(flags
.metric
|| 0),
143 flags
.table
|| 'main',
151 parseRule: function(s
) {
152 var lines
= s
.trim().split(/\n/),
155 for (var i
= 0; i
< lines
.length
; i
++) {
156 var m
= lines
[i
].match(/^(\d+):\s+(.+)$/),
157 prio
= m
? m
[1] : null,
158 rule
= m
? m
[2] : null;
169 render: function(data
) {
170 var networks
= data
[0],
171 ip4neigh
= data
[1].stdout
|| '',
172 ip4route
= data
[2].stdout
|| '',
173 ip4rule
= data
[3].stdout
|| '',
174 ip6neigh
= data
[4].stdout
|| '',
175 ip6route
= data
[5].stdout
|| '',
176 ip6rule
= data
[6].stdout
|| '';
178 var device_title
= _('Which is used to access this %s').format(_('Target'));
179 var target_title
= _('Network and its mask that define the size of the destination');
180 var gateway_title
= _('The address through which this %s is reachable').format(_('Target'));
181 var metric_title
= _('Quantifies the cost or distance to a destination in a way that allows routers to make informed decisions about the optimal path to forward data packets');
182 var table_title
= _('Common name or numeric ID of the %s in which this route is found').format(_('Table'));
183 var proto_title
= _('The routing protocol identifier of this route');
184 var source_title
= _('Network and its mask that define which source addresses use this route');
186 var neigh4tbl
= E('table', { 'class': 'table' }, [
187 E('tr', { 'class': 'tr table-titles' }, [
188 E('th', { 'class': 'th' }, [ _('IP address') ]),
189 E('th', { 'class': 'th' }, [ _('MAC address') ]),
190 E('th', { 'class': 'th' }, [ _('Interface') ])
194 var route4tbl
= E('table', { 'class': 'table' }, [
195 E('tr', { 'class': 'tr table-titles' }, [
196 E('th', { 'class': 'th', 'title': device_title
}, [ _('Device') ]),
197 E('th', { 'class': 'th', 'title': target_title
}, [ _('Target') ]),
198 E('th', { 'class': 'th', 'title': gateway_title
}, [ _('Gateway') ]),
199 E('th', { 'class': 'th', 'title': metric_title
}, [ _('Metric') ]),
200 E('th', { 'class': 'th', 'title': table_title
}, [ _('Table') ]),
201 E('th', { 'class': 'th', 'title': proto_title
}, [ _('Protocol') ])
205 var rule4tbl
= E('table', { 'class': 'table' }, [
206 E('tr', { 'class': 'tr table-titles' }, [
207 E('th', { 'class': 'th' }, [ _('Priority') ]),
208 E('th', { 'class': 'th' }, [ _('Rule') ])
212 var neigh6tbl
= E('table', { 'class': 'table' }, [
213 E('tr', { 'class': 'tr table-titles' }, [
214 E('th', { 'class': 'th' }, [ _('IP address') ]),
215 E('th', { 'class': 'th' }, [ _('MAC address') ]),
216 E('th', { 'class': 'th' }, [ _('Interface') ])
220 var route6tbl
= E('table', { 'class': 'table' }, [
221 E('tr', { 'class': 'tr table-titles' }, [
222 E('th', { 'class': 'th', 'title': device_title
}, [ _('Device') ]),
223 E('th', { 'class': 'th', 'title': target_title
}, [ _('Target') ]),
224 E('th', { 'class': 'th', 'title': source_title
}, [ _('Source') ]),
225 E('th', { 'class': 'th', 'title': metric_title
}, [ _('Metric') ]),
226 E('th', { 'class': 'th', 'title': table_title
}, [ _('Table') ]),
227 E('th', { 'class': 'th', 'title': proto_title
}, [ _('Protocol') ])
231 var rule6tbl
= E('table', { 'class': 'table' }, [
232 E('tr', { 'class': 'tr table-titles' }, [
233 E('th', { 'class': 'th' }, [ _('Priority') ]),
234 E('th', { 'class': 'th' }, [ _('Rule') ])
238 cbi_update_table(neigh4tbl
, this.parseNeigh(ip4neigh
, networks
, false),
239 E('em', _('No entries available'))
241 cbi_update_table(route4tbl
, this.parseRoute(ip4route
, networks
, false),
242 E('em', _('No entries available'))
244 cbi_update_table(rule4tbl
, this.parseRule(ip4rule
, networks
, false),
245 E('em', _('No entries available'))
247 cbi_update_table(neigh6tbl
, this.parseNeigh(ip6neigh
, networks
, true),
248 E('em', _('No entries available'))
250 cbi_update_table(route6tbl
, this.parseRoute(ip6route
, networks
, true),
251 E('em', _('No entries available'))
253 cbi_update_table(rule6tbl
, this.parseRule(ip6rule
, networks
, false),
254 E('em', _('No entries available'))
258 E('h2', {}, [ _('Routing') ]),
259 E('p', {}, [ _('The following rules are currently active on this system.') ]),
261 E('div', { 'class': 'cbi-section', 'data-tab': 'ipv4routing', 'data-tab-title': _('IPv4 Routing') }, [
262 E('h3', {}, [ _('IPv4 Neighbours') ]),
265 E('h3', {}, [ _('Active IPv4 Routes') ]),
268 E('h3', {}, [ _('Active IPv4 Rules') ]),
271 E('div', { 'class': 'cbi-section', 'data-tab': 'ipv6routing', 'data-tab-title': _('IPv6 Routing') }, [
272 E('h3', {}, [ _('IPv6 Neighbours') ]),
275 E('h3', {}, [ _('Active IPv6 Routes') ]),
278 E('h3', {}, [ _('Active IPv6 Rules') ]),
284 ui
.tabs
.initTabGroup(view
.lastElementChild
.childNodes
);
289 handleSaveApply
: null,