xref: /aosp_15_r20/external/ot-br-posix/src/openwrt/view/admin_thread/thread_setting.htm (revision 4a64e381480ef79f0532b2421e44e6ee336b8e0d)
1<%-
2	local ubus = require "ubus"
3	local sys = require "luci.sys"
4	local utl = require "luci.util"
5
6	function connect_ubus(methods)
7		local result
8		local conn = ubus.connect()
9
10		if not conn then
11			error("Failed to connect to ubusd")
12		end
13
14		result = conn:call("otbr", methods, {})
15
16		return result
17	end
18
19	function threadget(action)
20		local result = connect_ubus(action)
21
22		return result
23	end
24
25	local state = threadget("state").State
26
27
28
29	function addrlist()
30		local k, v
31		local l = { }
32
33		local addrlist = connect_ubus("macfilteraddr").addrlist
34
35		for k, v in pairs(addrlist) do
36			l[#l+1] = v
37		end
38
39		return l
40	end
41
42
43-%>
44<%+header%>
45
46<h2><%:Thread Network: %><%=threadget("networkname").NetworkName%><%: (wpan0)%></h2>
47<div> The Network Configuration section covers physical settings of the Thread Network such as channel, PAN ID. Per interface related settings like networkkey or MAC-filter are grouped in the Interface Configuration.</div>
48<br />
49
50<form class="inline" action="<%=url('admin/network/thread_handler_setting')%>" method="post" id="settingForm" name="settingForm" onsubmit="return validateForm()">
51	<h3><%:Network Configuration%></h3>
52	<br />
53	<ul class="cbi-tabmenu">
54		<li class="cbi-tab" id="generaltab"><a href="javascript:generalSetting();"><%:General Setup%></a></li>
55		<li class="cbi-tab-disabled" id="advancedtab"><a href="javascript:advancedSetting();"><%:Advanced Settings%></a></li>
56	</ul>
57
58	<input type="hidden" name="submitcontent" id="submitcontent" />
59	<input type="hidden" name="removeAddrIndex" id="removeAddrIndex" />
60	<input type="hidden" name="token" value="<%=token%>" />
61	<!-- General Setup -->
62	<div style="width:80%;margin-left:10%;" id="generaldiv">
63		<div class="cbi-value">
64			<label class="cbi-value-title" style="margin-right:5%;">Thread Name</label>
65			<div class="cbi-value-title">
66				<input type="text" name="threadname" value="<%=threadget("networkname").NetworkName%>" style="width:30%;"/>
67			</div>
68		</div>
69		<div class="cbi-value">
70			<label class="cbi-value-title" style="margin-right:5%;">Status</label>
71			<div class="cbi-value-title">
72				<span class="ifacebadge large" style="padding:2%;">
73					<span>
74					<strong>PAN ID: </strong>
75						<%=threadget("panid").PanId%>
76					<br>
77					<strong>Extended PAN ID: </strong>
78						<%=threadget("extpanid").ExtPanId%>
79					<br>
80					<strong>State:  </strong>
81						<%=state%>
82					<br>
83					<strong>Channel: </strong>
84						<%=threadget("channel").Channel%>
85					<span>
86				</span>
87			</div>
88		</div>
89		<div class="cbi-value">
90			<% if state == "disabled" then %>
91			<label class="cbi-value-title" style="margin-right:5%;">Thread network is disabled</label>
92			<div class="cbi-value-field">
93				<input class="cbi-button cbi-button-add" type="submit" id="enable" name="enable" value="Enable" />
94			</div>
95			<% else %>
96			<label class="cbi-value-title" style="margin-right:5%;">Thread network is enabled</label>
97			<div class="cbi-value-field">
98				<input class="cbi-button cbi-button-reset" type="submit" id="disable" name="disable" value="Disable" />
99			</div>
100			<% end %>
101		</div>
102		<div class="cbi-value">
103			<label class="cbi-value-title" style="margin-right:5%;">Protocol</label>
104			<div class="cbi-value-field">
105				<select style="width:30%;" id="protocol" name="protocol">
106					<option value>unmanaged</option>
107				</select>
108			</div>
109		</div>
110	</div>
111
112	<!-- Advanced Settings -->
113	<div style="width:70%;margin-left:10%;display:none;" id="advanceddiv">
114		<div class="cbi-value">
115			<label class="cbi-value-title" style="margin-right:5%;">Channel</label>
116			<div class="cbi-value-title">
117				<input type="text" name="channel" value="<%=threadget("channel").Channel%>" style="width:50%;"/>
118			</div>
119		</div>
120		<div class="cbi-value">
121			<label class="cbi-value-title" style="margin-right:5%;">PAN ID</label>
122			<div class="cbi-value-title">
123				<input type="text" name="panid" value="<%=threadget("panid").PanId%>" style="width:50%;"/>
124			</div>
125		</div>
126		<div class="cbi-value">
127			<label class="cbi-value-title" style="margin-right:5%;">Extended PAN ID</label>
128			<div class="cbi-value-title">
129				<input type="text" name="extpanid" value="<%=threadget("extpanid").ExtPanId%>" style="width:50%;"/>
130			</div>
131		</div>
132		<div class="cbi-value">
133			<% if state == 'disabled' then %>
134			<label class="cbi-value-title" style="margin-right:5%;">Mode</label>
135			<div class="cbi-value-title">
136			<input type="text" name="mode" value="<%=threadget("mode").Mode%>" style="width:50%;"/>
137			</div>
138			<div style="margin-left:30%;margin-top:1%;">
139				<span><img src="<%=resource .. "/cbi/help.gif"%>"/><%:set the thread device mode value, must be consist of 'r', 's', 'd', 'n'.%></span>
140			</div>
141			<% else %>
142			<label class="cbi-value-title" style="margin-right:5%;">Mode</label>
143			<div class="cbi-value-title">
144			<input type="text" name="mode" value="<%=threadget("mode").Mode%>" readonly="readonly" style="width:50%;"/>
145			</div>
146			<div style="margin-left:30%;margin-top:1%;">
147				<span><img src="<%=resource .. "/cbi/help.gif"%>"/><%:can not change mode when thread network is started.%></span>
148			</div>
149			<% end %>
150		</div>
151		<div class="cbi-value" style="display:none">
152			<label class="cbi-value-title" style="margin-right:5%;">State</label>
153			<div class="cbi-value-field">
154				<select style="width:30%;" id="state" name="state" value="<%=state%>">
155					<option value="disabled">disabled</option>
156					<option value="leader">leader</option>
157					<option value="router">router</option>
158					<option value="child">child</option>
159				</select>
160			</div>
161		</div>
162		<div class="cbi-value">
163			<label class="cbi-value-title" style="margin-right:5%;">PartitionId</label>
164			<div class="cbi-value-title">
165			<%=threadget("partitionid").Partitionid%>
166			</div>
167			<div style="margin-left:30%;margin-top:1%;">
168				<span><img src="<%=resource .. "/cbi/help.gif"%>"/><%:can not change partitionid when thread network is started.%></span>
169			</div>
170		</div>
171		<div class="cbi-value">
172			<label class="cbi-value-title" style="margin-right:5%;">Leave</label>
173			<div class="cbi-value-field">
174				<input class="cbi-button cbi-button-reset" type="submit" id="leave" name="leave" value="LEAVE" />
175			</div>
176			<div style="margin-left:30%;margin-top:1%;">
177				<span><img src="<%=resource .. "/cbi/help.gif"%>"/><%:This will delete all the existed Configuration of your thread network!%></span>
178			</div>
179		</div>
180	</div>
181
182	<h3><%:Interface Configuration%></h3>
183	<br />
184	<ul class="cbi-tabmenu">
185		<li class="cbi-tab" id="securitytab"><a href="javascript:securitySetting();"><%:Thread Security%></a></li>
186		<li class="cbi-tab-disabled" id="macfiltertab"><a href="javascript:macfilterSetting();"><%:MAC-Filter%></a></li>
187	</ul>
188	<br/>
189
190	<!-- Thread Security -->
191	<div style="width:60%;margin-left:10%;" id="securitydiv">
192		<div class="cbi-value">
193			<label class="cbi-value-title" style="margin-right:5%;">Network Key</label>
194			<div class="cbi-value-title">
195				<input type="text" name="networkkey" value="<%=threadget("networkkey").Networkkey%>" style="width:60%;"/>
196			</div>
197		</div>
198		<div class="cbi-value">
199			<label class="cbi-value-title" style="margin-right:5%;">Network Password</label>
200			<div class="cbi-value-title">
201				<input type="text" name="pskc" value="<%=threadget("pskc").pskc%>" style="width:60%;"/>
202			</div>
203		</div>
204	</div>
205
206	<!-- MAC Filter -->
207	<div style="width:60%;margin-left:10%;display:none;" id="macfilterdiv">
208		<div class="cbi-value">
209			<label class="cbi-value-title" style="margin-right:1%;">Protocol</label>
210			<div class="cbi-value-field">
211				<select style="width:30%;" id="macfilterselect" name="macfilterselect" onchange='macselectchange()' autocomplete="off">
212					<option value="disable">Disable</option>
213					<option value="allowlist">Allowlist</option>
214					<option value="denylist">Denylist</option>
215				</select>
216			</div>
217		</div>
218		<div class="cbi-value" id="macfilterlistdiv" style="display:none;">
219			<div class="table">
220				<label class="cbi-value-title" style="margin-right:1%;">Existed Address</label>
221				<div class="cbi-value-field">
222					<!-- addr list -->
223					<% for i, addr in ipairs(addrlist()) do %>
224					<input type="hidden" id="macfilterremove" name="macfilterremove" value="<%=addr%>" />
225					<% if i == 1 then %>
226					<div class="tr">
227						<div class="center" style="margin-top:15px;"><%=addr%></div>
228						<div class="th cbi-section-actions">
229							<input class="cbi-button cbi-button-reset" type="submit" id="removeAddr<%=i%>" name="removeAddr<%=i%>" value="<%:Remove%>" />
230						</div>
231					</div>
232					<% else %>
233					<div class="tr cbi-rowstyle-<%=1 + ((i-1) % 2)%>">
234						<div class="td col-2 center"><%=addr%></div>
235						<div class="td cbi-section-actions">
236							<input class="cbi-button cbi-button-reset" type="submit" id="removeAddr<%=i%>" name="removeAddr<%=i%>" value="<%:Remove%>" />
237						</div>
238					</div>
239					<% end %>
240					<% end %>
241					<!-- /addr list -->
242				</div>
243			</div>
244
245			<div class="cbi-value">
246				<div class="cbi-value-field">
247					<input class="cbi-button cbi-button-reset" type="submit" id="clearAddr" name="clearAddr" value="<%:Clear%>" />
248					<span style="margin-left:3%"><img src="<%=resource .. "/cbi/help.gif"%>" style="margin-right:2%"/><%:This will clear all existed macfilter address!%></span>
249				</div>
250			</div>
251
252			<label class="cbi-value-title" style="margin-right:1%;">Add Address</label>
253			<div class="cbi-value-field">
254				<div class="table">
255					<div class="tr table-titles">
256						<label><input type="text" id="macfilteradd" name="macfilteradd"/></label>
257						<input class="cbi-button cbi-button-add" type="submit" id="addAddr" name="addAddr" value="<%:Add%>" />
258					</div>
259				</div>
260			</div>
261		</div>
262	</div>
263
264	<div class="cbi-page-actions right">
265		<input class="cbi-button cbi-button-neutral" style="float:left;" type="button" onclick="window.location.href='thread'" value="<%:Back to Overview%>" />
266		<input class="cbi-button cbi-button-apply" type="submit" id="save" value="<%:Save & Apply%>" />
267		<input class="cbi-button cbi-button-reset" type="reset" value="<%:Reset%>" />
268	</div>
269
270</form>
271
272<%+footer%>
273
274<script type="text/javascript" src="/luci-static/resources/handle_error.js"></script>
275<script type="text/javascript">//<![CDATA[
276	handle_error(GetURLParameter('error'));
277
278	var macfilterstate = "<%=threadget("macfilterstate").state%>";
279	var macselect = document.querySelector('#macfilterselect');
280
281	if(macselect) {
282		macselect.value = macfilterstate;
283		var opt = macselect.options[macselect.selectedIndex];
284
285		if(opt.value == "disable")
286		{
287			document.getElementById('macfilterlistdiv').style.display = "none";
288		}
289		else
290		{
291			document.getElementById('macfilterlistdiv').style.display = "block";
292		}
293	}
294
295	function macselectchange()
296	{
297		var macselect = document.querySelector('#macfilterselect');
298
299		if(macselect) {
300			var opt = macselect.options[macselect.selectedIndex];
301			if(opt.value == "disable")
302			{
303				document.getElementById('macfilterlistdiv').style.display = "none";
304			}
305			else
306			{
307				document.getElementById('macfilterlistdiv').style.display = "block";
308			}
309		}
310	}
311
312	function generalSetting() {
313		document.getElementById('generaldiv').style.display = "block";
314		document.getElementById('advanceddiv').style.display = "none";
315		document.getElementById('generaltab').className = "cbi-tab";
316		document.getElementById('advancedtab').className = "cbi-tab-disabled";
317	}
318
319	function advancedSetting() {
320		document.getElementById('generaldiv').style.display = "none";
321		document.getElementById('advanceddiv').style.display = "block";
322		document.getElementById('generaltab').className = "cbi-tab-disabled";
323		document.getElementById('advancedtab').className = "cbi-tab";
324	}
325
326	function securitySetting() {
327		document.getElementById('securitydiv').style.display = "block";
328		document.getElementById('macfilterdiv').style.display = "none";
329		document.getElementById('securitytab').className = "cbi-tab";
330		document.getElementById('macfiltertab').className = "cbi-tab-disabled";
331	}
332
333	function macfilterSetting() {
334		document.getElementById('securitydiv').style.display = "none";
335		document.getElementById('macfilterdiv').style.display = "block";
336		document.getElementById('securitytab').className = "cbi-tab-disabled";
337		document.getElementById('macfiltertab').className = "cbi-tab";
338	}
339
340	document.getElementById('settingForm').addEventListener('submit', function() {
341		var length = document.activeElement.id.length;
342		document.getElementById('submitcontent').value = document.activeElement.id.substring(0, 10);
343		document.getElementById('removeAddrIndex').value = document.activeElement.id.substring(10, length);
344	});
345
346	function validateForm()
347	{
348		var activeElement = document.activeElement.id;
349		if(activeElement == "addAddr")
350		{
351			var addr = document.forms["settingForm"]["macfilteradd"].value;
352			if(addr.length != 16)
353			{
354				alert("Address length must be 16 bytes");
355				return false;
356			}
357		}
358		else if(activeElement.substring(0, 10) != "removeAddr")
359		{
360			var panid = document.forms["settingForm"]["panid"].value;
361			if (isNaN(panid)) {
362				alert("panid must be a number");
363				return false;
364			}
365
366			var extpanid = document.forms["settingForm"]["extpanid"].value;
367			var re = /^[0-9a-f]+$/;
368			var OK = re.exec(extpanid);
369			if (!OK) {
370				alert("extpanid must be a number");
371				return false;
372			}
373			if (extpanid.length != 16) {
374				alert("extpanid length must be 16 bytes");
375				return false;
376			}
377
378			var mode = document.forms["settingForm"]["mode"].value;
379			var re = /^[rsdn]+$/;
380			var OK = re.exec(mode);
381			if (!OK) {
382				alert("mode must be consist of 'r', 's', 'd', 'n'");
383				return false;
384			}
385
386			var networkkey = document.forms["settingForm"]["networkkey"].value;
387			if (networkkey.length != 32) {
388				alert("Networkkey length must be 32 bytes");
389				return false;
390			}
391
392			var pskc = document.forms["settingForm"]["pskc"].value;
393			if (pskc.length != 32) {
394				alert("Network password length must be 32 bytes");
395				return false;
396			}
397		}
398	}
399//]]></script>
400