更新配置
This commit is contained in:
parent
34ad59d34e
commit
405213d682
@ -2,12 +2,8 @@
|
||||
|
||||
module("luci.controller.schedule", package.seeall)
|
||||
|
||||
I18N = require "luci.i18n"
|
||||
translate = I18N.translate
|
||||
|
||||
function index()
|
||||
local page
|
||||
|
||||
page = entry({"admin", "services", "schedule"}, cbi("schedule"), _(translate("Scheduled Reboot")), 61)
|
||||
page = entry({"admin", "services", "schedule"}, cbi("schedule"), _("Scheduled Reboot"), 61)
|
||||
page.dependent = true
|
||||
end
|
||||
|
@ -23,8 +23,8 @@ o = d1:option(DummyValue, "zonename", translate("Timezone : "), translate("Be su
|
||||
d = m:section(TypedSection, "reboot", " ")
|
||||
|
||||
c1 = d:option(ListValue, "enable", " ");
|
||||
c1:value("0", translate("Disabled"))
|
||||
c1:value("1", translate("Enabled"))
|
||||
c1:value("0", "Disabled")
|
||||
c1:value("1", "Enabled")
|
||||
c1.default=0
|
||||
|
||||
sdhour = d:option(ListValue, "sdhour", translate("Reboot Time :"))
|
||||
|
@ -3,9 +3,6 @@
|
||||
|
||||
module("luci.controller.p910ndx", package.seeall)
|
||||
|
||||
I18N = require "luci.i18n"
|
||||
translate = I18N.translate
|
||||
|
||||
function index()
|
||||
if not nixio.fs.access("/etc/config/p910nd") then
|
||||
return
|
||||
@ -13,6 +10,6 @@ function index()
|
||||
|
||||
local page
|
||||
|
||||
page = entry({"admin", "services", "p910ndx"}, cbi("p910ndx"), _(translate("Print Server")), 60)
|
||||
page = entry({"admin", "services", "p910ndx"}, cbi("p910ndx"), _("Print Server"), 60)
|
||||
page.dependent = true
|
||||
end
|
||||
|
@ -3,15 +3,13 @@
|
||||
|
||||
module("luci.controller.hd_idle", package.seeall)
|
||||
|
||||
I18N = require "luci.i18n"
|
||||
translate = I18N.translate
|
||||
|
||||
function index()
|
||||
if not nixio.fs.access("/etc/config/hd-idle") then
|
||||
return
|
||||
end
|
||||
|
||||
local page
|
||||
page = entry({"admin", "services", "hd_idle"}, cbi("hd_idle"), _(translate("Hard Drive Idle")), 60)
|
||||
|
||||
page = entry({"admin", "services", "hd_idle"}, cbi("hd_idle"), _("Hard Drive Idle"), 60)
|
||||
page.dependent = true
|
||||
end
|
||||
|
@ -1,11 +1,8 @@
|
||||
module("luci.controller.umount", package.seeall)
|
||||
|
||||
I18N = require "luci.i18n"
|
||||
translate = I18N.translate
|
||||
|
||||
function index()
|
||||
local page
|
||||
|
||||
page = entry({"admin", "services", "umount"}, cbi("umount", {hidesavebtn=true, hideresetbtn=true}), translate("Safely Eject Drive"), 25)
|
||||
page = entry({"admin", "services", "umount"}, cbi("umount", {hidesavebtn=true, hideresetbtn=true}), "Safely Eject Drive", 25)
|
||||
page.dependent = true
|
||||
end
|
||||
|
@ -4,7 +4,8 @@
|
||||
require("nixio.fs")
|
||||
|
||||
m = Map("hd-idle", "Hard Drive Idle",
|
||||
translate("This is a utility program for spinning-down external disks after a period of idle time."))
|
||||
translate("This is a utility program for spinning-down external " ..
|
||||
"disks after a period of idle time."))
|
||||
|
||||
s = m:section(TypedSection, "hd-idle", translate("Settings"))
|
||||
s.anonymous = true
|
||||
|
@ -5,22 +5,21 @@ translate = I18N.translate
|
||||
|
||||
function index()
|
||||
local fs = require "nixio.fs"
|
||||
if not fs.stat("/etc/nosms") then
|
||||
local page
|
||||
page = entry({"admin", "modem", "sms"}, template("rooter/sms"), translate("短信功能"), 35)
|
||||
page.dependent = true
|
||||
|
||||
end
|
||||
|
||||
|
||||
if not fs.stat("/etc/nosms") then
|
||||
local page
|
||||
page = entry({"admin", "modem", "sms"}, template("rooter/sms"), translate("短信功能"), 35)
|
||||
page.dependent = true
|
||||
|
||||
end
|
||||
|
||||
entry({"admin", "modem", "check_read"}, call("action_check_read"))
|
||||
entry({"admin", "modem", "del_sms"}, call("action_del_sms"))
|
||||
entry({"admin", "modem", "send_sms"}, call("action_send_sms"))
|
||||
entry({"admin", "modem", "change_sms"}, call("action_change_sms"))
|
||||
entry({"admin", "modem", "change_smsdn"}, call("action_change_smsdn"))
|
||||
entry({"admin", "modem", "change_smsflag"}, call("action_change_smsflag"))
|
||||
entry({"admin", "modem", "delall_sms"}, call("action_delall_sms"))
|
||||
end
|
||||
|
||||
function trim(s)
|
||||
@ -71,12 +70,16 @@ function action_send_sms()
|
||||
luci.http.write_json(rv)
|
||||
end
|
||||
|
||||
function action_delall_sms()
|
||||
smsnum = luci.model.uci.cursor():get("modem", "general", "smsnum")
|
||||
os.execute("/usr/lib/sms/delall.sh " .. smsnum)
|
||||
end
|
||||
|
||||
function action_del_sms()
|
||||
local set = tonumber(luci.http.formvalue("set"))
|
||||
if set ~= nil and set > 0 then
|
||||
set = set - 1;
|
||||
local set = luci.http.formvalue("set")
|
||||
if set ~= nil then
|
||||
smsnum = luci.model.uci.cursor():get("modem", "general", "smsnum")
|
||||
os.execute("/usr/lib/sms/delsms.sh " .. smsnum .. " " .. set)
|
||||
os.execute("/usr/lib/sms/delsms.sh " .. smsnum .. " " .. set)
|
||||
os.execute("touch /tmp/smswakeup" .. smsnum)
|
||||
end
|
||||
end
|
||||
@ -122,7 +125,7 @@ function action_check_read()
|
||||
line = file:read("*line")
|
||||
full = full .. line
|
||||
if k < i then
|
||||
full = full .. '<br />'
|
||||
full = full .. '\n'
|
||||
end
|
||||
end
|
||||
else
|
||||
@ -157,4 +160,3 @@ function action_change_smsflag()
|
||||
local set = tonumber(luci.http.formvalue("set"))
|
||||
os.execute("/usr/lib/sms/toggle.sh " .. set)
|
||||
end
|
||||
|
||||
|
@ -22,7 +22,7 @@
|
||||
if ( ss == "0" )
|
||||
{
|
||||
clearListBox("smsList");
|
||||
document.getElementById('message').innerHTML="";
|
||||
document.getElementById('message').value="";
|
||||
document.getElementById('total').innerHTML="";
|
||||
document.getElementById('used').innerHTML="";
|
||||
document.getElementById('mslots').innerHTML="";
|
||||
@ -32,7 +32,7 @@
|
||||
if ( ss == "1" )
|
||||
{
|
||||
clearListBox("smsList");
|
||||
document.getElementById('message').innerHTML="";
|
||||
document.getElementById('message').value="";
|
||||
document.getElementById('total').innerHTML="";
|
||||
document.getElementById('used').innerHTML="";
|
||||
document.getElementById('mslots').innerHTML="";
|
||||
@ -86,7 +86,7 @@
|
||||
var i;
|
||||
for(i=0;i<len;i++)
|
||||
{
|
||||
index[indx] = parseInt(arr[i]);
|
||||
index[indx] = arr[i];
|
||||
number[indx] = arr[i+1];
|
||||
ttext[indx] = arr[i+2];
|
||||
var txtline = arr[i+3];
|
||||
@ -102,7 +102,7 @@
|
||||
if ( selectline == -1 )
|
||||
{
|
||||
select.value = 0;
|
||||
document.getElementById('message').innerHTML=ttext[0];
|
||||
document.getElementById('message').value=ttext[0];
|
||||
selectline = 0;
|
||||
}
|
||||
else
|
||||
@ -112,7 +112,7 @@
|
||||
selectline = indx -1 ;
|
||||
}
|
||||
select.value = selectline;
|
||||
document.getElementById('message').innerHTML=ttext[selectline];
|
||||
document.getElementById('message').value=ttext[selectline];
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -120,7 +120,7 @@
|
||||
}
|
||||
);
|
||||
|
||||
document.getElementById('message').innerHTML=" ";
|
||||
document.getElementById('message').value=" ";
|
||||
document.getElementById('total').innerHTML="0";
|
||||
document.getElementById('used').innerHTML="0";
|
||||
document.getElementById('mslots').innerHTML="0";
|
||||
@ -167,7 +167,7 @@
|
||||
{
|
||||
var s = document.getElementById("smsList").value;
|
||||
selectline = s;
|
||||
document.getElementById('message').innerHTML=ttext[s];
|
||||
document.getElementById('message').value=ttext[s];
|
||||
}
|
||||
|
||||
function sendsms()
|
||||
@ -203,7 +203,7 @@
|
||||
}
|
||||
num = num.concat(t);
|
||||
alert("<%:SMS will be queued for processing.\nA status update will follow.%>");
|
||||
document.getElementById("sstat").innerHTML="<%:状态 :消息正在发送%>";
|
||||
document.getElementById("sstat").innerHTML="<%:状态 消息正在发送%>";
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin", "modem", "send_sms")%>',
|
||||
{ set: num },
|
||||
function(x, rv)
|
||||
@ -215,90 +215,113 @@
|
||||
);
|
||||
}
|
||||
|
||||
function readcheck()
|
||||
{
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin", "modem", "check_read")%>', null,
|
||||
function(x, rv)
|
||||
{
|
||||
var ss = rv.ready;
|
||||
document.getElementById('message').style.color = "initial";
|
||||
document.getElementById('conntype').innerHTML=rv.conntype;
|
||||
if ( ss == "1" )
|
||||
{
|
||||
clearListBox("smsList");
|
||||
document.getElementById('message').value="";
|
||||
document.getElementById('total').innerHTML="";
|
||||
document.getElementById('used').innerHTML="";
|
||||
document.getElementById('supported').innerHTML="<%:您有未读的短信,请前往查看%>";
|
||||
}
|
||||
if ( ss == "3" )
|
||||
{
|
||||
document.getElementById('supported').innerHTML="<%:消息读取有问题%>";
|
||||
}
|
||||
if ( ss == "2" )
|
||||
{
|
||||
document.getElementById('supported').innerHTML="<%:存在短信%>";
|
||||
clearListBox("smsList");
|
||||
document.getElementById('total').innerHTML=rv.max;
|
||||
document.getElementById('used').innerHTML=rv.used;
|
||||
var line=rv.line;
|
||||
var arr=(line.split("\x1D"));
|
||||
var len = arr.length;
|
||||
indx = 0;
|
||||
var i;
|
||||
for(i=0;i<len;i++)
|
||||
{
|
||||
index[indx] = parseInt(arr[i]);
|
||||
number[indx] = arr[i+1];
|
||||
ttext[indx] = arr[i+2];
|
||||
var txtline = arr[i+3];
|
||||
txtline = txtline.replace(/ /g,"\240");
|
||||
|
||||
var select = document.getElementById("smsList");
|
||||
select.options[select.options.length] = new Option(txtline, indx);
|
||||
i = i + 3;
|
||||
indx = indx + 1;
|
||||
}
|
||||
if ( indx != -1 )
|
||||
{
|
||||
if ( selectline == -1 )
|
||||
{
|
||||
select.value = 0;
|
||||
document.getElementById('message').value=ttext[0];
|
||||
selectline = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( selectline > indx-1 )
|
||||
{
|
||||
selectline = indx -1 ;
|
||||
}
|
||||
select.value = selectline;
|
||||
document.getElementById('message').value=ttext[selectline];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function delallsms()
|
||||
{
|
||||
var r=confirm("<%:是否确定要删除所有短信?%>");
|
||||
if (r==false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
clearListBox("smsList");
|
||||
document.getElementById('message').style.color = "red";
|
||||
document.getElementById('message').value="<%:将删除所有短信.更新列表可能需要一些时间.%>";
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin", "modem", "删除所有短信")%>',
|
||||
null,
|
||||
function()
|
||||
{
|
||||
readcheck();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function delsms()
|
||||
{
|
||||
if ( selectline == -1 )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
var r=confirm("<%:确认删除选中消息 ?%>");
|
||||
var r=confirm("<%:确认删除选中消息?%>");
|
||||
if (r==false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
var s = document.getElementById("smsList").value;
|
||||
var dx = index[s];
|
||||
dx = dx + 1;
|
||||
clearListBox("smsList");
|
||||
document.getElementById('message').style.color = "red";
|
||||
document.getElementById('message').innerHTML="<%:短信将被删除,同步到列表可能会很久(反复提交删除申请一样很久)%>";
|
||||
document.getElementById('message').value="<%:短信将被删除,同步到列表可能会很久(反复提交删除申请一样很久)%>";
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin", "modem", "del_sms")%>',
|
||||
{ set: dx },
|
||||
function()
|
||||
{
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin", "modem", "check_read")%>', null,
|
||||
function(x, rv)
|
||||
{
|
||||
var ss = rv.ready;
|
||||
document.getElementById('message').style.color = "initial";
|
||||
document.getElementById('conntype').innerHTML=rv.conntype;
|
||||
if ( ss == "1" )
|
||||
{
|
||||
clearListBox("smsList");
|
||||
document.getElementById('message').innerHTML="";
|
||||
document.getElementById('total').innerHTML="";
|
||||
document.getElementById('used').innerHTML="";
|
||||
document.getElementById('supported').innerHTML="<%:您有未读的短信,请前往查看%>";
|
||||
}
|
||||
if ( ss == "3" )
|
||||
{
|
||||
document.getElementById('supported').innerHTML="<%:消息读取有问题%>";
|
||||
}
|
||||
if ( ss == "2" )
|
||||
{
|
||||
document.getElementById('supported').innerHTML="<%:存在短信%>";
|
||||
clearListBox("smsList");
|
||||
document.getElementById('total').innerHTML=rv.max;
|
||||
document.getElementById('used').innerHTML=rv.used;
|
||||
var line=rv.line;
|
||||
var arr=(line.split("\x1D"));
|
||||
var len = arr.length;
|
||||
indx = 0;
|
||||
var i;
|
||||
for(i=0;i<len;i++)
|
||||
{
|
||||
index[indx] = parseInt(arr[i]);
|
||||
number[indx] = arr[i+1];
|
||||
ttext[indx] = arr[i+2];
|
||||
var txtline = arr[i+3];
|
||||
txtline = txtline.replace(/ /g,"\240");
|
||||
|
||||
var select = document.getElementById("smsList");
|
||||
select.options[select.options.length] = new Option(txtline, indx);
|
||||
i = i + 3;
|
||||
indx = indx + 1;
|
||||
}
|
||||
if ( indx != -1 )
|
||||
{
|
||||
if ( selectline == -1 )
|
||||
{
|
||||
select.value = 0;
|
||||
document.getElementById('message').innerHTML=ttext[0];
|
||||
selectline = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( selectline > indx-1 )
|
||||
{
|
||||
selectline = indx -1 ;
|
||||
}
|
||||
select.value = selectline;
|
||||
document.getElementById('message').innerHTML=ttext[selectline];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
readcheck();
|
||||
}
|
||||
);
|
||||
}
|
||||
@ -413,8 +436,8 @@
|
||||
|
||||
<table width="550" border="0">
|
||||
<tr>
|
||||
<td width="18%"><div align="center"><strong><%:SIM可存放的短信空间 (条)%></strong></div></td>
|
||||
<td width="18%"><div align="center"><strong><%:已使用的SIM短信空间 (条)%></strong></div></td>
|
||||
<td width="18%"><div align="center"><strong><u><%:SIM可存放的短信空间 (条)%></u></strong></div></td>
|
||||
<td width="18%"><div align="center"><strong><u><%:已使用的SIM短信空间 (条)%></u></strong></div></td>
|
||||
<td width="34%"> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
@ -443,6 +466,14 @@
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<table width="700" border="0">
|
||||
<tr>
|
||||
<td width="3%"> </td>
|
||||
<td width="17%"><input type="button" id="delallbtn" class="cbi-button cbi-button-remove" value="<%:删除所有短信%>" onclick="return delallsms()" /></td>
|
||||
<td width="80%"> </td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<table width="700" border="0">
|
||||
<tr>
|
||||
<td width="4%"><div align="center"><strong><u><%:已读状态%></u></strong></div></td>
|
||||
@ -450,7 +481,6 @@
|
||||
<td width="8%"><div align="left"><strong><u><%:Date%></u></strong></div></td>
|
||||
<td width="11%"><div align="left"><strong><u><%:时间%></u></strong></div></td>
|
||||
<td width="35%"><div align="left"><strong><u><%:短信%></u></strong></div></td>
|
||||
|
||||
<td width="24%"><div align="left"> </div></td>
|
||||
|
||||
</tr>
|
||||
@ -467,15 +497,18 @@
|
||||
|
||||
<table width="550" border="0">
|
||||
<tr>
|
||||
<td width="15%"><div align="left"><strong><%:短信内容 :%></strong></div></td>
|
||||
<td width="70%"><ul id="message"></ul></td>
|
||||
<td width="15%"> </td>
|
||||
<td width="7%"><div align="left"><strong><%:短信内容 :%></strong></div></td>
|
||||
<!-- <td width="70%"><ul id="message"></ul></td> -->
|
||||
<td width="80%">
|
||||
<textarea readonly="readonly" name="message" id="message" rows="6" style="font-size : 20px;width: 600px;" maxlength="160"></textarea>
|
||||
</td>
|
||||
<td width="13%"> </td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<table width="550" border="0">
|
||||
<tr>
|
||||
<td width="17%"><input type="button" id="delbtn" class="cbi-button cbi-button-apply" value="<%:删除短信%>" onclick="return delsms()" /></td>
|
||||
<td width="17%"><input type="button" id="delbtn" class="cbi-button cbi-button-remove" value="<%:删除短信%>" onclick="return delsms()" /></td>
|
||||
<td width="17%"><input type="button" id="replybtn" class="cbi-button cbi-button-apply" value="<%:回复短信%>" onclick="return replysms()" /></td>
|
||||
<td width="17%"><input type="button" id="newbtn" class="cbi-button cbi-button-apply" value="<%:新建短信%>" onclick="return newsms()" /></td>
|
||||
<td width="49%"> </td>
|
||||
@ -494,7 +527,6 @@
|
||||
|
||||
<table id="sendtxt" width="700" border="0" style="display:table;">
|
||||
<tr>
|
||||
|
||||
<td width="100%">
|
||||
<textarea name="txtmessage" id="txtmessage" rows="6" style="width: 600px;" maxlength="160"></textarea>
|
||||
</td>
|
||||
@ -522,4 +554,3 @@
|
||||
</div>
|
||||
</form>
|
||||
<%+footer%>
|
||||
|
||||
|
35
rooter/0basicsupport/ext-sms/files/usr/lib/sms/delall.sh
Normal file
35
rooter/0basicsupport/ext-sms/files/usr/lib/sms/delall.sh
Normal file
@ -0,0 +1,35 @@
|
||||
#!/bin/sh
|
||||
|
||||
ROOTER=/usr/lib/rooter
|
||||
|
||||
log() {
|
||||
modlog "Delete SMS" "$@"
|
||||
}
|
||||
|
||||
CURRMODEM=$1
|
||||
COMMPORT="/dev/ttyUSB"$(uci get modem.modem$CURRMODEM.commport)
|
||||
SMSLOC=$(uci -q get modem.modem$CURRMODEM.smsloc)
|
||||
|
||||
LOCKDIR="/tmp/smslock$CURRMODEM"
|
||||
PIDFILE="${LOCKDIR}/PID"
|
||||
|
||||
while [ 1 -lt 6 ]; do
|
||||
if mkdir "${LOCKDIR}" &>/dev/null; then
|
||||
echo "$$" > "${PIDFILE}"
|
||||
ATCMDD="AT+CPMS=\"$SMSLOC\";+CMGD=1,4"
|
||||
OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD")
|
||||
log "$OX"
|
||||
uci set modem.modem$CURRMODEM.smsnum=999
|
||||
uci commit modem
|
||||
break
|
||||
else
|
||||
OTHERPID="$(cat "${PIDFILE}")"
|
||||
if [ $? = 0 ]; then
|
||||
if ! kill -0 $OTHERPID &>/dev/null; then
|
||||
rm -rf "${LOCKDIR}"
|
||||
fi
|
||||
fi
|
||||
sleep 1
|
||||
fi
|
||||
done
|
||||
rm -rf "${LOCKDIR}"
|
@ -3,12 +3,13 @@
|
||||
ROOTER=/usr/lib/rooter
|
||||
|
||||
log() {
|
||||
logger -t "Delete SMS" "$@"
|
||||
modlog "Delete SMS" "$@"
|
||||
}
|
||||
|
||||
CURRMODEM=$1
|
||||
shift 1
|
||||
SLOTS="$@"
|
||||
log "$SLOTS"
|
||||
|
||||
COMMPORT="/dev/ttyUSB"$(uci get modem.modem$CURRMODEM.commport)
|
||||
|
||||
@ -17,13 +18,14 @@ SMSLOC=$(uci -q get modem.modem$CURRMODEM.smsloc)
|
||||
LOCKDIR="/tmp/smslock$CURRMODEM"
|
||||
PIDFILE="${LOCKDIR}/PID"
|
||||
|
||||
while [ 1 -lt 6 ]; do
|
||||
while [ true ]; do
|
||||
if mkdir "${LOCKDIR}" &>/dev/null; then
|
||||
echo "$$" > "${PIDFILE}"
|
||||
for SLOT in $SLOTS
|
||||
do
|
||||
ATCMDD="AT+CPMS=\"$SMSLOC\";+CMGD=$SLOT"
|
||||
OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD")
|
||||
log "$OX"
|
||||
done
|
||||
uci set modem.modem$CURRMODEM.smsnum=999
|
||||
uci commit modem
|
||||
|
165
rooter/0basicsupport/ext-sms/files/usr/lib/sms/merge.lua
Normal file
165
rooter/0basicsupport/ext-sms/files/usr/lib/sms/merge.lua
Normal file
@ -0,0 +1,165 @@
|
||||
#!/usr/bin/lua
|
||||
|
||||
function ltrim(s)
|
||||
return s:match'^%s*(.*)'
|
||||
end
|
||||
|
||||
file=arg[1]
|
||||
filet=arg[1]
|
||||
|
||||
overall = {}
|
||||
|
||||
cntr = 1
|
||||
filein = io.open(file, "r")
|
||||
maxslot = -1
|
||||
repeat
|
||||
message = {}
|
||||
local line = filein:read("*line")
|
||||
if line == nil then
|
||||
break
|
||||
end
|
||||
if cntr < 2 then
|
||||
maxused = line
|
||||
line = filein:read("*line")
|
||||
maxslots = line
|
||||
cntr=2
|
||||
else
|
||||
message['slot'] = line
|
||||
message['phone'] = filein:read("*line")
|
||||
nline = filein:read("*line")
|
||||
message['nline'] = nline
|
||||
ncntr = 1
|
||||
msg=""
|
||||
message['msgnum'] = "xxx"
|
||||
message['msgord'] = "xxx"
|
||||
message['msgmax'] = "xxx"
|
||||
lines = filein:read("*line")
|
||||
s, e = lines:find("Msg# ")
|
||||
if s ~= nil then
|
||||
bs, be = lines:find(",", e+1)
|
||||
msgnum = lines:sub(e+1, be-1)
|
||||
message['msgnum'] = msgnum
|
||||
s, e = lines:find("/", be+1)
|
||||
msgord = lines:sub(be+1, e-1)
|
||||
message['msgord'] = msgord
|
||||
message['msgmax'] = lines:sub(e+1)
|
||||
lines = filein:read("*line")
|
||||
end
|
||||
msg = lines
|
||||
nc = tonumber(nline)
|
||||
if nc > 2 then
|
||||
for i=1,nc-2,1
|
||||
do
|
||||
lines = filein:read("*line")
|
||||
if lines ~= "" then
|
||||
msg = msg .. "\n" .. lines
|
||||
else
|
||||
if i == nc-2 then
|
||||
if msgord == message['msgmax'] then
|
||||
msg = msg .. "\n\n"
|
||||
else
|
||||
msg = msg .. "\n\n"
|
||||
end
|
||||
else
|
||||
msg = msg .. "\n"
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
--print(nln, msg)
|
||||
--msg = msg .. "\n"
|
||||
end
|
||||
message['msg'] = msg
|
||||
message['numlines'] = nc - 1
|
||||
sht = filein:read("*line")
|
||||
s, e = sht:find("Msg#")
|
||||
if s ~= nil then
|
||||
shtt = sht:sub(1, s-1)
|
||||
bs, be = sht:find("/", e)
|
||||
sht = shtt .. sht:sub(be+2)
|
||||
end
|
||||
message['short'] = sht
|
||||
overall[message['slot']] = message
|
||||
if maxslot < tonumber(message['slot']) then
|
||||
maxslot = tonumber(message['slot'])
|
||||
end
|
||||
end
|
||||
until 1==0
|
||||
filein:close()
|
||||
|
||||
fileout = io.open(filet, "w")
|
||||
fileout:write(maxused, "\n")
|
||||
fileout:write(maxslots, "\n")
|
||||
|
||||
for i=0,maxslot,1
|
||||
do
|
||||
msgbuild = {}
|
||||
shortmsg = {}
|
||||
if overall[tostring(i)] ~= nil then
|
||||
--print(i, overall[tostring(i)]['msgnum'])
|
||||
if overall[tostring(i)]['msgnum'] == "xxx" then
|
||||
fileout:write(overall[tostring(i)]['slot'], "\n")
|
||||
fileout:write(overall[tostring(i)]['phone'], "\n")
|
||||
fileout:write(overall[tostring(i)]['nline'], "\n")
|
||||
fileout:write(overall[tostring(i)]['msg'], "\n")
|
||||
fileout:write(overall[tostring(i)]['short'], "\n")
|
||||
else
|
||||
msgnum = overall[tostring(i)]['msgnum']
|
||||
msgtmp = overall[tostring(i)]['slot']
|
||||
msgord = overall[tostring(i)]['msgord']
|
||||
msgmax = tonumber(overall[tostring(i)]['msgmax'])
|
||||
msg = overall[tostring(i)]['msg']
|
||||
numlines = overall[tostring(i)]['numlines']
|
||||
--print(numlines)
|
||||
msgbuild[overall[tostring(i)]['msgord']] = overall[tostring(i)]['msg']
|
||||
shortmsg[overall[tostring(i)]['msgord']] = overall[tostring(i)]['short']
|
||||
for j=i+1,maxslot,1
|
||||
do
|
||||
if overall[tostring(j)] ~= nil then
|
||||
if overall[tostring(j)]['msgnum'] == msgnum then
|
||||
numlines = numlines + (overall[tostring(j)]['numlines'])
|
||||
--print(overall[tostring(j)]['numlines'])
|
||||
msgtmp = msgtmp .. " " .. overall[tostring(j)]['slot']
|
||||
msgbuild[overall[tostring(j)]['msgord']] = overall[tostring(j)]['msg']
|
||||
shortmsg[overall[tostring(j)]['msgord']] = overall[tostring(j)]['short']
|
||||
overall[tostring(j)] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
msg=""
|
||||
mflg = 0
|
||||
short = nil
|
||||
for j=1,msgmax,1
|
||||
do
|
||||
if msgbuild[tostring(j)] ~= nil then
|
||||
msg = msg .. msgbuild[tostring(j)]
|
||||
if short == nil then
|
||||
short = shortmsg[tostring(j)]
|
||||
end
|
||||
else
|
||||
mflg = 1
|
||||
end
|
||||
end
|
||||
fileout:write(msgtmp, "\n")
|
||||
fileout:write(overall[tostring(i)]['phone'], "\n")
|
||||
|
||||
if mflg ~= 0 then
|
||||
msg = "Partial Message : " .. msg
|
||||
t = short:gsub("%s+", " ")
|
||||
short = "Partial Message " .. t
|
||||
end
|
||||
endc = string.sub(msg, -2)
|
||||
if endc == "\n\n" then
|
||||
mlen = msg:len() - 2
|
||||
msg = string.sub(msg,1,mlen)
|
||||
end
|
||||
local _,n = msg:gsub("\n","")
|
||||
fileout:write(tostring(n+1), "\n")
|
||||
fileout:write(msg, "\n")
|
||||
fileout:write(short, "\n")
|
||||
end
|
||||
end
|
||||
end
|
||||
fileout:close()
|
||||
|
||||
|
@ -855,6 +855,7 @@ else
|
||||
end
|
||||
tfile:close()
|
||||
end
|
||||
os.execute("/usr/lib/sms/merge.lua " .. tfname)
|
||||
os.execute("mv " .. tfname .. " /tmp/smstext" .. modemn)
|
||||
|
||||
if #delslots > 0 then
|
||||
|
@ -1,15 +1,12 @@
|
||||
module("luci.controller.guestwifi", package.seeall)
|
||||
|
||||
I18N = require "luci.i18n"
|
||||
translate = I18N.translate
|
||||
|
||||
function index()
|
||||
local page
|
||||
if not nixio.fs.access("/etc/config/wireless") then
|
||||
return
|
||||
end
|
||||
|
||||
page = entry({"admin", "network", "guestwifi"}, cbi("guestwifi", {hidesavebtn=true, hideresetbtn=true}), translate("Guest Wifi"), 22)
|
||||
page = entry({"admin", "network", "guestwifi"}, cbi("guestwifi", {hidesavebtn=true, hideresetbtn=true}), "Guest Wifi", 22)
|
||||
page.dependent = true
|
||||
entry( {"admin", "network", "guestwifi", "edit"}, cbi("guestwifi-edit"), nil ).leaf = true
|
||||
|
||||
|
@ -99,12 +99,12 @@ function auto.cfgvalue(self, section)
|
||||
val = 0
|
||||
end
|
||||
if val == "1" then
|
||||
return translate("WPA-PSK (Medium Security)")
|
||||
return "WPA-PSK (Medium Security)"
|
||||
else
|
||||
if val == "2" then
|
||||
return translate("WPA2-PSK (Strong Security)")
|
||||
return "WPA2-PSK (Strong Security)"
|
||||
else
|
||||
return translate("None")
|
||||
return "None"
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -118,9 +118,9 @@ function qos.cfgvalue(self, section)
|
||||
if val == "1" then
|
||||
dl_cfg = self.map:get(section, "dl")
|
||||
ul_cfg = self.map:get(section, "ul")
|
||||
return translate("Download : ") .. dl_cfg .. translate(" Mbit/s / Upload : ") .. ul_cfg .. translate(" Mbit/s")
|
||||
return "Download : " .. dl_cfg .. " Mbit/s / Upload : " .. ul_cfg .. " Mbit/s"
|
||||
else
|
||||
return translate("Disabled")
|
||||
return "Disabled"
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -328,6 +328,14 @@ _proto_mbim_setup() {
|
||||
log "Failed to connect to network"
|
||||
return 1
|
||||
fi
|
||||
log "Save Connect Data"
|
||||
uci set modem.modem$CURRMODEM.mdevice=$device
|
||||
uci set modem.modem$CURRMODEM.mapn=$apn
|
||||
uci set modem.modem$CURRMODEM.mipt=$itp
|
||||
uci set modem.modem$CURRMODEM.mauth=$auth
|
||||
uci set modem.modem$CURRMODEM.musername=$username
|
||||
uci set modem.modem$CURRMODEM.mpassword=$password
|
||||
uci commit modem
|
||||
|
||||
tid=$((tid + 1))
|
||||
|
||||
@ -467,6 +475,10 @@ _proto_mbim_setup() {
|
||||
# SIGNAL=$(umbim $DBG -n -t $tid -d $device signal)
|
||||
# CSQ=$(echo "$SIGNAL" | awk '/rssi:/ {print $2}')
|
||||
|
||||
if [ -e $ROOTER/modem-led.sh ]; then
|
||||
$ROOTER/modem-led.sh $CURRMODEM 3
|
||||
fi
|
||||
|
||||
$ROOTER/log/logger "Modem #$CURRMODEM Connected"
|
||||
log "Modem $CURRMODEM Connected"
|
||||
|
||||
@ -540,7 +552,8 @@ _proto_mbim_setup() {
|
||||
$ROOTER/timezone.sh &
|
||||
fi
|
||||
fi
|
||||
CLB=$(uci -q get modem.modeminfo$CURRMODEM.lb)
|
||||
#CLB=$(uci -q get modem.modeminfo$CURRMODEM.lb)
|
||||
CLB=1
|
||||
if [ -e /etc/config/mwan3 ]; then
|
||||
INTER=$(uci get modem.modeminfo$CURRMODEM.inter)
|
||||
if [ -z $INTER ]; then
|
||||
@ -577,6 +590,8 @@ proto_mbim_setup() {
|
||||
CPORT=$(uci get modem.modem$CURRMODEM.commport)
|
||||
ATCMDD="AT+COPS=0"
|
||||
OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD")
|
||||
#log "Restart Modem"
|
||||
#/usr/lib/rooter/luci/restart.sh $CURRMODEM
|
||||
sleep 5
|
||||
}
|
||||
|
||||
|
@ -32,11 +32,7 @@ define Package/rqmi/description
|
||||
endef
|
||||
|
||||
TARGET_CFLAGS += \
|
||||
-I$(STAGING_DIR)/usr/include \
|
||||
-ffunction-sections \
|
||||
-fdata-sections \
|
||||
-Wno-error=dangling-pointer \
|
||||
-Wno-error=maybe-uninitialized
|
||||
-I$(STAGING_DIR)/usr/include -ffunction-sections -fdata-sections
|
||||
|
||||
TARGET_LDFLAGS += -Wl,--gc-sections
|
||||
|
||||
|
@ -202,6 +202,14 @@ for isp in $isplist
|
||||
if [[ -z $(echo "$CONN" | grep -o "disconnected") ]]; then
|
||||
ret=0
|
||||
|
||||
uci set modem.modem$CURRMODEM.mdevice=$device
|
||||
uci set modem.modem$CURRMODEM.mcid=$cid
|
||||
uci set modem.modem$CURRMODEM.mapn=$NAPN
|
||||
uci set modem.modem$CURRMODEM.mauth=$auth
|
||||
uci set modem.modem$CURRMODEM.musername=$username
|
||||
uci set modem.modem$CURRMODEM.mpassword=$password
|
||||
uci commit modem
|
||||
|
||||
CONN4=$(uqmi -s -d "$device" --set-client-id wds,"$cid" --get-current-settings)
|
||||
log "GET-CURRENT-SETTINGS is $CONN4"
|
||||
|
||||
|
@ -1,34 +0,0 @@
|
||||
#Owned by DairyMan@Whirlpool
|
||||
#
|
||||
#Copyright GNU act.
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=mesh-mesh
|
||||
PKG_VERSION:=4.500
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/mesh-mesh
|
||||
SECTION:=utils
|
||||
CATEGORY:=ROOter
|
||||
SUBMENU:=Mesh Support
|
||||
DEPENDS:=+kmod-batman-adv +alfred +batctl +ip
|
||||
TITLE:=Install scripts for Mesh Network
|
||||
PKGARCH:=all
|
||||
endef
|
||||
|
||||
define Package/mesh-mesh/description
|
||||
Install scripts for Mesh Network
|
||||
endef
|
||||
|
||||
|
||||
define Build/Compile
|
||||
endef
|
||||
|
||||
define Package/mesh-mesh/install
|
||||
$(CP) ./files/* $(1)/
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,mesh-mesh))
|
@ -1,16 +0,0 @@
|
||||
config mesh 'bat0'
|
||||
option aggregated_ogms '1'
|
||||
option ap_isolation '0'
|
||||
option bonding '0'
|
||||
option fragmentation '0'
|
||||
option gw_bandwidth '10000/2000'
|
||||
option gw_mode 'client'
|
||||
option gw_sel_class '20'
|
||||
option log_level '2'
|
||||
option orig_interval '1000'
|
||||
option bridge_loop_avoidance '1'
|
||||
option distributed_arp_table '1'
|
||||
option multicast_mode '1'
|
||||
option network_coding '0'
|
||||
option hop_penalty '30'
|
||||
option isolation_mark '0'
|
@ -1,18 +0,0 @@
|
||||
|
||||
config radio 'radio'
|
||||
option radionumber '0'
|
||||
option usedfs '1'
|
||||
option channelwidth '0'
|
||||
option channellist '0'
|
||||
option channelindex '10'
|
||||
option dedicated '0'
|
||||
|
||||
config network 'network'
|
||||
option networkid 'MeshCloud'
|
||||
option netencrypted '1'
|
||||
option netpassword 'MeshPassword123'
|
||||
|
||||
config roam 'roam'
|
||||
option signalenable '1'
|
||||
option signalid 'abcd'
|
||||
|
@ -1,34 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
dhcp4_discover () {
|
||||
ifup lan_dhcp
|
||||
}
|
||||
|
||||
dhcp4_kill () {
|
||||
ifdown lan_dhcp
|
||||
}
|
||||
|
||||
dnsmasq_start () {
|
||||
uci revert -P/var/state dhcp.@dnsmasq[0].domainneeded
|
||||
uci revert -P/var/state dhcp.@dnsmasq[0].boguspriv
|
||||
uci revert -P/var/state dhcp.@dnsmasq[0].rebind_protection
|
||||
uci revert -P/var/state dhcp.lan.ignore
|
||||
/etc/init.d/dnsmasq restart
|
||||
}
|
||||
|
||||
dnsmasq_stop () {
|
||||
uci set -P/var/state dhcp.@dnsmasq[0].domainneeded=
|
||||
uci set -P/var/state dhcp.@dnsmasq[0].boguspriv=
|
||||
uci set -P/var/state dhcp.@dnsmasq[0].rebind_protection=0
|
||||
uci set -P/var/state dhcp.lan.ignore=1
|
||||
echo no-dhcp-interface=br-lan >> /var/etc/dnsmasq.conf
|
||||
/etc/init.d/dnsmasq restart
|
||||
}
|
||||
|
||||
if [ "$BATTYPE" = "gw" ] ; then
|
||||
case "$BATACTION" in
|
||||
add) dnsmasq_stop ; dhcp4_discover ;;
|
||||
del) dhcp4_kill ; dnsmasq_start ;;
|
||||
change) dhcp4_kill ; sleep 5 ; dhcp4_discover ;;
|
||||
esac
|
||||
fi
|
@ -1,9 +0,0 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
# Copyright (C) 2006 OpenWrt.org
|
||||
|
||||
START=99
|
||||
|
||||
start() {
|
||||
/usr/lib/mesh/checker.sh
|
||||
}
|
||||
|
@ -1,249 +0,0 @@
|
||||
--[[
|
||||
LuCI - Lua Configuration Interface
|
||||
|
||||
Copyright 2012 Jo-Philipp Wich <xm@subsignal.org>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
$Id$
|
||||
]]--
|
||||
|
||||
module("luci.controller.batman", package.seeall)
|
||||
|
||||
local function split(str, pat)
|
||||
local t = {} -- NOTE: use {n = 0} in Lua-5.0
|
||||
local fpat = "(.-)" .. pat
|
||||
local last_end = 1
|
||||
local s, e, cap = str:find(fpat, 1)
|
||||
while s do
|
||||
if s ~= 1 or cap ~= "" then
|
||||
table.insert(t,cap)
|
||||
end
|
||||
last_end = e+1
|
||||
s, e, cap = str:find(fpat, last_end)
|
||||
end
|
||||
if last_end <= #str then
|
||||
cap = str:sub(last_end)
|
||||
table.insert(t, cap)
|
||||
end
|
||||
return t
|
||||
end
|
||||
|
||||
|
||||
function index()
|
||||
local page
|
||||
|
||||
page = node("admin", "mesh", "batman")
|
||||
page.target = template("batman/batman")
|
||||
page.title = _("Mesh Status")
|
||||
page.order = 1
|
||||
|
||||
node("batman")
|
||||
|
||||
page = node("batman", "json")
|
||||
page.target = call("act_json")
|
||||
|
||||
page = node("batman", "topo")
|
||||
page.target = call("act_topo")
|
||||
page.leaf = true
|
||||
|
||||
page = node("batman", "graph")
|
||||
page.target = template("batman_graph")
|
||||
page.leaf = true
|
||||
end
|
||||
|
||||
function act_topo(mode)
|
||||
if not mode or mode == "dot" or mode == "json" then
|
||||
local fd = io.popen("batadv-vis -f %s" %( mode or "dot" ))
|
||||
if fd then
|
||||
if mode == "json" then
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write("[")
|
||||
local ln
|
||||
repeat
|
||||
ln = fd:read("*l")
|
||||
if ln then
|
||||
luci.http.write(ln)
|
||||
luci.http.write(", ")
|
||||
end
|
||||
until not ln
|
||||
luci.http.write("{ } ]")
|
||||
else
|
||||
luci.http.prepare_content("text/vnd.graphviz")
|
||||
luci.http.header("Content-Disposition",
|
||||
"attachment; filename=topo-%s-%s.vd"
|
||||
%{ luci.sys.hostname(), os.date("%Y%m%d-%H%M%S") })
|
||||
luci.http.write(fd:read("*a"))
|
||||
end
|
||||
fd:close()
|
||||
else
|
||||
luci.http.status(500, "No data")
|
||||
end
|
||||
else
|
||||
luci.http.status(500, "Bad mode")
|
||||
end
|
||||
end
|
||||
|
||||
function act_json()
|
||||
local v, l, fd
|
||||
local rv = {
|
||||
interfaces = { },
|
||||
originators = { },
|
||||
gateways = { }
|
||||
}
|
||||
|
||||
--
|
||||
-- interfaces
|
||||
--
|
||||
fd = io.popen("batctl if")
|
||||
if fd then
|
||||
repeat
|
||||
l = fd:read("*l")
|
||||
v = l and l:match("^(.-):")
|
||||
if v then
|
||||
rv.interfaces[#rv.interfaces+1] = v
|
||||
end
|
||||
until not l
|
||||
fd:close()
|
||||
end
|
||||
|
||||
os.execute("cat /proc/net/arp > /tmp/arp")
|
||||
|
||||
iplist = {}
|
||||
maclist = {}
|
||||
index = 0
|
||||
fd = io.open("/tmp/arp")
|
||||
if fd then
|
||||
-- skip header line
|
||||
fd:read("*l")
|
||||
repeat
|
||||
l = fd:read("*l")
|
||||
if l then
|
||||
lan = l
|
||||
s1, e1 = lan:find("0x2")
|
||||
if s1 ~= nil then
|
||||
s, e = l:find(" ")
|
||||
if s ~= nil then
|
||||
ip = l:sub(0, e-1)
|
||||
|
||||
fc = io.popen("batctl translate " .. ip)
|
||||
if fc then
|
||||
mac = fc:read("*l")
|
||||
fc:close()
|
||||
iplist[index] = ip
|
||||
maclist[index] = mac
|
||||
index = index + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
until not l
|
||||
fd:close()
|
||||
end
|
||||
|
||||
--
|
||||
-- originators
|
||||
--
|
||||
local originators_command = (
|
||||
"batctl o -H 2>/dev/null ".. -- gets originators from batctl
|
||||
"| tr -d '[]()' ".. -- removes brackets and parenthesis
|
||||
"| sed 's/^ / -/g' ".. -- normalizes output, adding a minus when no asterisk is outputed in each line
|
||||
"| sed 's/^ //g' ".. -- removes the space from the beginning of the line
|
||||
"| sed -r 's/\\s+/,/g'".. -- replaces tabs for commas
|
||||
"| sed -r 's/s,/,/g'" -- removes the 's' from the last_seen field referencing seconds
|
||||
)
|
||||
fd = io.popen(originators_command)
|
||||
if fd then
|
||||
repeat
|
||||
l = fd:read()
|
||||
if l then
|
||||
local asterisk, originator_name, last_seen, link_quality, next_hop, outgoing_if
|
||||
asterisk, originator_name, last_seen, link_quality, next_hop, outgoing_if = unpack(split(l, ","))
|
||||
if originator_name and last_seen and link_quality then
|
||||
if originator_name == next_hop then
|
||||
next_hop = "Here"
|
||||
end
|
||||
if index > 0 then
|
||||
for j=0,index-1 do
|
||||
if maclist[j] == originator_name then
|
||||
originator_name = iplist[j] .. " (" .. originator_name .. ")"
|
||||
end
|
||||
if maclist[j] == next_hop then
|
||||
next_hop = iplist[j]
|
||||
end
|
||||
end
|
||||
end
|
||||
rv.originators[#rv.originators+1] = {
|
||||
originator_name,
|
||||
tonumber(last_seen) * 1000,
|
||||
tonumber(link_quality),
|
||||
next_hop,
|
||||
outgoing_if
|
||||
}
|
||||
end
|
||||
end
|
||||
until not l
|
||||
fd:close()
|
||||
end
|
||||
|
||||
--
|
||||
-- gateways
|
||||
--
|
||||
fd = io.popen("batctl gwl")
|
||||
if fd then
|
||||
-- skip header line
|
||||
fd:read("*l")
|
||||
fd:read("*l")
|
||||
|
||||
repeat
|
||||
l = fd:read("*l")
|
||||
if l then
|
||||
local a, m, q, n, i, r = l:match("^(%S*) +([^ ]+) +%( *(%d+)%) +([^ ]+) +%[ *(%S+)%]: +(%S+)")
|
||||
if a and m and q and n and i and r then
|
||||
c="0"
|
||||
if index > 0 then
|
||||
for j=0,index-1 do
|
||||
if maclist[j] == m then
|
||||
m = iplist[j]
|
||||
end
|
||||
if maclist[j] == n then
|
||||
n = iplist[j]
|
||||
end
|
||||
end
|
||||
end
|
||||
rv.gateways[#rv.gateways+1] = {
|
||||
#a > 0,
|
||||
m,
|
||||
tonumber(q),
|
||||
n,
|
||||
i,
|
||||
tonumber(c),
|
||||
r
|
||||
}
|
||||
end
|
||||
end
|
||||
until not l
|
||||
fd:close()
|
||||
end
|
||||
|
||||
-- local Gateway status
|
||||
|
||||
rv.status = "Client"
|
||||
fd = io.popen("batctl gw")
|
||||
if fd then
|
||||
l = fd:read("*l")
|
||||
s, e = l:find("server")
|
||||
if s ~= nil then
|
||||
rv.status = "Server"
|
||||
end
|
||||
fd:close()
|
||||
end
|
||||
|
||||
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(rv)
|
||||
end
|
@ -1,76 +0,0 @@
|
||||
module("luci.controller.mesh", package.seeall)
|
||||
function index()
|
||||
local page
|
||||
entry({"admin", "mesh"}, firstchild(), "Mesh", 71).dependent=false
|
||||
page = entry({"admin", "mesh", "mesh"}, template("mesh/mesh-setup"), "Mesh Configuration", 71)
|
||||
page.dependent = true
|
||||
|
||||
entry({"admin", "mesh", "getstate"}, call("action_getstate"))
|
||||
entry({"admin", "mesh", "sendmeshstate"}, call("action_sendmeshstate"))
|
||||
entry({"admin", "mesh", "meshcfg"}, call("action_meshcfg"))
|
||||
entry({"admin", "mesh", "meshstartstop"}, call("action_meshstartstop"))
|
||||
end
|
||||
|
||||
function action_getstate()
|
||||
local rv = {}
|
||||
local radiolist = {}
|
||||
|
||||
file = io.open("/etc/meshrun", "r")
|
||||
if file == nil then
|
||||
rv["state"] = "0"
|
||||
else
|
||||
rv["state"] = "1"
|
||||
file:close()
|
||||
end
|
||||
os.execute("/usr/lib/mesh/radio.sh ")
|
||||
file = io.open("/tmp/radiolist", "r")
|
||||
if file ~= nil then
|
||||
j = file:read("*line")
|
||||
rv['radio'] = j
|
||||
if j ~=0 then
|
||||
for i=0, j-1 do
|
||||
radiolist[i] = file:read("*line")
|
||||
end
|
||||
rv['radiolist'] = radiolist
|
||||
end
|
||||
rv['radionumber'] = file:read("*line")
|
||||
rv['channelindex'] = file:read("*line")
|
||||
rv['channellist'] = file:read("*line")
|
||||
rv['channelwidth'] = file:read("*line")
|
||||
rv['usedfs'] = file:read("*line")
|
||||
rv['dedicated'] = file:read("*line")
|
||||
|
||||
rv['networkid'] = file:read("*line")
|
||||
rv['netencrypted'] = file:read("*line")
|
||||
rv['netpassword'] = file:read("*line")
|
||||
|
||||
rv['signalenable'] = file:read("*line")
|
||||
rv['signalid'] = file:read("*line")
|
||||
|
||||
file:close()
|
||||
else
|
||||
rv["radio"] = "0"
|
||||
end
|
||||
|
||||
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(rv)
|
||||
end
|
||||
|
||||
function action_sendmeshstate()
|
||||
local set = luci.http.formvalue("set")
|
||||
|
||||
os.execute('/usr/lib/mesh/save.sh "' .. set .. '"')
|
||||
end
|
||||
|
||||
function action_meshcfg()
|
||||
local set = luci.http.formvalue("set")
|
||||
|
||||
os.execute('/usr/lib/mesh/savecfg.sh "' .. set .. '"')
|
||||
end
|
||||
|
||||
function action_meshstartstop()
|
||||
os.execute('/usr/lib/mesh/startstop.sh')
|
||||
os.execute("reboot &")
|
||||
end
|
||||
|
@ -1,300 +0,0 @@
|
||||
<%#
|
||||
LuCI - Lua Configuration Interface
|
||||
Copyright 2012 Jo-Philipp Wich <xm@subsignal.org>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
$Id$
|
||||
|
||||
-%>
|
||||
|
||||
<% luci.http.prepare_content("text/html") %>
|
||||
|
||||
<%+header%>
|
||||
|
||||
<script type="text/javascript" src="<%=resource%>/cbi.js"></script>
|
||||
<script type="text/javascript" src="<%=resource%>/dracula/raphael-min.js"></script>
|
||||
<script type="text/javascript" src="<%=resource%>/dracula/dracula_graffle.js"></script>
|
||||
<script type="text/javascript" src="<%=resource%>/dracula/dracula_graph.js"></script>
|
||||
<script type="text/javascript" src="<%=resource%>/jquery/jquery-1.4.js"></script>
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
function gw_apply(field)
|
||||
{
|
||||
var mode, val;
|
||||
|
||||
if (field.type == 'radio') {
|
||||
val = '';
|
||||
mode = field.value;
|
||||
}
|
||||
else {
|
||||
val = field.value;
|
||||
mode = document.getElementById('gw_gateway').checked ? 'server' : 'client';
|
||||
}
|
||||
|
||||
document.getElementById('gw_apply').style.display = '';
|
||||
document.getElementById('gw_form').style.display = 'none';
|
||||
document.getElementById('gw_form_val').parentNode.style.display = (mode != 'off') ? '' : 'none';
|
||||
|
||||
XHR.get('<%=luci.dispatcher.build_url("batman/gw")%>/'+mode+'/'+encodeURIComponent(val), null,
|
||||
function(x, info) {
|
||||
document.getElementById('gw_form').style.display = '';
|
||||
document.getElementById('gw_apply').style.display = 'none';
|
||||
document.getElementById('gw_form_val').value = info;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
XHR.poll(5, '<%=luci.dispatcher.build_url("batman/json")%>', null,
|
||||
function(x, info)
|
||||
{
|
||||
var t;
|
||||
|
||||
var og = info.originators;
|
||||
var gw = info.gateways;
|
||||
var server = info.status;
|
||||
|
||||
if ( server == 'Client' )
|
||||
{
|
||||
document.getElementById('status').innerHTML="No local Internet access, running as Client";
|
||||
}
|
||||
else
|
||||
{
|
||||
document.getElementById('status').innerHTML="Local Internet access, running as Gateway Server";
|
||||
}
|
||||
|
||||
if (!!(t = document.getElementById('originator_table')))
|
||||
{
|
||||
/* clear all rows */
|
||||
while (t.rows.length > 1)
|
||||
t.rows[0].parentNode.deleteRow(1);
|
||||
|
||||
og.sort(function(a, b) { return parseInt(b[2]) - parseInt(a[2]) });
|
||||
|
||||
for (var i = 0; i < og.length; i++)
|
||||
{
|
||||
var tr = t.rows[0].parentNode.insertRow(-1);
|
||||
tr.className = 'cbi-section-table-row cbi-rowstyle-' + (1 + (i % 2));
|
||||
|
||||
var icon;
|
||||
if (og[i][2] < 64)
|
||||
icon = "<%=resource%>/icons/signal-0-25.png";
|
||||
else if (og[i][2] < 128)
|
||||
icon = "<%=resource%>/icons/signal-25-50.png";
|
||||
else if (og[i][2] < 192)
|
||||
icon = "<%=resource%>/icons/signal-50-75.png";
|
||||
else
|
||||
icon = "<%=resource%>/icons/signal-75-100.png";
|
||||
|
||||
tr.insertCell(-1).innerHTML = String.format(
|
||||
'<img src="%s" title="<%:Quality%>: %d / 255" style="vertical-align:middle" /> %d/255',
|
||||
icon, og[i][2], og[i][2]
|
||||
);
|
||||
|
||||
if ( og[i][3] == "Here" )
|
||||
{
|
||||
tr.insertCell(-1).innerHTML = '<strong>' + og[i][0] + '</strong>' ;
|
||||
og[i][3] = " ";
|
||||
}
|
||||
else
|
||||
{
|
||||
tr.insertCell(-1).innerHTML = og[i][0];
|
||||
}
|
||||
tr.insertCell(-1).innerHTML = String.format('%dms', og[i][1]);
|
||||
tr.insertCell(-1).innerHTML = og[i][4];
|
||||
tr.insertCell(-1).innerHTML = og[i][3];
|
||||
}
|
||||
|
||||
if (t.rows.length == 1)
|
||||
{
|
||||
var tr = t.rows[0].parentNode.insertRow(-1);
|
||||
tr.className = 'cbi-section-table-row';
|
||||
|
||||
var td = tr.insertCell(-1);
|
||||
td.colSpan = 3;
|
||||
td.innerHTML = '<br /><em><%:There are no active neighbors%></em>';
|
||||
}
|
||||
}
|
||||
|
||||
if (!!(t = document.getElementById('gateway_table')))
|
||||
{
|
||||
/* clear all rows */
|
||||
while (t.rows.length > 1)
|
||||
t.rows[0].parentNode.deleteRow(1);
|
||||
|
||||
gw.sort(function(a, b) { return a[0] > b[0] });
|
||||
|
||||
for (var i = 0; i < gw.length; i++)
|
||||
{
|
||||
var tr = t.rows[0].parentNode.insertRow(-1);
|
||||
tr.className = 'cbi-section-table-row cbi-rowstyle-' + (1 + (i % 2));
|
||||
|
||||
tr.insertCell(-1).innerHTML = gw[i][0]
|
||||
? String.format('<strong>%s (active)</strong>', gw[i][1])
|
||||
: gw[i][1];
|
||||
|
||||
tr.insertCell(-1).innerHTML = gw[i][6];
|
||||
tr.insertCell(-1).innerHTML = String.format('%d/255', gw[i][2]);
|
||||
tr.insertCell(-1).innerHTML = gw[i][4];
|
||||
tr.insertCell(-1).innerHTML = gw[i][3];
|
||||
}
|
||||
|
||||
if (t.rows.length == 1)
|
||||
{
|
||||
var tr = t.rows[0].parentNode.insertRow(-1);
|
||||
tr.className = 'cbi-section-table-row';
|
||||
|
||||
var td = tr.insertCell(-1);
|
||||
td.colSpan = 3;
|
||||
td.innerHTML = '<br /><em><%:There are no active mesh gateways%></em>';
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
XHR.get('<%=luci.dispatcher.build_url("batman/topo/json")%>', null,
|
||||
function(x, data)
|
||||
{
|
||||
var g = new Graph();
|
||||
|
||||
|
||||
var render = function(r, node) {
|
||||
var color = Raphael.getColor();
|
||||
var rect = r.rect(node.point[0]-50, node.point[1]-10, 100, 20)
|
||||
.attr({"fill": color, "stroke": color, "stroke-width": 2, r : "9px"})
|
||||
var set = r.set().
|
||||
push(rect).
|
||||
push(r.text(node.point[0], node.point[1], node.label || node.id)
|
||||
.attr({"fill": "#000"}));
|
||||
return set;
|
||||
};
|
||||
|
||||
for (var i = 0; i < (data.length-1); i++)
|
||||
{
|
||||
// node->node
|
||||
if (data[i].router && data[i].neighbor) {
|
||||
g.addNode(data[i].router, { render: render });
|
||||
g.addNode(data[i].neighbor, { render: render });
|
||||
g.addEdge(data[i].router, data[i].neighbor,
|
||||
{ label: parseFloat(data[i].label).toFixed(1),
|
||||
directed: true, stroke: '#aaaaaa' });
|
||||
}
|
||||
else if (data[i].secondary) {
|
||||
g.addNode(data[i].secondary, { render: render });
|
||||
g.addNode(data[i].of, { render: render });
|
||||
g.addEdge(data[i].secondary, data[i].of,
|
||||
{ fill: "#000" } );
|
||||
}
|
||||
}
|
||||
|
||||
document.getElementById('canvas').innerHTML = "";
|
||||
var canvas = document.getElementById('canvas');
|
||||
|
||||
var layouter = new Graph.Layout.Spring(g);
|
||||
layouter.layout();
|
||||
|
||||
var renderer = new Graph.Renderer.Raphael(canvas.id, g, canvas.offsetWidth, canvas.offsetHeight);
|
||||
renderer.draw();
|
||||
}
|
||||
);
|
||||
|
||||
XHR.poll(25, '<%=luci.dispatcher.build_url("batman/topo/json")%>', null,
|
||||
function(x, data)
|
||||
{
|
||||
var g = new Graph();
|
||||
|
||||
|
||||
var render = function(r, node) {
|
||||
var color = Raphael.getColor();
|
||||
var rect = r.rect(node.point[0]-50, node.point[1]-10, 100, 20)
|
||||
.attr({"fill": color, "stroke": color, "stroke-width": 2, r : "9px"})
|
||||
var set = r.set().
|
||||
push(rect).
|
||||
push(r.text(node.point[0], node.point[1], node.label || node.id)
|
||||
.attr({"fill": "#000"}));
|
||||
return set;
|
||||
};
|
||||
|
||||
for (var i = 0; i < (data.length-1); i++)
|
||||
{
|
||||
// node->node
|
||||
if (data[i].router && data[i].neighbor) {
|
||||
g.addNode(data[i].router, { render: render });
|
||||
g.addNode(data[i].neighbor, { render: render });
|
||||
g.addEdge(data[i].router, data[i].neighbor,
|
||||
{ label: parseFloat(data[i].label).toFixed(1),
|
||||
directed: true, stroke: '#aaaaaa' });
|
||||
}
|
||||
else if (data[i].secondary) {
|
||||
g.addNode(data[i].secondary, { render: render });
|
||||
g.addNode(data[i].of, { render: render });
|
||||
g.addEdge(data[i].secondary, data[i].of,
|
||||
{ fill: "#000" } );
|
||||
}
|
||||
}
|
||||
|
||||
document.getElementById('canvas').innerHTML = "";
|
||||
var canvas = document.getElementById('canvas');
|
||||
|
||||
var layouter = new Graph.Layout.Spring(g);
|
||||
layouter.layout();
|
||||
|
||||
var renderer = new Graph.Renderer.Raphael(canvas.id, g, canvas.offsetWidth, canvas.offsetHeight);
|
||||
renderer.draw();
|
||||
}
|
||||
);
|
||||
//]]></script>
|
||||
|
||||
<h2><a id="content" name="content"><%:Mesh Status%></a></h2>
|
||||
|
||||
<fieldset class="cbi-section">
|
||||
<table width="550" border="0">
|
||||
<tr>
|
||||
<td width="17%"><div align="right"><strong>Internet Status : </strong></div></td>
|
||||
<td width="19%"><ul id="status"></ul></td>
|
||||
<td width="65%"></td>
|
||||
</tr>
|
||||
</table>
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="cbi-section">
|
||||
<legend><%:Active Mesh Nodes%></legend>
|
||||
<table class="cbi-section-table" id="originator_table">
|
||||
<tr class="cbi-section-table-titles">
|
||||
<th class="cbi-section-table-cell"><%:Link Quality%></th>
|
||||
<th class="cbi-section-table-cell"><%:MAC-Address%></th>
|
||||
<th class="cbi-section-table-cell"><%:Last Seen%></th>
|
||||
<th class="cbi-section-table-cell"><%:Interface%></th>
|
||||
<th class="cbi-section-table-cell"><%:Next Hop%></th>
|
||||
</tr>
|
||||
<tr class="cbi-section-table-row">
|
||||
<td colspan="3"><em><br /><%:Collecting data...%></em></td>
|
||||
</tr>
|
||||
</table>
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="cbi-section">
|
||||
<legend><%:Other Mesh Nodes with Internet Access%></legend>
|
||||
<table class="cbi-section-table" id="gateway_table">
|
||||
<tr class="cbi-section-table-titles">
|
||||
<th class="cbi-section-table-cell"><%:MAC-Address%></th>
|
||||
<th class="cbi-section-table-cell"><%:Speed%></th>
|
||||
<th class="cbi-section-table-cell"><%:Link Quality%></th>
|
||||
<th class="cbi-section-table-cell"><%:Interface%></th>
|
||||
<th class="cbi-section-table-cell"><%:Next Hop%></th>
|
||||
</tr>
|
||||
<tr class="cbi-section-table-row">
|
||||
<td colspan="3"><em><br /><%:Collecting data...%></em></td>
|
||||
</tr>
|
||||
</table>
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="cbi-section">
|
||||
<legend><%:Visualization%></legend>
|
||||
<div id="canvas" style="min-width:800px; min-height:600px"></div>
|
||||
</fieldset>
|
||||
|
||||
<%+footer%>
|
@ -1,912 +0,0 @@
|
||||
<%+header%>
|
||||
<%
|
||||
local sys = require "luci.sys"
|
||||
local utl = require "luci.util"
|
||||
local fs = require "nixio.fs"
|
||||
|
||||
function showicon(lck)
|
||||
if lck == 0 then
|
||||
return resource .. "/icons/unlock1.png"
|
||||
else
|
||||
return resource .. "/icons/lock1.png"
|
||||
end
|
||||
end
|
||||
|
||||
-%>
|
||||
<script type="text/javascript" src="<%=resource%>/xhr.js"></script>
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
|
||||
var change=0;
|
||||
var radnum = 1; // radio number option radionumber '0'
|
||||
var channelindex = 0 ; // index in to list option channelindex '0'
|
||||
var channellist = 0; // list number 0-2 option channellist "0"
|
||||
var channelwidth = 1; // index of bw 0-3 option channelwidth '0'
|
||||
var usedfs = 0; // 1 is dfs channels option usedfs "0"
|
||||
var detecatedradio = 1; // 1 is dedicated radio option dedicated "0"
|
||||
|
||||
var networkid = "MeshCloud";
|
||||
var netencrypted = 0;
|
||||
var netpassword = "password";
|
||||
|
||||
var signalenable = 1;
|
||||
var signalid = "mesh";
|
||||
|
||||
var radiolist = new Array() ;
|
||||
var partsArray = new Array;
|
||||
var channels = new Array;
|
||||
var cwidth = ["20", "40", "80", "80"];
|
||||
var channelnum = 0;
|
||||
var chan2num = 14;
|
||||
var chan5num = 10;
|
||||
var chan5dfsnum = 23;
|
||||
var channel2 = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14" ];
|
||||
var channel5 = ["36", "40", "44", "48", "149", "153", "157", "161", "165", "169"];
|
||||
var channel5dfs = ["36", "40", "44", "48", "52", "56", "60", "64", "100", "104", "104", "112", "116", "132", "136", "140", "144", "149", "153", "157", "161", "165", "169"];
|
||||
|
||||
function setwidth(width)
|
||||
{
|
||||
switch (width)
|
||||
{
|
||||
case "0":
|
||||
num = 1;
|
||||
dropname = "drop5";
|
||||
break;
|
||||
case "1":
|
||||
num = 2;
|
||||
dropname = "drop6";
|
||||
break;
|
||||
case "2":
|
||||
num = 3;
|
||||
dropname = "drop7";
|
||||
break;
|
||||
case "3":
|
||||
num = 3;
|
||||
dropname = "drop8";
|
||||
break;
|
||||
}
|
||||
x = document.getElementById(dropname);
|
||||
for (i = 0; i < num; i++)
|
||||
{
|
||||
option = document.createElement("option");
|
||||
option.text = cwidth[i] + "Mhz";
|
||||
x.add(option);
|
||||
}
|
||||
}
|
||||
|
||||
function changebw(flg)
|
||||
{
|
||||
partsArray = radiolist[radnum].split('|');
|
||||
channelw = partsArray[2];
|
||||
|
||||
switch (channelw)
|
||||
{
|
||||
case "0":
|
||||
document.getElementById("radio46").style.visibility="visible";
|
||||
if ( flg == 1 )
|
||||
{
|
||||
document.getElementById("radio46").style.display = "";
|
||||
}
|
||||
document.getElementById("drop5").selectedIndex = channelwidth;
|
||||
document.getElementById("radio47").style.display = "none";
|
||||
document.getElementById("radio47").style.visibility="hidden";
|
||||
document.getElementById("radio48").style.display = "none";
|
||||
document.getElementById("radio48").style.visibility="hidden";
|
||||
document.getElementById("radio49").style.display = "none";
|
||||
document.getElementById("radio49").style.visibility="hidden";
|
||||
break;
|
||||
case "1":
|
||||
document.getElementById("radio47").style.visibility="visible";
|
||||
if ( flg == 1 )
|
||||
{
|
||||
document.getElementById("radio47").style.display = "";
|
||||
}
|
||||
document.getElementById("drop6").selectedIndex = channelwidth;
|
||||
document.getElementById("radio46").style.display = "none";
|
||||
document.getElementById("radio46").style.visibility="hidden";
|
||||
document.getElementById("radio48").style.display = "none";
|
||||
document.getElementById("radio48").style.visibility="hidden";
|
||||
document.getElementById("radio49").style.display = "none";
|
||||
document.getElementById("radio49").style.visibility="hidden";
|
||||
break;
|
||||
case "2":
|
||||
document.getElementById("radio48").style.visibility="visible";
|
||||
if ( flg == 1 )
|
||||
{
|
||||
document.getElementById("radio48").style.display = "";
|
||||
}
|
||||
document.getElementById("drop7").selectedIndex = channelwidth;
|
||||
document.getElementById("radio46").style.display = "none";
|
||||
document.getElementById("radio46").style.visibility="hidden";
|
||||
document.getElementById("radio47").style.display = "none";
|
||||
document.getElementById("radio47").style.visibility="hidden";
|
||||
document.getElementById("radio49").style.display = "none";
|
||||
document.getElementById("radio49").style.visibility="hidden";
|
||||
break;
|
||||
case "3":
|
||||
document.getElementById("radio49").style.visibility="visible";
|
||||
if ( flg == 1 )
|
||||
{
|
||||
document.getElementById("radio49").style.display = "";
|
||||
}
|
||||
document.getElementById("drop8").selectedIndex = channelwidth;
|
||||
document.getElementById("radio46").style.display = "none";
|
||||
document.getElementById("radio46").style.visibility="hidden";
|
||||
document.getElementById("radio47").style.display = "none";
|
||||
document.getElementById("radio47").style.visibility="hidden";
|
||||
document.getElementById("radio48").style.display = "none";
|
||||
document.getElementById("radio48").style.visibility="hidden";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function vischannel(flg)
|
||||
{
|
||||
partsArray = radiolist[radnum].split('|');
|
||||
if ( partsArray[0] == "1" )
|
||||
{
|
||||
document.getElementById("radio3").style.display = "none";
|
||||
document.getElementById("radio3").style.visibility="hidden";
|
||||
document.getElementById("radio33").style.display = "none";
|
||||
document.getElementById("radio33").style.visibility="hidden";
|
||||
document.getElementById("drop2").style.display = "none";
|
||||
document.getElementById("drop2").style.visibility="hidden";
|
||||
|
||||
if ( usedfs == 0 )
|
||||
{
|
||||
document.getElementById("radio4").style.display = "block";
|
||||
document.getElementById("radio4").style.visibility="visible";
|
||||
document.getElementById("drop3").style.display = "block";
|
||||
document.getElementById("drop3").style.visibility="visible";
|
||||
document.getElementById("radio44").style.visibility="visible";
|
||||
if ( flg == 1 )
|
||||
{
|
||||
document.getElementById("radio44").style.display = "";
|
||||
}
|
||||
channellist = 1;
|
||||
document.getElementById("drop3").selectedIndex = channelindex;
|
||||
|
||||
document.getElementById("radio5").style.display = "none";
|
||||
document.getElementById("radio5").style.visibility="hidden";
|
||||
document.getElementById("drop4").style.display = "none";
|
||||
document.getElementById("drop4").style.visibility="hidden";
|
||||
document.getElementById("radio55").style.display = "none";
|
||||
document.getElementById("radio55").style.visibility="hidden";
|
||||
}
|
||||
else
|
||||
{
|
||||
document.getElementById("radio5").style.display = "block";
|
||||
document.getElementById("radio5").style.visibility="visible";
|
||||
document.getElementById("drop4").style.display = "block";
|
||||
document.getElementById("drop4").style.visibility="visible";
|
||||
document.getElementById("radio55").style.visibility="visible";
|
||||
if ( flg == 1 )
|
||||
{
|
||||
document.getElementById("radio55").style.display = "";
|
||||
}
|
||||
channellist = 2;
|
||||
document.getElementById("drop4").selectedIndex = channelindex;
|
||||
|
||||
document.getElementById("radio4").style.display = "none";
|
||||
document.getElementById("radio4").style.visibility="hidden";
|
||||
document.getElementById("drop3").style.display = "none";
|
||||
document.getElementById("drop3").style.visibility="hidden";
|
||||
document.getElementById("radio44").style.display = "none";
|
||||
document.getElementById("radio44").style.visibility="hidden";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
document.getElementById("radio3").style.display = "block";
|
||||
document.getElementById("radio3").style.visibility="visible";
|
||||
document.getElementById("radio33").style.visibility="visible";
|
||||
if ( flg == 1 )
|
||||
{
|
||||
document.getElementById("radio33").style.display = "";
|
||||
}
|
||||
channellist = 0;
|
||||
document.getElementById("drop2").style.display = "block";
|
||||
document.getElementById("drop2").style.visibility="visible";
|
||||
document.getElementById("drop2").selectedIndex = channelindex;
|
||||
|
||||
document.getElementById("radio4").style.display = "none";
|
||||
document.getElementById("radio4").style.visibility="hidden";
|
||||
document.getElementById("drop3").style.display = "none";
|
||||
document.getElementById("drop3").style.visibility="hidden";
|
||||
document.getElementById("radio44").style.display = "none";
|
||||
document.getElementById("radio44").style.visibility="hidden";
|
||||
|
||||
document.getElementById("radio5").style.display = "none";
|
||||
document.getElementById("radio5").style.visibility="hidden";
|
||||
document.getElementById("drop4").style.display = "none";
|
||||
document.getElementById("drop4").style.visibility="hidden";
|
||||
document.getElementById("radio55").style.display = "none";
|
||||
document.getElementById("radio55").style.visibility="hidden";
|
||||
}
|
||||
}
|
||||
|
||||
function setchannels(freq)
|
||||
{
|
||||
switch ( freq )
|
||||
{
|
||||
case "0" :
|
||||
channels = channel2;
|
||||
chansize = chan2num;
|
||||
dropname = "drop2";
|
||||
break;
|
||||
case "1" :
|
||||
channels = channel5;
|
||||
chansize = chan5num;
|
||||
dropname = "drop3";
|
||||
break;
|
||||
case "2" :
|
||||
channels = channel5dfs;
|
||||
chansize = chan5dfsnum;
|
||||
dropname = "drop4";
|
||||
break;
|
||||
default :
|
||||
break;
|
||||
}
|
||||
|
||||
x = document.getElementById(dropname);
|
||||
for (i = 0; i < chansize; i++)
|
||||
{
|
||||
option = document.createElement("option");
|
||||
option.text = "Channel " + channels[i];
|
||||
x.add(option);
|
||||
}
|
||||
x.selectedIndex = channelnum;
|
||||
}
|
||||
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin", "mesh", "getstate")%>',
|
||||
null,
|
||||
function(x, rv)
|
||||
{
|
||||
document.getElementById("cbi-modw").style.display = "none";
|
||||
document.getElementById("cbi-modw").style.visibility="hidden";
|
||||
document.getElementById("cbi-mod1").style.display = "block";
|
||||
document.getElementById("cbi-mod1").style.visibility="visible";
|
||||
document.getElementById("cbi-mod2").style.display = "block";
|
||||
document.getElementById("cbi-mod2").style.visibility="visible";
|
||||
document.getElementById("cbi-mod3").style.display = "block";
|
||||
document.getElementById("cbi-mod3").style.visibility="visible";
|
||||
|
||||
radnum = parseInt(rv.radionumber);
|
||||
channelindex = parseInt(rv.channelindex);
|
||||
channellist = parseInt(rv.channellist);
|
||||
channelwidth = parseInt(rv.channelwidth);
|
||||
usedfs = parseInt(rv.usedfs);
|
||||
detecatedradio = parseInt(rv.dedicated);
|
||||
|
||||
networkid = rv.networkid;
|
||||
netencrypted = parseInt(rv.netencrypted);
|
||||
netpassword = rv.netpassword;
|
||||
|
||||
signalenable = parseInt(rv.signalenable);
|
||||
signalid = rv.signalid;
|
||||
|
||||
document.getElementById("dedicated").checked = false;
|
||||
if ( detecatedradio == 1 )
|
||||
{
|
||||
document.getElementById("dedicated").checked = true;
|
||||
}
|
||||
document.getElementById("dfs").checked = false;
|
||||
document.getElementById("dfs3").checked = false;
|
||||
if ( usedfs == 1)
|
||||
{
|
||||
document.getElementById("dfs").checked = true;
|
||||
document.getElementById("dfs3").checked = true;
|
||||
}
|
||||
|
||||
num_radio = parseInt(rv.radio);
|
||||
if ( num_radio > 0 )
|
||||
{
|
||||
radiolist = rv.radiolist;
|
||||
x = document.getElementById("drop1");
|
||||
for (i = 0; i < num_radio; i++)
|
||||
{
|
||||
partsArray = radiolist[i].split('|');
|
||||
dropradio = "Radio" + partsArray[1];
|
||||
if ( partsArray[0] == "1" )
|
||||
{
|
||||
dropradio = dropradio + " (5Ghz)";
|
||||
}
|
||||
else
|
||||
{
|
||||
dropradio = dropradio + " (2.4Ghz)";
|
||||
}
|
||||
option = document.createElement("option");
|
||||
option.text = dropradio;
|
||||
x.add(option);
|
||||
}
|
||||
x.selectedIndex = radnum;
|
||||
setchannels("0");
|
||||
setchannels("1");
|
||||
setchannels("2");
|
||||
setwidth("0");
|
||||
setwidth("1");
|
||||
setwidth("2");
|
||||
setwidth("3");
|
||||
vischannel(0);
|
||||
changebw(0);
|
||||
|
||||
document.getElementById("idnam").value = networkid;
|
||||
document.getElementById("encr").checked = false;
|
||||
document.getElementById("enc2").style.display = "none";
|
||||
document.getElementById("enc2").style.visibility="hidden";
|
||||
document.getElementById("netpass").style.display = "none";
|
||||
document.getElementById("netpass").style.visibility="hidden";
|
||||
if ( netencrypted == 1 )
|
||||
{
|
||||
document.getElementById("encr").checked = true;
|
||||
document.getElementById("enc2").style.display = "block";
|
||||
document.getElementById("enc2").style.visibility="visible";
|
||||
document.getElementById("netpass").style.display = "block";
|
||||
document.getElementById("netpass").style.visibility="visible";
|
||||
}
|
||||
document.getElementById("netpass").value = netpassword;
|
||||
|
||||
document.getElementById("sigenb").checked = false;
|
||||
document.getElementById("roam11").style.display = "none";
|
||||
document.getElementById("roam11").style.visibility="hidden";
|
||||
|
||||
document.getElementById("idsig").value = signalid;
|
||||
|
||||
if ( signalenable == 1 )
|
||||
{
|
||||
document.getElementById("sigenb").checked = true;
|
||||
document.getElementById("roam11").style.display = "";
|
||||
document.getElementById("roam11").style.visibility="visible";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
);
|
||||
function changes(value)
|
||||
{
|
||||
change = value;
|
||||
if ( value == 0 )
|
||||
{
|
||||
document.getElementById("meshstat1").innerHTML = "No Changes";
|
||||
document.getElementById("meshstat1").style.color = "inherit";
|
||||
document.getElementById("meshstat1").style.fontWeight = "bold" ;
|
||||
}
|
||||
else
|
||||
{
|
||||
document.getElementById("meshstat1").innerHTML = "Unsaved Changes";
|
||||
document.getElementById("meshstat1").style.color = "red";
|
||||
document.getElementById("meshstat1").style.fontWeight = "bold" ;
|
||||
}
|
||||
}
|
||||
|
||||
function radiochange(drop)
|
||||
{
|
||||
radnum = document.getElementById("drop1").selectedIndex;
|
||||
channelindex = 0;
|
||||
vischannel(1);
|
||||
channelwidth = 0;
|
||||
changebw(1);
|
||||
changes(1);
|
||||
}
|
||||
|
||||
function dedicatedrad(check)
|
||||
{
|
||||
if ( check.checked == true )
|
||||
{
|
||||
detecatedradio = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
detecatedradio = 0;
|
||||
}
|
||||
changes(1);
|
||||
}
|
||||
|
||||
function setdfs(check)
|
||||
{
|
||||
if ( check.checked == true )
|
||||
{
|
||||
usedfs = 1;
|
||||
radiochange();
|
||||
document.getElementById("dfs").checked = true;
|
||||
document.getElementById("dfs3").checked = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
usedfs = 0;
|
||||
radiochange();
|
||||
document.getElementById("dfs").checked = false;
|
||||
document.getElementById("dfs3").checked = false;
|
||||
}
|
||||
changes(1);
|
||||
}
|
||||
|
||||
function bwchange(bwbox)
|
||||
{
|
||||
bw = bwbox.selectedIndex;
|
||||
channelwidth = bw;
|
||||
changes(1);
|
||||
}
|
||||
|
||||
function channelchange(chn)
|
||||
{
|
||||
channelindex = chn.selectedIndex;
|
||||
radnum = document.getElementById("drop1").selectedIndex;
|
||||
partsArray = radiolist[radnum].split('|');
|
||||
if ( partsArray[0] == "1" )
|
||||
{
|
||||
channellist = 1;
|
||||
if ( usedfs == 1 )
|
||||
{
|
||||
channellist = 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
channellist = 0;
|
||||
}
|
||||
changes(1);
|
||||
}
|
||||
|
||||
function setencr(check)
|
||||
{
|
||||
if ( check.checked == true )
|
||||
{
|
||||
document.getElementById("enc2").style.display = "block";
|
||||
document.getElementById("enc2").style.visibility="visible";
|
||||
document.getElementById("netpass").style.display = "block";
|
||||
document.getElementById("netpass").style.visibility="visible";
|
||||
netencrypted = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
document.getElementById("enc2").style.display = "none";
|
||||
document.getElementById("enc2").style.visibility="hidden";
|
||||
document.getElementById("netpass").style.display = "none";
|
||||
document.getElementById("netpass").style.visibility="hidden";
|
||||
netencrypted = 0;
|
||||
}
|
||||
changes(1);
|
||||
}
|
||||
|
||||
function setlow(check)
|
||||
{
|
||||
if ( check.checked == true )
|
||||
{
|
||||
document.getElementById("roam11").style.display = "";
|
||||
document.getElementById("roam11").style.visibility="visible";
|
||||
signalenable = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
document.getElementById("roam11").style.display = "none";
|
||||
document.getElementById("roam11").style.visibility="hidden";
|
||||
signalenable = 0;
|
||||
}
|
||||
changes(1);
|
||||
}
|
||||
|
||||
function changeid()
|
||||
{
|
||||
changes(1);
|
||||
}
|
||||
|
||||
function changesigid()
|
||||
{
|
||||
signalid = document.getElementById("idsig").value ;
|
||||
if ( !signalid )
|
||||
{
|
||||
document.getElementById("idsig").value = 'abcd' ;
|
||||
signalid = 'abcd';
|
||||
}
|
||||
changes(1);
|
||||
}
|
||||
|
||||
function configup(btn)
|
||||
{
|
||||
var filex = btn.files[0];
|
||||
var reader = new FileReader();
|
||||
reader.readAsText(filex);
|
||||
reader.onload = loaded;
|
||||
}
|
||||
|
||||
function loaded(evt)
|
||||
{
|
||||
var fileString = evt.target.result;
|
||||
partsArray = fileString.split('|');
|
||||
if ( partsArray[0] == "meshcfg" )
|
||||
{
|
||||
radionumber = parseInt(partsArray[0]);
|
||||
channelindex = parseInt(partsArray[1]);
|
||||
channellist = parseInt(partsArray[2]);
|
||||
usedfs = parseInt(partsArray[3]);
|
||||
channelwidth = parseInt(partsArray[4]);
|
||||
detecatedradio = parseInt(partsArray[5]);
|
||||
networkid=partsArray[6];
|
||||
netencrypted = parseInt(partsArray[7]);
|
||||
netpassword=partsArray[8];
|
||||
signalenable = parseInt(partsArray[9]);
|
||||
signalmeasure = parseInt(partsArray[10]);
|
||||
signalinterval = parseInt(partsArray[11]);
|
||||
signalcount = parseInt(partsArray[12]);
|
||||
snrconnect = parseInt(partsArray[13]);
|
||||
snrchange = parseInt(partsArray[14]);
|
||||
sigconnect = parseInt(partsArray[15]);
|
||||
sigchange = parseInt(partsArray[16]);
|
||||
window.location.reload(false);
|
||||
}
|
||||
changes(1);
|
||||
}
|
||||
|
||||
function buildsave()
|
||||
{
|
||||
netpassword = document.getElementById("netpass").value;
|
||||
if ( netencrypted == 1 )
|
||||
{
|
||||
if ( netpassword.length < 8 )
|
||||
{
|
||||
alert("You must enter a password at least 8 charactets long!!");
|
||||
return "1";
|
||||
}
|
||||
}
|
||||
if ( netpassword.length < 8 )
|
||||
{
|
||||
netpassword="password";
|
||||
}
|
||||
|
||||
var stat = radnum.toString() + "|" + channelindex.toString() + "|" + channellist.toString() + "|" + usedfs.toString() + "|" + channelwidth.toString() + "|" + detecatedradio.toString() + "|" + networkid + "|" + netencrypted.toString() + "|" + netpassword + "|" ;
|
||||
|
||||
var rom = signalenable.toString() + "|" + signalid + "|" ;
|
||||
|
||||
stat = stat + rom;
|
||||
|
||||
return stat;
|
||||
}
|
||||
|
||||
function saveconf(btn)
|
||||
{
|
||||
statusm = buildsave();
|
||||
if ( statusm == "1" )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
statusm = "meshcfg|" + statusm;
|
||||
|
||||
//document.getElementById("attxt").value=statusm;
|
||||
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin", "mesh", "meshcfg")%>',
|
||||
{ set: statusm },
|
||||
function()
|
||||
{
|
||||
window.open('http://'+window.location.hostname+'/package/meshcfg.meshcfg', '_self')
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function savemesh(btn)
|
||||
{
|
||||
statusm = buildsave();
|
||||
if ( statusm == "1" )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin", "mesh", "sendmeshstate")%>',
|
||||
{ set: statusm },
|
||||
function()
|
||||
{
|
||||
window.location.reload(false);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function reloadmesh()
|
||||
{
|
||||
changes(0);
|
||||
window.location.reload(false);
|
||||
}
|
||||
|
||||
var tries = 0,
|
||||
message = document.querySelector('p.reboot-message'),
|
||||
label = message.querySelector('span');
|
||||
|
||||
function ok() {
|
||||
window.location = '<%=url("admin")%>';
|
||||
}
|
||||
|
||||
function check() {
|
||||
window.setTimeout(ping, 5000);
|
||||
}
|
||||
|
||||
function ping() {
|
||||
var img = document.createElement('img');
|
||||
|
||||
img.onload = ok;
|
||||
img.onerror = check;
|
||||
img.src = '<%=resource%>/icons/loading.gif?' + Math.random();
|
||||
|
||||
if (tries++ >= 30) {
|
||||
message.classList.remove('notice');
|
||||
message.classList.add('warning');
|
||||
label.innerHTML = '<%:Device unreachable! Still waiting for device...%>';
|
||||
}
|
||||
}
|
||||
|
||||
function startstopmesh(btn)
|
||||
{
|
||||
if (change == 1 )
|
||||
{
|
||||
savech = confirm("Unsaved changes will be lost. Save first?");
|
||||
if ( savech == true )
|
||||
{
|
||||
statusm = buildsave();
|
||||
if ( statusm !== "1" )
|
||||
{
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin", "mesh", "sendmeshstate")%>',
|
||||
{ set: statusm },
|
||||
function()
|
||||
{
|
||||
}
|
||||
);
|
||||
changes(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
cont = confirm("Router will reboot after applying settings. Continue?");
|
||||
if ( cont == false )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
document.getElementById("cbi-modw").style.display = "block";
|
||||
document.getElementById("cbi-modw").style.visibility="visible";
|
||||
document.getElementById("cbi-mod1").style.display = "none";
|
||||
document.getElementById("cbi-mod1").style.visibility="hidden";
|
||||
document.getElementById("cbi-mod2").style.display = "none";
|
||||
document.getElementById("cbi-mod2").style.visibility="hidden";
|
||||
document.getElementById("cbi-mod3").style.display = "none";
|
||||
document.getElementById("cbi-mod3").style.visibility="hidden";
|
||||
document.getElementById("fileup").disabled=true;
|
||||
document.getElementById("meshconf").disabled=true;
|
||||
document.getElementById("meshsave").disabled=true;
|
||||
document.getElementById("meshstart").disabled=true;
|
||||
document.getElementById("meshstat1").style.display = "none";
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin", "mesh", "meshstartstop")%>',
|
||||
{ set: "1" },
|
||||
function()
|
||||
{
|
||||
}
|
||||
);
|
||||
check();
|
||||
}
|
||||
|
||||
//document.getElementById("attxt").value=partsArray[0].toString();
|
||||
|
||||
//]]></script>
|
||||
|
||||
<form method="post" action="<%=REQUEST_URI%>">
|
||||
<div class="cbi-map" id="cbi-modem">
|
||||
<h2><a id="content" name="content">Mesh Network Configuration</a></h2>
|
||||
<div class="cbi-map-descr"> </div>
|
||||
|
||||
<fieldset class="cbi-section" id="cbi-mod">
|
||||
|
||||
<table width="100%" border="0" id="meshstatus">
|
||||
<tr>
|
||||
<td width="20%"><div align="center" id="meshstat2" style="font-size:1.5em"><strong>Config Status</strong></div></td>
|
||||
<td width="20%"><div align="center" id="upl2" ><strong>Import Configuration File</strong></div></td>
|
||||
<td width="13%"><div align="center" id="upl3" ><strong>Export Configuration File</strong></div></td>
|
||||
<td width="10%"><div align="center" id="up42" ><strong>Save Settings</strong></div></td>
|
||||
<td width="10%"><div align="center" id="up52" ><strong>Apply Settings</strong></div></td>
|
||||
<td width="10%"><div align="center" id="up52" ><strong>Reload Settings</strong></div></td>
|
||||
<td width="17%"></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td width="20%"><div align="center" id="meshstat1" ><strong>No Changes</strong></div></td>
|
||||
<td width="20%"><input type="file" accept=".meshcfg" align="center" name="fileup" id="fileup" class="cbi-button cbi-button-positive" onchange="return configup(this)" /></td>
|
||||
<td width="13%"><input type="button" align="center" id="meshconf" class="cbi-button cbi-button-positive" value="<%:Save Configuration File%>" onclick="return saveconf(this)" /></td>
|
||||
<td width="10%"><input type="button" align="center" id="meshsave" class="cbi-button cbi-button-positive" value="<%:Save Settings%>" onclick="return savemesh(this)" /></td>
|
||||
<td width="10%"><input type="button" align="center" id="meshstart" class="cbi-button cbi-button-positive" value="<%:Apply Settings%>" onclick="return startstopmesh(this)" /></td>
|
||||
<td width="10%"><input type="button" align="center" id="meshreload" class="cbi-button cbi-button-positive" value="<%:Reload Settings%>" onclick="return reloadmesh(this)" /></td>
|
||||
<td width="17%"></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="cbi-section" id="cbi-modw" style="visibility:hidden">
|
||||
<table width="100%" cellspacing="10" id="waiting">
|
||||
<tr>
|
||||
<td width="40%"></td>
|
||||
<td id="waiticon"><img src="<%=resource%>/icons/loading.gif" style="vertical-align:middle" /> Waiting for Reboot...</td>
|
||||
</tr>
|
||||
</table>
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="cbi-section" id="cbi-mod1">
|
||||
<table width="100%" border="0" id="meshradio" >
|
||||
<tr>
|
||||
<td width="17%"><div align="left" id="radio1" style="font-size:1.5em"><strong>Mesh Radio Settings</strong></div></td>
|
||||
<td width="15%"></td>
|
||||
<td width="12%"></td>
|
||||
<td width="5%"></td>
|
||||
<td width="20%"></td>
|
||||
<td width="31%"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="17%"><div align="right" id="radio2" ><strong>Select Backhaul Radio </strong></div></td>
|
||||
<td width="15%">
|
||||
<select style="width:200px" name="raddrop" id="drop1" onchange="return radiochange(this)">
|
||||
</select>
|
||||
</td>
|
||||
<td width="12%"><div align="left" id="dedicated1" style="font-size:1em"><strong>Dedicated Backhaul Radio </strong></div></td>
|
||||
<td width="5%"><input type="checkbox" id="dedicated" onclick="return dedicatedrad(this)" /></td>
|
||||
<td width="20%"></td>
|
||||
<td width="31%"></td>
|
||||
</tr>
|
||||
|
||||
<tr id="radio33">
|
||||
<td width="17%"><div align="right" id="radio3" ><strong>Select Backhaul Channel </strong></div></td>
|
||||
<td width="15%">
|
||||
<select style="width:200px" name="chandrop" id="drop2" onchange="return channelchange(this)">
|
||||
</select>
|
||||
</td>
|
||||
<td width="12%"></td>
|
||||
<td width="5%"></td>
|
||||
<td width="20%"></td>
|
||||
<td width="31%"></td>
|
||||
</tr>
|
||||
|
||||
<tr id="radio44">
|
||||
<td width="17%"><div align="right" id="radio4" ><strong>Select Backhaul Channel </strong></div></td>
|
||||
<td width="15%">
|
||||
<select style="width:200px" name="chandrop1" id="drop3" onchange="return channelchange(this)">
|
||||
</select>
|
||||
</td>
|
||||
<td width="12%"><div align="left" id="dfs1" style="font-size:1em"><strong>Use DFS Channels </strong></div></td>
|
||||
<td width="5%"><input type="checkbox" id="dfs" onclick="return setdfs(this)" /></td>
|
||||
<td width="20%"></td>
|
||||
<td width="31%"></td>
|
||||
</tr>
|
||||
|
||||
<tr id="radio55">
|
||||
<td width="17%"><div align="right" id="radio5" ><strong>Select Backhaul Channel </strong></div></td>
|
||||
<td width="15%">
|
||||
<select style="width:200px" name="chandrop2" id="drop4" onchange="return channelchange(this)">
|
||||
</select>
|
||||
</td>
|
||||
<td width="12%"><div align="left" id="dfs2" style="font-size:1em"><strong>Use DFS Channels </strong></div></td>
|
||||
<td width="5%"><input type="checkbox" id="dfs3" onclick="return setdfs(this)" /></td>
|
||||
<td width="20%"></td>
|
||||
<td width="31%"></td>
|
||||
</tr>
|
||||
|
||||
<tr id="radio46">
|
||||
<td width="17%"><div align="right" id="radio6" ><strong>Channel Bandwidth </strong></div></td>
|
||||
<td width="15%">
|
||||
<select style="width:200px" name="chandrop3" id="drop5" onchange="return bwchange(this)">
|
||||
</select>
|
||||
</td>
|
||||
<td width="12%"></td>
|
||||
<td width="5%"></td>
|
||||
<td width="20%"></td>
|
||||
<td width="31%"></td>
|
||||
</tr>
|
||||
|
||||
<tr id="radio47">
|
||||
<td width="17%"><div align="right" id="radio7" ><strong>Channel Bandwidth </strong></div></td>
|
||||
<td width="15%">
|
||||
<select style="width:200px" name="chandrop3" id="drop6" onchange="return bwchange(this)">
|
||||
</select>
|
||||
</td>
|
||||
<td width="12%"></td>
|
||||
<td width="5%"></td>
|
||||
<td width="20%"></td>
|
||||
<td width="31%"></td>
|
||||
</tr>
|
||||
|
||||
<tr id="radio48">
|
||||
<td width="17%"><div align="right" id="radio7" ><strong>Channel Bandwidth </strong></div></td>
|
||||
<td width="15%">
|
||||
<select style="width:200px" name="chandrop3" id="drop7" onchange="return bwchange(this)">
|
||||
</select>
|
||||
</td>
|
||||
<td width="12%"></td>
|
||||
<td width="5%"></td>
|
||||
<td width="20%"></td>
|
||||
<td width="31%"></td>
|
||||
</tr>
|
||||
|
||||
<tr id="radio49">
|
||||
<td width="17%"><div align="right" id="radio7" ><strong>Channel Bandwidth </strong></div></td>
|
||||
<td width="15%">
|
||||
<select style="width:200px" name="chandrop3" id="drop8" onchange="return bwchange(this)">
|
||||
</select>
|
||||
</td>
|
||||
<td width="12%"></td>
|
||||
<td width="5%"></td>
|
||||
<td width="20%"></td>
|
||||
<td width="31%"></td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="cbi-section" id="cbi-mod2" >
|
||||
<table width="100%" border="0" id="meshnet" >
|
||||
<tr>
|
||||
<td width="17%"><div align="left" id="net1" style="font-size:1.5em"><strong>Mesh Network Settings</strong></div></td>
|
||||
<td width="10%"></td>
|
||||
<td width="12%"></td>
|
||||
<td width="15%"></td>
|
||||
<td width="15%"></td>
|
||||
<td width="31%"></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td width="17%"><div align="right" id="net2" ><strong>Mesh Network ID </strong></div></td>
|
||||
<td width="10%" ><input style="width: 200px;" type="text" name="idnam" id="idnam" class="cbi-input-text" value="MeshCloud" onchange="return changeid()" ></input></td>
|
||||
<td width="12%"></td>
|
||||
<td width="15%"></td>
|
||||
<td width="15%"></td>
|
||||
<td width="31%"></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td width="17%"><div align="right" id="enc1" style="font-size:1em"><strong>Network Encrypted </strong></div></td>
|
||||
<td width="10%"><input type="checkbox" id="encr" onclick="return setencr(this)" /></td>
|
||||
<td width="12%"><div align="left" id="enc2" style="font-size:1em; visibility:hidden"><strong>Network Password </strong></div></td>
|
||||
<td width="15%"><input style="width: 200px; visibility:hidden" type="text" name="netpass" id="netpass" class="cbi-input-text" placeholder="password" onchange="return changeid()" ></input></td>
|
||||
<td width="15%"></td>
|
||||
<td width="31%"></td>
|
||||
</tr>
|
||||
</table>
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="cbi-section" id="cbi-mod3" >
|
||||
<table width="100%" border="0" id="meshroam" >
|
||||
<tr>
|
||||
<td width="17%"><div align="left" id="roam1" style="font-size:1.5em"><strong>Access Point Roaming</strong></div></td>
|
||||
<td width="10%"></td>
|
||||
<td width="12%"></td>
|
||||
<td width="15%"></td>
|
||||
<td width="15%"></td>
|
||||
<td width="31%"></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td width="17%"><div align="right" id="enc1" style="font-size:1em"><strong>Enable Low Signal Roaming </strong></div></td>
|
||||
<td width="10%"><input type="checkbox" id="sigenb" onclick="return setlow(this)" /></td>
|
||||
<td width="12%"></td>
|
||||
<td width="15%"></td>
|
||||
<td width="15%"></td>
|
||||
<td width="31%"></td>
|
||||
</tr>
|
||||
|
||||
<tr id="roam11">
|
||||
<td width="17%"><div align="right" id="roam1" ><strong>Roaming ID </strong></div></td>
|
||||
<td width="10%" ><input style="width: 200px;" type="text" name="idsig" id="idsig" class="cbi-input-text" value="mesh" onchange="return changesigid()" ></input></td>
|
||||
<td width="12%"></td>
|
||||
<td width="15%"></td>
|
||||
<td width="15%"></td>
|
||||
<td width="31%"></td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
|
||||
<table id="cmdtxt" width="700" border="0" style="display:table;">
|
||||
<tr>
|
||||
<td width="100%">
|
||||
<textarea readonly="readonly" name="attxt" id="attxt" rows="6" style="width: 600px;" maxlength="160"></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</fieldset>
|
||||
|
||||
</div>
|
||||
</form>
|
||||
<%+footer%>
|
@ -1,251 +0,0 @@
|
||||
#!/bin/sh
|
||||
. /lib/functions.sh
|
||||
|
||||
log() {
|
||||
logger -t "Checker" "$@"
|
||||
}
|
||||
|
||||
channel2="1,2,3,4,5,6,7,8,9,10,11,12,13,14"
|
||||
channel5="36,40,44,48,149,153,157,161,165,169"
|
||||
channel5dfs="36,40,44,48,52,56,60,64,100,104,104,112,116,132,136,140,144,149,153,157,161,165,169"
|
||||
|
||||
absolute() {
|
||||
num=$1
|
||||
if [ "$num" -lt 0 ]; then
|
||||
num=$((-num))
|
||||
fi
|
||||
}
|
||||
|
||||
loadconfig() {
|
||||
X=$(uci -q get wireless.wmesh.device)
|
||||
uci set mesh.radio.radionumber=$(echo ${X#radio})
|
||||
|
||||
uci set mesh.radio.dedicated=$(uci -q get wireless.default_$X.disabled)
|
||||
|
||||
chanwidth=$(uci -q get wireless.$X.htmode)
|
||||
case $chanwidth in
|
||||
"HT20" )
|
||||
chanwidth=0
|
||||
;;
|
||||
"HT40" )
|
||||
chanwidth=1
|
||||
;;
|
||||
"VHT80" )
|
||||
chanwidth=2
|
||||
;;
|
||||
"VHT160" )
|
||||
chanwidth=2
|
||||
;;
|
||||
esac
|
||||
uci set mesh.radio.channelwidth=$chanwidth
|
||||
|
||||
chan=$(uci -q get wireless.$X.channel)
|
||||
if [ $chan -lt 15 ]; then
|
||||
uci set mesh.radio.channellist=0
|
||||
uci set mesh.radio.channelindex=$((${chan}-1))
|
||||
else
|
||||
dfs=$(uci -q get wireless.$X.usedfs)
|
||||
if [ -z $dfs ]; then
|
||||
dfs=1
|
||||
uci set mesh.radio.usedfs=1
|
||||
else
|
||||
uci set mesh.radio.usedfs=$dfs
|
||||
fi
|
||||
if [ $dfs -eq 0 ]; then
|
||||
uci set mesh.radio.channellist=1
|
||||
clist=$channel5
|
||||
else
|
||||
uci set mesh.radio.channellist=2
|
||||
clist=$channel5dfs
|
||||
fi
|
||||
cindex=1
|
||||
while [ true ]
|
||||
do
|
||||
chan=$(echo "$clist" | cut -d, -f$cindex)
|
||||
if [ $chan -eq $channel ]; then
|
||||
uci set mesh.radio.channelindex=$((${cindex}-1))
|
||||
break
|
||||
fi
|
||||
cindex=$((${cindex}+1))
|
||||
done
|
||||
fi
|
||||
|
||||
enc=$(uci -q get wireless.wmesh.encryption)
|
||||
if [ $enc = "sae" ]; then
|
||||
uci set mesh.network.netencrypted=1
|
||||
uci set mesh.network.netpassword=$(uci -q get wireless.wmesh.key)
|
||||
else
|
||||
uci set mesh.network.netencrypted=0
|
||||
uci set mesh.network.netpassword="password"
|
||||
fi
|
||||
|
||||
uci set mesh.network.networkid=$(uci -q get wireless.wmesh.mesh_id)
|
||||
|
||||
snr=$(uci -q get wireless.default_$X.ieee80211r)
|
||||
if [ ! -z $snr ]; then
|
||||
uci set mesh.roam.signalenable=$snr
|
||||
uci set mesh.roam.signalid=$(uci -q get wireless.default_$X.mobility_domain)
|
||||
else
|
||||
uci set mesh.roam.signalenable=0
|
||||
uci set mesh.roam.signalid="abcd"
|
||||
fi
|
||||
|
||||
uci commit mesh
|
||||
}
|
||||
|
||||
count_radio() {
|
||||
local config=$1
|
||||
local channel
|
||||
|
||||
uci set wireless.default_radio$count.ieee80211r=$signalenable
|
||||
uci set wireless.default_radio$count.mobility_domain=$signalid
|
||||
uci set wireless.default_radio$count.ft_over_ds="1"
|
||||
uci set wireless.default_radio$count.ft_psk_generate_local="1"
|
||||
count=$((${count}+1))
|
||||
|
||||
}
|
||||
|
||||
loadmesh() {
|
||||
radionum=$(uci -q get mesh.radio.radionumber)
|
||||
dedicated=$(uci -q get mesh.radio.dedicated)
|
||||
if [ -z $dedicated ]; then
|
||||
dedicated="0"
|
||||
fi
|
||||
log "default_radio$radionum disabled = $dedicated"
|
||||
|
||||
chanwidth=$(uci -q get mesh.radio.channelwidth)
|
||||
case $chanwidth in
|
||||
"0" )
|
||||
chanwidth=20
|
||||
;;
|
||||
"1" )
|
||||
chanwidth=40
|
||||
;;
|
||||
"2" )
|
||||
chanwidth=80
|
||||
;;
|
||||
"3" )
|
||||
chanwidth=80
|
||||
;;
|
||||
esac
|
||||
cwidth=$(uci -q get wireless.radio$radionum.htmode)
|
||||
ht=$(echo "$cwidth" | grep "VHT")
|
||||
if [ ! -z $ht ]; then
|
||||
cwidth="VHT"$chanwidth
|
||||
else
|
||||
cwidth="HT"$chanwidth
|
||||
fi
|
||||
log "radio$radionum htmode = $cwidth"
|
||||
|
||||
clist=$(uci -q get mesh.radio.channellist)
|
||||
cindex=$(uci -q get mesh.radio.channelindex)
|
||||
cindex=$((${cindex}+1))
|
||||
case $clist in
|
||||
"0" )
|
||||
channel=$(echo "$channel2" | cut -d, -f$cindex)
|
||||
;;
|
||||
"1" )
|
||||
channel=$(echo "$channel5" | cut -d, -f$cindex)
|
||||
;;
|
||||
"2" )
|
||||
channel=$(echo "$channel5dfs" | cut -d, -f$cindex)
|
||||
;;
|
||||
esac
|
||||
log "radio$radionum channel = $channel"
|
||||
|
||||
networkid=$(uci -q get mesh.network.networkid)
|
||||
netencrypted=$(uci -q get mesh.network.netencrypted)
|
||||
netpassword=$(uci -q get mesh.network.netpassword)
|
||||
log "mesh_id = $networkid"
|
||||
log "encryption = $netencrypted key = $netpassword"
|
||||
|
||||
signalenable=$(uci -q get mesh.roam.signalenable)
|
||||
signalid=$(uci -q get mesh.roam.signalid)
|
||||
log "roam enable = $signalenable"
|
||||
log "id = $signalid"
|
||||
|
||||
ipaddr=$(uci -q get network.lan.ipaddr)
|
||||
|
||||
uci set wireless.default_radio$radionum.disabled=$dedicated
|
||||
uci set wireless.radio$radionum.htmode=$cwidth
|
||||
uci set wireless.radio$radionum.channel=$channel
|
||||
|
||||
count=0
|
||||
config_load wireless
|
||||
config_foreach count_radio wifi-iface
|
||||
|
||||
uci set wireless.wmesh=wifi-iface
|
||||
uci set wireless.wmesh.device=radio$radionum
|
||||
uci set wireless.wmesh.network="mesh"
|
||||
uci set wireless.wmesh.ifname="if-mesh"
|
||||
uci set wireless.wmesh.mode="mesh"
|
||||
uci set wireless.wmesh.mesh_fwding="0"
|
||||
uci set wireless.wmesh.mesh_id=$networkid
|
||||
uci set wireless.w.encryption="none"
|
||||
if [ $netencrypted = "1" ]; then
|
||||
uci set wireless.wmesh.encryption="sae"
|
||||
uci set wireless.wmesh.key=$netpassword
|
||||
fi
|
||||
uci set wireless.wmesh.mesh_ttl='1'
|
||||
uci set wireless.wmesh.mcast_rate='24000'
|
||||
uci set wireless.wmesh.disabled='0'
|
||||
uci commit wireless
|
||||
|
||||
uci set alfred.alfred.batmanif='bat0'
|
||||
uci set alfred.alfred.disabled='0'
|
||||
uci commit alfred
|
||||
|
||||
uci set network.bat0=interface
|
||||
uci set network.bat0.proto='batadv'
|
||||
uci set network.bat0.routing_algo='BATMAN_IV'
|
||||
uci set network.bat0.aggregated_ogms='1'
|
||||
uci set network.bat0.ap_isolation='0'
|
||||
uci set network.bat0.bonding='0'
|
||||
uci set network.bat0.bridge_loop_avoidance='1'
|
||||
uci set network.bat0.distributed_arp_table='1'
|
||||
uci set network.bat0.fragmentation='1'
|
||||
uci set network.bat0.gw_mode='off'
|
||||
uci set network.bat0.hop_penalty='30'
|
||||
uci set network.bat0.isolation_mark='0x00000000/0x00000000'
|
||||
uci set network.bat0.log_level='0'
|
||||
uci set network.bat0.multicast_mode='1'
|
||||
uci set network.bat0.multicast_fanout='16'
|
||||
uci set network.bat0.network_coding='0'
|
||||
uci set network.bat0.orig_interval='1000'
|
||||
|
||||
uci set network.mesh=interface
|
||||
uci set network.mesh.proto='batadv_hardif'
|
||||
uci set network.mesh.master='bat0'
|
||||
uci set network.mesh.mtu='2304'
|
||||
uci set network.mesh.throughput_override='0'
|
||||
|
||||
uci set network.bat0_hardif_eth0=interface
|
||||
uci set network.bat0_hardif_eth0.proto='batadv_hardif'
|
||||
uci set network.bat0_hardif_eth0.master='bat0'
|
||||
uci set network.bat0_hardif_eth0.mtu='1536'
|
||||
uci set network.bat0_hardif_eth0.device='eth0'
|
||||
|
||||
uci set network.bat0_lan=interface
|
||||
uci set network.bat0_lan.proto='static'
|
||||
uci set network.bat0_lan.ipaddr=$ipaddr
|
||||
uci set network.bat0_lan.netmask='255.255.255.0'
|
||||
uci set network.bat0_lan.ip6assign='60'
|
||||
uci set network.bat0_lan.device='bat0'
|
||||
uci commit network
|
||||
}
|
||||
|
||||
cmd=$1
|
||||
if [ -z $cmd ]; then
|
||||
WW=$(uci get wireless.wmesh)
|
||||
if [ -z $WW ]; then
|
||||
loadmesh
|
||||
reboot -f
|
||||
else
|
||||
loadconfig
|
||||
/usr/lib/mesh/ping.sh &
|
||||
fi
|
||||
else
|
||||
loadmesh
|
||||
fi
|
||||
|
||||
return
|
@ -1,34 +0,0 @@
|
||||
#!/bin/sh
|
||||
. /lib/functions.sh
|
||||
|
||||
pinging() {
|
||||
PING=0
|
||||
RETURN_CODE_1=$(curl -m 10 -s -o /dev/null -w "%{http_code}" http://www.google.com/)
|
||||
RETURN_CODE_2=$(curl -m 10 -s -o /dev/null -w "%{http_code}" http://www.example.org/)
|
||||
RETURN_CODE_3=$(curl -m 10 -s -o /dev/null -w "%{http_code}" https://github.com)
|
||||
|
||||
if [[ "$RETURN_CODE_1" != "200" && "$RETURN_CODE_2" != "200" && "$RETURN_CODE_3" != "200" ]]; then
|
||||
PING=1
|
||||
fi
|
||||
}
|
||||
|
||||
gateway() {
|
||||
mode=$1
|
||||
# batman-adv gateway handling (DHCP mangling)
|
||||
[ "$(uci -q get batman-adv.bat0.gw_mode)" == "client" ] || return
|
||||
if grep -q "^=>" /sys/kernel/debug/batman_adv/bat0/gateways ; then
|
||||
BATTYPE=gw BATACTION=$mode /etc/hotplug.d/net/99-batman-gw
|
||||
fi
|
||||
}
|
||||
|
||||
while true ; do
|
||||
sleep 20
|
||||
pinging
|
||||
if [ $PING -eq 1 ]; then
|
||||
gateway add
|
||||
batctl gw_mode client
|
||||
else
|
||||
gateway del
|
||||
batctl gw_mode server 10000
|
||||
fi
|
||||
done
|
@ -1,78 +0,0 @@
|
||||
#!/bin/sh
|
||||
. /lib/functions.sh
|
||||
|
||||
log() {
|
||||
logger -t "Radio" "$@"
|
||||
}
|
||||
|
||||
count_radio() {
|
||||
local config=$1
|
||||
local channel
|
||||
|
||||
config_get channel $1 channel
|
||||
count=$((${count}+1))
|
||||
}
|
||||
|
||||
do_radio() {
|
||||
local config=$1
|
||||
local channel
|
||||
|
||||
config_get channel $1 channel
|
||||
rn=${config#radio}
|
||||
freq="1"
|
||||
if [ $channel -lt 15 ]; then
|
||||
freq="0"
|
||||
fi
|
||||
iwin=$(iw phy phy$rn info)
|
||||
hw=0
|
||||
hwt=$(echo "$iwin" | grep 'short GI for 40 MHz')
|
||||
if [ ! -z "$hwt" ]; then
|
||||
hw=1
|
||||
fi
|
||||
hwt=$(echo "$iwin" | grep 'short GI (80 MHz)')
|
||||
if [ ! -z "$hwt" ]; then
|
||||
hw=2
|
||||
fi
|
||||
hwt=$(echo "$iwin" | grep 'short GI (160')
|
||||
if [ ! -z "$hwt" ]; then
|
||||
hw=3
|
||||
fi
|
||||
echo "$freq|$rn|$hw" >> /tmp/radiolist
|
||||
}
|
||||
|
||||
count=0
|
||||
rm -f /tmp/radiolist
|
||||
config_load wireless
|
||||
config_foreach count_radio wifi-device
|
||||
if [ $count -gt 0 ]; then
|
||||
echo "$count" > /tmp/radiolist
|
||||
config_foreach do_radio wifi-device
|
||||
fi
|
||||
|
||||
CF1=$(uci -q get mesh.radio.radionumber)
|
||||
CF2=$(uci -q get mesh.radio.channelindex)
|
||||
CF3=$(uci -q get mesh.radio.channellist)
|
||||
CF4=$(uci -q get mesh.radio.channelwidth)
|
||||
CF5=$(uci -q get mesh.radio.usedfs)
|
||||
CF6=$(uci -q get mesh.radio.dedicated)
|
||||
echo "$CF1" >> /tmp/radiolist
|
||||
echo "$CF2" >> /tmp/radiolist
|
||||
echo "$CF3" >> /tmp/radiolist
|
||||
echo "$CF4" >> /tmp/radiolist
|
||||
echo "$CF5" >> /tmp/radiolist
|
||||
echo "$CF6" >> /tmp/radiolist
|
||||
|
||||
CF1=$(uci -q get mesh.network.networkid)
|
||||
CF2=$(uci -q get mesh.network.netencrypted)
|
||||
CF3=$(uci -q get mesh.network.netpassword)
|
||||
echo "$CF1" >> /tmp/radiolist
|
||||
echo "$CF2" >> /tmp/radiolist
|
||||
echo "$CF3" >> /tmp/radiolist
|
||||
|
||||
CF1=$(uci -q get mesh.roam.signalenable)
|
||||
CF2=$(uci -q get mesh.roam.signalid)
|
||||
echo "$CF1" >> /tmp/radiolist
|
||||
echo "$CF2" >> /tmp/radiolist
|
||||
|
||||
|
||||
|
@ -1,25 +0,0 @@
|
||||
#!/bin/sh
|
||||
. /lib/functions.sh
|
||||
|
||||
log() {
|
||||
logger -t "Save" "$@"
|
||||
}
|
||||
|
||||
state=$1
|
||||
|
||||
state=$(echo "$state" | tr "|" ",")
|
||||
uci set mesh.radio.radionumber=$(echo "$state" | cut -d, -f1)
|
||||
uci set mesh.radio.channelindex=$(echo "$state" | cut -d, -f2)
|
||||
uci set mesh.radio.channellist=$(echo "$state" | cut -d, -f3)
|
||||
uci set mesh.radio.usedfs=$(echo "$state" | cut -d, -f4)
|
||||
uci set mesh.radio.channelwidth=$(echo "$state" | cut -d, -f5)
|
||||
uci set mesh.radio.dedicated=$(echo "$state" | cut -d, -f6)
|
||||
|
||||
uci set mesh.network.networkid=$(echo "$state" | cut -d, -f7)
|
||||
uci set mesh.network.netencrypted=$(echo "$state" | cut -d, -f8)
|
||||
uci set mesh.network.netpassword=$(echo "$state" | cut -d, -f9)
|
||||
|
||||
uci set mesh.roam.signalenable=$(echo "$state" | cut -d, -f10)
|
||||
uci set mesh.roam.signalid=$(echo "$state" | cut -d, -f11)
|
||||
|
||||
uci commit mesh
|
@ -1,16 +0,0 @@
|
||||
#!/bin/sh
|
||||
. /lib/functions.sh
|
||||
|
||||
log() {
|
||||
logger -t "Save" "$@"
|
||||
}
|
||||
|
||||
state=$1
|
||||
|
||||
PKI_DIR="/www"
|
||||
cd ${PKI_DIR}
|
||||
mkdir -p package
|
||||
cd ..
|
||||
chmod -R 0777 ${PKI_DIR}/package
|
||||
|
||||
echo "$state" > ${PKI_DIR}/package/meshcfg.meshcfg
|
@ -1,8 +0,0 @@
|
||||
#!/bin/sh
|
||||
. /lib/functions.sh
|
||||
|
||||
log() {
|
||||
logger -t "Start Mesh" "$@"
|
||||
}
|
||||
|
||||
/usr/lib/mesh/checker.sh 1
|
@ -1 +0,0 @@
|
||||
Raphael.fn.connection=function(a,b,c){var d=this,e={draw:function(){for(var f=a.getBBox(),g=b.getBBox(),h=0,i=0,j=[{x:f.x+f.width/2,y:f.y-h},{x:f.x+f.width/2,y:f.y+f.height+h},{x:f.x-h,y:f.y+f.height/2},{x:f.x+f.width+h,y:f.y+f.height/2},{x:g.x+g.width/2,y:g.y-i},{x:g.x+g.width/2,y:g.y+g.height+i},{x:g.x-i,y:g.y+g.height/2},{x:g.x+g.width+i,y:g.y+g.height/2}],k={},l=[],m=0;m<4;m++)for(var n=4;n<8;n++){var o=Math.abs(j[m].x-j[n].x),p=Math.abs(j[m].y-j[n].y);(m==n-4||(3!=m&&6!=n||j[m].x<j[n].x)&&(2!=m&&7!=n||j[m].x>j[n].x)&&(0!=m&&5!=n||j[m].y>j[n].y)&&(1!=m&&4!=n||j[m].y<j[n].y))&&(l.push(o+p),k[l[l.length-1].toFixed(3)]=[m,n])}var q=0==l.length?[0,4]:k[Math.min.apply(Math,l).toFixed(3)],r=j[q[0]].x,s=j[q[0]].y,t=j[q[1]].x,u=j[q[1]].y,o=Math.max(Math.abs(r-t)/2,10),p=Math.max(Math.abs(s-u)/2,10),v=[r,r,r-o,r+o][q[0]].toFixed(3),w=[s-p,s+p,s,s][q[0]].toFixed(3),x=[0,0,0,0,t,t,t-o,t+o][q[1]].toFixed(3),y=[0,0,0,0,s+p,s-p,u,u][q[1]].toFixed(3),z=["M",r.toFixed(3),s.toFixed(3),"C",v,w,x,y,t.toFixed(3),u.toFixed(3)].join(",");if(c&&c.directed){var A=Math.sqrt((u-y)*(u-y)+(t-x)*(t-x)),B=function(a,b){return-a*(b||5)/A},C=[{x:(B(t-x)+B(u-y)+t).toFixed(3),y:(B(u-y)+B(t-x)+u).toFixed(3)},{x:(B(t-x)-B(u-y)+t).toFixed(3),y:(B(u-y)-B(t-x)+u).toFixed(3)}];z=z+",M"+C[0].x+","+C[0].y+",L"+t+","+u+",L"+C[1].x+","+C[1].y}var D="attr";e.fg&&e.fg[D]({path:z})||(e.fg=d.path(z).attr({stroke:c&&c.stroke||"#000",fill:"none"}).toBack()),e.bg&&e.bg[D]({path:z})||c&&c.fill&&(e.bg=c.fill.split&&d.path(z).attr({stroke:c.fill.split("|")[0],fill:"none","stroke-width":c.fill.split("|")[1]||3}).toBack()),c&&c.label&&(e.label&&e.label.attr({x:(r+t)/2,y:(s+u)/2})||(e.label=d.text((r+t)/2,(s+u)/2,c.label).attr({fill:"#000","font-size":c["font-size"]||"12px"}))),c&&c.label&&c["label-style"]&&e.label&&e.label.attr(c["label-style"]),c&&c.callback&&c.callback(e)}};return e.draw(),e};
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,154 +0,0 @@
|
||||
/*!
|
||||
* jQuery JavaScript Library v1.4.2
|
||||
* http://jquery.com/
|
||||
*
|
||||
* Copyright 2010, John Resig
|
||||
* Dual licensed under the MIT or GPL Version 2 licenses.
|
||||
* http://jquery.org/license
|
||||
*
|
||||
* Includes Sizzle.js
|
||||
* http://sizzlejs.com/
|
||||
* Copyright 2010, The Dojo Foundation
|
||||
* Released under the MIT, BSD, and GPL Licenses.
|
||||
*
|
||||
* Date: Sat Feb 13 22:33:48 2010 -0500
|
||||
*/
|
||||
(function(A,w){function ma(){if(!c.isReady){try{s.documentElement.doScroll("left")}catch(a){setTimeout(ma,1);return}c.ready()}}function Qa(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)}function X(a,b,d,f,e,j){var i=a.length;if(typeof b==="object"){for(var o in b)X(a,o,b[o],f,e,d);return a}if(d!==w){f=!j&&f&&c.isFunction(d);for(o=0;o<i;o++)e(a[o],b,f?d.call(a[o],o,e(a[o],b)):d,j);return a}return i?
|
||||
e(a[0],b):w}function J(){return(new Date).getTime()}function Y(){return false}function Z(){return true}function na(a,b,d){d[0].type=a;return c.event.handle.apply(b,d)}function oa(a){var b,d=[],f=[],e=arguments,j,i,o,k,n,r;i=c.data(this,"events");if(!(a.liveFired===this||!i||!i.live||a.button&&a.type==="click")){a.liveFired=this;var u=i.live.slice(0);for(k=0;k<u.length;k++){i=u[k];i.origType.replace(O,"")===a.type?f.push(i.selector):u.splice(k--,1)}j=c(a.target).closest(f,a.currentTarget);n=0;for(r=
|
||||
j.length;n<r;n++)for(k=0;k<u.length;k++){i=u[k];if(j[n].selector===i.selector){o=j[n].elem;f=null;if(i.preType==="mouseenter"||i.preType==="mouseleave")f=c(a.relatedTarget).closest(i.selector)[0];if(!f||f!==o)d.push({elem:o,handleObj:i})}}n=0;for(r=d.length;n<r;n++){j=d[n];a.currentTarget=j.elem;a.data=j.handleObj.data;a.handleObj=j.handleObj;if(j.handleObj.origHandler.apply(j.elem,e)===false){b=false;break}}return b}}function pa(a,b){return"live."+(a&&a!=="*"?a+".":"")+b.replace(/\./g,"`").replace(/ /g,
|
||||
"&")}function qa(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function ra(a,b){var d=0;b.each(function(){if(this.nodeName===(a[d]&&a[d].nodeName)){var f=c.data(a[d++]),e=c.data(this,f);if(f=f&&f.events){delete e.handle;e.events={};for(var j in f)for(var i in f[j])c.event.add(this,j,f[j][i],f[j][i].data)}}})}function sa(a,b,d){var f,e,j;b=b&&b[0]?b[0].ownerDocument||b[0]:s;if(a.length===1&&typeof a[0]==="string"&&a[0].length<512&&b===s&&!ta.test(a[0])&&(c.support.checkClone||!ua.test(a[0]))){e=
|
||||
true;if(j=c.fragments[a[0]])if(j!==1)f=j}if(!f){f=b.createDocumentFragment();c.clean(a,b,f,d)}if(e)c.fragments[a[0]]=j?f:1;return{fragment:f,cacheable:e}}function K(a,b){var d={};c.each(va.concat.apply([],va.slice(0,b)),function(){d[this]=a});return d}function wa(a){return"scrollTo"in a&&a.document?a:a.nodeType===9?a.defaultView||a.parentWindow:false}var c=function(a,b){return new c.fn.init(a,b)},Ra=A.jQuery,Sa=A.$,s=A.document,T,Ta=/^[^<]*(<[\w\W]+>)[^>]*$|^#([\w-]+)$/,Ua=/^.[^:#\[\.,]*$/,Va=/\S/,
|
||||
Wa=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,Xa=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,P=navigator.userAgent,xa=false,Q=[],L,$=Object.prototype.toString,aa=Object.prototype.hasOwnProperty,ba=Array.prototype.push,R=Array.prototype.slice,ya=Array.prototype.indexOf;c.fn=c.prototype={init:function(a,b){var d,f;if(!a)return this;if(a.nodeType){this.context=this[0]=a;this.length=1;return this}if(a==="body"&&!b){this.context=s;this[0]=s.body;this.selector="body";this.length=1;return this}if(typeof a==="string")if((d=Ta.exec(a))&&
|
||||
(d[1]||!b))if(d[1]){f=b?b.ownerDocument||b:s;if(a=Xa.exec(a))if(c.isPlainObject(b)){a=[s.createElement(a[1])];c.fn.attr.call(a,b,true)}else a=[f.createElement(a[1])];else{a=sa([d[1]],[f]);a=(a.cacheable?a.fragment.cloneNode(true):a.fragment).childNodes}return c.merge(this,a)}else{if(b=s.getElementById(d[2])){if(b.id!==d[2])return T.find(a);this.length=1;this[0]=b}this.context=s;this.selector=a;return this}else if(!b&&/^\w+$/.test(a)){this.selector=a;this.context=s;a=s.getElementsByTagName(a);return c.merge(this,
|
||||
a)}else return!b||b.jquery?(b||T).find(a):c(b).find(a);else if(c.isFunction(a))return T.ready(a);if(a.selector!==w){this.selector=a.selector;this.context=a.context}return c.makeArray(a,this)},selector:"",jquery:"1.4.2",length:0,size:function(){return this.length},toArray:function(){return R.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this.slice(a)[0]:this[a]},pushStack:function(a,b,d){var f=c();c.isArray(a)?ba.apply(f,a):c.merge(f,a);f.prevObject=this;f.context=this.context;if(b===
|
||||
"find")f.selector=this.selector+(this.selector?" ":"")+d;else if(b)f.selector=this.selector+"."+b+"("+d+")";return f},each:function(a,b){return c.each(this,a,b)},ready:function(a){c.bindReady();if(c.isReady)a.call(s,c);else Q&&Q.push(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(R.apply(this,arguments),"slice",R.call(arguments).join(","))},map:function(a){return this.pushStack(c.map(this,
|
||||
function(b,d){return a.call(b,d,b)}))},end:function(){return this.prevObject||c(null)},push:ba,sort:[].sort,splice:[].splice};c.fn.init.prototype=c.fn;c.extend=c.fn.extend=function(){var a=arguments[0]||{},b=1,d=arguments.length,f=false,e,j,i,o;if(typeof a==="boolean"){f=a;a=arguments[1]||{};b=2}if(typeof a!=="object"&&!c.isFunction(a))a={};if(d===b){a=this;--b}for(;b<d;b++)if((e=arguments[b])!=null)for(j in e){i=a[j];o=e[j];if(a!==o)if(f&&o&&(c.isPlainObject(o)||c.isArray(o))){i=i&&(c.isPlainObject(i)||
|
||||
c.isArray(i))?i:c.isArray(o)?[]:{};a[j]=c.extend(f,i,o)}else if(o!==w)a[j]=o}return a};c.extend({noConflict:function(a){A.$=Sa;if(a)A.jQuery=Ra;return c},isReady:false,ready:function(){if(!c.isReady){if(!s.body)return setTimeout(c.ready,13);c.isReady=true;if(Q){for(var a,b=0;a=Q[b++];)a.call(s,c);Q=null}c.fn.triggerHandler&&c(s).triggerHandler("ready")}},bindReady:function(){if(!xa){xa=true;if(s.readyState==="complete")return c.ready();if(s.addEventListener){s.addEventListener("DOMContentLoaded",
|
||||
L,false);A.addEventListener("load",c.ready,false)}else if(s.attachEvent){s.attachEvent("onreadystatechange",L);A.attachEvent("onload",c.ready);var a=false;try{a=A.frameElement==null}catch(b){}s.documentElement.doScroll&&a&&ma()}}},isFunction:function(a){return $.call(a)==="[object Function]"},isArray:function(a){return $.call(a)==="[object Array]"},isPlainObject:function(a){if(!a||$.call(a)!=="[object Object]"||a.nodeType||a.setInterval)return false;if(a.constructor&&!aa.call(a,"constructor")&&!aa.call(a.constructor.prototype,
|
||||
"isPrototypeOf"))return false;var b;for(b in a);return b===w||aa.call(a,b)},isEmptyObject:function(a){for(var b in a)return false;return true},error:function(a){throw a;},parseJSON:function(a){if(typeof a!=="string"||!a)return null;a=c.trim(a);if(/^[\],:{}\s]*$/.test(a.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,"")))return A.JSON&&A.JSON.parse?A.JSON.parse(a):(new Function("return "+
|
||||
a))();else c.error("Invalid JSON: "+a)},noop:function(){},globalEval:function(a){if(a&&Va.test(a)){var b=s.getElementsByTagName("head")[0]||s.documentElement,d=s.createElement("script");d.type="text/javascript";if(c.support.scriptEval)d.appendChild(s.createTextNode(a));else d.text=a;b.insertBefore(d,b.firstChild);b.removeChild(d)}},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,b,d){var f,e=0,j=a.length,i=j===w||c.isFunction(a);if(d)if(i)for(f in a){if(b.apply(a[f],
|
||||
d)===false)break}else for(;e<j;){if(b.apply(a[e++],d)===false)break}else if(i)for(f in a){if(b.call(a[f],f,a[f])===false)break}else for(d=a[0];e<j&&b.call(d,e,d)!==false;d=a[++e]);return a},trim:function(a){return(a||"").replace(Wa,"")},makeArray:function(a,b){b=b||[];if(a!=null)a.length==null||typeof a==="string"||c.isFunction(a)||typeof a!=="function"&&a.setInterval?ba.call(b,a):c.merge(b,a);return b},inArray:function(a,b){if(b.indexOf)return b.indexOf(a);for(var d=0,f=b.length;d<f;d++)if(b[d]===
|
||||
a)return d;return-1},merge:function(a,b){var d=a.length,f=0;if(typeof b.length==="number")for(var e=b.length;f<e;f++)a[d++]=b[f];else for(;b[f]!==w;)a[d++]=b[f++];a.length=d;return a},grep:function(a,b,d){for(var f=[],e=0,j=a.length;e<j;e++)!d!==!b(a[e],e)&&f.push(a[e]);return f},map:function(a,b,d){for(var f=[],e,j=0,i=a.length;j<i;j++){e=b(a[j],j,d);if(e!=null)f[f.length]=e}return f.concat.apply([],f)},guid:1,proxy:function(a,b,d){if(arguments.length===2)if(typeof b==="string"){d=a;a=d[b];b=w}else if(b&&
|
||||
!c.isFunction(b)){d=b;b=w}if(!b&&a)b=function(){return a.apply(d||this,arguments)};if(a)b.guid=a.guid=a.guid||b.guid||c.guid++;return b},uaMatch:function(a){a=a.toLowerCase();a=/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version)?[ \/]([\w.]+)/.exec(a)||/(msie) ([\w.]+)/.exec(a)||!/compatible/.test(a)&&/(mozilla)(?:.*? rv:([\w.]+))?/.exec(a)||[];return{browser:a[1]||"",version:a[2]||"0"}},browser:{}});P=c.uaMatch(P);if(P.browser){c.browser[P.browser]=true;c.browser.version=P.version}if(c.browser.webkit)c.browser.safari=
|
||||
true;if(ya)c.inArray=function(a,b){return ya.call(b,a)};T=c(s);if(s.addEventListener)L=function(){s.removeEventListener("DOMContentLoaded",L,false);c.ready()};else if(s.attachEvent)L=function(){if(s.readyState==="complete"){s.detachEvent("onreadystatechange",L);c.ready()}};(function(){c.support={};var a=s.documentElement,b=s.createElement("script"),d=s.createElement("div"),f="script"+J();d.style.display="none";d.innerHTML=" <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>";
|
||||
var e=d.getElementsByTagName("*"),j=d.getElementsByTagName("a")[0];if(!(!e||!e.length||!j)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(j.getAttribute("style")),hrefNormalized:j.getAttribute("href")==="/a",opacity:/^0.55$/.test(j.style.opacity),cssFloat:!!j.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:s.createElement("select").appendChild(s.createElement("option")).selected,
|
||||
parentNode:d.removeChild(d.appendChild(s.createElement("div"))).parentNode===null,deleteExpando:true,checkClone:false,scriptEval:false,noCloneEvent:true,boxModel:null};b.type="text/javascript";try{b.appendChild(s.createTextNode("window."+f+"=1;"))}catch(i){}a.insertBefore(b,a.firstChild);if(A[f]){c.support.scriptEval=true;delete A[f]}try{delete b.test}catch(o){c.support.deleteExpando=false}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function k(){c.support.noCloneEvent=
|
||||
false;d.detachEvent("onclick",k)});d.cloneNode(true).fireEvent("onclick")}d=s.createElement("div");d.innerHTML="<input type='radio' name='radiotest' checked='checked'/>";a=s.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var k=s.createElement("div");k.style.width=k.style.paddingLeft="1px";s.body.appendChild(k);c.boxModel=c.support.boxModel=k.offsetWidth===2;s.body.removeChild(k).style.display="none"});a=function(k){var n=
|
||||
s.createElement("div");k="on"+k;var r=k in n;if(!r){n.setAttribute(k,"return;");r=typeof n[k]==="function"}return r};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=e=j=null}})();c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};var G="jQuery"+J(),Ya=0,za={};c.extend({cache:{},expando:G,noData:{embed:true,object:true,
|
||||
applet:true},data:function(a,b,d){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var f=a[G],e=c.cache;if(!f&&typeof b==="string"&&d===w)return null;f||(f=++Ya);if(typeof b==="object"){a[G]=f;e[f]=c.extend(true,{},b)}else if(!e[f]){a[G]=f;e[f]={}}a=e[f];if(d!==w)a[b]=d;return typeof b==="string"?a[b]:a}},removeData:function(a,b){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var d=a[G],f=c.cache,e=f[d];if(b){if(e){delete e[b];c.isEmptyObject(e)&&c.removeData(a)}}else{if(c.support.deleteExpando)delete a[c.expando];
|
||||
else a.removeAttribute&&a.removeAttribute(c.expando);delete f[d]}}}});c.fn.extend({data:function(a,b){if(typeof a==="undefined"&&this.length)return c.data(this[0]);else if(typeof a==="object")return this.each(function(){c.data(this,a)});var d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===w){var f=this.triggerHandler("getData"+d[1]+"!",[d[0]]);if(f===w&&this.length)f=c.data(this[0],a);return f===w&&d[1]?this.data(d[0]):f}else return this.trigger("setData"+d[1]+"!",[d[0],b]).each(function(){c.data(this,
|
||||
a,b)})},removeData:function(a){return this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var f=c.data(a,b);if(!d)return f||[];if(!f||c.isArray(d))f=c.data(a,b,c.makeArray(d));else f.push(d);return f}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),f=d.shift();if(f==="inprogress")f=d.shift();if(f){b==="fx"&&d.unshift("inprogress");f.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b===
|
||||
w)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var Aa=/[\n\t]/g,ca=/\s+/,Za=/\r/g,$a=/href|src|style/,ab=/(button|input)/i,bb=/(button|input|object|select|textarea)/i,
|
||||
cb=/^(a|area)$/i,Ba=/radio|checkbox/;c.fn.extend({attr:function(a,b){return X(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(n){var r=c(this);r.addClass(a.call(this,n,r.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(ca),d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1)if(e.className){for(var j=" "+e.className+" ",
|
||||
i=e.className,o=0,k=b.length;o<k;o++)if(j.indexOf(" "+b[o]+" ")<0)i+=" "+b[o];e.className=c.trim(i)}else e.className=a}return this},removeClass:function(a){if(c.isFunction(a))return this.each(function(k){var n=c(this);n.removeClass(a.call(this,k,n.attr("class")))});if(a&&typeof a==="string"||a===w)for(var b=(a||"").split(ca),d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1&&e.className)if(a){for(var j=(" "+e.className+" ").replace(Aa," "),i=0,o=b.length;i<o;i++)j=j.replace(" "+b[i]+" ",
|
||||
" ");e.className=c.trim(j)}else e.className=""}return this},toggleClass:function(a,b){var d=typeof a,f=typeof b==="boolean";if(c.isFunction(a))return this.each(function(e){var j=c(this);j.toggleClass(a.call(this,e,j.attr("class"),b),b)});return this.each(function(){if(d==="string")for(var e,j=0,i=c(this),o=b,k=a.split(ca);e=k[j++];){o=f?o:!i.hasClass(e);i[o?"addClass":"removeClass"](e)}else if(d==="undefined"||d==="boolean"){this.className&&c.data(this,"__className__",this.className);this.className=
|
||||
this.className||a===false?"":c.data(this,"__className__")||""}})},hasClass:function(a){a=" "+a+" ";for(var b=0,d=this.length;b<d;b++)if((" "+this[b].className+" ").replace(Aa," ").indexOf(a)>-1)return true;return false},val:function(a){if(a===w){var b=this[0];if(b){if(c.nodeName(b,"option"))return(b.attributes.value||{}).specified?b.value:b.text;if(c.nodeName(b,"select")){var d=b.selectedIndex,f=[],e=b.options;b=b.type==="select-one";if(d<0)return null;var j=b?d:0;for(d=b?d+1:e.length;j<d;j++){var i=
|
||||
e[j];if(i.selected){a=c(i).val();if(b)return a;f.push(a)}}return f}if(Ba.test(b.type)&&!c.support.checkOn)return b.getAttribute("value")===null?"on":b.value;return(b.value||"").replace(Za,"")}return w}var o=c.isFunction(a);return this.each(function(k){var n=c(this),r=a;if(this.nodeType===1){if(o)r=a.call(this,k,n.val());if(typeof r==="number")r+="";if(c.isArray(r)&&Ba.test(this.type))this.checked=c.inArray(n.val(),r)>=0;else if(c.nodeName(this,"select")){var u=c.makeArray(r);c("option",this).each(function(){this.selected=
|
||||
c.inArray(c(this).val(),u)>=0});if(!u.length)this.selectedIndex=-1}else this.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,f){if(!a||a.nodeType===3||a.nodeType===8)return w;if(f&&b in c.attrFn)return c(a)[b](d);f=a.nodeType!==1||!c.isXMLDoc(a);var e=d!==w;b=f&&c.props[b]||b;if(a.nodeType===1){var j=$a.test(b);if(b in a&&f&&!j){if(e){b==="type"&&ab.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed");
|
||||
a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&b.specified?b.value:bb.test(a.nodeName)||cb.test(a.nodeName)&&a.href?0:w;return a[b]}if(!c.support.style&&f&&b==="style"){if(e)a.style.cssText=""+d;return a.style.cssText}e&&a.setAttribute(b,""+d);a=!c.support.hrefNormalized&&f&&j?a.getAttribute(b,2):a.getAttribute(b);return a===null?w:a}return c.style(a,b,d)}});var O=/\.(.*)$/,db=function(a){return a.replace(/[^\w\s\.\|`]/g,
|
||||
function(b){return"\\"+b})};c.event={add:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){if(a.setInterval&&a!==A&&!a.frameElement)a=A;var e,j;if(d.handler){e=d;d=e.handler}if(!d.guid)d.guid=c.guid++;if(j=c.data(a)){var i=j.events=j.events||{},o=j.handle;if(!o)j.handle=o=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(o.elem,arguments):w};o.elem=a;b=b.split(" ");for(var k,n=0,r;k=b[n++];){j=e?c.extend({},e):{handler:d,data:f};if(k.indexOf(".")>-1){r=k.split(".");
|
||||
k=r.shift();j.namespace=r.slice(0).sort().join(".")}else{r=[];j.namespace=""}j.type=k;j.guid=d.guid;var u=i[k],z=c.event.special[k]||{};if(!u){u=i[k]=[];if(!z.setup||z.setup.call(a,f,r,o)===false)if(a.addEventListener)a.addEventListener(k,o,false);else a.attachEvent&&a.attachEvent("on"+k,o)}if(z.add){z.add.call(a,j);if(!j.handler.guid)j.handler.guid=d.guid}u.push(j);c.event.global[k]=true}a=null}}},global:{},remove:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){var e,j=0,i,o,k,n,r,u,z=c.data(a),
|
||||
C=z&&z.events;if(z&&C){if(b&&b.type){d=b.handler;b=b.type}if(!b||typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(e in C)c.event.remove(a,e+b)}else{for(b=b.split(" ");e=b[j++];){n=e;i=e.indexOf(".")<0;o=[];if(!i){o=e.split(".");e=o.shift();k=new RegExp("(^|\\.)"+c.map(o.slice(0).sort(),db).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(r=C[e])if(d){n=c.event.special[e]||{};for(B=f||0;B<r.length;B++){u=r[B];if(d.guid===u.guid){if(i||k.test(u.namespace)){f==null&&r.splice(B--,1);n.remove&&n.remove.call(a,u)}if(f!=
|
||||
null)break}}if(r.length===0||f!=null&&r.length===1){if(!n.teardown||n.teardown.call(a,o)===false)Ca(a,e,z.handle);delete C[e]}}else for(var B=0;B<r.length;B++){u=r[B];if(i||k.test(u.namespace)){c.event.remove(a,n,u.handler,B);r.splice(B--,1)}}}if(c.isEmptyObject(C)){if(b=z.handle)b.elem=null;delete z.events;delete z.handle;c.isEmptyObject(z)&&c.removeData(a)}}}}},trigger:function(a,b,d,f){var e=a.type||a;if(!f){a=typeof a==="object"?a[G]?a:c.extend(c.Event(e),a):c.Event(e);if(e.indexOf("!")>=0){a.type=
|
||||
e=e.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[e]&&c.each(c.cache,function(){this.events&&this.events[e]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===8)return w;a.result=w;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(f=c.data(d,"handle"))&&f.apply(d,b);f=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+e]&&d["on"+e].apply(d,b)===false)a.result=false}catch(j){}if(!a.isPropagationStopped()&&
|
||||
f)c.event.trigger(a,b,f,true);else if(!a.isDefaultPrevented()){f=a.target;var i,o=c.nodeName(f,"a")&&e==="click",k=c.event.special[e]||{};if((!k._default||k._default.call(d,a)===false)&&!o&&!(f&&f.nodeName&&c.noData[f.nodeName.toLowerCase()])){try{if(f[e]){if(i=f["on"+e])f["on"+e]=null;c.event.triggered=true;f[e]()}}catch(n){}if(i)f["on"+e]=i;c.event.triggered=false}}},handle:function(a){var b,d,f,e;a=arguments[0]=c.event.fix(a||A.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive;
|
||||
if(!b){d=a.type.split(".");a.type=d.shift();f=new RegExp("(^|\\.)"+d.slice(0).sort().join("\\.(?:.*\\.)?")+"(\\.|$)")}e=c.data(this,"events");d=e[a.type];if(e&&d){d=d.slice(0);e=0;for(var j=d.length;e<j;e++){var i=d[e];if(b||f.test(i.namespace)){a.handler=i.handler;a.data=i.data;a.handleObj=i;i=i.handler.apply(this,arguments);if(i!==w){a.result=i;if(i===false){a.preventDefault();a.stopPropagation()}}if(a.isImmediatePropagationStopped())break}}}return a.result},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
|
||||
fix:function(a){if(a[G])return a;var b=a;a=c.Event(b);for(var d=this.props.length,f;d;){f=this.props[--d];a[f]=b[f]}if(!a.target)a.target=a.srcElement||s;if(a.target.nodeType===3)a.target=a.target.parentNode;if(!a.relatedTarget&&a.fromElement)a.relatedTarget=a.fromElement===a.target?a.toElement:a.fromElement;if(a.pageX==null&&a.clientX!=null){b=s.documentElement;d=s.body;a.pageX=a.clientX+(b&&b.scrollLeft||d&&d.scrollLeft||0)-(b&&b.clientLeft||d&&d.clientLeft||0);a.pageY=a.clientY+(b&&b.scrollTop||
|
||||
d&&d.scrollTop||0)-(b&&b.clientTop||d&&d.clientTop||0)}if(!a.which&&(a.charCode||a.charCode===0?a.charCode:a.keyCode))a.which=a.charCode||a.keyCode;if(!a.metaKey&&a.ctrlKey)a.metaKey=a.ctrlKey;if(!a.which&&a.button!==w)a.which=a.button&1?1:a.button&2?3:a.button&4?2:0;return a},guid:1E8,proxy:c.proxy,special:{ready:{setup:c.bindReady,teardown:c.noop},live:{add:function(a){c.event.add(this,a.origType,c.extend({},a,{handler:oa}))},remove:function(a){var b=true,d=a.origType.replace(O,"");c.each(c.data(this,
|
||||
"events").live||[],function(){if(d===this.origType.replace(O,""))return b=false});b&&c.event.remove(this,a.origType,oa)}},beforeunload:{setup:function(a,b,d){if(this.setInterval)this.onbeforeunload=d;return false},teardown:function(a,b){if(this.onbeforeunload===b)this.onbeforeunload=null}}}};var Ca=s.removeEventListener?function(a,b,d){a.removeEventListener(b,d,false)}:function(a,b,d){a.detachEvent("on"+b,d)};c.Event=function(a){if(!this.preventDefault)return new c.Event(a);if(a&&a.type){this.originalEvent=
|
||||
a;this.type=a.type}else this.type=a;this.timeStamp=J();this[G]=true};c.Event.prototype={preventDefault:function(){this.isDefaultPrevented=Z;var a=this.originalEvent;if(a){a.preventDefault&&a.preventDefault();a.returnValue=false}},stopPropagation:function(){this.isPropagationStopped=Z;var a=this.originalEvent;if(a){a.stopPropagation&&a.stopPropagation();a.cancelBubble=true}},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=Z;this.stopPropagation()},isDefaultPrevented:Y,isPropagationStopped:Y,
|
||||
isImmediatePropagationStopped:Y};var Da=function(a){var b=a.relatedTarget;try{for(;b&&b!==this;)b=b.parentNode;if(b!==this){a.type=a.data;c.event.handle.apply(this,arguments)}}catch(d){}},Ea=function(a){a.type=a.data;c.event.handle.apply(this,arguments)};c.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){c.event.special[a]={setup:function(d){c.event.add(this,b,d&&d.selector?Ea:Da,a)},teardown:function(d){c.event.remove(this,b,d&&d.selector?Ea:Da)}}});if(!c.support.submitBubbles)c.event.special.submit=
|
||||
{setup:function(){if(this.nodeName.toLowerCase()!=="form"){c.event.add(this,"click.specialSubmit",function(a){var b=a.target,d=b.type;if((d==="submit"||d==="image")&&c(b).closest("form").length)return na("submit",this,arguments)});c.event.add(this,"keypress.specialSubmit",function(a){var b=a.target,d=b.type;if((d==="text"||d==="password")&&c(b).closest("form").length&&a.keyCode===13)return na("submit",this,arguments)})}else return false},teardown:function(){c.event.remove(this,".specialSubmit")}};
|
||||
if(!c.support.changeBubbles){var da=/textarea|input|select/i,ea,Fa=function(a){var b=a.type,d=a.value;if(b==="radio"||b==="checkbox")d=a.checked;else if(b==="select-multiple")d=a.selectedIndex>-1?c.map(a.options,function(f){return f.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},fa=function(a,b){var d=a.target,f,e;if(!(!da.test(d.nodeName)||d.readOnly)){f=c.data(d,"_change_data");e=Fa(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data",
|
||||
e);if(!(f===w||e===f))if(f!=null||e){a.type="change";return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:fa,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return fa.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return fa.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a,
|
||||
"_change_data",Fa(a))}},setup:function(){if(this.type==="file")return false;for(var a in ea)c.event.add(this,a+".specialChange",ea[a]);return da.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return da.test(this.nodeName)}};ea=c.event.special.change.filters}s.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(f){f=c.event.fix(f);f.type=b;return c.event.handle.call(this,f)}c.event.special[b]={setup:function(){this.addEventListener(a,
|
||||
d,true)},teardown:function(){this.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,f,e){if(typeof d==="object"){for(var j in d)this[b](j,f,d[j],e);return this}if(c.isFunction(f)){e=f;f=w}var i=b==="one"?c.proxy(e,function(k){c(this).unbind(k,i);return e.apply(this,arguments)}):e;if(d==="unload"&&b!=="one")this.one(d,f,e);else{j=0;for(var o=this.length;j<o;j++)c.event.add(this[j],d,i,f)}return this}});c.fn.extend({unbind:function(a,b){if(typeof a==="object"&&
|
||||
!a.preventDefault)for(var d in a)this.unbind(d,a[d]);else{d=0;for(var f=this.length;d<f;d++)c.event.remove(this[d],a,b)}return this},delegate:function(a,b,d,f){return this.live(b,d,f,a)},undelegate:function(a,b,d){return arguments.length===0?this.unbind("live"):this.die(b,null,d,a)},trigger:function(a,b){return this.each(function(){c.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0]){a=c.Event(a);a.preventDefault();a.stopPropagation();c.event.trigger(a,b,this[0]);return a.result}},
|
||||
toggle:function(a){for(var b=arguments,d=1;d<b.length;)c.proxy(a,b[d++]);return this.click(c.proxy(a,function(f){var e=(c.data(this,"lastToggle"+a.guid)||0)%d;c.data(this,"lastToggle"+a.guid,e+1);f.preventDefault();return b[e].apply(this,arguments)||false}))},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}});var Ga={focus:"focusin",blur:"focusout",mouseenter:"mouseover",mouseleave:"mouseout"};c.each(["live","die"],function(a,b){c.fn[b]=function(d,f,e,j){var i,o=0,k,n,r=j||this.selector,
|
||||
u=j?this:c(this.context);if(c.isFunction(f)){e=f;f=w}for(d=(d||"").split(" ");(i=d[o++])!=null;){j=O.exec(i);k="";if(j){k=j[0];i=i.replace(O,"")}if(i==="hover")d.push("mouseenter"+k,"mouseleave"+k);else{n=i;if(i==="focus"||i==="blur"){d.push(Ga[i]+k);i+=k}else i=(Ga[i]||i)+k;b==="live"?u.each(function(){c.event.add(this,pa(i,r),{data:f,selector:r,handler:e,origType:i,origHandler:e,preType:n})}):u.unbind(pa(i,r),e)}}return this}});c.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error".split(" "),
|
||||
function(a,b){c.fn[b]=function(d){return d?this.bind(b,d):this.trigger(b)};if(c.attrFn)c.attrFn[b]=true});A.attachEvent&&!A.addEventListener&&A.attachEvent("onunload",function(){for(var a in c.cache)if(c.cache[a].handle)try{c.event.remove(c.cache[a].handle.elem)}catch(b){}});(function(){function a(g){for(var h="",l,m=0;g[m];m++){l=g[m];if(l.nodeType===3||l.nodeType===4)h+=l.nodeValue;else if(l.nodeType!==8)h+=a(l.childNodes)}return h}function b(g,h,l,m,q,p){q=0;for(var v=m.length;q<v;q++){var t=m[q];
|
||||
if(t){t=t[g];for(var y=false;t;){if(t.sizcache===l){y=m[t.sizset];break}if(t.nodeType===1&&!p){t.sizcache=l;t.sizset=q}if(t.nodeName.toLowerCase()===h){y=t;break}t=t[g]}m[q]=y}}}function d(g,h,l,m,q,p){q=0;for(var v=m.length;q<v;q++){var t=m[q];if(t){t=t[g];for(var y=false;t;){if(t.sizcache===l){y=m[t.sizset];break}if(t.nodeType===1){if(!p){t.sizcache=l;t.sizset=q}if(typeof h!=="string"){if(t===h){y=true;break}}else if(k.filter(h,[t]).length>0){y=t;break}}t=t[g]}m[q]=y}}}var f=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
|
||||
e=0,j=Object.prototype.toString,i=false,o=true;[0,0].sort(function(){o=false;return 0});var k=function(g,h,l,m){l=l||[];var q=h=h||s;if(h.nodeType!==1&&h.nodeType!==9)return[];if(!g||typeof g!=="string")return l;for(var p=[],v,t,y,S,H=true,M=x(h),I=g;(f.exec(""),v=f.exec(I))!==null;){I=v[3];p.push(v[1]);if(v[2]){S=v[3];break}}if(p.length>1&&r.exec(g))if(p.length===2&&n.relative[p[0]])t=ga(p[0]+p[1],h);else for(t=n.relative[p[0]]?[h]:k(p.shift(),h);p.length;){g=p.shift();if(n.relative[g])g+=p.shift();
|
||||
t=ga(g,t)}else{if(!m&&p.length>1&&h.nodeType===9&&!M&&n.match.ID.test(p[0])&&!n.match.ID.test(p[p.length-1])){v=k.find(p.shift(),h,M);h=v.expr?k.filter(v.expr,v.set)[0]:v.set[0]}if(h){v=m?{expr:p.pop(),set:z(m)}:k.find(p.pop(),p.length===1&&(p[0]==="~"||p[0]==="+")&&h.parentNode?h.parentNode:h,M);t=v.expr?k.filter(v.expr,v.set):v.set;if(p.length>0)y=z(t);else H=false;for(;p.length;){var D=p.pop();v=D;if(n.relative[D])v=p.pop();else D="";if(v==null)v=h;n.relative[D](y,v,M)}}else y=[]}y||(y=t);y||k.error(D||
|
||||
g);if(j.call(y)==="[object Array]")if(H)if(h&&h.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&E(h,y[g])))l.push(t[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&l.push(t[g]);else l.push.apply(l,y);else z(y,l);if(S){k(S,q,l,m);k.uniqueSort(l)}return l};k.uniqueSort=function(g){if(B){i=o;g.sort(B);if(i)for(var h=1;h<g.length;h++)g[h]===g[h-1]&&g.splice(h--,1)}return g};k.matches=function(g,h){return k(g,null,null,h)};k.find=function(g,h,l){var m,q;if(!g)return[];
|
||||
for(var p=0,v=n.order.length;p<v;p++){var t=n.order[p];if(q=n.leftMatch[t].exec(g)){var y=q[1];q.splice(1,1);if(y.substr(y.length-1)!=="\\"){q[1]=(q[1]||"").replace(/\\/g,"");m=n.find[t](q,h,l);if(m!=null){g=g.replace(n.match[t],"");break}}}}m||(m=h.getElementsByTagName("*"));return{set:m,expr:g}};k.filter=function(g,h,l,m){for(var q=g,p=[],v=h,t,y,S=h&&h[0]&&x(h[0]);g&&h.length;){for(var H in n.filter)if((t=n.leftMatch[H].exec(g))!=null&&t[2]){var M=n.filter[H],I,D;D=t[1];y=false;t.splice(1,1);if(D.substr(D.length-
|
||||
1)!=="\\"){if(v===p)p=[];if(n.preFilter[H])if(t=n.preFilter[H](t,v,l,p,m,S)){if(t===true)continue}else y=I=true;if(t)for(var U=0;(D=v[U])!=null;U++)if(D){I=M(D,t,U,v);var Ha=m^!!I;if(l&&I!=null)if(Ha)y=true;else v[U]=false;else if(Ha){p.push(D);y=true}}if(I!==w){l||(v=p);g=g.replace(n.match[H],"");if(!y)return[];break}}}if(g===q)if(y==null)k.error(g);else break;q=g}return v};k.error=function(g){throw"Syntax error, unrecognized expression: "+g;};var n=k.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF-]|\\.)+)/,
|
||||
CLASS:/\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(g){return g.getAttribute("href")}},
|
||||
relative:{"+":function(g,h){var l=typeof h==="string",m=l&&!/\W/.test(h);l=l&&!m;if(m)h=h.toLowerCase();m=0;for(var q=g.length,p;m<q;m++)if(p=g[m]){for(;(p=p.previousSibling)&&p.nodeType!==1;);g[m]=l||p&&p.nodeName.toLowerCase()===h?p||false:p===h}l&&k.filter(h,g,true)},">":function(g,h){var l=typeof h==="string";if(l&&!/\W/.test(h)){h=h.toLowerCase();for(var m=0,q=g.length;m<q;m++){var p=g[m];if(p){l=p.parentNode;g[m]=l.nodeName.toLowerCase()===h?l:false}}}else{m=0;for(q=g.length;m<q;m++)if(p=g[m])g[m]=
|
||||
l?p.parentNode:p.parentNode===h;l&&k.filter(h,g,true)}},"":function(g,h,l){var m=e++,q=d;if(typeof h==="string"&&!/\W/.test(h)){var p=h=h.toLowerCase();q=b}q("parentNode",h,m,g,p,l)},"~":function(g,h,l){var m=e++,q=d;if(typeof h==="string"&&!/\W/.test(h)){var p=h=h.toLowerCase();q=b}q("previousSibling",h,m,g,p,l)}},find:{ID:function(g,h,l){if(typeof h.getElementById!=="undefined"&&!l)return(g=h.getElementById(g[1]))?[g]:[]},NAME:function(g,h){if(typeof h.getElementsByName!=="undefined"){var l=[];
|
||||
h=h.getElementsByName(g[1]);for(var m=0,q=h.length;m<q;m++)h[m].getAttribute("name")===g[1]&&l.push(h[m]);return l.length===0?null:l}},TAG:function(g,h){return h.getElementsByTagName(g[1])}},preFilter:{CLASS:function(g,h,l,m,q,p){g=" "+g[1].replace(/\\/g,"")+" ";if(p)return g;p=0;for(var v;(v=h[p])!=null;p++)if(v)if(q^(v.className&&(" "+v.className+" ").replace(/[\t\n]/g," ").indexOf(g)>=0))l||m.push(v);else if(l)h[p]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()},
|
||||
CHILD:function(g){if(g[1]==="nth"){var h=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=h[1]+(h[2]||1)-0;g[3]=h[3]-0}g[0]=e++;return g},ATTR:function(g,h,l,m,q,p){h=g[1].replace(/\\/g,"");if(!p&&n.attrMap[h])g[1]=n.attrMap[h];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,h,l,m,q){if(g[1]==="not")if((f.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,h);else{g=k.filter(g[3],h,l,true^q);l||m.push.apply(m,
|
||||
g);return false}else if(n.match.POS.test(g[0])||n.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,h,l){return!!k(l[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)},
|
||||
text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}},
|
||||
setFilters:{first:function(g,h){return h===0},last:function(g,h,l,m){return h===m.length-1},even:function(g,h){return h%2===0},odd:function(g,h){return h%2===1},lt:function(g,h,l){return h<l[3]-0},gt:function(g,h,l){return h>l[3]-0},nth:function(g,h,l){return l[3]-0===h},eq:function(g,h,l){return l[3]-0===h}},filter:{PSEUDO:function(g,h,l,m){var q=h[1],p=n.filters[q];if(p)return p(g,l,h,m);else if(q==="contains")return(g.textContent||g.innerText||a([g])||"").indexOf(h[3])>=0;else if(q==="not"){h=
|
||||
h[3];l=0;for(m=h.length;l<m;l++)if(h[l]===g)return false;return true}else k.error("Syntax error, unrecognized expression: "+q)},CHILD:function(g,h){var l=h[1],m=g;switch(l){case "only":case "first":for(;m=m.previousSibling;)if(m.nodeType===1)return false;if(l==="first")return true;m=g;case "last":for(;m=m.nextSibling;)if(m.nodeType===1)return false;return true;case "nth":l=h[2];var q=h[3];if(l===1&&q===0)return true;h=h[0];var p=g.parentNode;if(p&&(p.sizcache!==h||!g.nodeIndex)){var v=0;for(m=p.firstChild;m;m=
|
||||
m.nextSibling)if(m.nodeType===1)m.nodeIndex=++v;p.sizcache=h}g=g.nodeIndex-q;return l===0?g===0:g%l===0&&g/l>=0}},ID:function(g,h){return g.nodeType===1&&g.getAttribute("id")===h},TAG:function(g,h){return h==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===h},CLASS:function(g,h){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(h)>-1},ATTR:function(g,h){var l=h[1];g=n.attrHandle[l]?n.attrHandle[l](g):g[l]!=null?g[l]:g.getAttribute(l);l=g+"";var m=h[2];h=h[4];return g==null?m==="!=":m===
|
||||
"="?l===h:m==="*="?l.indexOf(h)>=0:m==="~="?(" "+l+" ").indexOf(h)>=0:!h?l&&g!==false:m==="!="?l!==h:m==="^="?l.indexOf(h)===0:m==="$="?l.substr(l.length-h.length)===h:m==="|="?l===h||l.substr(0,h.length+1)===h+"-":false},POS:function(g,h,l,m){var q=n.setFilters[h[2]];if(q)return q(g,l,h,m)}}},r=n.match.POS;for(var u in n.match){n.match[u]=new RegExp(n.match[u].source+/(?![^\[]*\])(?![^\(]*\))/.source);n.leftMatch[u]=new RegExp(/(^(?:.|\r|\n)*?)/.source+n.match[u].source.replace(/\\(\d+)/g,function(g,
|
||||
h){return"\\"+(h-0+1)}))}var z=function(g,h){g=Array.prototype.slice.call(g,0);if(h){h.push.apply(h,g);return h}return g};try{Array.prototype.slice.call(s.documentElement.childNodes,0)}catch(C){z=function(g,h){h=h||[];if(j.call(g)==="[object Array]")Array.prototype.push.apply(h,g);else if(typeof g.length==="number")for(var l=0,m=g.length;l<m;l++)h.push(g[l]);else for(l=0;g[l];l++)h.push(g[l]);return h}}var B;if(s.documentElement.compareDocumentPosition)B=function(g,h){if(!g.compareDocumentPosition||
|
||||
!h.compareDocumentPosition){if(g==h)i=true;return g.compareDocumentPosition?-1:1}g=g.compareDocumentPosition(h)&4?-1:g===h?0:1;if(g===0)i=true;return g};else if("sourceIndex"in s.documentElement)B=function(g,h){if(!g.sourceIndex||!h.sourceIndex){if(g==h)i=true;return g.sourceIndex?-1:1}g=g.sourceIndex-h.sourceIndex;if(g===0)i=true;return g};else if(s.createRange)B=function(g,h){if(!g.ownerDocument||!h.ownerDocument){if(g==h)i=true;return g.ownerDocument?-1:1}var l=g.ownerDocument.createRange(),m=
|
||||
h.ownerDocument.createRange();l.setStart(g,0);l.setEnd(g,0);m.setStart(h,0);m.setEnd(h,0);g=l.compareBoundaryPoints(Range.START_TO_END,m);if(g===0)i=true;return g};(function(){var g=s.createElement("div"),h="script"+(new Date).getTime();g.innerHTML="<a name='"+h+"'/>";var l=s.documentElement;l.insertBefore(g,l.firstChild);if(s.getElementById(h)){n.find.ID=function(m,q,p){if(typeof q.getElementById!=="undefined"&&!p)return(q=q.getElementById(m[1]))?q.id===m[1]||typeof q.getAttributeNode!=="undefined"&&
|
||||
q.getAttributeNode("id").nodeValue===m[1]?[q]:w:[]};n.filter.ID=function(m,q){var p=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&p&&p.nodeValue===q}}l.removeChild(g);l=g=null})();(function(){var g=s.createElement("div");g.appendChild(s.createComment(""));if(g.getElementsByTagName("*").length>0)n.find.TAG=function(h,l){l=l.getElementsByTagName(h[1]);if(h[1]==="*"){h=[];for(var m=0;l[m];m++)l[m].nodeType===1&&h.push(l[m]);l=h}return l};g.innerHTML="<a href='#'></a>";
|
||||
if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")n.attrHandle.href=function(h){return h.getAttribute("href",2)};g=null})();s.querySelectorAll&&function(){var g=k,h=s.createElement("div");h.innerHTML="<p class='TEST'></p>";if(!(h.querySelectorAll&&h.querySelectorAll(".TEST").length===0)){k=function(m,q,p,v){q=q||s;if(!v&&q.nodeType===9&&!x(q))try{return z(q.querySelectorAll(m),p)}catch(t){}return g(m,q,p,v)};for(var l in g)k[l]=g[l];h=null}}();
|
||||
(function(){var g=s.createElement("div");g.innerHTML="<div class='test e'></div><div class='test'></div>";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){n.order.splice(1,0,"CLASS");n.find.CLASS=function(h,l,m){if(typeof l.getElementsByClassName!=="undefined"&&!m)return l.getElementsByClassName(h[1])};g=null}}})();var E=s.compareDocumentPosition?function(g,h){return!!(g.compareDocumentPosition(h)&16)}:
|
||||
function(g,h){return g!==h&&(g.contains?g.contains(h):true)},x=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false},ga=function(g,h){var l=[],m="",q;for(h=h.nodeType?[h]:h;q=n.match.PSEUDO.exec(g);){m+=q[0];g=g.replace(n.match.PSEUDO,"")}g=n.relative[g]?g+"*":g;q=0;for(var p=h.length;q<p;q++)k(g,h[q],l);return k.filter(m,l)};c.find=k;c.expr=k.selectors;c.expr[":"]=c.expr.filters;c.unique=k.uniqueSort;c.text=a;c.isXMLDoc=x;c.contains=E})();var eb=/Until$/,fb=/^(?:parents|prevUntil|prevAll)/,
|
||||
gb=/,/;R=Array.prototype.slice;var Ia=function(a,b,d){if(c.isFunction(b))return c.grep(a,function(e,j){return!!b.call(e,j,e)===d});else if(b.nodeType)return c.grep(a,function(e){return e===b===d});else if(typeof b==="string"){var f=c.grep(a,function(e){return e.nodeType===1});if(Ua.test(b))return c.filter(b,f,!d);else b=c.filter(b,f)}return c.grep(a,function(e){return c.inArray(e,b)>=0===d})};c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,f=0,e=this.length;f<e;f++){d=b.length;
|
||||
c.find(a,this[f],b);if(f>0)for(var j=d;j<b.length;j++)for(var i=0;i<d;i++)if(b[i]===b[j]){b.splice(j--,1);break}}return b},has:function(a){var b=c(a);return this.filter(function(){for(var d=0,f=b.length;d<f;d++)if(c.contains(this,b[d]))return true})},not:function(a){return this.pushStack(Ia(this,a,false),"not",a)},filter:function(a){return this.pushStack(Ia(this,a,true),"filter",a)},is:function(a){return!!a&&c.filter(a,this).length>0},closest:function(a,b){if(c.isArray(a)){var d=[],f=this[0],e,j=
|
||||
{},i;if(f&&a.length){e=0;for(var o=a.length;e<o;e++){i=a[e];j[i]||(j[i]=c.expr.match.POS.test(i)?c(i,b||this.context):i)}for(;f&&f.ownerDocument&&f!==b;){for(i in j){e=j[i];if(e.jquery?e.index(f)>-1:c(f).is(e)){d.push({selector:i,elem:f});delete j[i]}}f=f.parentNode}}return d}var k=c.expr.match.POS.test(a)?c(a,b||this.context):null;return this.map(function(n,r){for(;r&&r.ownerDocument&&r!==b;){if(k?k.index(r)>-1:c(r).is(a))return r;r=r.parentNode}return null})},index:function(a){if(!a||typeof a===
|
||||
"string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){a=typeof a==="string"?c(a,b||this.context):c.makeArray(a);b=c.merge(this.get(),a);return this.pushStack(qa(a[0])||qa(b[0])?b:c.unique(b))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode",
|
||||
d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")?
|
||||
a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,f){var e=c.map(this,b,d);eb.test(a)||(f=d);if(f&&typeof f==="string")e=c.filter(f,e);e=this.length>1?c.unique(e):e;if((this.length>1||gb.test(f))&&fb.test(a))e=e.reverse();return this.pushStack(e,a,R.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return c.find.matches(a,b)},dir:function(a,b,d){var f=[];for(a=a[b];a&&a.nodeType!==9&&(d===w||a.nodeType!==1||!c(a).is(d));){a.nodeType===
|
||||
1&&f.push(a);a=a[b]}return f},nth:function(a,b,d){b=b||1;for(var f=0;a;a=a[d])if(a.nodeType===1&&++f===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var Ja=/ jQuery\d+="(?:\d+|null)"/g,V=/^\s+/,Ka=/(<([\w:]+)[^>]*?)\/>/g,hb=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,La=/<([\w:]+)/,ib=/<tbody/i,jb=/<|&#?\w+;/,ta=/<script|<object|<embed|<option|<style/i,ua=/checked\s*(?:[^=]|=\s*.checked.)/i,Ma=function(a,b,d){return hb.test(d)?
|
||||
a:b+"></"+d+">"},F={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]};F.optgroup=F.option;F.tbody=F.tfoot=F.colgroup=F.caption=F.thead;F.th=F.td;if(!c.support.htmlSerialize)F._default=[1,"div<div>","</div>"];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d=
|
||||
c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==w)return this.empty().append((this[0]&&this[0].ownerDocument||s).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this},
|
||||
wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})},
|
||||
prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,
|
||||
this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,f;(f=this[d])!=null;d++)if(!a||c.filter(a,[f]).length){if(!b&&f.nodeType===1){c.cleanData(f.getElementsByTagName("*"));c.cleanData([f])}f.parentNode&&f.parentNode.removeChild(f)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild);
|
||||
return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,f=this.ownerDocument;if(!d){d=f.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(Ja,"").replace(/=([^="'>\s]+\/)>/g,'="$1">').replace(V,"")],f)[0]}else return this.cloneNode(true)});if(a===true){ra(this,b);ra(this.find("*"),b.find("*"))}return b},html:function(a){if(a===w)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Ja,
|
||||
""):null;else if(typeof a==="string"&&!ta.test(a)&&(c.support.leadingWhitespace||!V.test(a))&&!F[(La.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Ka,Ma);try{for(var b=0,d=this.length;b<d;b++)if(this[b].nodeType===1){c.cleanData(this[b].getElementsByTagName("*"));this[b].innerHTML=a}}catch(f){this.empty().append(a)}}else c.isFunction(a)?this.each(function(e){var j=c(this),i=j.html();j.empty().append(function(){return a.call(this,e,i)})}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&
|
||||
this[0].parentNode){if(c.isFunction(a))return this.each(function(b){var d=c(this),f=d.html();d.replaceWith(a.call(this,b,f))});if(typeof a!=="string")a=c(a).detach();return this.each(function(){var b=this.nextSibling,d=this.parentNode;c(this).remove();b?c(b).before(a):c(d).append(a)})}else return this.pushStack(c(c.isFunction(a)?a():a),"replaceWith",a)},detach:function(a){return this.remove(a,true)},domManip:function(a,b,d){function f(u){return c.nodeName(u,"table")?u.getElementsByTagName("tbody")[0]||
|
||||
u.appendChild(u.ownerDocument.createElement("tbody")):u}var e,j,i=a[0],o=[],k;if(!c.support.checkClone&&arguments.length===3&&typeof i==="string"&&ua.test(i))return this.each(function(){c(this).domManip(a,b,d,true)});if(c.isFunction(i))return this.each(function(u){var z=c(this);a[0]=i.call(this,u,b?z.html():w);z.domManip(a,b,d)});if(this[0]){e=i&&i.parentNode;e=c.support.parentNode&&e&&e.nodeType===11&&e.childNodes.length===this.length?{fragment:e}:sa(a,this,o);k=e.fragment;if(j=k.childNodes.length===
|
||||
1?(k=k.firstChild):k.firstChild){b=b&&c.nodeName(j,"tr");for(var n=0,r=this.length;n<r;n++)d.call(b?f(this[n],j):this[n],n>0||e.cacheable||this.length>1?k.cloneNode(true):k)}o.length&&c.each(o,Qa)}return this}});c.fragments={};c.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var f=[];d=c(d);var e=this.length===1&&this[0].parentNode;if(e&&e.nodeType===11&&e.childNodes.length===1&&d.length===1){d[b](this[0]);
|
||||
return this}else{e=0;for(var j=d.length;e<j;e++){var i=(e>0?this.clone(true):this).get();c.fn[b].apply(c(d[e]),i);f=f.concat(i)}return this.pushStack(f,a,d.selector)}}});c.extend({clean:function(a,b,d,f){b=b||s;if(typeof b.createElement==="undefined")b=b.ownerDocument||b[0]&&b[0].ownerDocument||s;for(var e=[],j=0,i;(i=a[j])!=null;j++){if(typeof i==="number")i+="";if(i){if(typeof i==="string"&&!jb.test(i))i=b.createTextNode(i);else if(typeof i==="string"){i=i.replace(Ka,Ma);var o=(La.exec(i)||["",
|
||||
""])[1].toLowerCase(),k=F[o]||F._default,n=k[0],r=b.createElement("div");for(r.innerHTML=k[1]+i+k[2];n--;)r=r.lastChild;if(!c.support.tbody){n=ib.test(i);o=o==="table"&&!n?r.firstChild&&r.firstChild.childNodes:k[1]==="<table>"&&!n?r.childNodes:[];for(k=o.length-1;k>=0;--k)c.nodeName(o[k],"tbody")&&!o[k].childNodes.length&&o[k].parentNode.removeChild(o[k])}!c.support.leadingWhitespace&&V.test(i)&&r.insertBefore(b.createTextNode(V.exec(i)[0]),r.firstChild);i=r.childNodes}if(i.nodeType)e.push(i);else e=
|
||||
c.merge(e,i)}}if(d)for(j=0;e[j];j++)if(f&&c.nodeName(e[j],"script")&&(!e[j].type||e[j].type.toLowerCase()==="text/javascript"))f.push(e[j].parentNode?e[j].parentNode.removeChild(e[j]):e[j]);else{e[j].nodeType===1&&e.splice.apply(e,[j+1,0].concat(c.makeArray(e[j].getElementsByTagName("script"))));d.appendChild(e[j])}return e},cleanData:function(a){for(var b,d,f=c.cache,e=c.event.special,j=c.support.deleteExpando,i=0,o;(o=a[i])!=null;i++)if(d=o[c.expando]){b=f[d];if(b.events)for(var k in b.events)e[k]?
|
||||
c.event.remove(o,k):Ca(o,k,b.handle);if(j)delete o[c.expando];else o.removeAttribute&&o.removeAttribute(c.expando);delete f[d]}}});var kb=/z-?index|font-?weight|opacity|zoom|line-?height/i,Na=/alpha\([^)]*\)/,Oa=/opacity=([^)]*)/,ha=/float/i,ia=/-([a-z])/ig,lb=/([A-Z])/g,mb=/^-?\d+(?:px)?$/i,nb=/^-?\d/,ob={position:"absolute",visibility:"hidden",display:"block"},pb=["Left","Right"],qb=["Top","Bottom"],rb=s.defaultView&&s.defaultView.getComputedStyle,Pa=c.support.cssFloat?"cssFloat":"styleFloat",ja=
|
||||
function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){return X(this,a,b,true,function(d,f,e){if(e===w)return c.curCSS(d,f);if(typeof e==="number"&&!kb.test(f))e+="px";c.style(d,f,e)})};c.extend({style:function(a,b,d){if(!a||a.nodeType===3||a.nodeType===8)return w;if((b==="width"||b==="height")&&parseFloat(d)<0)d=w;var f=a.style||a,e=d!==w;if(!c.support.opacity&&b==="opacity"){if(e){f.zoom=1;b=parseInt(d,10)+""==="NaN"?"":"alpha(opacity="+d*100+")";a=f.filter||c.curCSS(a,"filter")||"";f.filter=
|
||||
Na.test(a)?a.replace(Na,b):b}return f.filter&&f.filter.indexOf("opacity=")>=0?parseFloat(Oa.exec(f.filter)[1])/100+"":""}if(ha.test(b))b=Pa;b=b.replace(ia,ja);if(e)f[b]=d;return f[b]},css:function(a,b,d,f){if(b==="width"||b==="height"){var e,j=b==="width"?pb:qb;function i(){e=b==="width"?a.offsetWidth:a.offsetHeight;f!=="border"&&c.each(j,function(){f||(e-=parseFloat(c.curCSS(a,"padding"+this,true))||0);if(f==="margin")e+=parseFloat(c.curCSS(a,"margin"+this,true))||0;else e-=parseFloat(c.curCSS(a,
|
||||
"border"+this+"Width",true))||0})}a.offsetWidth!==0?i():c.swap(a,ob,i);return Math.max(0,Math.round(e))}return c.curCSS(a,b,d)},curCSS:function(a,b,d){var f,e=a.style;if(!c.support.opacity&&b==="opacity"&&a.currentStyle){f=Oa.test(a.currentStyle.filter||"")?parseFloat(RegExp.$1)/100+"":"";return f===""?"1":f}if(ha.test(b))b=Pa;if(!d&&e&&e[b])f=e[b];else if(rb){if(ha.test(b))b="float";b=b.replace(lb,"-$1").toLowerCase();e=a.ownerDocument.defaultView;if(!e)return null;if(a=e.getComputedStyle(a,null))f=
|
||||
a.getPropertyValue(b);if(b==="opacity"&&f==="")f="1"}else if(a.currentStyle){d=b.replace(ia,ja);f=a.currentStyle[b]||a.currentStyle[d];if(!mb.test(f)&&nb.test(f)){b=e.left;var j=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;e.left=d==="fontSize"?"1em":f||0;f=e.pixelLeft+"px";e.left=b;a.runtimeStyle.left=j}}return f},swap:function(a,b,d){var f={};for(var e in b){f[e]=a.style[e];a.style[e]=b[e]}d.call(a);for(e in b)a.style[e]=f[e]}});if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b=
|
||||
a.offsetWidth,d=a.offsetHeight,f=a.nodeName.toLowerCase()==="tr";return b===0&&d===0&&!f?true:b>0&&d>0&&!f?false:c.curCSS(a,"display")==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var sb=J(),tb=/<script(.|\s)*?\/script>/gi,ub=/select|textarea/i,vb=/color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,N=/=\?(&|$)/,ka=/\?/,wb=/(\?|&)_=.*?(&|$)/,xb=/^(\w+:)?\/\/([^\/?#]+)/,yb=/%20/g,zb=c.fn.load;c.fn.extend({load:function(a,b,d){if(typeof a!==
|
||||
"string")return zb.call(this,a);else if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var e=a.slice(f,a.length);a=a.slice(0,f)}f="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b==="object"){b=c.param(b,c.ajaxSettings.traditional);f="POST"}var j=this;c.ajax({url:a,type:f,dataType:"html",data:b,complete:function(i,o){if(o==="success"||o==="notmodified")j.html(e?c("<div />").append(i.responseText.replace(tb,"")).find(e):i.responseText);d&&j.each(d,[i.responseText,o,i])}});return this},
|
||||
serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ub.test(this.nodeName)||vb.test(this.type))}).map(function(a,b){a=c(this).val();return a==null?null:c.isArray(a)?c.map(a,function(d){return{name:b.name,value:d}}):{name:b.name,value:a}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),
|
||||
function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:f})},getScript:function(a,b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:f})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href,
|
||||
global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:A.XMLHttpRequest&&(A.location.protocol!=="file:"||!A.ActiveXObject)?function(){return new A.XMLHttpRequest}:function(){try{return new A.ActiveXObject("Microsoft.XMLHTTP")}catch(a){}},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},etag:{},ajax:function(a){function b(){e.success&&
|
||||
e.success.call(k,o,i,x);e.global&&f("ajaxSuccess",[x,e])}function d(){e.complete&&e.complete.call(k,x,i);e.global&&f("ajaxComplete",[x,e]);e.global&&!--c.active&&c.event.trigger("ajaxStop")}function f(q,p){(e.context?c(e.context):c.event).trigger(q,p)}var e=c.extend(true,{},c.ajaxSettings,a),j,i,o,k=a&&a.context||e,n=e.type.toUpperCase();if(e.data&&e.processData&&typeof e.data!=="string")e.data=c.param(e.data,e.traditional);if(e.dataType==="jsonp"){if(n==="GET")N.test(e.url)||(e.url+=(ka.test(e.url)?
|
||||
"&":"?")+(e.jsonp||"callback")+"=?");else if(!e.data||!N.test(e.data))e.data=(e.data?e.data+"&":"")+(e.jsonp||"callback")+"=?";e.dataType="json"}if(e.dataType==="json"&&(e.data&&N.test(e.data)||N.test(e.url))){j=e.jsonpCallback||"jsonp"+sb++;if(e.data)e.data=(e.data+"").replace(N,"="+j+"$1");e.url=e.url.replace(N,"="+j+"$1");e.dataType="script";A[j]=A[j]||function(q){o=q;b();d();A[j]=w;try{delete A[j]}catch(p){}z&&z.removeChild(C)}}if(e.dataType==="script"&&e.cache===null)e.cache=false;if(e.cache===
|
||||
false&&n==="GET"){var r=J(),u=e.url.replace(wb,"$1_="+r+"$2");e.url=u+(u===e.url?(ka.test(e.url)?"&":"?")+"_="+r:"")}if(e.data&&n==="GET")e.url+=(ka.test(e.url)?"&":"?")+e.data;e.global&&!c.active++&&c.event.trigger("ajaxStart");r=(r=xb.exec(e.url))&&(r[1]&&r[1]!==location.protocol||r[2]!==location.host);if(e.dataType==="script"&&n==="GET"&&r){var z=s.getElementsByTagName("head")[0]||s.documentElement,C=s.createElement("script");C.src=e.url;if(e.scriptCharset)C.charset=e.scriptCharset;if(!j){var B=
|
||||
false;C.onload=C.onreadystatechange=function(){if(!B&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){B=true;b();d();C.onload=C.onreadystatechange=null;z&&C.parentNode&&z.removeChild(C)}}}z.insertBefore(C,z.firstChild);return w}var E=false,x=e.xhr();if(x){e.username?x.open(n,e.url,e.async,e.username,e.password):x.open(n,e.url,e.async);try{if(e.data||a&&a.contentType)x.setRequestHeader("Content-Type",e.contentType);if(e.ifModified){c.lastModified[e.url]&&x.setRequestHeader("If-Modified-Since",
|
||||
c.lastModified[e.url]);c.etag[e.url]&&x.setRequestHeader("If-None-Match",c.etag[e.url])}r||x.setRequestHeader("X-Requested-With","XMLHttpRequest");x.setRequestHeader("Accept",e.dataType&&e.accepts[e.dataType]?e.accepts[e.dataType]+", */*":e.accepts._default)}catch(ga){}if(e.beforeSend&&e.beforeSend.call(k,x,e)===false){e.global&&!--c.active&&c.event.trigger("ajaxStop");x.abort();return false}e.global&&f("ajaxSend",[x,e]);var g=x.onreadystatechange=function(q){if(!x||x.readyState===0||q==="abort"){E||
|
||||
d();E=true;if(x)x.onreadystatechange=c.noop}else if(!E&&x&&(x.readyState===4||q==="timeout")){E=true;x.onreadystatechange=c.noop;i=q==="timeout"?"timeout":!c.httpSuccess(x)?"error":e.ifModified&&c.httpNotModified(x,e.url)?"notmodified":"success";var p;if(i==="success")try{o=c.httpData(x,e.dataType,e)}catch(v){i="parsererror";p=v}if(i==="success"||i==="notmodified")j||b();else c.handleError(e,x,i,p);d();q==="timeout"&&x.abort();if(e.async)x=null}};try{var h=x.abort;x.abort=function(){x&&h.call(x);
|
||||
g("abort")}}catch(l){}e.async&&e.timeout>0&&setTimeout(function(){x&&!E&&g("timeout")},e.timeout);try{x.send(n==="POST"||n==="PUT"||n==="DELETE"?e.data:null)}catch(m){c.handleError(e,x,null,m);d()}e.async||g();return x}},handleError:function(a,b,d,f){if(a.error)a.error.call(a.context||a,b,d,f);if(a.global)(a.context?c(a.context):c.event).trigger("ajaxError",[b,a,f])},active:0,httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status===
|
||||
1223||a.status===0}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"),f=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(f)c.etag[b]=f;return a.status===304||a.status===0},httpData:function(a,b,d){var f=a.getResponseHeader("content-type")||"",e=b==="xml"||!b&&f.indexOf("xml")>=0;a=e?a.responseXML:a.responseText;e&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b===
|
||||
"json"||!b&&f.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&f.indexOf("javascript")>=0)c.globalEval(a);return a},param:function(a,b){function d(i,o){if(c.isArray(o))c.each(o,function(k,n){b||/\[\]$/.test(i)?f(i,n):d(i+"["+(typeof n==="object"||c.isArray(n)?k:"")+"]",n)});else!b&&o!=null&&typeof o==="object"?c.each(o,function(k,n){d(i+"["+k+"]",n)}):f(i,o)}function f(i,o){o=c.isFunction(o)?o():o;e[e.length]=encodeURIComponent(i)+"="+encodeURIComponent(o)}var e=[];if(b===w)b=c.ajaxSettings.traditional;
|
||||
if(c.isArray(a)||a.jquery)c.each(a,function(){f(this.name,this.value)});else for(var j in a)d(j,a[j]);return e.join("&").replace(yb,"+")}});var la={},Ab=/toggle|show|hide/,Bb=/^([+-]=)?([\d+-.]+)(.*)$/,W,va=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b){if(a||a===0)return this.animate(K("show",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");
|
||||
this[a].style.display=d||"";if(c.css(this[a],"display")==="none"){d=this[a].nodeName;var f;if(la[d])f=la[d];else{var e=c("<"+d+" />").appendTo("body");f=e.css("display");if(f==="none")f="block";e.remove();la[d]=f}c.data(this[a],"olddisplay",f)}}a=0;for(b=this.length;a<b;a++)this[a].style.display=c.data(this[a],"olddisplay")||"";return this}},hide:function(a,b){if(a||a===0)return this.animate(K("hide",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");!d&&d!=="none"&&c.data(this[a],
|
||||
"olddisplay",c.css(this[a],"display"))}a=0;for(b=this.length;a<b;a++)this[a].style.display="none";return this}},_toggle:c.fn.toggle,toggle:function(a,b){var d=typeof a==="boolean";if(c.isFunction(a)&&c.isFunction(b))this._toggle.apply(this,arguments);else a==null||d?this.each(function(){var f=d?a:c(this).is(":hidden");c(this)[f?"show":"hide"]()}):this.animate(K("toggle",3),a,b);return this},fadeTo:function(a,b,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,d)},
|
||||
animate:function(a,b,d,f){var e=c.speed(b,d,f);if(c.isEmptyObject(a))return this.each(e.complete);return this[e.queue===false?"each":"queue"](function(){var j=c.extend({},e),i,o=this.nodeType===1&&c(this).is(":hidden"),k=this;for(i in a){var n=i.replace(ia,ja);if(i!==n){a[n]=a[i];delete a[i];i=n}if(a[i]==="hide"&&o||a[i]==="show"&&!o)return j.complete.call(this);if((i==="height"||i==="width")&&this.style){j.display=c.css(this,"display");j.overflow=this.style.overflow}if(c.isArray(a[i])){(j.specialEasing=
|
||||
j.specialEasing||{})[i]=a[i][1];a[i]=a[i][0]}}if(j.overflow!=null)this.style.overflow="hidden";j.curAnim=c.extend({},a);c.each(a,function(r,u){var z=new c.fx(k,j,r);if(Ab.test(u))z[u==="toggle"?o?"show":"hide":u](a);else{var C=Bb.exec(u),B=z.cur(true)||0;if(C){u=parseFloat(C[2]);var E=C[3]||"px";if(E!=="px"){k.style[r]=(u||1)+E;B=(u||1)/z.cur(true)*B;k.style[r]=B+E}if(C[1])u=(C[1]==="-="?-1:1)*u+B;z.custom(B,u,E)}else z.custom(B,u,"")}});return true})},stop:function(a,b){var d=c.timers;a&&this.queue([]);
|
||||
this.each(function(){for(var f=d.length-1;f>=0;f--)if(d[f].elem===this){b&&d[f](true);d.splice(f,1)}});b||this.dequeue();return this}});c.each({slideDown:K("show",1),slideUp:K("hide",1),slideToggle:K("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(a,b){c.fn[a]=function(d,f){return this.animate(b,d,f)}});c.extend({speed:function(a,b,d){var f=a&&typeof a==="object"?a:{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};f.duration=c.fx.off?0:typeof f.duration===
|
||||
"number"?f.duration:c.fx.speeds[f.duration]||c.fx.speeds._default;f.old=f.complete;f.complete=function(){f.queue!==false&&c(this).dequeue();c.isFunction(f.old)&&f.old.call(this)};return f},easing:{linear:function(a,b,d,f){return d+f*a},swing:function(a,b,d,f){return(-Math.cos(a*Math.PI)/2+0.5)*f+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]||
|
||||
c.fx.step._default)(this);if((this.prop==="height"||this.prop==="width")&&this.elem.style)this.elem.style.display="block"},cur:function(a){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];return(a=parseFloat(c.css(this.elem,this.prop,a)))&&a>-10000?a:parseFloat(c.curCSS(this.elem,this.prop))||0},custom:function(a,b,d){function f(j){return e.step(j)}this.startTime=J();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start;
|
||||
this.pos=this.state=0;var e=this;f.elem=this.elem;if(f()&&c.timers.push(f)&&!W)W=setInterval(c.fx.tick,13)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(a){var b=J(),d=true;if(a||b>=this.options.duration+this.startTime){this.now=
|
||||
this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var f in this.options.curAnim)if(this.options.curAnim[f]!==true)d=false;if(d){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;a=c.data(this.elem,"olddisplay");this.elem.style.display=a?a:this.options.display;if(c.css(this.elem,"display")==="none")this.elem.style.display="block"}this.options.hide&&c(this.elem).hide();if(this.options.hide||this.options.show)for(var e in this.options.curAnim)c.style(this.elem,
|
||||
e,this.options.orig[e]);this.options.complete.call(this.elem)}return false}else{e=b-this.startTime;this.state=e/this.options.duration;a=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||a](this.state,e,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a=c.timers,b=0;b<a.length;b++)a[b]()||a.splice(b--,1);a.length||
|
||||
c.fx.stop()},stop:function(){clearInterval(W);W=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){c.style(a.elem,"opacity",a.now)},_default:function(a){if(a.elem.style&&a.elem.style[a.prop]!=null)a.elem.style[a.prop]=(a.prop==="width"||a.prop==="height"?Math.max(0,a.now):a.now)+a.unit;else a.elem[a.prop]=a.now}}});if(c.expr&&c.expr.filters)c.expr.filters.animated=function(a){return c.grep(c.timers,function(b){return a===b.elem}).length};c.fn.offset="getBoundingClientRect"in s.documentElement?
|
||||
function(a){var b=this[0];if(a)return this.each(function(e){c.offset.setOffset(this,a,e)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);var d=b.getBoundingClientRect(),f=b.ownerDocument;b=f.body;f=f.documentElement;return{top:d.top+(self.pageYOffset||c.support.boxModel&&f.scrollTop||b.scrollTop)-(f.clientTop||b.clientTop||0),left:d.left+(self.pageXOffset||c.support.boxModel&&f.scrollLeft||b.scrollLeft)-(f.clientLeft||b.clientLeft||0)}}:function(a){var b=
|
||||
this[0];if(a)return this.each(function(r){c.offset.setOffset(this,a,r)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);c.offset.initialize();var d=b.offsetParent,f=b,e=b.ownerDocument,j,i=e.documentElement,o=e.body;f=(e=e.defaultView)?e.getComputedStyle(b,null):b.currentStyle;for(var k=b.offsetTop,n=b.offsetLeft;(b=b.parentNode)&&b!==o&&b!==i;){if(c.offset.supportsFixedPosition&&f.position==="fixed")break;j=e?e.getComputedStyle(b,null):b.currentStyle;
|
||||
k-=b.scrollTop;n-=b.scrollLeft;if(b===d){k+=b.offsetTop;n+=b.offsetLeft;if(c.offset.doesNotAddBorder&&!(c.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(b.nodeName))){k+=parseFloat(j.borderTopWidth)||0;n+=parseFloat(j.borderLeftWidth)||0}f=d;d=b.offsetParent}if(c.offset.subtractsBorderForOverflowNotVisible&&j.overflow!=="visible"){k+=parseFloat(j.borderTopWidth)||0;n+=parseFloat(j.borderLeftWidth)||0}f=j}if(f.position==="relative"||f.position==="static"){k+=o.offsetTop;n+=o.offsetLeft}if(c.offset.supportsFixedPosition&&
|
||||
f.position==="fixed"){k+=Math.max(i.scrollTop,o.scrollTop);n+=Math.max(i.scrollLeft,o.scrollLeft)}return{top:k,left:n}};c.offset={initialize:function(){var a=s.body,b=s.createElement("div"),d,f,e,j=parseFloat(c.curCSS(a,"marginTop",true))||0;c.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"});b.innerHTML="<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";
|
||||
a.insertBefore(b,a.firstChild);d=b.firstChild;f=d.firstChild;e=d.nextSibling.firstChild.firstChild;this.doesNotAddBorder=f.offsetTop!==5;this.doesAddBorderForTableAndCells=e.offsetTop===5;f.style.position="fixed";f.style.top="20px";this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15;f.style.position=f.style.top="";d.style.overflow="hidden";d.style.position="relative";this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5;this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==j;a.removeChild(b);
|
||||
c.offset.initialize=c.noop},bodyOffset:function(a){var b=a.offsetTop,d=a.offsetLeft;c.offset.initialize();if(c.offset.doesNotIncludeMarginInBodyOffset){b+=parseFloat(c.curCSS(a,"marginTop",true))||0;d+=parseFloat(c.curCSS(a,"marginLeft",true))||0}return{top:b,left:d}},setOffset:function(a,b,d){if(/static/.test(c.curCSS(a,"position")))a.style.position="relative";var f=c(a),e=f.offset(),j=parseInt(c.curCSS(a,"top",true),10)||0,i=parseInt(c.curCSS(a,"left",true),10)||0;if(c.isFunction(b))b=b.call(a,
|
||||
d,e);d={top:b.top-e.top+j,left:b.left-e.left+i};"using"in b?b.using.call(a,d):f.css(d)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),f=/^body|html$/i.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.curCSS(a,"marginTop",true))||0;d.left-=parseFloat(c.curCSS(a,"marginLeft",true))||0;f.top+=parseFloat(c.curCSS(b[0],"borderTopWidth",true))||0;f.left+=parseFloat(c.curCSS(b[0],"borderLeftWidth",true))||0;return{top:d.top-
|
||||
f.top,left:d.left-f.left}},offsetParent:function(){return this.map(function(){for(var a=this.offsetParent||s.body;a&&!/^body|html$/i.test(a.nodeName)&&c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(f){var e=this[0],j;if(!e)return null;if(f!==w)return this.each(function(){if(j=wa(this))j.scrollTo(!a?f:c(j).scrollLeft(),a?f:c(j).scrollTop());else this[d]=f});else return(j=wa(e))?"pageXOffset"in j?j[a?"pageYOffset":
|
||||
"pageXOffset"]:c.support.boxModel&&j.document.documentElement[d]||j.document.body[d]:e[d]}});c.each(["Height","Width"],function(a,b){var d=b.toLowerCase();c.fn["inner"+b]=function(){return this[0]?c.css(this[0],d,false,"padding"):null};c.fn["outer"+b]=function(f){return this[0]?c.css(this[0],d,false,f?"margin":"border"):null};c.fn[d]=function(f){var e=this[0];if(!e)return f==null?null:this;if(c.isFunction(f))return this.each(function(j){var i=c(this);i[d](f.call(this,j,i[d]()))});return"scrollTo"in
|
||||
e&&e.document?e.document.compatMode==="CSS1Compat"&&e.document.documentElement["client"+b]||e.document.body["client"+b]:e.nodeType===9?Math.max(e.documentElement["client"+b],e.body["scroll"+b],e.documentElement["scroll"+b],e.body["offset"+b],e.documentElement["offset"+b]):f===w?c.css(e,d):this.css(d,typeof f==="string"?f:f+"px")}});A.jQuery=A.$=c})(window);
|
@ -1,8 +0,0 @@
|
||||
'use strict';
|
||||
'require network';
|
||||
|
||||
return network.registerProtocol('batadv', {
|
||||
getI18n: function() {
|
||||
return _('Batman');
|
||||
}
|
||||
});
|
@ -1,8 +0,0 @@
|
||||
'use strict';
|
||||
'require network';
|
||||
|
||||
return network.registerProtocol('batadv_hardif', {
|
||||
getI18n: function() {
|
||||
return _('Mesh');
|
||||
}
|
||||
});
|
@ -1,29 +0,0 @@
|
||||
#Owned by DairyMan@Whirlpool
|
||||
#
|
||||
#Copyright GNU act.
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=mesh-wpad
|
||||
PKG_VERSION:=1.000
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/mesh-wpad
|
||||
SECTION:=utils
|
||||
CATEGORY:=ROOter
|
||||
SUBMENU:=Mesh Support
|
||||
DEPENDS:=+wpad-mesh-openssl
|
||||
TITLE:=Support for Mesh routing
|
||||
PKGARCH:=all
|
||||
endef
|
||||
|
||||
define Package/mesh-wpad/description
|
||||
Helper scripts to install Meshing
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,mesh-wpad))
|
@ -238,7 +238,7 @@ btn.inputtitle = translate("Send Test of Text or Email")
|
||||
btn.inputstyle = "apply"
|
||||
btn:depends("text", "1")
|
||||
function btn.write()
|
||||
luci.sys.call("/usr/lib/bwmon/dotext.sh")
|
||||
luci.sys.call("/usr/lib/bwmon/dotext.sh &")
|
||||
end
|
||||
|
||||
b4 = s:option(DummyValue, "blank", " ");
|
||||
|
@ -6,7 +6,7 @@ START=60
|
||||
start() {
|
||||
WX=$(uci -q get custom.bwallocate.lock)
|
||||
if [ "$WX" = "1" ]; then
|
||||
uci set bwmon.general.enabled=$enable
|
||||
uci set bwmon.general.enabled=1
|
||||
uci commit bwmon
|
||||
fi
|
||||
/usr/lib/bwmon/wrtbwmon.sh &
|
||||
|
@ -23,8 +23,14 @@ end
|
||||
|
||||
aamt = arg[1]
|
||||
uamt = arg[2]
|
||||
amt = aamt - uamt
|
||||
amts = calc(amt)
|
||||
if uamt > aamt then
|
||||
amt = uamt - aamt
|
||||
amts = calc(amt)
|
||||
amts = "-" .. amts
|
||||
else
|
||||
amt = aamt - uamt
|
||||
amts = calc(math.abs(amt))
|
||||
end
|
||||
tfile = io.open("/tmp/amtleft", "w")
|
||||
tfile:write(amts, "\n")
|
||||
tfile:close()
|
@ -4,10 +4,11 @@ alloc = arg[1] -- allocate increment in GB
|
||||
per = arg[2] -- fixed percentage in GB
|
||||
used = arg[3] -- amt used in Kb
|
||||
|
||||
used = used / 10000 -- used in GB
|
||||
percent = used / alloc
|
||||
--used = used / 10000 -- used in GB
|
||||
percent = (used / alloc) * 100
|
||||
|
||||
running = "0"
|
||||
if percent >= per then
|
||||
if percent >= tonumber(per) then
|
||||
running = "1"
|
||||
end
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
. /lib/functions.sh
|
||||
|
||||
log() {
|
||||
logger -t "TEXTING" "$@"
|
||||
modlog "TEXTING" "$@"
|
||||
}
|
||||
|
||||
checktime() {
|
||||
@ -96,7 +96,7 @@ checkper() {
|
||||
istime=$(checktime)
|
||||
if [ $istime = '1' ]; then
|
||||
prev=$(uci -q get custom.texting.used)
|
||||
per=$(uci -q get custom.bwallocate.percent)
|
||||
per=$(uci -q get custom.texting.percent)
|
||||
persent=$(uci -q get custom.bwallocate.persent)
|
||||
if [ "$persent" != "1" ]; then
|
||||
getbw
|
||||
@ -141,7 +141,7 @@ do
|
||||
if [ $running = "1" ]; then
|
||||
EN=$(uci -q get custom.texting.text)
|
||||
if [ $EN = "1" ]; then
|
||||
/usr/lib/bwmon/dotext.sh
|
||||
/usr/lib/bwmon/dotext.sh &
|
||||
sleep $delay
|
||||
fi
|
||||
else
|
||||
|
@ -1,13 +1,10 @@
|
||||
module("luci.controller.blacklist", package.seeall)
|
||||
|
||||
I18N = require "luci.i18n"
|
||||
translate = I18N.translate
|
||||
|
||||
function index()
|
||||
local page
|
||||
local lock = luci.model.uci.cursor():get("custom", "menu", "full")
|
||||
--if lock == "1" then
|
||||
page = entry({"admin", "adminmenu", "blacklist"}, cbi("blacklist"), translate("Blacklist by Mac"), 10)
|
||||
if lock == "1" then
|
||||
page = entry({"admin", "adminmenu", "blacklist"}, cbi("blacklist"), "---Blacklist by Mac", 10)
|
||||
page.dependent = true
|
||||
--end
|
||||
end
|
||||
end
|
||||
|
@ -3,34 +3,33 @@
|
||||
#Copyright GNU act.
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=ext-domain
|
||||
PKG_NAME:=ext-blockport
|
||||
PKG_VERSION:=1.000
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/ext-domain
|
||||
define Package/ext-blockport
|
||||
SECTION:=utils
|
||||
CATEGORY:=ROOter
|
||||
SUBMENU:=Optional Applications
|
||||
DEPENDS:=+dnsmasq-full +ipset
|
||||
TITLE:=Domain Filter
|
||||
TITLE:=Install Port Blocking
|
||||
PKGARCH:=all
|
||||
endef
|
||||
|
||||
define Package/ext-domain/description
|
||||
Helper scripts to install Domain Filter on ROOter
|
||||
define Package/ext-blockport/description
|
||||
Helper scripts to install Port Blocking
|
||||
endef
|
||||
|
||||
|
||||
define Build/Compile
|
||||
endef
|
||||
|
||||
define Package/ext-domain/install
|
||||
define Package/ext-blockport/install
|
||||
$(CP) ./files/* $(1)/
|
||||
|
||||
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,ext-domain))
|
||||
$(eval $(call BuildPackage,ext-blockport))
|
||||
|
@ -0,0 +1,4 @@
|
||||
|
||||
config port 'port'
|
||||
|
||||
|
@ -1 +0,0 @@
|
||||
config filter filter
|
@ -1,46 +0,0 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
|
||||
START=99
|
||||
|
||||
log() {
|
||||
logger -t "Domain Filter " "$@"
|
||||
}
|
||||
|
||||
start()
|
||||
{
|
||||
ff=$(uci -q get firewall.filter)
|
||||
if [ -z $ff ]; then
|
||||
uci set firewall.filter="ipset"
|
||||
uci set firewall.filter.name="filter"
|
||||
uci set firewall.filter.family="ipv4"
|
||||
uci set firewall.filter.storage="hash"
|
||||
uci set firewall.filter.match="ip"
|
||||
uci set firewall.filter6="ipset"
|
||||
uci set firewall.filter6.name="filter6"
|
||||
uci set firewall.filter6.family="ipv6"
|
||||
uci set firewall.filter6.storage="hash"
|
||||
uci set firewall.filter6.match="ip"
|
||||
|
||||
# Filter LAN client traffic with IP sets
|
||||
uci set firewall.filter_fwd="rule"
|
||||
uci set firewall.filter_fwd.name="Filter-IPset-DNS-Forward"
|
||||
uci set firewall.filter_fwd.src="lan"
|
||||
uci set firewall.filter_fwd.dest="wan"
|
||||
uci set firewall.filter_fwd.ipset="filter dest"
|
||||
uci set firewall.filter_fwd.family="ipv4"
|
||||
uci set firewall.filter_fwd.proto="all"
|
||||
uci set firewall.filter_fwd.target="REJECT"
|
||||
uci set firewall.filter6_fwd="rule"
|
||||
uci set firewall.filter6_fwd.name="Filter6-IPset-DNS-Forward"
|
||||
uci set firewall.filter6_fwd.src="lan"
|
||||
uci set firewall.filter6_fwd.dest="wan"
|
||||
uci set firewall.filter6_fwd.ipset="filter6 dest"
|
||||
uci set firewall.filter6_fwd.family="ipv6"
|
||||
uci set firewall.filter6_fwd.proto="all"
|
||||
uci set firewall.filter6_fwd.target="REJECT"
|
||||
|
||||
uci commit firewall
|
||||
/etc/init.d/firewall restart
|
||||
fi
|
||||
/usr/lib/domain/filter.sh
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
#!/bin/sh
|
||||
. /lib/functions.sh
|
||||
|
||||
config="firewall"
|
||||
|
||||
do_block_remove() {
|
||||
config_get name $1 name
|
||||
if [ "$name" = "Block_src" ]; then
|
||||
uci delete $config".""$1"
|
||||
fi
|
||||
}
|
||||
|
||||
handle_port() {
|
||||
echo $1
|
||||
uci add $config rule
|
||||
uci set $config.@rule[-1].src='lan'
|
||||
uci set $config.@rule[-1].family='ipv4'
|
||||
uci set $config.@rule[-1].dest='wan'
|
||||
uci set $config.@rule[-1].target='DROP'
|
||||
uci set $config.@rule[-1].proto='tcp'
|
||||
uci set $config.@rule[-1].src_port="$1"
|
||||
uci set $config.@rule[-1].name='Block_src'
|
||||
}
|
||||
|
||||
do_port() {
|
||||
config_list_foreach "$1" block handle_port
|
||||
}
|
||||
|
||||
sleep 8
|
||||
config_load $config
|
||||
config_foreach do_block_remove rule
|
||||
|
||||
config_load blockport
|
||||
config_foreach do_port port
|
||||
uci commit $config
|
||||
/etc/init.d/firewall restart 2>/dev/null
|
||||
|
@ -1,26 +0,0 @@
|
||||
#!/bin/sh
|
||||
. /lib/functions.sh
|
||||
|
||||
log() {
|
||||
logger -t "Domain Filter " "$@"
|
||||
}
|
||||
|
||||
handle_ipset() {
|
||||
local ips=$1
|
||||
uci add_list dhcp.@dnsmasq[0].ipset='/'$ips'/filter,filter6'
|
||||
}
|
||||
|
||||
do_ipset() {
|
||||
local config=$1
|
||||
local ipset
|
||||
|
||||
config_list_foreach "$config" ipset handle_ipset
|
||||
}
|
||||
|
||||
sleep 3
|
||||
|
||||
uci -q delete dhcp.@dnsmasq[0].ipset
|
||||
config_load filter
|
||||
config_foreach do_ipset filter
|
||||
uci commit dhcp
|
||||
/etc/init.d/dnsmasq restart
|
@ -0,0 +1,12 @@
|
||||
-- Licensed to the public under the Apache License 2.0.
|
||||
|
||||
module("luci.controller.blockport", package.seeall)
|
||||
|
||||
function index()
|
||||
local lock = luci.model.uci.cursor():get("custom", "menu", "full")
|
||||
if lock == "1" then
|
||||
local page
|
||||
page = entry({"admin", "adminmenu", "blockport"}, cbi("portblk"), _("---Port Blocking"), 10)
|
||||
page.dependent = true
|
||||
end
|
||||
end
|
@ -1,15 +0,0 @@
|
||||
-- Licensed to the public under the Apache License 2.0.
|
||||
|
||||
module("luci.controller.domain", package.seeall)
|
||||
|
||||
I18N = require "luci.i18n"
|
||||
translate = I18N.translate
|
||||
|
||||
function index()
|
||||
local lock = luci.model.uci.cursor():get("custom", "menu", "full")
|
||||
--if lock == "1" then
|
||||
local page
|
||||
page = entry({"admin", "adminmenu", "domain"}, cbi("domainfltr"), _(translate("Domain Filter")), 9)
|
||||
page.dependent = true
|
||||
--end
|
||||
end
|
@ -5,17 +5,17 @@ local zones = require "luci.sys.zoneinfo"
|
||||
local fs = require "nixio.fs"
|
||||
local conf = require "luci.config"
|
||||
|
||||
m = Map("filter", translate("Domain Filter"), translate("Block traffic to specified URLs"))
|
||||
m = Map("blockport", translate("Port Blocking"), translate("Block traffic using specific ports"))
|
||||
|
||||
m.on_after_save = function(self)
|
||||
luci.sys.call("/usr/lib/domain/filter.sh &")
|
||||
luci.sys.call("/usr/lib/blockport/blockport.sh &")
|
||||
end
|
||||
|
||||
s = m:section(TypedSection, "filter", translate("Block List"))
|
||||
s = m:section(TypedSection, "port", translate("Block Port List"))
|
||||
s.anonymous = true
|
||||
s.addremove = false
|
||||
|
||||
s:option(DynamicList, "ipset", translate("Domain URLs"))
|
||||
s:option(DynamicList, "block", translate("Ports"))
|
||||
|
||||
|
||||
return m
|
@ -1,35 +0,0 @@
|
||||
#Owned by DairyMan@Whirlpool
|
||||
#
|
||||
#Copyright GNU act.
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=ext-menu
|
||||
PKG_VERSION:=1.000
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/ext-menu
|
||||
SECTION:=utils
|
||||
CATEGORY:=ROOter
|
||||
SUBMENU:=Optional Applications
|
||||
TITLE:=Menu Selection
|
||||
PKGARCH:=all
|
||||
endef
|
||||
|
||||
define Package/ext-menu/description
|
||||
Helper scripts to install Menu Selection on ROOter
|
||||
endef
|
||||
|
||||
|
||||
define Build/Compile
|
||||
endef
|
||||
|
||||
define Package/ext-menu/install
|
||||
$(CP) ./files/* $(1)/
|
||||
|
||||
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,ext-menu))
|
@ -1,10 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
fv=$(uci -q get custom.menu.full)
|
||||
if [ $fv = "0" ]; then
|
||||
fv="1"
|
||||
else
|
||||
fv="0"
|
||||
fi
|
||||
|
||||
/usr/lib/fullmenu/setmenu.sh $fv
|
@ -1,28 +0,0 @@
|
||||
module("luci.controller.firewall", package.seeall)
|
||||
|
||||
function index()
|
||||
entry({"admin", "network", "firewall"},
|
||||
alias("admin", "network", "firewall", "zones"),
|
||||
_("Firewall"), 60)
|
||||
|
||||
entry({"admin", "network", "firewall", "zones"},
|
||||
view("firewall/zones"), _("General Settings"), 10)
|
||||
|
||||
entry({"admin", "network", "firewall", "forwards"},
|
||||
view("firewall/forwards"), _("Port Forwards"), 20)
|
||||
|
||||
entry({"admin", "network", "firewall", "rules"},
|
||||
view("firewall/rules"), _("Traffic Rules"), 30)
|
||||
|
||||
entry({"admin", "network", "firewall", "snats"},
|
||||
view("firewall/snats"), _("NAT Rules"), 40)
|
||||
|
||||
entry({"admin", "network", "firewall", "custom"},
|
||||
view("firewall/custom"), _("Custom Rules"), 45).leaf = true
|
||||
|
||||
if nixio.fs.access("/etc/config/modem") then
|
||||
entry({"admin", "network", "firewall", "ttl"},
|
||||
cbi("firewall/ttlx"),
|
||||
_("Custom TTL Settings"), 50).leaf = true
|
||||
end
|
||||
end
|
@ -1,103 +0,0 @@
|
||||
{
|
||||
"admin/status/overview": {
|
||||
"title": "Overview",
|
||||
"order": 1,
|
||||
"action": {
|
||||
"type": "template",
|
||||
"path": "admin_status/index"
|
||||
}
|
||||
},
|
||||
|
||||
"admin/status/iptables": {
|
||||
"title": "Firewall",
|
||||
"order": 2,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "status/iptables"
|
||||
}
|
||||
},
|
||||
|
||||
"admin/status/routes": {
|
||||
"title": "Routes",
|
||||
"order": 3,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "status/routes"
|
||||
}
|
||||
},
|
||||
|
||||
"admin/status/syslog": {
|
||||
"title": "System Log",
|
||||
"order": 4,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "status/syslog"
|
||||
}
|
||||
},
|
||||
|
||||
"admin/status/dmesg": {
|
||||
"title": "Kernel Log",
|
||||
"order": 5,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "status/dmesg"
|
||||
}
|
||||
},
|
||||
|
||||
"admin/status/processes": {
|
||||
"title": "Processes",
|
||||
"order": 6,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "status/processes"
|
||||
}
|
||||
},
|
||||
|
||||
"admin/status/realtime": {
|
||||
"title": "Realtime Graphs",
|
||||
"order": 7,
|
||||
"action": {
|
||||
"type": "alias",
|
||||
"path": "admin/status/realtime/load"
|
||||
}
|
||||
},
|
||||
|
||||
"admin/status/realtime/load": {
|
||||
"title": "Load",
|
||||
"order": 1,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "status/load"
|
||||
}
|
||||
},
|
||||
|
||||
"admin/status/realtime/bandwidth": {
|
||||
"title": "Traffic",
|
||||
"order": 2,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "status/bandwidth"
|
||||
}
|
||||
},
|
||||
|
||||
"admin/status/realtime/wireless": {
|
||||
"title": "Wireless",
|
||||
"order": 3,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "status/wireless"
|
||||
},
|
||||
"depends": {
|
||||
"uci": { "wireless": { "@wifi-device": true } }
|
||||
}
|
||||
},
|
||||
|
||||
"admin/status/realtime/connections": {
|
||||
"title": "Connections",
|
||||
"order": 4,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "status/connections"
|
||||
}
|
||||
}
|
||||
}
|
@ -1,111 +0,0 @@
|
||||
{
|
||||
"admin/system/system": {
|
||||
"title": "System",
|
||||
"order": 1,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "system/system"
|
||||
}
|
||||
},
|
||||
|
||||
"admin/system/admin": {
|
||||
"title": "Administration",
|
||||
"order": 2,
|
||||
"action": {
|
||||
"type": "firstchild"
|
||||
}
|
||||
},
|
||||
|
||||
"admin/system/admin/password": {
|
||||
"title": "Router Password",
|
||||
"order": 1,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "system/password"
|
||||
}
|
||||
},
|
||||
|
||||
"admin/system/admin/dropbear": {
|
||||
"title": "SSH Access",
|
||||
"order": 2,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "system/dropbear"
|
||||
},
|
||||
"depends": {
|
||||
"fs": { "/usr/sbin/dropbear": "executable" }
|
||||
}
|
||||
},
|
||||
|
||||
"admin/system/admin/sshkeys": {
|
||||
"title": "SSH-Keys",
|
||||
"order": 3,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "system/sshkeys"
|
||||
},
|
||||
"depends": {
|
||||
"fs": { "/usr/sbin/dropbear": "executable" }
|
||||
}
|
||||
},
|
||||
|
||||
"admin/system/startup": {
|
||||
"title": "Startup",
|
||||
"order": 45,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "system/startup"
|
||||
}
|
||||
},
|
||||
|
||||
"admin/system/crontab": {
|
||||
"title": "Scheduled Tasks",
|
||||
"order": 46,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "system/crontab"
|
||||
}
|
||||
},
|
||||
|
||||
"admin/system/mounts": {
|
||||
"title": "Mount Points",
|
||||
"order": 50,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "system/mounts"
|
||||
},
|
||||
"depends": {
|
||||
"fs": { "/sbin/block": "executable" }
|
||||
}
|
||||
},
|
||||
|
||||
"admin/system/leds": {
|
||||
"title": "LED Configuration",
|
||||
"order": 60,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "system/leds"
|
||||
},
|
||||
"depends": {
|
||||
"fs": { "/sys/class/leds": "directory" }
|
||||
}
|
||||
},
|
||||
|
||||
"admin/system/flash": {
|
||||
"title": "Backup / Flash Firmware",
|
||||
"order": 70,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "system/flash"
|
||||
}
|
||||
},
|
||||
|
||||
"admin/system/reboot": {
|
||||
"title": "Reboot",
|
||||
"order": 90,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "system/reboot"
|
||||
}
|
||||
}
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
-- Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
-- Copyright 2011-2018 Jo-Philipp Wich <jo@mein.io>
|
||||
-- Licensed to the public under the Apache License 2.0.
|
||||
|
||||
module("luci.controller.admin.network", package.seeall)
|
||||
|
||||
function index()
|
||||
local page
|
||||
|
||||
-- if page.inreq then
|
||||
page = entry({"admin", "network", "switch"}, view("network/switch"), _("Switch"), 20)
|
||||
page.uci_depends = { network = { ["@switch[0]"] = "switch" } }
|
||||
|
||||
page = entry({"admin", "network", "wireless"}, view("network/wireless"), _('Wireless'), 15)
|
||||
page.uci_depends = { wireless = { ["@wifi-device[0]"] = "wifi-device" } }
|
||||
page.leaf = true
|
||||
|
||||
page = entry({"admin", "network", "network"}, view("network/interfaces"), _("Interfaces"), 10)
|
||||
page.leaf = true
|
||||
page.subindex = true
|
||||
|
||||
page = node("admin", "network", "dhcp")
|
||||
page.uci_depends = { dhcp = true }
|
||||
page.target = view("network/dhcp")
|
||||
page.title = _("DHCP and DNS")
|
||||
page.order = 30
|
||||
|
||||
page = node("admin", "network", "hosts")
|
||||
page.uci_depends = { dhcp = true }
|
||||
page.target = view("network/hosts")
|
||||
page.title = _("Hostnames")
|
||||
page.order = 40
|
||||
|
||||
page = node("admin", "network", "routes")
|
||||
page.target = view("network/routes")
|
||||
page.title = _("Static Routes")
|
||||
page.order = 50
|
||||
|
||||
page = node("admin", "network", "diagnostics")
|
||||
page.target = view("network/diagnostics")
|
||||
page.title = _("Diagnostics")
|
||||
page.order = 60
|
||||
-- end
|
||||
end
|
@ -1,117 +0,0 @@
|
||||
-- Copyright 2018 Jo-Philipp Wich <jo@mein.io>
|
||||
-- Licensed to the public under the Apache License 2.0.
|
||||
|
||||
module("luci.controller.opkg", package.seeall)
|
||||
|
||||
function index()
|
||||
entry({"admin", "system", "opkg"}, template("opkg"), _("Software"), 30)
|
||||
entry({"admin", "system", "opkg", "list"}, call("action_list")).leaf = true
|
||||
entry({"admin", "system", "opkg", "exec"}, post("action_exec")).leaf = true
|
||||
entry({"admin", "system", "opkg", "statvfs"}, call("action_statvfs")).leaf = true
|
||||
entry({"admin", "system", "opkg", "config"}, post_on({ data = true }, "action_config")).leaf = true
|
||||
end
|
||||
|
||||
function action_list(mode)
|
||||
local util = require "luci.util"
|
||||
local cmd
|
||||
|
||||
if mode == "installed" then
|
||||
cmd = { "/bin/cat", "/usr/lib/opkg/status" }
|
||||
else
|
||||
local lists_dir = nil
|
||||
|
||||
local fd = io.popen([[sed -rne 's#^lists_dir \S+ (\S+)#\1#p' /etc/opkg.conf /etc/opkg/*.conf 2>/dev/null]], "r")
|
||||
if fd then
|
||||
lists_dir = fd:read("*l")
|
||||
fd:close()
|
||||
end
|
||||
|
||||
if not lists_dir or #lists_dir == "" then
|
||||
lists_dir = "/tmp/opkg-lists"
|
||||
end
|
||||
|
||||
cmd = { "/bin/sh", "-c", [[find %s -type f '!' -name '*.sig' | xargs -r gzip -cd]] % util.shellquote(lists_dir) }
|
||||
end
|
||||
|
||||
luci.http.prepare_content("text/plain; charset=utf-8")
|
||||
luci.sys.process.exec(cmd, luci.http.write)
|
||||
end
|
||||
|
||||
function action_exec(command, package)
|
||||
local sys = require "luci.sys"
|
||||
local cmd = { "/bin/opkg", "--force-removal-of-dependent-packages" }
|
||||
local pkg = luci.http.formvalue("package")
|
||||
|
||||
if luci.http.formvalue("autoremove") == "true" then
|
||||
cmd[#cmd + 1] = "--autoremove"
|
||||
end
|
||||
|
||||
if luci.http.formvalue("overwrite") == "true" then
|
||||
cmd[#cmd + 1] = "--force-overwrite"
|
||||
end
|
||||
|
||||
cmd[#cmd + 1] = command
|
||||
|
||||
if pkg then
|
||||
cmd[#cmd + 1] = pkg
|
||||
end
|
||||
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(sys.process.exec(cmd, true, true))
|
||||
end
|
||||
|
||||
function action_statvfs()
|
||||
local fs = require "nixio.fs"
|
||||
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(fs.statvfs("/") or {})
|
||||
end
|
||||
|
||||
function action_config()
|
||||
local fs = require "nixio.fs"
|
||||
local js = require "luci.jsonc"
|
||||
local data = luci.http.formvalue("data")
|
||||
|
||||
if data then
|
||||
data = js.parse(data)
|
||||
|
||||
if not data then
|
||||
luci.http.status(400, "Bad Request")
|
||||
return
|
||||
end
|
||||
|
||||
local file, content
|
||||
for file, content in pairs(data) do
|
||||
if type(content) ~= "string" or
|
||||
(file ~= "opkg.conf" and not file:match("^opkg/[^/]+%.conf$"))
|
||||
then
|
||||
luci.http.status(400, "Bad Request")
|
||||
return
|
||||
end
|
||||
|
||||
local path = "/etc/%s" % file
|
||||
if not fs.access(path, "w") then
|
||||
luci.http.status(403, "Permission denied")
|
||||
return
|
||||
end
|
||||
|
||||
fs.writefile(path, content:gsub("\r\n", "\n"))
|
||||
end
|
||||
|
||||
luci.http.status(204, "Saved")
|
||||
else
|
||||
local rv = { ["opkg.conf"] = fs.readfile("/etc/opkg.conf") }
|
||||
local entries = fs.dir("/etc/opkg")
|
||||
if entries then
|
||||
local entry
|
||||
for entry in entries do
|
||||
if entry:match("%.conf$") then
|
||||
rv["opkg/%s" % entry] = fs.readfile("/etc/opkg/%s" % entry)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(rv)
|
||||
end
|
||||
end
|
@ -1,70 +0,0 @@
|
||||
{
|
||||
"admin/network/firewall": {
|
||||
"title": "Firewall",
|
||||
"order": 60,
|
||||
"action": {
|
||||
"type": "alias",
|
||||
"path": "admin/network/firewall/zones"
|
||||
},
|
||||
"depends": {
|
||||
"acl": [ "luci-app-firewall" ],
|
||||
"fs": { "/sbin/fw3": "executable" },
|
||||
"uci": { "firewall": true }
|
||||
}
|
||||
},
|
||||
|
||||
"admin/network/firewall/zones": {
|
||||
"title": "General Settings",
|
||||
"order": 10,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "firewall/zones"
|
||||
}
|
||||
},
|
||||
|
||||
"admin/network/firewall/forwards": {
|
||||
"title": "Port Forwards",
|
||||
"order": 20,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "firewall/forwards"
|
||||
}
|
||||
},
|
||||
|
||||
"admin/network/firewall/rules": {
|
||||
"title": "Traffic Rules",
|
||||
"order": 30,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "firewall/rules"
|
||||
}
|
||||
},
|
||||
|
||||
"admin/network/firewall/snats": {
|
||||
"title": "NAT Rules",
|
||||
"order": 40,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "firewall/snats"
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
"admin/network/firewall/custom": {
|
||||
"title": "Custom Rules",
|
||||
"order": 50,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "firewall/custom"
|
||||
}
|
||||
},
|
||||
|
||||
"admin/network/firewall/customttl": {
|
||||
"title": "Custom TTL Settings",
|
||||
"order": 55,
|
||||
"action": {
|
||||
"type": "cbi",
|
||||
"path": "firewall/ttlx"
|
||||
}
|
||||
}
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
{
|
||||
"admin/system/opkg": {
|
||||
"title": "Software",
|
||||
"order": 30,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "opkg"
|
||||
},
|
||||
"depends": {
|
||||
"acl": [ "luci-app-opkg" ]
|
||||
}
|
||||
}
|
||||
}
|
@ -1,98 +0,0 @@
|
||||
{
|
||||
"admin/network/switch": {
|
||||
"title": "Switch",
|
||||
"order": 20,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "network/switch"
|
||||
},
|
||||
"depends": {
|
||||
"acl": [ "luci-mod-network-config" ],
|
||||
"fs": { "/sbin/swconfig": "executable" },
|
||||
"uci": { "network": { "@switch": true } }
|
||||
}
|
||||
},
|
||||
|
||||
"admin/network/wireless": {
|
||||
"title": "Wireless",
|
||||
"order": 15,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "network/wireless"
|
||||
},
|
||||
"depends": {
|
||||
"acl": [ "luci-mod-network-config" ],
|
||||
"uci": { "wireless": { "@wifi-device": true } }
|
||||
}
|
||||
},
|
||||
|
||||
"admin/network/remote_addr/*": {
|
||||
"action": {
|
||||
"type": "call",
|
||||
"module": "luci.controller.admin.network",
|
||||
"function": "remote_addr"
|
||||
}
|
||||
},
|
||||
|
||||
"admin/network/network": {
|
||||
"title": "Interfaces",
|
||||
"order": 10,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "network/interfaces"
|
||||
},
|
||||
"depends": {
|
||||
"acl": [ "luci-mod-network-config" ]
|
||||
}
|
||||
},
|
||||
|
||||
"admin/network/dhcp": {
|
||||
"title": "DHCP and DNS",
|
||||
"order": 30,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "network/dhcp"
|
||||
},
|
||||
"depends": {
|
||||
"acl": [ "luci-mod-network-dhcp" ],
|
||||
"uci": { "dhcp": true }
|
||||
}
|
||||
},
|
||||
|
||||
"admin/network/hosts": {
|
||||
"title": "Hostnames",
|
||||
"order": 40,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "network/hosts"
|
||||
},
|
||||
"depends": {
|
||||
"acl": [ "luci-mod-network-dhcp" ],
|
||||
"uci": { "dhcp": true }
|
||||
}
|
||||
},
|
||||
|
||||
"admin/network/routes": {
|
||||
"title": "Static Routes",
|
||||
"order": 50,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "network/routes"
|
||||
},
|
||||
"depends": {
|
||||
"acl": [ "luci-mod-network-config" ]
|
||||
}
|
||||
},
|
||||
|
||||
"admin/network/diagnostics": {
|
||||
"title": "Diagnostics",
|
||||
"order": 60,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "network/diagnostics"
|
||||
},
|
||||
"depends": {
|
||||
"acl": [ "luci-mod-network-diagnostics" ]
|
||||
}
|
||||
}
|
||||
}
|
@ -1,137 +0,0 @@
|
||||
{
|
||||
"admin/status/overview": {
|
||||
"title": "Overview",
|
||||
"order": 1,
|
||||
"action": {
|
||||
"type": "template",
|
||||
"path": "admin_status/index"
|
||||
},
|
||||
"depends": {
|
||||
"acl": [ "luci-mod-status-index" ]
|
||||
}
|
||||
},
|
||||
|
||||
"admin/status/iptables": {
|
||||
"title": "Firewall",
|
||||
"order": 2,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "status/iptables"
|
||||
},
|
||||
"depends": {
|
||||
"acl": [ "luci-mod-status-firewall" ]
|
||||
}
|
||||
},
|
||||
|
||||
"admin/status/routes": {
|
||||
"title": "Routes",
|
||||
"order": 3,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "status/routes"
|
||||
},
|
||||
"depends": {
|
||||
"acl": [ "luci-mod-status-routes" ]
|
||||
}
|
||||
},
|
||||
|
||||
"admin/status/syslog": {
|
||||
"title": "System Log",
|
||||
"order": 4,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "status/syslog"
|
||||
},
|
||||
"depends": {
|
||||
"acl": [ "luci-mod-status-logs" ]
|
||||
}
|
||||
},
|
||||
|
||||
"admin/status/dmesg": {
|
||||
"title": "Kernel Log",
|
||||
"order": 5,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "status/dmesg"
|
||||
},
|
||||
"depends": {
|
||||
"acl": [ "luci-mod-status-logs" ]
|
||||
}
|
||||
},
|
||||
|
||||
"admin/status/processes": {
|
||||
"title": "Processes",
|
||||
"order": 6,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "status/processes"
|
||||
},
|
||||
"depends": {
|
||||
"acl": [ "luci-mod-status-processes" ]
|
||||
}
|
||||
},
|
||||
|
||||
"admin/status/channel_analysis": {
|
||||
"title": "Channel Analysis",
|
||||
"order": 7,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "status/channel_analysis"
|
||||
},
|
||||
"depends": {
|
||||
"acl": [ "luci-mod-status-channel_analysis" ],
|
||||
"uci": { "wireless": { "@wifi-device": true } }
|
||||
}
|
||||
},
|
||||
|
||||
"admin/status/realtime": {
|
||||
"title": "Realtime Graphs",
|
||||
"order": 7,
|
||||
"action": {
|
||||
"type": "alias",
|
||||
"path": "admin/status/realtime/load"
|
||||
},
|
||||
"depends": {
|
||||
"acl": [ "luci-mod-status-realtime" ]
|
||||
}
|
||||
},
|
||||
|
||||
"admin/status/realtime/load": {
|
||||
"title": "Load",
|
||||
"order": 1,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "status/load"
|
||||
}
|
||||
},
|
||||
|
||||
"admin/status/realtime/bandwidth": {
|
||||
"title": "Traffic",
|
||||
"order": 2,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "status/bandwidth"
|
||||
}
|
||||
},
|
||||
|
||||
"admin/status/realtime/wireless": {
|
||||
"title": "Wireless",
|
||||
"order": 3,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "status/wireless"
|
||||
},
|
||||
"depends": {
|
||||
"uci": { "wireless": { "@wifi-device": true } }
|
||||
}
|
||||
},
|
||||
|
||||
"admin/status/realtime/connections": {
|
||||
"title": "Connections",
|
||||
"order": 4,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "status/connections"
|
||||
}
|
||||
}
|
||||
}
|
@ -1,136 +0,0 @@
|
||||
{
|
||||
"admin/system/system": {
|
||||
"title": "System",
|
||||
"order": 1,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "system/system"
|
||||
},
|
||||
"depends": {
|
||||
"acl": [ "luci-mod-system-config" ]
|
||||
}
|
||||
},
|
||||
|
||||
"admin/system/admin": {
|
||||
"title": "Administration",
|
||||
"order": 2,
|
||||
"action": {
|
||||
"type": "firstchild"
|
||||
},
|
||||
"depends": {
|
||||
"acl": [ "luci-mod-system-config", "luci-mod-system-ssh" ]
|
||||
}
|
||||
},
|
||||
|
||||
"admin/system/admin/password": {
|
||||
"title": "Router Password",
|
||||
"order": 1,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "system/password"
|
||||
},
|
||||
"depends": {
|
||||
"acl": [ "luci-mod-system-config" ]
|
||||
}
|
||||
},
|
||||
|
||||
"admin/system/admin/dropbear": {
|
||||
"title": "SSH Access",
|
||||
"order": 2,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "system/dropbear"
|
||||
},
|
||||
"depends": {
|
||||
"acl": [ "luci-mod-system-ssh" ],
|
||||
"fs": { "/usr/sbin/dropbear": "executable" }
|
||||
}
|
||||
},
|
||||
|
||||
"admin/system/admin/sshkeys": {
|
||||
"title": "SSH-Keys",
|
||||
"order": 3,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "system/sshkeys"
|
||||
},
|
||||
"depends": {
|
||||
"acl": [ "luci-mod-system-ssh" ],
|
||||
"fs": { "/usr/sbin/dropbear": "executable" }
|
||||
}
|
||||
},
|
||||
|
||||
"admin/system/startup": {
|
||||
"title": "Startup",
|
||||
"order": 45,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "system/startup"
|
||||
},
|
||||
"depends": {
|
||||
"acl": [ "luci-mod-system-init" ]
|
||||
}
|
||||
},
|
||||
|
||||
"admin/system/crontab": {
|
||||
"title": "Scheduled Tasks",
|
||||
"order": 46,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "system/crontab"
|
||||
},
|
||||
"depends": {
|
||||
"acl": [ "luci-mod-system-cron" ]
|
||||
}
|
||||
},
|
||||
|
||||
"admin/system/mounts": {
|
||||
"title": "Mount Points",
|
||||
"order": 50,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "system/mounts"
|
||||
},
|
||||
"depends": {
|
||||
"acl": [ "luci-mod-system-mounts" ],
|
||||
"fs": { "/sbin/block": "executable" }
|
||||
}
|
||||
},
|
||||
|
||||
"admin/system/leds": {
|
||||
"title": "LED Configuration",
|
||||
"order": 60,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "system/leds"
|
||||
},
|
||||
"depends": {
|
||||
"acl": [ "luci-mod-system-config" ],
|
||||
"fs": { "/sys/class/leds": "directory" }
|
||||
}
|
||||
},
|
||||
|
||||
"admin/system/flash": {
|
||||
"title": "Backup / Flash Firmware",
|
||||
"order": 70,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "system/flash"
|
||||
},
|
||||
"depends": {
|
||||
"acl": [ "luci-mod-system-flash" ]
|
||||
}
|
||||
},
|
||||
|
||||
"admin/system/reboot": {
|
||||
"title": "Reboot",
|
||||
"order": 90,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "system/reboot"
|
||||
},
|
||||
"depends": {
|
||||
"acl": [ "luci-mod-system-reboot" ]
|
||||
}
|
||||
}
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
module("luci.controller.firewall", package.seeall)
|
||||
|
||||
function index()
|
||||
entry({"admin", "network", "firewall"},
|
||||
alias("admin", "network", "firewall", "zones"),
|
||||
_("Firewall"), 60)
|
||||
|
||||
entry({"admin", "network", "firewall", "zones"},
|
||||
view("firewall/zones"), _("General Settings"), 10)
|
||||
|
||||
entry({"admin", "network", "firewall", "forwards"},
|
||||
view("firewall/forwards"), _("Port Forwards"), 20)
|
||||
|
||||
entry({"admin", "network", "firewall", "rules"},
|
||||
view("firewall/rules"), _("Traffic Rules"), 30)
|
||||
|
||||
entry({"admin", "network", "firewall", "snats"},
|
||||
view("firewall/snats"), _("NAT Rules"), 40)
|
||||
|
||||
entry({"admin", "network", "firewall", "custom"},
|
||||
view("firewall/custom"), _("Custom Rules"), 45).leaf = true
|
||||
|
||||
if nixio.fs.access("/etc/config/modem") then
|
||||
entry({"admin", "network", "firewall", "ttl"},
|
||||
cbi("firewall/ttlx"),
|
||||
_("Custom TTL Settings"), 50).leaf = true
|
||||
end
|
||||
end
|
@ -1,19 +0,0 @@
|
||||
{
|
||||
"admin/status/overview": {
|
||||
"title": "Overview",
|
||||
"order": 1,
|
||||
"action": {
|
||||
"type": "template",
|
||||
"path": "admin_status/index"
|
||||
}
|
||||
},
|
||||
|
||||
"admin/status/syslog": {
|
||||
"title": "System Log",
|
||||
"order": 4,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "status/syslog"
|
||||
}
|
||||
}
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
{
|
||||
"admin/system/system": {
|
||||
"title": "System",
|
||||
"order": 1,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "system/system"
|
||||
}
|
||||
},
|
||||
|
||||
"admin/system/admin": {
|
||||
"title": "Administration",
|
||||
"order": 2,
|
||||
"action": {
|
||||
"type": "firstchild"
|
||||
}
|
||||
},
|
||||
|
||||
"admin/system/admin/password": {
|
||||
"title": "Router Password",
|
||||
"order": 1,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "system/password"
|
||||
}
|
||||
},
|
||||
|
||||
"admin/system/flash": {
|
||||
"title": "Flash Firmware",
|
||||
"order": 70,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "system/flash"
|
||||
}
|
||||
},
|
||||
|
||||
"admin/system/reboot": {
|
||||
"title": "Reboot",
|
||||
"order": 90,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "system/reboot"
|
||||
}
|
||||
}
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
-- Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
-- Copyright 2011-2018 Jo-Philipp Wich <jo@mein.io>
|
||||
-- Licensed to the public under the Apache License 2.0.
|
||||
|
||||
module("luci.controller.admin.network", package.seeall)
|
||||
|
||||
function index()
|
||||
local page
|
||||
|
||||
-- if page.inreq then
|
||||
page = entry({"admin", "network", "switch"}, view("network/switch"), _("Switch"), 20)
|
||||
page.uci_depends = { network = { ["@switch[0]"] = "switch" } }
|
||||
|
||||
page = entry({"admin", "network", "wireless"}, view("network/wireless"), _('Wireless'), 15)
|
||||
page.uci_depends = { wireless = { ["@wifi-device[0]"] = "wifi-device" } }
|
||||
page.leaf = true
|
||||
|
||||
page = entry({"admin", "network", "network"}, view("network/interfaces"), _("Interfaces"), 10)
|
||||
page.leaf = true
|
||||
page.subindex = true
|
||||
|
||||
page = node("admin", "network", "dhcp")
|
||||
page.uci_depends = { dhcp = true }
|
||||
page.target = view("network/dhcp")
|
||||
page.title = _("DHCP and DNS")
|
||||
page.order = 30
|
||||
|
||||
page = node("admin", "network", "hosts")
|
||||
page.uci_depends = { dhcp = true }
|
||||
page.target = view("network/hosts")
|
||||
page.title = _("Hostnames")
|
||||
page.order = 40
|
||||
|
||||
page = node("admin", "network", "routes")
|
||||
page.target = view("network/routes")
|
||||
page.title = _("Static Routes")
|
||||
page.order = 50
|
||||
|
||||
page = node("admin", "network", "diagnostics")
|
||||
page.target = view("network/diagnostics")
|
||||
page.title = _("Diagnostics")
|
||||
page.order = 60
|
||||
-- end
|
||||
end
|
@ -1,117 +0,0 @@
|
||||
-- Copyright 2018 Jo-Philipp Wich <jo@mein.io>
|
||||
-- Licensed to the public under the Apache License 2.0.
|
||||
|
||||
module("luci.controller.opkg", package.seeall)
|
||||
|
||||
function index()
|
||||
entry({"admin", "system", "opkg"}, template("opkg"), _("Software"), 30)
|
||||
entry({"admin", "system", "opkg", "list"}, call("action_list")).leaf = true
|
||||
entry({"admin", "system", "opkg", "exec"}, post("action_exec")).leaf = true
|
||||
entry({"admin", "system", "opkg", "statvfs"}, call("action_statvfs")).leaf = true
|
||||
entry({"admin", "system", "opkg", "config"}, post_on({ data = true }, "action_config")).leaf = true
|
||||
end
|
||||
|
||||
function action_list(mode)
|
||||
local util = require "luci.util"
|
||||
local cmd
|
||||
|
||||
if mode == "installed" then
|
||||
cmd = { "/bin/cat", "/usr/lib/opkg/status" }
|
||||
else
|
||||
local lists_dir = nil
|
||||
|
||||
local fd = io.popen([[sed -rne 's#^lists_dir \S+ (\S+)#\1#p' /etc/opkg.conf /etc/opkg/*.conf 2>/dev/null]], "r")
|
||||
if fd then
|
||||
lists_dir = fd:read("*l")
|
||||
fd:close()
|
||||
end
|
||||
|
||||
if not lists_dir or #lists_dir == "" then
|
||||
lists_dir = "/tmp/opkg-lists"
|
||||
end
|
||||
|
||||
cmd = { "/bin/sh", "-c", [[find %s -type f '!' -name '*.sig' | xargs -r gzip -cd]] % util.shellquote(lists_dir) }
|
||||
end
|
||||
|
||||
luci.http.prepare_content("text/plain; charset=utf-8")
|
||||
luci.sys.process.exec(cmd, luci.http.write)
|
||||
end
|
||||
|
||||
function action_exec(command, package)
|
||||
local sys = require "luci.sys"
|
||||
local cmd = { "/bin/opkg", "--force-removal-of-dependent-packages" }
|
||||
local pkg = luci.http.formvalue("package")
|
||||
|
||||
if luci.http.formvalue("autoremove") == "true" then
|
||||
cmd[#cmd + 1] = "--autoremove"
|
||||
end
|
||||
|
||||
if luci.http.formvalue("overwrite") == "true" then
|
||||
cmd[#cmd + 1] = "--force-overwrite"
|
||||
end
|
||||
|
||||
cmd[#cmd + 1] = command
|
||||
|
||||
if pkg then
|
||||
cmd[#cmd + 1] = pkg
|
||||
end
|
||||
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(sys.process.exec(cmd, true, true))
|
||||
end
|
||||
|
||||
function action_statvfs()
|
||||
local fs = require "nixio.fs"
|
||||
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(fs.statvfs("/") or {})
|
||||
end
|
||||
|
||||
function action_config()
|
||||
local fs = require "nixio.fs"
|
||||
local js = require "luci.jsonc"
|
||||
local data = luci.http.formvalue("data")
|
||||
|
||||
if data then
|
||||
data = js.parse(data)
|
||||
|
||||
if not data then
|
||||
luci.http.status(400, "Bad Request")
|
||||
return
|
||||
end
|
||||
|
||||
local file, content
|
||||
for file, content in pairs(data) do
|
||||
if type(content) ~= "string" or
|
||||
(file ~= "opkg.conf" and not file:match("^opkg/[^/]+%.conf$"))
|
||||
then
|
||||
luci.http.status(400, "Bad Request")
|
||||
return
|
||||
end
|
||||
|
||||
local path = "/etc/%s" % file
|
||||
if not fs.access(path, "w") then
|
||||
luci.http.status(403, "Permission denied")
|
||||
return
|
||||
end
|
||||
|
||||
fs.writefile(path, content:gsub("\r\n", "\n"))
|
||||
end
|
||||
|
||||
luci.http.status(204, "Saved")
|
||||
else
|
||||
local rv = { ["opkg.conf"] = fs.readfile("/etc/opkg.conf") }
|
||||
local entries = fs.dir("/etc/opkg")
|
||||
if entries then
|
||||
local entry
|
||||
for entry in entries do
|
||||
if entry:match("%.conf$") then
|
||||
rv["opkg/%s" % entry] = fs.readfile("/etc/opkg/%s" % entry)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(rv)
|
||||
end
|
||||
end
|
@ -1,70 +0,0 @@
|
||||
{
|
||||
"admin/network/firewall": {
|
||||
"title": "Firewall",
|
||||
"order": 60,
|
||||
"action": {
|
||||
"type": "alias",
|
||||
"path": "admin/network/firewall/zones"
|
||||
},
|
||||
"depends": {
|
||||
"acl": [ "luci-app-firewall" ],
|
||||
"fs": { "/sbin/fw3": "executable" },
|
||||
"uci": { "firewall": true }
|
||||
}
|
||||
},
|
||||
|
||||
"admin/network/firewall/zones": {
|
||||
"title": "General Settings",
|
||||
"order": 10,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "firewall/zones"
|
||||
}
|
||||
},
|
||||
|
||||
"admin/network/firewall/forwards": {
|
||||
"title": "Port Forwards",
|
||||
"order": 20,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "firewall/forwards"
|
||||
}
|
||||
},
|
||||
|
||||
"admin/network/firewall/rules": {
|
||||
"title": "Traffic Rules",
|
||||
"order": 30,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "firewall/rules"
|
||||
}
|
||||
},
|
||||
|
||||
"admin/network/firewall/snats": {
|
||||
"title": "NAT Rules",
|
||||
"order": 40,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "firewall/snats"
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
"admin/network/firewall/custom": {
|
||||
"title": "Custom Rules",
|
||||
"order": 50,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "firewall/custom"
|
||||
}
|
||||
},
|
||||
|
||||
"admin/network/firewall/customttl": {
|
||||
"title": "Custom TTL Settings",
|
||||
"order": 55,
|
||||
"action": {
|
||||
"type": "cbi",
|
||||
"path": "firewall/ttlx"
|
||||
}
|
||||
}
|
||||
}
|
@ -1,98 +0,0 @@
|
||||
{
|
||||
"admin/network/switch": {
|
||||
"title": "Switch",
|
||||
"order": 20,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "network/switch"
|
||||
},
|
||||
"depends": {
|
||||
"acl": [ "luci-mod-network-config" ],
|
||||
"fs": { "/sbin/swconfig": "executable" },
|
||||
"uci": { "network": { "@switch": true } }
|
||||
}
|
||||
},
|
||||
|
||||
"admin/network/wireless": {
|
||||
"title": "Wireless",
|
||||
"order": 15,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "network/wireless"
|
||||
},
|
||||
"depends": {
|
||||
"acl": [ "luci-mod-network-config" ],
|
||||
"uci": { "wireless": { "@wifi-device": true } }
|
||||
}
|
||||
},
|
||||
|
||||
"admin/network/remote_addr/*": {
|
||||
"action": {
|
||||
"type": "call",
|
||||
"module": "luci.controller.admin.network",
|
||||
"function": "remote_addr"
|
||||
}
|
||||
},
|
||||
|
||||
"admin/network/network": {
|
||||
"title": "Interfaces",
|
||||
"order": 10,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "network/interfaces"
|
||||
},
|
||||
"depends": {
|
||||
"acl": [ "luci-mod-network-config" ]
|
||||
}
|
||||
},
|
||||
|
||||
"admin/network/dhcp": {
|
||||
"title": "DHCP and DNS",
|
||||
"order": 30,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "network/dhcp"
|
||||
},
|
||||
"depends": {
|
||||
"acl": [ "luci-mod-network-dhcp" ],
|
||||
"uci": { "dhcp": true }
|
||||
}
|
||||
},
|
||||
|
||||
"admin/network/hosts": {
|
||||
"title": "Hostnames",
|
||||
"order": 40,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "network/hosts"
|
||||
},
|
||||
"depends": {
|
||||
"acl": [ "luci-mod-network-dhcp" ],
|
||||
"uci": { "dhcp": true }
|
||||
}
|
||||
},
|
||||
|
||||
"admin/network/routes": {
|
||||
"title": "Static Routes",
|
||||
"order": 50,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "network/routes"
|
||||
},
|
||||
"depends": {
|
||||
"acl": [ "luci-mod-network-config" ]
|
||||
}
|
||||
},
|
||||
|
||||
"admin/network/diagnostics": {
|
||||
"title": "Diagnostics",
|
||||
"order": 60,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "network/diagnostics"
|
||||
},
|
||||
"depends": {
|
||||
"acl": [ "luci-mod-network-diagnostics" ]
|
||||
}
|
||||
}
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
{
|
||||
"admin/status/overview": {
|
||||
"title": "Overview",
|
||||
"order": 1,
|
||||
"action": {
|
||||
"type": "template",
|
||||
"path": "admin_status/index"
|
||||
},
|
||||
"depends": {
|
||||
"acl": [ "luci-mod-status-index" ]
|
||||
}
|
||||
},
|
||||
|
||||
"admin/status/syslog": {
|
||||
"title": "System Log",
|
||||
"order": 4,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "status/syslog"
|
||||
},
|
||||
"depends": {
|
||||
"acl": [ "luci-mod-status-logs" ]
|
||||
}
|
||||
},
|
||||
|
||||
"admin/status/channel_analysis": {
|
||||
"title": "Wifi Channel Analysis",
|
||||
"order": 7,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "status/channel_analysis"
|
||||
},
|
||||
"depends": {
|
||||
"acl": [ "luci-mod-status-channel_analysis" ],
|
||||
"uci": { "wireless": { "@wifi-device": true } }
|
||||
}
|
||||
},
|
||||
}
|
@ -1,60 +0,0 @@
|
||||
{
|
||||
"admin/system/system": {
|
||||
"title": "System",
|
||||
"order": 1,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "system/system"
|
||||
},
|
||||
"depends": {
|
||||
"acl": [ "luci-mod-system-config" ]
|
||||
}
|
||||
},
|
||||
|
||||
"admin/system/admin": {
|
||||
"title": "Administration",
|
||||
"order": 2,
|
||||
"action": {
|
||||
"type": "firstchild"
|
||||
},
|
||||
"depends": {
|
||||
"acl": [ "luci-mod-system-config", "luci-mod-system-ssh" ]
|
||||
}
|
||||
},
|
||||
|
||||
"admin/system/admin/password": {
|
||||
"title": "Router Password",
|
||||
"order": 1,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "system/password"
|
||||
},
|
||||
"depends": {
|
||||
"acl": [ "luci-mod-system-config" ]
|
||||
}
|
||||
},
|
||||
|
||||
"admin/system/flash": {
|
||||
"title": "Flash Firmware",
|
||||
"order": 70,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "system/flash"
|
||||
},
|
||||
"depends": {
|
||||
"acl": [ "luci-mod-system-flash" ]
|
||||
}
|
||||
},
|
||||
|
||||
"admin/system/reboot": {
|
||||
"title": "Reboot",
|
||||
"order": 90,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "system/reboot"
|
||||
},
|
||||
"depends": {
|
||||
"acl": [ "luci-mod-system-reboot" ]
|
||||
}
|
||||
}
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
#!/bin/sh
|
||||
. /lib/functions.sh
|
||||
|
||||
log() {
|
||||
logger -t "Menu Change" "$@"
|
||||
}
|
||||
|
||||
full=$1
|
||||
source /etc/openwrt_release
|
||||
twone=$(echo "$DISTRIB_RELEASE" | grep "21.02")
|
||||
|
||||
if [ $full = "0" ]; then
|
||||
fv="1"
|
||||
if [ ! -z "$twone" ]; then # 21.02
|
||||
cp /usr/lib/fullmenu/full21/luci-mod-status.json /usr/share/luci/menu.d
|
||||
cp /usr/lib/fullmenu/full21/luci-mod-system.json /usr/share/luci/menu.d
|
||||
cp /usr/lib/fullmenu/full21/luci-app-opkg.json /usr/share/luci/menu.d
|
||||
else # 19.07.6
|
||||
cp /usr/lib/fullmenu/full19/luci-mod-status.json /usr/share/luci/menu.d
|
||||
cp /usr/lib/fullmenu/full19/luci-mod-system.json /usr/share/luci/menu.d
|
||||
fi
|
||||
else
|
||||
fv="0"
|
||||
if [ ! -z "$twone" ]; then # 21.02
|
||||
cp /usr/lib/fullmenu/limited21/luci-mod-status.json /usr/share/luci/menu.d
|
||||
cp /usr/lib/fullmenu/limited21/luci-mod-system.json /usr/share/luci/menu.d
|
||||
rm -f /usr/share/luci/menu.d/luci-app-opkg.json
|
||||
else # 19.07.6
|
||||
cp /usr/lib/fullmenu/limited19/luci-mod-status.json /usr/share/luci/menu.d
|
||||
cp /usr/lib/fullmenu/limited19/luci-mod-system.json /usr/share/luci/menu.d
|
||||
fi
|
||||
fi
|
||||
uci set custom.menu.full=$fv
|
||||
uci commit custom
|
@ -1,28 +0,0 @@
|
||||
module("luci.controller.fullmenu", package.seeall)
|
||||
function index()
|
||||
local fs = require "nixio.fs"
|
||||
local page
|
||||
page = entry({"admin", "system", "fullmenu"}, template("fullmenu/fullmenu"), "Menu Selection", 96)
|
||||
page.dependent = true
|
||||
|
||||
entry({"admin", "system", "getmenu"}, call("action_getmenu"))
|
||||
entry({"admin", "system", "setmenu"}, call("action_setmenu"))
|
||||
|
||||
end
|
||||
|
||||
function action_getmenu()
|
||||
local rv = {}
|
||||
id = luci.model.uci.cursor():get("custom", "menu", "full")
|
||||
rv["full"] = id
|
||||
password = luci.model.uci.cursor():get("custom", "menu", "password")
|
||||
rv["password"] = password
|
||||
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(rv)
|
||||
end
|
||||
|
||||
function action_setmenu()
|
||||
local set = luci.http.formvalue("set")
|
||||
os.execute("/usr/lib/fullmenu/setmenu.sh " .. set)
|
||||
|
||||
end
|
@ -1,166 +0,0 @@
|
||||
<%+header%>
|
||||
<%
|
||||
local sys = require "luci.sys"
|
||||
local utl = require "luci.util"
|
||||
local fs = require "nixio.fs"
|
||||
|
||||
function showicon(lck)
|
||||
if lck == 0 then
|
||||
return resource .. "/icons/unlock1.png"
|
||||
else
|
||||
return resource .. "/icons/lock1.png"
|
||||
end
|
||||
end
|
||||
|
||||
-%>
|
||||
<script type="text/javascript" src="<%=resource%>/xhr.js"></script>
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
|
||||
var lockb = 0;
|
||||
var full;
|
||||
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin", "system", "getmenu")%>',
|
||||
null,
|
||||
function(x, rv)
|
||||
{
|
||||
document.getElementById("password").value=rv.password;
|
||||
full = rv.full;
|
||||
if ( full == "0" )
|
||||
{
|
||||
document.getElementById("idf").style.visibility="visible";
|
||||
document.getElementById("idn").style.visibility="hidden";
|
||||
document.getElementById("idn").style.display = "none";
|
||||
}
|
||||
else
|
||||
{
|
||||
document.getElementById("idf").style.visibility="hidden";
|
||||
document.getElementById("idf").style.display = "none";
|
||||
document.getElementById("idn").style.visibility="visible";
|
||||
}
|
||||
}
|
||||
|
||||
);
|
||||
|
||||
function done() {
|
||||
document.getElementById("popup").style.display = "none";
|
||||
passw = document.getElementById("password").value;
|
||||
var r = document.getElementById("pass").value;
|
||||
if ( r == null )
|
||||
|
||||
{
|
||||
document.getElementById("pass").value="";
|
||||
return false;
|
||||
}
|
||||
if ( r == passw )
|
||||
{
|
||||
// change menu type here
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin", "system", "setmenu")%>',
|
||||
{ set: full },
|
||||
function()
|
||||
{
|
||||
document.getElementById("pass").value="";
|
||||
window.location.reload(false);
|
||||
}
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
alert("<%:Incorrect Password!!!%>");
|
||||
document.getElementById("pass").value="";
|
||||
}
|
||||
document.getElementById("lockbtn").disabled=false;
|
||||
document.getElementById("unlockbtn").disabled=false;
|
||||
return false;
|
||||
};
|
||||
|
||||
function unlock(btn)
|
||||
{
|
||||
document.getElementById("popup").style.display = "block";
|
||||
document.getElementById("lockbtn").disabled=true;
|
||||
document.getElementById("unlockbtn").disabled=true;
|
||||
return false;
|
||||
}
|
||||
|
||||
//]]></script>
|
||||
|
||||
<form method="post" action="<%=REQUEST_URI%>">
|
||||
<div class="cbi-map" id="cbi-modem">
|
||||
<h2><a id="content" name="content"><%:Menu Selection%></a></h2>
|
||||
<div class="cbi-map-descr"> </div>
|
||||
<head>
|
||||
<style>
|
||||
#popup {
|
||||
width:560px;
|
||||
height:190px;
|
||||
padding:20px;
|
||||
background-color:gainsboro;
|
||||
border-style : solid;
|
||||
position:fixed;
|
||||
top : 40%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
left: 0;
|
||||
right: 0;
|
||||
text-align: center;
|
||||
display:none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<fieldset class="cbi-section" id="cbi-mod">
|
||||
|
||||
<table style="visibility:hidden" width="700" border="0" id="atpass">
|
||||
<tr>
|
||||
<td width="10%"><div id="password" align="right"></div></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<div id="popup">
|
||||
<table width="500" border="0">
|
||||
<tr>
|
||||
<td width="50px"><div><%:Enter Password to Change Menu Type%></div></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="200px"><input id="pass" type="password"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><input type="image" src="<%=showicon(0)%>" style="width:48px;height:48px;" onclick="return done()" /></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<table width="465" border="0" id="idf">
|
||||
<tr>
|
||||
<td width="15%"></td>
|
||||
<td width="20%"><div align="center" style="font-size:1.5em" id="netidt"><strong><%:Current Menu is Limited.%></strong></div></td>
|
||||
<td width="5%"></td>
|
||||
<td width="60%"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td><div align="center" ><strong><%:You must enter a password to change to the full Menu.%></strong></div></td>
|
||||
<td><input type="image" align="center" id="lockbtn" name="lockbtn" src="<%=showicon(1)%>" style="width:48px;height:48px;" onclick="return unlock(this)" /></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<table width="465" border="0" id="idn">
|
||||
<tr>
|
||||
<td width="15%"></td>
|
||||
<td width="20%"><div align="center" style="font-size:1.5em" id="netidt"><strong><%:Current Menu is Full.%></strong></div></td>
|
||||
<td width="5%"></td>
|
||||
<td width="60%"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td><div align="center"><strong><%:You must enter a password to change to the limited Menu.%></strong></div></td>
|
||||
<td><input type="image" align="center" id="unlockbtn" name="unlockbtn" src="<%=showicon(1)%>" style="width:48px;height:48px;" onclick="return unlock(this)" /></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</fieldset>
|
||||
|
||||
</div>
|
||||
</form>
|
||||
<%+footer%>
|
@ -1,11 +1,7 @@
|
||||
module("luci.controller.speedtest", package.seeall)
|
||||
|
||||
I18N = require "luci.i18n"
|
||||
translate = I18N.translate
|
||||
|
||||
function index()
|
||||
local page
|
||||
entry({"admin", "speed"}, firstchild(), translate("Speed Test"), 95).dependent=false
|
||||
page = entry({"admin", "speed", "speedtest"}, template("speedtest/speedtest"), translate("OpenSpeedTest"), 71)
|
||||
entry({"admin", "speed"}, firstchild(), "Speed Test", 81).dependent=false
|
||||
page = entry({"admin", "speed", "speedtest"}, template("speedtest/speedtest"), "OpenSpeedTest", 71)
|
||||
page.dependent = true
|
||||
end
|
||||
|
@ -17,8 +17,8 @@
|
||||
|
||||
<form method="post" action="<%=REQUEST_URI%>">
|
||||
<div class="cbi-map" id="cbi-misc">
|
||||
<h2><a id="content" name="content"><%:Browser Speed Test%></a></h2>
|
||||
<div class="cbi-map-descr"><%:A Speed Test using OpenSpeedTest that runs in the browser%></div>
|
||||
<h2><a id="content" name="content">Browser Speed Test</a></h2>
|
||||
<div class="cbi-map-descr">A Speed Test using OpenSpeedTest that runs in the browser</div>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<link rel="stylesheet" href="/luci-static/speed/css/iconmoon_splash.css">
|
||||
|
@ -1,16 +1,8 @@
|
||||
module("luci.controller.texting", package.seeall)
|
||||
function index()
|
||||
local lock = luci.model.uci.cursor():get("custom", "menu", "full")
|
||||
local multilock = luci.model.uci.cursor():get("custom", "multiuser", "multi") or "0"
|
||||
local rootlock = luci.model.uci.cursor():get("custom", "multiuser", "root") or "0"
|
||||
if (multilock == "0") or (multilock == "1" and rootlock == "1") then
|
||||
if lock == "1" then
|
||||
if (multilock == "1" and rootlock == "1") then
|
||||
entry({"admin", "adminmenu", "texting"}, cbi("fullmenu/texting"), "Random Texting", 9)
|
||||
else
|
||||
entry({"admin", "adminmenu", "texting"}, cbi("fullmenu/texting"), "---Random Texting", 9)
|
||||
end
|
||||
end
|
||||
if lock == "1" then
|
||||
entry({"admin", "adminmenu", "texting"}, cbi("fullmenu/texting"), "---Random Texting", 8)
|
||||
end
|
||||
|
||||
entry({"admin", "services", "chksms"}, call("action_chksms"))
|
||||
|
@ -1,36 +0,0 @@
|
||||
#Owned by DairyMan@Whirlpool
|
||||
#
|
||||
#Copyright GNU act.
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=ext-throttle
|
||||
PKG_VERSION:=1.000
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/ext-throttle
|
||||
SECTION:=utils
|
||||
CATEGORY:=ROOter
|
||||
SUBMENU:=Optional Applications
|
||||
DEPENDS:=+tc +kmod-sched-core +kmod-ifb +iptables \
|
||||
+iptables-mod-ipopt +iptables-mod-conntrack-extra \
|
||||
+kmod-sched-cake
|
||||
TITLE:=support for Throttle
|
||||
PKGARCH:=all
|
||||
endef
|
||||
|
||||
define Package/ext-throttle/description
|
||||
Helper scripts to enable Throttle
|
||||
endef
|
||||
|
||||
|
||||
define Build/Compile
|
||||
endef
|
||||
|
||||
define Package/ext-throttle/install
|
||||
$(CP) ./files/* $(1)/
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,ext-throttle))
|
@ -1,34 +0,0 @@
|
||||
|
||||
config queue 'wan'
|
||||
option enabled '0'
|
||||
option download '85000'
|
||||
option upload '10000'
|
||||
option qdisc 'cake'
|
||||
option script 'piece_of_cake.qos'
|
||||
option linklayer 'none'
|
||||
option interface '0'
|
||||
option debug_logging '0'
|
||||
option verbosity '5'
|
||||
|
||||
config queue 'wan1'
|
||||
option enabled '0'
|
||||
option download '85000'
|
||||
option upload '10000'
|
||||
option qdisc 'cake'
|
||||
option script 'piece_of_cake.qos'
|
||||
option linklayer 'none'
|
||||
option debug_logging '0'
|
||||
option verbosity '5'
|
||||
option interface '0'
|
||||
|
||||
config queue 'wan2'
|
||||
option enabled '0'
|
||||
option download '85000'
|
||||
option upload '10000'
|
||||
option qdisc 'cake'
|
||||
option script 'piece_of_cake.qos'
|
||||
option linklayer 'none'
|
||||
option interface '0'
|
||||
option debug_logging '0'
|
||||
option verbosity '5'
|
||||
|
@ -1,27 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ "$ACTION" = ifdown ]; then
|
||||
if [ $INTERFACE = "wan" -o $INTERFACE = "wan1" -o $INTERFACE = "wan2" ]; then
|
||||
uci set sqm.$INTERFACE.interface='0'
|
||||
uci commit sqm
|
||||
logger -t THROTTLE-DEBUG "$ACTION $INTERFACE"
|
||||
fi
|
||||
fi
|
||||
|
||||
[ -n "$DEVICE" ] || exit 0
|
||||
|
||||
restart_sqm() {
|
||||
/usr/lib/sqm/run.sh stop ${DEVICE}
|
||||
/usr/lib/sqm/run.sh start ${DEVICE}
|
||||
}
|
||||
|
||||
if [ "$ACTION" = ifup ]; then
|
||||
if [ $INTERFACE = "wan" -o $INTERFACE = "wan1" -o $INTERFACE = "wan2" ]; then
|
||||
uci set sqm.$INTERFACE.interface=$DEVICE
|
||||
uci commit sqm
|
||||
/etc/init.d/sqm enabled
|
||||
restart_sqm
|
||||
logger -t THROTTLE-DEBUG "$DEVICE $ACTION $INTERFACE"
|
||||
fi
|
||||
fi
|
||||
|
@ -1,31 +0,0 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
|
||||
START=50
|
||||
USE_PROCD=1
|
||||
|
||||
service_triggers()
|
||||
{
|
||||
procd_add_reload_trigger "sqm"
|
||||
}
|
||||
|
||||
reload_service()
|
||||
{
|
||||
stop "$@"
|
||||
start "$@"
|
||||
}
|
||||
|
||||
start_service()
|
||||
{
|
||||
/usr/lib/sqm/run.sh start "$@"
|
||||
}
|
||||
|
||||
stop_service()
|
||||
{
|
||||
/usr/lib/sqm/run.sh stop "$@"
|
||||
}
|
||||
|
||||
boot()
|
||||
{
|
||||
export SQM_VERBOSITY_MIN=5 # Silence errors
|
||||
start "$@"
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
SQM_LIB_DIR=/usr/lib/sqm
|
||||
SQM_STATE_DIR=/var/run/sqm
|
||||
SQM_QDISC_STATE_DIR=${SQM_STATE_DIR}/available_qdiscs
|
||||
SQM_CHECK_QDISCS="fq_codel codel pie sfq cake"
|
||||
SQM_SYSLOG=1
|
@ -1,12 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
uci -q batch <<-EOF >/dev/null
|
||||
delete ucitrack.@sqm[-1]
|
||||
add ucitrack sqm
|
||||
set ucitrack.@sqm[-1].init=sqm
|
||||
del_list ucitrack.@firewall[0].affects=sqm
|
||||
add_list ucitrack.@firewall[0].affects=sqm
|
||||
commit ucitrack
|
||||
EOF
|
||||
|
||||
exit 0
|
@ -1,109 +0,0 @@
|
||||
# You need to jiggle these parameters. Note limits are tuned towards a <10Mbit uplink <60Mbup down
|
||||
|
||||
[ -z "$SCRIPT" ] && SCRIPT=
|
||||
[ -z "$UPLINK" ] && UPLINK=2302
|
||||
[ -z "$DOWNLINK" ] && DOWNLINK=14698
|
||||
[ -z "$IFACE" ] && IFACE=eth0
|
||||
[ -z "$QDISC" ] && QDISC=fq_codel
|
||||
[ -z "$LLAM" ] && LLAM="default"
|
||||
[ -z "$LINKLAYER" ] && LINKLAYER="none"
|
||||
[ -z "$OVERHEAD" ] && OVERHEAD=0
|
||||
[ -z "$STAB_MTU" ] && STAB_MTU=2047
|
||||
[ -z "$STAB_MPU" ] && STAB_MPU=0
|
||||
[ -z "$STAB_TSIZE" ] && STAB_TSIZE=512
|
||||
[ -z "$AUTOFLOW" ] && AUTOFLOW=0
|
||||
[ -z "$LIMIT" ] && LIMIT=1001 # sane global default for *LIMIT for fq_codel on a small memory device
|
||||
[ -z "$ILIMIT" ] && ILIMIT=
|
||||
[ -z "$ELIMIT" ] && ELIMIT=
|
||||
[ -z "$ITARGET" ] && ITARGET=
|
||||
[ -z "$ETARGET" ] && ETARGET=
|
||||
[ -z "$IECN" ] && IECN="ECN"
|
||||
[ -z "$EECN" ] && EECN="ECN"
|
||||
# These two used to be called something else; preserve backwards compatibility
|
||||
[ -z "$ZERO_DSCP_INGRESS" ] && ZERO_DSCP_INGRESS="${ZERO_DSCP:-${SQUASH_DSCP:-1}}"
|
||||
[ -z "$IGNORE_DSCP_INGRESS" ] && IGNORE_DSCP_INGRESS="${IGNORE_DSCP:-${SQUASH_INGRESS:-1}}"
|
||||
|
||||
[ -z "$IQDISC_OPTS" ] && IQDISC_OPTS=""
|
||||
[ -z "$EQDISC_OPTS" ] && EQDISC_OPTS=""
|
||||
|
||||
# handling of specific important binaries
|
||||
[ -z "$TC" ] && TC=tc_wrapper
|
||||
[ -z "$TC_BINARY" ] && TC_BINARY=$(command -v tc)
|
||||
[ -z "$IP" ] && IP=ip_wrapper
|
||||
[ -z "$IP_BINARY" ] && IP_BINARY=$(command -v ip)
|
||||
[ -z "$IPTABLES" ] && IPTABLES=iptables_wrapper
|
||||
[ -z "$IPTABLES_BINARY" ] && IPTABLES_BINARY=$(command -v iptables)
|
||||
[ -z "$IP6TABLES" ] && IP6TABLES=ip6tables_wrapper
|
||||
[ -z "$IP6TABLES_BINARY" ] && IP6TABLES_BINARY=$(command -v ip6tables)
|
||||
[ -z "$IPTABLES_ARGS" ] && IPTABLES_ARGS="-w 1"
|
||||
|
||||
|
||||
# Try modprobe first, fall back to insmod
|
||||
if [ -z "$INSMOD" ]; then
|
||||
INSMOD=$(command -v modprobe)
|
||||
if [ -n "$INSMOD" ]; then
|
||||
INSMOD="${INSMOD} -q"
|
||||
else
|
||||
INSMOD=$(command -v insmod)
|
||||
fi
|
||||
fi
|
||||
|
||||
[ -z "$TARGET" ] && TARGET="5ms"
|
||||
[ -z "$IPT_MASK" ] && IPT_MASK="0xff" # to disable: set mask to 0xffffffff
|
||||
#sm: we need the functions above before trying to set the ingress IFB device
|
||||
#sm: *_CAKE_OPTS should contain the diffserv keyword for cake
|
||||
[ -z "$INGRESS_CAKE_OPTS" ] && INGRESS_CAKE_OPTS="diffserv3"
|
||||
[ -z "$EGRESS_CAKE_OPTS" ] && EGRESS_CAKE_OPTS="diffserv3"
|
||||
|
||||
[ -z "$CUR_DIRECTION" ] && CUR_DIRECTION="NONE"
|
||||
|
||||
|
||||
# HTB without a sufficiently large burst/cburst value is a bit CPU hungry
|
||||
# so allow to specify the permitted burst in the time domain (microseconds)
|
||||
# so the user has a feeling for the associated worst case latency cost
|
||||
# set to zero to use htb default butst of one MTU
|
||||
[ -z "$SHAPER_BURST_DUR_US" ] && SHAPER_BURST_DUR_US=1000
|
||||
[ -z "$ISHAPER_BURST_DUR_US" ] && ISHAPER_BURST_DUR_US=$SHAPER_BURST_DUR_US
|
||||
[ -z "$ESHAPER_BURST_DUR_US" ] && ESHAPER_BURST_DUR_US=$SHAPER_BURST_DUR_US
|
||||
|
||||
# use the same logic for the calculation of htb's quantum
|
||||
# quantum controlls how many bytes htb tries to deque from the current tier
|
||||
# before switching tiers.
|
||||
[ -z "$SHAPER_QUANTUM_DUR_US" ] && SHAPER_QUANTUM_DUR_US=$SHAPER_BURST_DUR_US
|
||||
[ -z "$ISHAPER_QUANTUM_DUR_US" ] && ISHAPER_QUANTUM_DUR_US=$SHAPER_QUANTUM_DUR_US
|
||||
[ -z "$ESHAPER_QUANTUM_DUR_US" ] && ESHAPER_QUANTUM_DUR_US=$SHAPER_QUANTUM_DUR_US
|
||||
|
||||
|
||||
# Logging verbosity
|
||||
VERBOSITY_SILENT=0
|
||||
VERBOSITY_ERROR=1
|
||||
VERBOSITY_WARNING=2
|
||||
VERBOSITY_INFO=5
|
||||
VERBOSITY_DEBUG=8
|
||||
VERBOSITY_TRACE=10
|
||||
[ -z "$SQM_VERBOSITY_MAX" ] && SQM_VERBOSITY_MAX=$VERBOSITY_INFO
|
||||
# For silencing only errors
|
||||
[ -z "$SQM_VERBOSITY_MIN" ] && SQM_VERBOSITY_MIN=$VERBOSITY_SILENT
|
||||
|
||||
[ -z "$SQM_DEBUG" ] && SQM_DEBUG=0
|
||||
if [ "$SQM_DEBUG" -eq "1" ]
|
||||
then
|
||||
SQM_DEBUG_STEM="${SQM_STATE_DIR}/${IFACE}"
|
||||
SQM_START_LOG="${SQM_DEBUG_STEM}.start-sqm.log"
|
||||
SQM_STOP_LOG="${SQM_DEBUG_STEM}.stop-sqm.log"
|
||||
[ -z "SQM_DEBUG_LOG" ] && SQM_DEBUG_LOG="${SQM_DEBUG_STEM}.debug.log"
|
||||
OUTPUT_TARGET="${SQM_DEBUG_LOG}"
|
||||
else
|
||||
OUTPUT_TARGET="/dev/null"
|
||||
fi
|
||||
|
||||
|
||||
# Can be overridden by callers that want to silence error output for a
|
||||
# particular command
|
||||
SILENT=0
|
||||
|
||||
# Transaction log for unwinding ipt rules
|
||||
IPT_TRANS_LOG="${SQM_STATE_DIR}/${IFACE}.iptables.log"
|
||||
|
||||
# These are the modules that do_modules() will attempt to load
|
||||
ALL_MODULES="act_ipt sch_$QDISC sch_ingress act_mirred cls_fw cls_flow cls_u32 sch_htb sch_hfsc"
|
@ -1,923 +0,0 @@
|
||||
################################################################################
|
||||
# (sqm) functions.sh
|
||||
#
|
||||
# These are all helper functions for various parts of SQM scripts. If you want
|
||||
# to play around with your own shaper-qdisc-filter configuration look here for
|
||||
# ready made tools, or examples start of on your own.
|
||||
#
|
||||
# Please note the SQM logger function is broken down into levels of logging.
|
||||
# Use only levels appropriate to touch points in your script and realize the
|
||||
# potential to overflow SYSLOG.
|
||||
#
|
||||
################################################################################
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# Copyright (C) 2012-2019
|
||||
# Michael D. Taht, Toke Høiland-Jørgensen, Sebastian Moeller
|
||||
# Eric Luehrsen
|
||||
#
|
||||
################################################################################
|
||||
|
||||
# Logging verbosity
|
||||
VERBOSITY_SILENT=0
|
||||
VERBOSITY_ERROR=1
|
||||
VERBOSITY_WARNING=2
|
||||
VERBOSITY_INFO=5
|
||||
VERBOSITY_DEBUG=8
|
||||
VERBOSITY_TRACE=10
|
||||
|
||||
sqm_logger() {
|
||||
local level_min
|
||||
local level_max
|
||||
local debug
|
||||
|
||||
case $1 in
|
||||
''|*[!0-9]*) LEVEL=$VERBOSITY_INFO ;; # empty or non-numbers
|
||||
*) LEVEL=$1; shift ;;
|
||||
esac
|
||||
|
||||
level_min=${SQM_VERBOSITY_MIN:-$VERBOSITY_SILENT}
|
||||
level_max=${SQM_VERBOSITY_MAX:-$VERBOSITY_INFO}
|
||||
debug=${SQM_DEBUG:-0}
|
||||
|
||||
if [ "$level_max" -ge "$LEVEL" ] && [ "$level_min" -le "$LEVEL" ] ; then
|
||||
if [ "$SQM_SYSLOG" -eq "1" ]; then
|
||||
logger -t SQM -s "$*"
|
||||
else
|
||||
echo "$@" >&2
|
||||
fi
|
||||
fi
|
||||
|
||||
# this writes into SQM_START_LOG or SQM_STOP_LOG, log files are trucated in
|
||||
# start-sqm/stop-sqm respectively and should only take little space
|
||||
if [ "$debug" -eq "1" ]; then
|
||||
echo "$@" >> "${SQM_DEBUG_LOG}"
|
||||
fi
|
||||
}
|
||||
|
||||
sqm_error() { sqm_logger $VERBOSITY_ERROR ERROR: "$@"; }
|
||||
sqm_warn() { sqm_logger $VERBOSITY_WARNING WARNING: "$@"; }
|
||||
sqm_log() { sqm_logger $VERBOSITY_INFO "$@"; }
|
||||
sqm_debug() { sqm_logger $VERBOSITY_DEBUG "$@"; }
|
||||
sqm_trace() { sqm_logger $VERBOSITY_TRACE "$@"; }
|
||||
|
||||
|
||||
# Inspired from https://stackoverflow.com/questions/85880/determine-if-a-function-exists-in-bash
|
||||
#fn_exists() { LC_ALL=C type $1 | grep -q 'is a function'; }
|
||||
fn_exists() {
|
||||
local FN_CANDIDATE
|
||||
local CUR_LC_ALL
|
||||
local TYPE_OUTPUT
|
||||
local RET
|
||||
FN_CANDIDATE=$1
|
||||
# check that a candidate nme was given
|
||||
if [ -z "${FN_CANDIDATE}" ]; then
|
||||
sqm_error "fn_exists: no function name specified as first argument."
|
||||
return 1
|
||||
fi
|
||||
sqm_debug "fn_exists: function candidate name: ${FN_CANDIDATE}"
|
||||
|
||||
# extract the textual type description
|
||||
TYPE_OUTPUT=$( LC_ALL=C type $1 2>&1 )
|
||||
sqm_debug "fn_exists: TYPE_OUTPUT: $TYPE_OUTPUT"
|
||||
|
||||
# OpenWrt (2019) returns 'is a function'
|
||||
# Debian Buster/raspbian returns 'is a shell function'
|
||||
# let's just hope no Linux system reurn 'is a shell builtin function'
|
||||
echo ${TYPE_OUTPUT} | grep -q 'is .*function'
|
||||
RET=$?
|
||||
|
||||
sqm_debug "fn_exists: return value: ${RET}"
|
||||
return ${RET}
|
||||
}
|
||||
|
||||
|
||||
# Transaction logging for ipt rules to allow for gracefull final teardown
|
||||
ipt_log_restart() {
|
||||
[ -f "$IPT_TRANS_LOG" ] && rm -f "$IPT_TRANS_LOG"
|
||||
}
|
||||
|
||||
|
||||
# Function to negate iptables commands. Turns addition and insertion into
|
||||
# deletion, and creation of new chains into deletion
|
||||
# Its output has quotes around all parameters so we can preserve arguments
|
||||
# containing whitespace across log file write & re-read
|
||||
ipt_negate()
|
||||
{
|
||||
for var in "$@"; do
|
||||
case "$var" in
|
||||
"-A"|"-I") echo -n '"-D" ' ;;
|
||||
"-N") echo -n '"-X" ' ;;
|
||||
*) echo -n "\"$var\" " ;;
|
||||
esac
|
||||
done
|
||||
echo ""
|
||||
}
|
||||
|
||||
ipt_log()
|
||||
{
|
||||
echo "$@" >> $IPT_TRANS_LOG
|
||||
}
|
||||
|
||||
# Split a string containing an iptables command line parameter invocation, then
|
||||
# run it through ipt(). This is used to turn lines read from the log file, or
|
||||
# output from ipt_negate() back into proper parameters contained in $@
|
||||
ipt_run_split()
|
||||
{
|
||||
eval "set -- $1"
|
||||
ipt "$@"
|
||||
}
|
||||
|
||||
# Read the transaction log in reverse and execute using ipt to undo changes.
|
||||
# Since we logged only ipt '-D' commands, ipt won't add them again to the
|
||||
# transaction log, but will include them in the syslog/debug log.
|
||||
ipt_log_rewind() {
|
||||
[ -f "$IPT_TRANS_LOG" ] || return 0
|
||||
sed -n '1!G;h;$p' "$IPT_TRANS_LOG" |
|
||||
while read line; do
|
||||
[ -n "$line" ] || continue
|
||||
ipt_run_split "$line"
|
||||
done
|
||||
}
|
||||
|
||||
ipt() {
|
||||
local neg
|
||||
|
||||
for var in "$@"; do
|
||||
case "$var" in
|
||||
"-A"|"-I"|"-N")
|
||||
# If the rule is an addition rule, we first run its negation,
|
||||
# then log that negation to be used by ipt_log_rewind() on
|
||||
# shutdown
|
||||
neg="$(ipt_negate "$@")"
|
||||
ipt_run_split "$neg"
|
||||
ipt_log "$neg"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
SILENT=1 ${IPTABLES} $IPTABLES_ARGS "$@"
|
||||
SILENT=1 ${IP6TABLES} $IPTABLES_ARGS "$@"
|
||||
}
|
||||
|
||||
|
||||
# wrapper to call iptables to allow debug logging
|
||||
iptables_wrapper(){
|
||||
cmd_wrapper iptables ${IPTABLES_BINARY} "$@"
|
||||
}
|
||||
|
||||
# wrapper to call ip6tables to allow debug logging
|
||||
ip6tables_wrapper(){
|
||||
cmd_wrapper ip6tables ${IP6TABLES_BINARY} "$@"
|
||||
}
|
||||
|
||||
# wrapper to call tc to allow debug logging
|
||||
tc_wrapper(){
|
||||
cmd_wrapper tc ${TC_BINARY} "$@"
|
||||
}
|
||||
|
||||
# wrapper to call ip to allow debug logging
|
||||
ip_wrapper(){
|
||||
cmd_wrapper ip ${IP_BINARY} "$@"
|
||||
}
|
||||
|
||||
# the actual command execution wrapper
|
||||
cmd_wrapper(){
|
||||
# $1: the symbolic name of the command for informative output
|
||||
# $2: the name of the binary to call (potentially including the full path)
|
||||
# $3-$end: the actual arguments for $2
|
||||
local CALLERID
|
||||
local CMD_BINARY
|
||||
local LAST_ERROR
|
||||
local RET
|
||||
local ERRLOG
|
||||
|
||||
CALLERID=$1 ; shift 1 # extract and remove the id string
|
||||
CMD_BINARY=$1 ; shift 1 # extract and remove the binary
|
||||
|
||||
# Handle silencing of errors from callers
|
||||
ERRLOG="sqm_error"
|
||||
if [ "$SILENT" -eq "1" ]; then
|
||||
ERRLOG="sqm_debug"
|
||||
sqm_debug "cmd_wrapper: ${CALLERID}: invocation silenced by request, FAILURE either expected or acceptable."
|
||||
# The busybox shell doesn't understand the concept of an inline variable
|
||||
# only applying to a single command, so we need to reset SILENT
|
||||
# afterwards. Ugly, but it works...
|
||||
SILENT=0
|
||||
fi
|
||||
|
||||
sqm_trace "cmd_wrapper: COMMAND: ${CMD_BINARY} $@"
|
||||
LAST_ERROR=$( ${CMD_BINARY} "$@" 2>&1 )
|
||||
RET=$?
|
||||
|
||||
if [ "$RET" -eq "0" ] ; then
|
||||
sqm_debug "cmd_wrapper: ${CALLERID}: SUCCESS: ${CMD_BINARY} $@"
|
||||
else
|
||||
# this went south, try to capture & report more detail
|
||||
$ERRLOG "cmd_wrapper: ${CALLERID}: FAILURE (${RET}): ${CMD_BINARY} $@"
|
||||
$ERRLOG "cmd_wrapper: ${CALLERID}: LAST ERROR: ${LAST_ERROR}"
|
||||
fi
|
||||
|
||||
return $RET
|
||||
}
|
||||
|
||||
|
||||
do_modules() {
|
||||
for m in $ALL_MODULES; do
|
||||
[ -d /sys/module/${m} ] || ${INSMOD} $m 2>>${OUTPUT_TARGET}
|
||||
done
|
||||
}
|
||||
|
||||
# Write a state file to the filename given as $1. This version will extract all
|
||||
# variable names defined in defaults.sh and since defaults.sh should contain all
|
||||
# used variables this should be the complete set.
|
||||
write_state_file() {
|
||||
local filename
|
||||
local awkscript
|
||||
awkscript='match($0, /[A-Z0-9_]+=/) {print substr($0, RSTART, RLENGTH-1)}'
|
||||
filename=$1
|
||||
shift
|
||||
awk "$awkscript" ${SQM_LIB_DIR}/defaults.sh | sort -u | while read var; do
|
||||
val=$(eval echo '$'$var)
|
||||
echo "$var=\"$val\""
|
||||
done > $filename
|
||||
}
|
||||
|
||||
check_state_dir() {
|
||||
local PERM
|
||||
local OWNER
|
||||
|
||||
if [ -z "${SQM_STATE_DIR}" ]; then
|
||||
SQM_DEBUG=0 sqm_error '$SQM_STATE_DIR is unset - check your config!'
|
||||
exit 1
|
||||
fi
|
||||
[ -d "${SQM_STATE_DIR}" ] || ( umask 077; mkdir -p "$SQM_STATE_DIR" ) || exit 1
|
||||
|
||||
if [ ! -w "${SQM_STATE_DIR}" ] || [ ! -x "${SQM_STATE_DIR}" ]; then
|
||||
SQM_DEBUG=0 sqm_error "Cannot write to state dir '$SQM_STATE_DIR'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# OpenWrt doesn't have stat; for now just skip the remaining tests if it's
|
||||
# not available
|
||||
command -v stat >/dev/null 2>&1 || return 0
|
||||
|
||||
PERM="0$(stat -L -c '%a' "${SQM_STATE_DIR}")"
|
||||
if [ "$((PERM & 0002))" -ne 0 ]; then
|
||||
SQM_DEBUG=0 sqm_error "State dir '$SQM_STATE_DIR' is world writable; this is unsafe, please fix"
|
||||
exit 1
|
||||
fi
|
||||
OWNER="$(stat -L -c '%u' "${SQM_STATE_DIR}")"
|
||||
if [ "$OWNER" -ne "$(id -u)" ]; then
|
||||
SQM_DEBUG=0 sqm_error "State dir '$SQM_STATE_DIR' is owned by a different user; this is unsafe, please fix"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
# find the ifb device associated with a specific interface, return nothing of no
|
||||
# ifb is associated with IF
|
||||
get_ifb_associated_with_if() {
|
||||
local CUR_IF
|
||||
local CUR_IFB
|
||||
local TMP
|
||||
CUR_IF=$1
|
||||
# Stray ' in the comment is a fix for broken editor syntax highlighting
|
||||
CUR_IFB=$( $TC_BINARY -p filter show parent ffff: dev ${CUR_IF} | grep -o -E ifb'[^)\ ]+' ) # '
|
||||
sqm_debug "ifb associated with interface ${CUR_IF}: ${CUR_IFB}"
|
||||
|
||||
# we could not detect an associated IFB for CUR_IF
|
||||
if [ -z "${CUR_IFB}" ]; then
|
||||
TMP=$( $TC_BINARY -p filter show parent ffff: dev ${CUR_IF} )
|
||||
if [ ! -z "${TMP}" ]; then
|
||||
# oops, there is output but we failed to properly parse it? Ask for a user report
|
||||
sqm_error "#---- CUT HERE ----#"
|
||||
sqm_error "get_ifb_associated_with_if failed to extrect the ifb name from:"
|
||||
sqm_error $( $TC_BINARY -p filter show parent ffff: dev ${CUR_IF} )
|
||||
sqm_error "Please report this as an issue at https://github.com/tohojo/sqm-scripts"
|
||||
sqm_error "Please copy and paste everything below the cut-here line into your issue report, thanks."
|
||||
else
|
||||
sqm_debug "Currently no ifb is associated with ${CUR_IF}, this is normal during starting of the sqm system."
|
||||
fi
|
||||
fi
|
||||
echo ${CUR_IFB}
|
||||
}
|
||||
|
||||
ifb_name() {
|
||||
local CUR_IF
|
||||
local MAX_IF_NAME_LENGTH
|
||||
local IFB_PREFIX
|
||||
local NEW_IFB
|
||||
CUR_IF=$1
|
||||
MAX_IF_NAME_LENGTH=15
|
||||
IFB_PREFIX="ifb4"
|
||||
NEW_IFB=$( echo -n "${IFB_PREFIX}${CUR_IF}" | head -c $MAX_IF_NAME_LENGTH )
|
||||
|
||||
echo ${NEW_IFB}
|
||||
}
|
||||
|
||||
# if required
|
||||
create_new_ifb_for_if() {
|
||||
local NEW_IFB
|
||||
NEW_IFB=$(ifb_name $1)
|
||||
create_ifb ${NEW_IFB}
|
||||
RET=$?
|
||||
echo $NEW_IFB
|
||||
return $RET
|
||||
}
|
||||
|
||||
|
||||
# TODO: report failures
|
||||
create_ifb() {
|
||||
local CUR_IFB
|
||||
CUR_IFB=${1}
|
||||
$IP link add name ${CUR_IFB} type ifb
|
||||
}
|
||||
|
||||
delete_ifb() {
|
||||
local CUR_IFB
|
||||
CUR_IFB=${1}
|
||||
$IP link set dev ${CUR_IFB} down
|
||||
$IP link delete ${CUR_IFB} type ifb
|
||||
}
|
||||
|
||||
|
||||
# the best match is either the IFB already associated with the current interface
|
||||
# or a new named IFB
|
||||
get_ifb_for_if() {
|
||||
local CUR_IF
|
||||
local CUR_IFB
|
||||
CUR_IF=$1
|
||||
# if an ifb is already associated return that
|
||||
CUR_IFB=$( get_ifb_associated_with_if ${CUR_IF} )
|
||||
[ -z "$CUR_IFB" ] && CUR_IFB=$( create_new_ifb_for_if ${CUR_IF} )
|
||||
[ -z "$CUR_IFB" ] && sqm_warn "Could not find existing IFB for ${CUR_IF}, nor create a new IFB instead..."
|
||||
echo ${CUR_IFB}
|
||||
}
|
||||
|
||||
|
||||
# Verify that a qdisc works, and optionally that it is part of a set of
|
||||
# supported qdiscs. If passed a $2, this function will first check if $1 is in
|
||||
# that (space-separated) list and return an error if it's not.
|
||||
#
|
||||
# note the ingress qdisc is different in that it requires tc qdisc replace dev
|
||||
# tmp_ifb ingress instead of "root ingress"
|
||||
verify_qdisc() {
|
||||
local qdisc
|
||||
local supported
|
||||
local ifb
|
||||
local root_string
|
||||
local args
|
||||
local IFB_MTU
|
||||
local found
|
||||
local randnum
|
||||
qdisc=$1
|
||||
supported="$2"
|
||||
randnum=$(tr -cd 0-9a-f < /dev/urandom 2>/dev/null | head -c 5)
|
||||
ifb=SQM_IFB_$randnum
|
||||
root_string="root" # this works for most qdiscs
|
||||
args=""
|
||||
IFB_MTU=1514
|
||||
|
||||
if [ -n "$supported" ]; then
|
||||
found=0
|
||||
for q in $supported; do
|
||||
[ "$qdisc" = "$q" ] && found=1
|
||||
done
|
||||
[ "$found" -eq "1" ] || return 1
|
||||
fi
|
||||
create_ifb $ifb || return 1
|
||||
|
||||
|
||||
case $qdisc in
|
||||
#ingress is special
|
||||
ingress) root_string="" ;;
|
||||
#cannot instantiate tbf without args
|
||||
tbf)
|
||||
IFB_MTU=$( get_mtu $ifb )
|
||||
IFB_MTU=$(( ${IFB_MTU} + 14 )) # TBF's warning is confused, it says MTU but it checks MTU + 14
|
||||
args="limit 1 burst ${IFB_MTU} rate 1kbps"
|
||||
;;
|
||||
esac
|
||||
|
||||
$TC qdisc replace dev $ifb $root_string $qdisc $args
|
||||
res=$?
|
||||
if [ "$res" = "0" ] ; then
|
||||
sqm_debug "QDISC $qdisc is useable."
|
||||
else
|
||||
sqm_error "QDISC $qdisc is NOT useable."
|
||||
fi
|
||||
delete_ifb $ifb
|
||||
return $res
|
||||
}
|
||||
|
||||
|
||||
get_htb_adsll_string() {
|
||||
ADSLL=""
|
||||
if [ "$LLAM" = "htb_private" -a "$LINKLAYER" != "none" ]; then
|
||||
# HTB defaults to MTU 1600 and an implicit fixed TSIZE of 256, but HTB
|
||||
# as of around 3.10.0 does not actually use a table in the kernel
|
||||
ADSLL="mpu ${STAB_MPU} linklayer ${LINKLAYER} overhead ${OVERHEAD} mtu ${STAB_MTU}"
|
||||
sqm_debug "ADSLL: ${ADSLL}"
|
||||
fi
|
||||
echo ${ADSLL}
|
||||
}
|
||||
|
||||
get_stab_string() {
|
||||
local STABSTRING
|
||||
local TMP_LLAM
|
||||
STABSTRING=""
|
||||
TMP_LLAM=${LLAM}
|
||||
if [ "${LLAM}" = "default" -a "$QDISC" != "cake" ]; then
|
||||
sqm_debug "LLA: default link layer adjustment method for !cake is tc_stab"
|
||||
TMP_LLAM="tc_stab"
|
||||
fi
|
||||
|
||||
if [ "${TMP_LLAM}" = "tc_stab" -a "$LINKLAYER" != "none" ]; then
|
||||
STABSTRING="stab mtu ${STAB_MTU} tsize ${STAB_TSIZE} mpu ${STAB_MPU} overhead ${OVERHEAD} linklayer ${LINKLAYER}"
|
||||
sqm_debug "STAB: ${STABSTRING}"
|
||||
fi
|
||||
echo ${STABSTRING}
|
||||
}
|
||||
|
||||
# cake knows how to handle ATM and per packet overhead, so expose and use this...
|
||||
get_cake_lla_string() {
|
||||
local STABSTRING
|
||||
local TMP_LLAM
|
||||
STABSTRING=""
|
||||
TMP_LLAM=${LLAM}
|
||||
if [ "${LLAM}" = "default" -a "$QDISC" = "cake" ]; then
|
||||
sqm_debug "LLA: default link layer adjustment method for cake is cake"
|
||||
TMP_LLAM="cake"
|
||||
fi
|
||||
|
||||
if [ "${TMP_LLAM}" = "cake" -a "${LINKLAYER}" != "none" ]; then
|
||||
if [ "${LINKLAYER}" = "atm" ]; then
|
||||
STABSTRING="atm"
|
||||
fi
|
||||
|
||||
STABSTRING="${STABSTRING} overhead ${OVERHEAD} mpu ${STAB_MPU}"
|
||||
|
||||
sqm_debug "cake link layer adjustments: ${STABSTRING}"
|
||||
fi
|
||||
echo ${STABSTRING}
|
||||
}
|
||||
|
||||
|
||||
# centralize the implementation for the default sqm_start sqeuence
|
||||
# the individual sqm_start function only need to do the individually
|
||||
# necessary checking.
|
||||
# This expects the calling script to supply both an egress() and ingress() function
|
||||
# and will warn if they are missing
|
||||
sqm_start_default() {
|
||||
#sqm_error "sqm_start_default"
|
||||
[ -n "$IFACE" ] || return 1
|
||||
|
||||
# reset the iptables trace log
|
||||
ipt_log_restart
|
||||
|
||||
if fn_exists sqm_prepare_script ; then
|
||||
sqm_debug "sqm_start_default: starting sqm_prepare_script"
|
||||
sqm_prepare_script
|
||||
else
|
||||
sqm_debug "sqm_start_default: no sqm_prepare_script function found, proceeding without."
|
||||
fi
|
||||
|
||||
do_modules
|
||||
verify_qdisc $QDISC || return 1
|
||||
sqm_debug "sqm_start_default: Starting ${SCRIPT}"
|
||||
|
||||
[ -z "$DEV" ] && DEV=$( get_ifb_for_if ${IFACE} )
|
||||
|
||||
if [ "${UPLINK}" -ne 0 ];
|
||||
then
|
||||
CUR_DIRECTION="egress"
|
||||
fn_exists egress && egress || sqm_warn "sqm_start_default: ${SCRIPT} lacks an egress() function"
|
||||
#egress
|
||||
sqm_debug "sqm_start_default: egress shaping activated"
|
||||
else
|
||||
sqm_debug "sqm_start_default: egress shaping deactivated"
|
||||
SILENT=1 $TC qdisc del dev ${IFACE} root
|
||||
fi
|
||||
if [ "${DOWNLINK}" -ne 0 ];
|
||||
then
|
||||
CUR_DIRECTION="ingress"
|
||||
verify_qdisc ingress "ingress" || return 1
|
||||
fn_exists ingress && ingress || sqm_warn "sqm_start_default: ${SCRIPT} lacks an ingress() function"
|
||||
#ingress
|
||||
sqm_debug "sqm_start_default: ingress shaping activated"
|
||||
else
|
||||
sqm_debug "sqm_start_default: ingress shaping deactivated"
|
||||
SILENT=1 $TC qdisc del dev ${DEV} root
|
||||
SILENT=1 $TC qdisc del dev ${IFACE} ingress
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
|
||||
sqm_stop() {
|
||||
if [ "${DOWNLINK}" -ne 0 ]; then
|
||||
$TC qdisc del dev $IFACE ingress
|
||||
$TC qdisc del dev $IFACE root
|
||||
[ -n "$CUR_IFB" ] && $TC qdisc del dev $CUR_IFB root
|
||||
[ -n "$CUR_IFB" ] && sqm_debug "${0}: ${CUR_IFB} shaper deleted"
|
||||
fi
|
||||
|
||||
# undo accumulated ipt commands during shutdown
|
||||
ipt_log_rewind
|
||||
# reset the iptables trace log
|
||||
ipt_log_restart
|
||||
|
||||
[ -n "$CUR_IFB" ] && $IP link set dev ${CUR_IFB} down
|
||||
[ -n "$CUR_IFB" ] && $IP link delete ${CUR_IFB} type ifb
|
||||
[ -n "$CUR_IFB" ] && sqm_debug "${0}: ${CUR_IFB} interface deleted"
|
||||
}
|
||||
|
||||
# Note this has side effects on the prio variable
|
||||
# and depends on the interface global too
|
||||
fc() {
|
||||
$TC filter add dev $interface protocol ip parent $1 prio $prio u32 match ip tos $2 0xfc classid $3
|
||||
prio=$(($prio + 1))
|
||||
$TC filter add dev $interface protocol ipv6 parent $1 prio $prio u32 match ip6 priority $2 0xfc classid $3
|
||||
prio=$(($prio + 1))
|
||||
}
|
||||
|
||||
|
||||
# allow better control over HTB's quantum variable
|
||||
# this controlls how many bytes htb ties to deque from the current tier before
|
||||
# switching to the next, if this is large mixing between pririty tiers will be
|
||||
# lumpy, but at a lower CPU cost. In first approximation quantum should not be
|
||||
# larger than burst.
|
||||
get_htb_quantum() {
|
||||
local HTB_MTU
|
||||
local BANDWIDTH
|
||||
local DURATION_US
|
||||
local MIN_QUANTUM
|
||||
local QUANTUM
|
||||
HTB_MTU=$( get_mtu $1 )
|
||||
BANDWIDTH=$2
|
||||
DURATION_US=$3
|
||||
|
||||
sqm_debug "get_htb_quantum: 1: ${1}, 2: ${2}, 3: ${3}"
|
||||
|
||||
if [ -z "${DURATION_US}" ] ; then
|
||||
DURATION_US=${SHAPER_QUANTUM_DUR_US} # the duration of the burst in microseconds
|
||||
sqm_warn "get_htb_quantum (by duration): Defaulting to ${DURATION_US} microseconds."
|
||||
fi
|
||||
|
||||
if [ -n "${HTB_MTU}" -a "${DURATION_US}" -gt "0" ] ; then
|
||||
QUANTUM=$( get_burst ${HTB_MTU} ${BANDWIDTH} ${DURATION_US} )
|
||||
fi
|
||||
|
||||
if [ -z "$QUANTUM" ]; then
|
||||
MIN_QUANTUM=$(( ${MTU} + 48 )) # add 48 bytes to MTU for the ovehead
|
||||
MIN_QUANTUM=$(( ${MIN_QUANTUM} + 47 )) # now do ceil(Min_BURST / 48) * 53 in shell integer arithmic
|
||||
MIN_QUANTUM=$(( ${MIN_QUANTUM} / 48 ))
|
||||
MIN_QUANTUM=$(( ${MIN_QUANTUM} * 53 )) # for MTU 1489 to 1536 this will result in MIN_BURST = 1749 Bytes
|
||||
sqm_warn "get_htb_quantum: 0 bytes quantum will not work, defaulting to one ATM/AAL5 expanded MTU packet with overhead: ${MIN_QUANTUM}"
|
||||
echo ${MIN_QUANTUM}
|
||||
else
|
||||
echo ${QUANTUM}
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
# try to define the burst parameter in the duration required to transmit a burst
|
||||
# at the configured bandwidth conceptuallly the matching quantum for this burst
|
||||
# should be BURST/number_of_tiers to give each htb tier a chance to dequeue into
|
||||
# each burst, but that most likely will end up with a somewhat too small quantum
|
||||
# note: to get htb to report the configured burst/cburt one needs to issue the
|
||||
# following command (for ifbpppoe-wan):
|
||||
# tc -d class show dev ifb4pppoe-wan
|
||||
get_burst() {
|
||||
local MTU
|
||||
local BANDWIDTH
|
||||
local SHAPER_BURST_US
|
||||
local MIN_BURST
|
||||
local BURST
|
||||
MTU=$1
|
||||
BANDWIDTH=$2 # note bandwidth is always given in kbps
|
||||
SHAPER_BURST_US=$3
|
||||
|
||||
sqm_debug "get_burst: 1: ${1}, 2: ${2}, 3: ${3}"
|
||||
|
||||
if [ -z "${SHAPER_BURST_US}" ] ; then
|
||||
SHAPER_BURST_US=1000 # the duration of the burst in microseconds
|
||||
sqm_warn "get_burst (by duration): Defaulting to ${SHAPER_BURST_US} microseconds bursts."
|
||||
fi
|
||||
|
||||
# let's assume ATM/AAL5 to be the worst case encapsulation
|
||||
# and 48 Bytes a reasonable worst case per packet overhead
|
||||
MIN_BURST=$(( ${MTU} + 48 )) # add 48 bytes to MTU for the ovehead
|
||||
MIN_BURST=$(( ${MIN_BURST} + 47 )) # now do ceil(Min_BURST / 48) * 53 in shell integer arithmic
|
||||
MIN_BURST=$(( ${MIN_BURST} / 48 ))
|
||||
MIN_BURST=$(( ${MIN_BURST} * 53 )) # for MTU 1489 to 1536 this will result in MIN_BURST = 1749 Bytes
|
||||
|
||||
# htb/tbf expect burst to be specified in bytes, while bandwidth is in kbps
|
||||
BURST=$(( ((${SHAPER_BURST_US} * ${BANDWIDTH}) / 8000) ))
|
||||
|
||||
if [ ${BURST} -lt ${MIN_BURST} ] ; then
|
||||
sqm_log "get_burst (by duration): the calculated burst/quantum size of ${BURST} bytes was below the minimum of ${MIN_BURST} bytes."
|
||||
BURST=${MIN_BURST}
|
||||
fi
|
||||
|
||||
sqm_debug "get_burst (by duration): BURST [Byte]: ${BURST}, BANDWIDTH [Kbps]: ${BANDWIDTH}, DURATION [us]: ${SHAPER_BURST_US}"
|
||||
|
||||
echo ${BURST}
|
||||
}
|
||||
|
||||
|
||||
# Create optional burst parameters to leap over CPU interupts when the CPU is
|
||||
# severly loaded. We need to be conservative though.
|
||||
get_htb_burst() {
|
||||
local HTB_MTU
|
||||
local BANDWIDTH
|
||||
local DURATION_US
|
||||
local BURST
|
||||
HTB_MTU=$( get_mtu $1 )
|
||||
BANDWIDTH=$2
|
||||
DURATION_US=$3
|
||||
|
||||
sqm_debug "get_htb_burst: 1: ${1}, 2: ${2}, 3: ${3}"
|
||||
|
||||
if [ -z "${DURATION_US}" ] ; then
|
||||
DURATION_US=${SHAPER_BURST_DUR_US} # the duration of the burst in microseconds
|
||||
sqm_warn "get_htb_burst (by duration): Defaulting to ${SHAPER_BURST_DUR_US} microseconds."
|
||||
fi
|
||||
|
||||
if [ -n "${HTB_MTU}" -a "${DURATION_US}" -gt "0" ] ; then
|
||||
BURST=$( get_burst ${HTB_MTU} ${BANDWIDTH} ${DURATION_US} )
|
||||
fi
|
||||
|
||||
if [ -z "$BURST" ]; then
|
||||
sqm_debug "get_htb_burst: Default Burst, HTB will use MTU plus shipping and handling"
|
||||
else
|
||||
echo burst $BURST cburst $BURST
|
||||
fi
|
||||
}
|
||||
|
||||
# For a default PPPoE link this returns 1492 just as expected but I fear we
|
||||
# actually need the wire size of the whole thing not so much the MTU
|
||||
get_mtu() {
|
||||
CUR_MTU=$(cat /sys/class/net/$1/mtu)
|
||||
sqm_debug "IFACE: ${1} MTU: ${CUR_MTU}"
|
||||
echo ${CUR_MTU}
|
||||
}
|
||||
|
||||
# Set the autoflow variable to 1 if you want to limit the number of flows
|
||||
# otherwise the default of 1024 will be used for all Xfq_codel qdiscs.
|
||||
|
||||
get_flows() {
|
||||
case $QDISC in
|
||||
codel|ns2_codel|pie|*fifo|pfifo_fast) ;;
|
||||
fq_codel|*fq_codel|sfq) echo flows $( get_flows_count ${1} ) ;;
|
||||
esac
|
||||
}
|
||||
|
||||
get_flows_count() {
|
||||
if [ "${AUTOFLOW}" -eq "1" ]; then
|
||||
FLOWS=8
|
||||
[ $1 -gt 999 ] && FLOWS=16
|
||||
[ $1 -gt 2999 ] && FLOWS=32
|
||||
[ $1 -gt 7999 ] && FLOWS=48
|
||||
[ $1 -gt 9999 ] && FLOWS=64
|
||||
[ $1 -gt 19999 ] && FLOWS=128
|
||||
[ $1 -gt 39999 ] && FLOWS=256
|
||||
[ $1 -gt 69999 ] && FLOWS=512
|
||||
[ $1 -gt 99999 ] && FLOWS=1024
|
||||
case $QDISC in
|
||||
codel|ns2_codel|pie|*fifo|pfifo_fast) ;;
|
||||
fq_codel|*fq_codel|sfq) echo $FLOWS ;;
|
||||
esac
|
||||
else
|
||||
case $QDISC in
|
||||
codel|ns2_codel|pie|*fifo|pfifo_fast) ;;
|
||||
fq_codel|*fq_codel|sfq) echo 1024 ;;
|
||||
esac
|
||||
fi
|
||||
}
|
||||
|
||||
# set the target parameter, also try to only take well formed inputs
|
||||
# Note, the link bandwidth in the current direction (ingress or egress)
|
||||
# is required to adjust the target for slow links
|
||||
get_target() {
|
||||
local CUR_TARGET
|
||||
local CUR_LINK_KBPS
|
||||
CUR_TARGET=${1}
|
||||
CUR_LINK_KBPS=${2}
|
||||
[ ! -z "$CUR_TARGET" ] && sqm_debug "cur_target: ${CUR_TARGET} cur_bandwidth: ${CUR_LINK_KBPS}"
|
||||
CUR_TARGET_STRING=
|
||||
# either e.g. 100ms or auto
|
||||
CUR_TARGET_VALUE=$( echo ${CUR_TARGET} | grep -o -e \^'[[:digit:]]\+' )
|
||||
CUR_TARGET_UNIT=$( echo ${CUR_TARGET} | grep -o -e '[[:alpha:]]\+'\$ )
|
||||
|
||||
AUTO_TARGET=
|
||||
UNIT_VALID=
|
||||
|
||||
case $QDISC in
|
||||
*codel|*pie)
|
||||
if [ ! -z "${CUR_TARGET_VALUE}" -a ! -z "${CUR_TARGET_UNIT}" ];
|
||||
then
|
||||
case ${CUR_TARGET_UNIT} in
|
||||
# permissible units taken from: tc_util.c get_time()
|
||||
s|sec|secs|ms|msec|msecs|us|usec|usecs)
|
||||
CUR_TARGET_STRING="target ${CUR_TARGET_VALUE}${CUR_TARGET_UNIT}"
|
||||
UNIT_VALID="1"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
# empty field in GUI or undefined GUI variable now defaults to auto
|
||||
if [ -z "${CUR_TARGET_VALUE}" -a -z "${CUR_TARGET_UNIT}" ];
|
||||
then
|
||||
if [ ! -z "${CUR_LINK_KBPS}" ]; then
|
||||
TMP_TARGET_US=$( adapt_target_to_slow_link $CUR_LINK_KBPS )
|
||||
TMP_INTERVAL_STRING=$( adapt_interval_to_slow_link $TMP_TARGET_US )
|
||||
CUR_TARGET_STRING="target ${TMP_TARGET_US}us ${TMP_INTERVAL_STRING}"
|
||||
AUTO_TARGET="1"
|
||||
sqm_debug "get_target defaulting to auto."
|
||||
else
|
||||
sqm_warn "required link bandwidth in kbps not passed to get_target()."
|
||||
fi
|
||||
fi
|
||||
# but still allow explicit use of the keyword auto for backward compatibility
|
||||
case ${CUR_TARGET_UNIT} in
|
||||
auto|Auto|AUTO)
|
||||
if [ ! -z "${CUR_LINK_KBPS}" ]; then
|
||||
TMP_TARGET_US=$( adapt_target_to_slow_link $CUR_LINK_KBPS )
|
||||
TMP_INTERVAL_STRING=$( adapt_interval_to_slow_link $TMP_TARGET_US )
|
||||
CUR_TARGET_STRING="target ${TMP_TARGET_US}us ${TMP_INTERVAL_STRING}"
|
||||
AUTO_TARGET="1"
|
||||
else
|
||||
sqm_warn "required link bandwidth in kbps not passed to get_target()."
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
case ${CUR_TARGET_UNIT} in
|
||||
default|Default|DEFAULT)
|
||||
if [ ! -z "${CUR_LINK_KBPS}" ]; then
|
||||
CUR_TARGET_STRING="" # return nothing so the default target is not over-ridden...
|
||||
AUTO_TARGET="1"
|
||||
sqm_debug "get_target using qdisc default, no explicit target string passed."
|
||||
else
|
||||
sqm_warn "required link bandwidth in kbps not passed to get_target()."
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
if [ ! -z "${CUR_TARGET}" ]; then
|
||||
if [ -z "${CUR_TARGET_VALUE}" -o -z "${UNIT_VALID}" ]; then
|
||||
[ -z "$AUTO_TARGET" ] && sqm_warn "${CUR_TARGET} is not a well formed tc target specifier; e.g.: 5ms (or s, us), or one of the strings auto or default."
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
echo $CUR_TARGET_STRING
|
||||
}
|
||||
|
||||
# for low bandwidth links fq_codels default target of 5ms does not work too well
|
||||
# so increase target for slow links (note below roughly 2500kbps a single packet
|
||||
# will take more than 5 ms to be tansfered over the wire)
|
||||
adapt_target_to_slow_link() {
|
||||
LINK_BW=$1
|
||||
# for ATM the worst case expansion including overhead seems to be 33 clls of
|
||||
# 53 bytes each
|
||||
MAX_DELAY=$(( 1000 * 1000 * 33 * 53 * 8 / 1000 )) # Max delay in us at 1kbps
|
||||
TARGET=$(( ${MAX_DELAY} / ${LINK_BW} )) # note this truncates the decimals
|
||||
|
||||
# do not change anything for fast links
|
||||
[ "$TARGET" -lt 5000 ] && TARGET=5000
|
||||
case ${QDISC} in
|
||||
*codel|pie)
|
||||
echo "${TARGET}"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# codel looks at a whole interval to figure out wether observed latency stayed
|
||||
# below target if target >= interval that will not work well, so increase
|
||||
# interval by the same amonut that target got increased
|
||||
adapt_interval_to_slow_link() {
|
||||
TARGET=$1
|
||||
case ${QDISC} in
|
||||
*codel)
|
||||
# Note this is not following codel theory to well as target should
|
||||
# be 5-10% of interval and the simple addition does not conserve
|
||||
# that relationship
|
||||
INTERVAL=$(( (100 - 5) * 1000 + ${TARGET} ))
|
||||
echo "interval ${INTERVAL}us"
|
||||
;;
|
||||
pie)
|
||||
## not sure if pie needs this, probably not
|
||||
#TUPDATE=$(( (30 - 20) * 1000 + ${TARGET} ))
|
||||
#echo "tupdate ${TUPDATE}us"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
|
||||
# set quantum parameter if available for this qdisc
|
||||
get_quantum() {
|
||||
case $QDISC in
|
||||
*fq_codel|fq_pie|drr) echo quantum $1 ;;
|
||||
*) ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# only show limits to qdiscs that can handle them...
|
||||
# Note that $LIMIT contains the default limit
|
||||
get_limit() {
|
||||
CURLIMIT=$1
|
||||
case $QDISC in
|
||||
*codel|*pie|pfifo_fast|sfq|pfifo) [ -z ${CURLIMIT} ] && CURLIMIT=${LIMIT} # global default limit
|
||||
;;
|
||||
bfifo) [ -z "$CURLIMIT" ] && [ ! -z "$LIMIT" ] && CURLIMIT=$(( ${LIMIT} * $( cat /sys/class/net/${IFACE}/mtu ) )) # bfifo defaults to txquelength * MTU,
|
||||
;;
|
||||
*) sqm_warn "qdisc ${QDISC} does not support a limit"
|
||||
;;
|
||||
esac
|
||||
sqm_debug "get_limit: $1 CURLIMIT: ${CURLIMIT}"
|
||||
|
||||
if [ ! -z "$CURLIMIT" ]; then
|
||||
echo "limit ${CURLIMIT}"
|
||||
fi
|
||||
}
|
||||
|
||||
get_ecn() {
|
||||
CURECN=$1
|
||||
case ${CURECN} in
|
||||
ECN)
|
||||
case $QDISC in
|
||||
*codel|*pie|*red)
|
||||
CURECN=ecn
|
||||
;;
|
||||
*)
|
||||
CURECN=""
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
NOECN)
|
||||
case $QDISC in
|
||||
*codel|*pie|*red)
|
||||
CURECN=noecn
|
||||
;;
|
||||
*)
|
||||
CURECN=""
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
*)
|
||||
sqm_warn "ecn value $1 not handled"
|
||||
;;
|
||||
esac
|
||||
sqm_debug "get_ECN: $1 CURECN: ${CURECN} IECN: ${IECN} EECN: ${EECN}"
|
||||
echo ${CURECN}
|
||||
|
||||
}
|
||||
|
||||
# This could be a complete diffserv implementation
|
||||
|
||||
diffserv() {
|
||||
|
||||
interface=$1
|
||||
prio=1
|
||||
|
||||
# Catchall
|
||||
|
||||
$TC filter add dev $interface parent 1:0 protocol all prio 999 u32 \
|
||||
match ip protocol 0 0x00 flowid 1:12
|
||||
|
||||
# Find the most common matches fast
|
||||
|
||||
fc 1:0 0x00 1:12 # BE
|
||||
fc 1:0 0x20 1:13 # CS1
|
||||
fc 1:0 0x10 1:11 # IMM
|
||||
fc 1:0 0xb8 1:11 # EF
|
||||
fc 1:0 0xc0 1:11 # CS3
|
||||
fc 1:0 0xe0 1:11 # CS6
|
||||
fc 1:0 0x90 1:11 # AF42 (mosh)
|
||||
|
||||
# Arp traffic
|
||||
$TC filter add dev $interface protocol arp parent 1:0 prio $prio handle 500 fw flowid 1:11
|
||||
|
||||
prio=$(($prio + 1))
|
||||
}
|
||||
|
||||
eth_setup() {
|
||||
ethtool -K $IFACE gso off
|
||||
ethtool -K $IFACE tso off
|
||||
ethtool -K $IFACE ufo off
|
||||
ethtool -K $IFACE gro off
|
||||
|
||||
if [ -e /sys/class/net/$IFACE/queues/tx-0/byte_queue_limits ]; then
|
||||
for i in /sys/class/net/$IFACE/queues/tx-*/byte_queue_limits
|
||||
do
|
||||
echo $(( 4 * $( get_mtu ${IFACE} ) )) > $i/limit_max
|
||||
done
|
||||
fi
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
# Cero3 Shaper
|
||||
# A cake shaper and AQM solution that allows several diffserv marking schemes
|
||||
# for ethernet gateways
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# Copyright (C) 2012-5 Michael D. Taht, Toke Høiland-Jørgensen, Sebastian Moeller
|
||||
|
||||
|
||||
#sm: TODO pass in the cake diffserv keyword
|
||||
|
||||
. ${SQM_LIB_DIR}/defaults.sh
|
||||
QDISC=cake
|
||||
|
||||
# Default traffic classication is passed in INGRESS_CAKE_OPTS and EGRESS_CAKE_OPTS, defined in defaults.sh now
|
||||
|
||||
|
||||
egress() {
|
||||
SILENT=1 $TC qdisc del dev $IFACE root
|
||||
$TC qdisc add dev $IFACE root $( get_stab_string ) cake \
|
||||
bandwidth ${UPLINK}kbit $( get_cake_lla_string ) ${EGRESS_CAKE_OPTS} ${EQDISC_OPTS}
|
||||
|
||||
}
|
||||
|
||||
|
||||
ingress() {
|
||||
|
||||
SILENT=1 $TC qdisc del dev $IFACE handle ffff: ingress
|
||||
$TC qdisc add dev $IFACE handle ffff: ingress
|
||||
|
||||
SILENT=1 $TC qdisc del dev $DEV root
|
||||
|
||||
[ "$IGNORE_DSCP_INGRESS" -eq "1" ] && INGRESS_CAKE_OPTS="$INGRESS_CAKE_OPTS besteffort"
|
||||
[ "$ZERO_DSCP_INGRESS" -eq "1" ] && INGRESS_CAKE_OPTS="$INGRESS_CAKE_OPTS wash"
|
||||
|
||||
$TC qdisc add dev $DEV root $( get_stab_string ) cake \
|
||||
bandwidth ${DOWNLINK}kbit $( get_cake_lla_string ) ${INGRESS_CAKE_OPTS} ${IQDISC_OPTS}
|
||||
|
||||
$IP link set dev $DEV up
|
||||
|
||||
# redirect all IP packets arriving in $IFACE to ifb0
|
||||
|
||||
$TC filter add dev $IFACE parent ffff: protocol all prio 10 u32 \
|
||||
match u32 0 0 flowid 1:1 action mirred egress redirect dev $DEV
|
||||
}
|
||||
|
||||
sqm_prepare_script() {
|
||||
do_modules
|
||||
verify_qdisc $QDISC "cake" || return 1
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
This uses the cake qdisc as a replacement for both htb as shaper and fq_codel as leaf qdisc.
|
||||
This exercises cake's diffserv profile(s) as different "layers" of priority.
|
||||
This script requires that cake is selected as qdisc, and forces its usage.
|
||||
See: http://www.bufferbloat.net/projects/codel/wiki/Cake for more information
|
@ -1,52 +0,0 @@
|
||||
# Cero3 Simple Shaper
|
||||
# A 1 tin cake shaper for
|
||||
# ethernet gateways. This is nearly the simplest possible
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# Copyright (C) 2012-5 Michael D. Taht, Toke Høiland-Jørgensen, Sebastian Moeller
|
||||
|
||||
|
||||
. ${SQM_LIB_DIR}/defaults.sh
|
||||
QDISC=cake
|
||||
|
||||
|
||||
# to keep this as simple as possible we ignore the *_CAKE_OPTS from defaults.sh
|
||||
INGRESS_CAKE_OPTS="besteffort"
|
||||
EGRESS_CAKE_OPTS="besteffort"
|
||||
|
||||
|
||||
egress() {
|
||||
sqm_debug "egress"
|
||||
SILENT=1 $TC qdisc del dev $IFACE root
|
||||
$TC qdisc add dev $IFACE root $( get_stab_string ) cake \
|
||||
bandwidth ${UPLINK}kbit $( get_cake_lla_string ) ${EGRESS_CAKE_OPTS} ${EQDISC_OPTS}
|
||||
}
|
||||
|
||||
|
||||
ingress() {
|
||||
sqm_debug "ingress"
|
||||
|
||||
SILENT=1 $TC qdisc del dev $IFACE handle ffff: ingress
|
||||
$TC qdisc add dev $IFACE handle ffff: ingress
|
||||
SILENT=1 $TC qdisc del dev $DEV root
|
||||
|
||||
[ "$ZERO_DSCP_INGRESS" -eq "1" ] && INGRESS_CAKE_OPTS="$INGRESS_CAKE_OPTS wash"
|
||||
|
||||
$TC qdisc add dev $DEV root $( get_stab_string ) cake \
|
||||
bandwidth ${DOWNLINK}kbit $( get_cake_lla_string ) ${INGRESS_CAKE_OPTS} ${IQDISC_OPTS}
|
||||
|
||||
$IP link set dev $DEV up
|
||||
|
||||
# redirect all IP packets arriving in $IFACE to ifb0
|
||||
|
||||
$TC filter add dev $IFACE parent ffff: protocol all prio 10 u32 \
|
||||
match u32 0 0 flowid 1:1 action mirred egress redirect dev $DEV
|
||||
}
|
||||
|
||||
sqm_prepare_script() {
|
||||
do_modules
|
||||
verify_qdisc $QDISC "cake" || return 1
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
This just uses the cake qdisc as a replacement for both htb as shaper and fq_codel as leaf qdisc.
|
||||
It just does not come any simpler than this, in other words it truely is a "piece of cake".
|
||||
This script requires that cake is selected as qdisc, and forces its usage.
|
||||
See: http://www.bufferbloat.net/projects/codel/wiki/Cake for more information
|
@ -1,130 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# Copyright (C) 2012-4 Michael D. Taht, Toke Høiland-Jørgensen, Sebastian Moeller
|
||||
|
||||
|
||||
. /lib/functions.sh
|
||||
|
||||
. /etc/sqm/sqm.conf
|
||||
. ${SQM_LIB_DIR}/functions.sh
|
||||
|
||||
ACTION="${1:-start}"
|
||||
RUN_IFACE="$2"
|
||||
LOCKDIR="${SQM_STATE_DIR}/sqm-run.lock"
|
||||
|
||||
check_state_dir
|
||||
[ -d "${SQM_QDISC_STATE_DIR}" ] || ${SQM_LIB_DIR}/update-available-qdiscs
|
||||
|
||||
stop_statefile() {
|
||||
local f
|
||||
f="$1"
|
||||
# Source the state file prior to stopping; we need the variables saved in
|
||||
# there.
|
||||
[ -f "$f" ] && ( . "$f";
|
||||
IFACE=$IFACE SCRIPT=$SCRIPT SQM_DEBUG=$SQM_DEBUG \
|
||||
SQM_DEBUG_LOG=$SQM_DEBUG_LOG \
|
||||
SQM_VERBOSITY_MAX=$SQM_VERBOSITY_MAX \
|
||||
SQM_VERBOSITY_MIN=$SQM_VERBOSITY_MIN \
|
||||
OUTPUT_TARGET=$OUTPUT_TARGET ${SQM_LIB_DIR}/stop-sqm )
|
||||
}
|
||||
|
||||
start_sqm_section() {
|
||||
local section
|
||||
section="$1"
|
||||
export IFACE=$(config_get "$section" interface)
|
||||
|
||||
[ -z "$RUN_IFACE" -o "$RUN_IFACE" = "$IFACE" ] || return
|
||||
[ "$(config_get "$section" enabled)" -eq 1 ] || return 0
|
||||
[ -f "${SQM_STATE_DIR}/${IFACE}.state" ] && return
|
||||
|
||||
export UPLINK=$(config_get "$section" upload)
|
||||
export DOWNLINK=$(config_get "$section" download)
|
||||
export LLAM=$(config_get "$section" linklayer_adaptation_mechanism)
|
||||
export LINKLAYER=$(config_get "$section" linklayer)
|
||||
export OVERHEAD=$(config_get "$section" overhead)
|
||||
export STAB_MTU=$(config_get "$section" tcMTU)
|
||||
export STAB_TSIZE=$(config_get "$section" tcTSIZE)
|
||||
export STAB_MPU=$(config_get "$section" tcMPU)
|
||||
export ILIMIT=$(config_get "$section" ilimit)
|
||||
export ELIMIT=$(config_get "$section" elimit)
|
||||
export ITARGET=$(config_get "$section" itarget)
|
||||
export ETARGET=$(config_get "$section" etarget)
|
||||
export IECN=$(config_get "$section" ingress_ecn)
|
||||
export EECN=$(config_get "$section" egress_ecn)
|
||||
export IQDISC_OPTS=$(config_get "$section" iqdisc_opts)
|
||||
export EQDISC_OPTS=$(config_get "$section" eqdisc_opts)
|
||||
export TARGET=$(config_get "$section" target)
|
||||
export QDISC=$(config_get "$section" qdisc)
|
||||
export SCRIPT=$(config_get "$section" script)
|
||||
|
||||
# The UCI names for these two variables are confusing and should have been
|
||||
# changed ages ago. For now, keep the bad UCI names but use meaningful
|
||||
# variable names in the scripts to not break user configs.
|
||||
export ZERO_DSCP_INGRESS=$(config_get "$section" squash_dscp)
|
||||
export IGNORE_DSCP_INGRESS=$(config_get "$section" squash_ingress)
|
||||
|
||||
# If SQM_DEBUG or SQM_VERBOSITY_* were passed in via the command line make
|
||||
# them available to the other scripts this allows to override sqm's log
|
||||
# level as set in the GUI for quick debugging without GUI accesss.
|
||||
export SQM_DEBUG=${SQM_DEBUG:-$(config_get "$section" debug_logging)}
|
||||
export SQM_VERBOSITY_MAX=${SQM_VERBOSITY_MAX:-$(config_get "$section" verbosity)}
|
||||
export SQM_VERBOSITY_MIN
|
||||
|
||||
"${SQM_LIB_DIR}/start-sqm"
|
||||
}
|
||||
|
||||
release_lock() {
|
||||
PID=$(cat "$LOCKDIR/pid")
|
||||
if [ "$PID" -ne "$$" ]; then
|
||||
sqm_error "Trying to release lock with wrong PID $PID != $$"
|
||||
return 1
|
||||
fi
|
||||
|
||||
rm -rf "$LOCKDIR"
|
||||
return 0
|
||||
}
|
||||
|
||||
take_lock() {
|
||||
|
||||
if mkdir "$LOCKDIR" 2>/dev/null; then
|
||||
sqm_trace "Acquired run lock"
|
||||
echo $$ > "$LOCKDIR/pid"
|
||||
|
||||
trap release_lock 0
|
||||
return 0
|
||||
fi
|
||||
PID=$(cat "$LOCKDIR/pid")
|
||||
sqm_warn "Unable to get run lock - already held by $PID"
|
||||
return 1
|
||||
}
|
||||
|
||||
MAX_TRIES=10
|
||||
tries=$MAX_TRIES
|
||||
while ! take_lock; do
|
||||
sleep 1
|
||||
tries=$((tries - 1))
|
||||
if [ "$tries" -eq 0 ]; then
|
||||
sqm_error "Giving up on getting lock after $MAX_TRIES attempts"
|
||||
sqm_error "This is a bug; please report it at https://github.com/tohojo/sqm-scripts/issues"
|
||||
sqm_error "Then, to re-enable sqm-scripts, manually remove $LOCKDIR"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$ACTION" = "stop" ]; then
|
||||
if [ -z "$RUN_IFACE" ]; then
|
||||
# Stopping all active interfaces
|
||||
for f in ${SQM_STATE_DIR}/*.state; do
|
||||
stop_statefile "$f"
|
||||
done
|
||||
else
|
||||
stop_statefile "${SQM_STATE_DIR}/${RUN_IFACE}.state"
|
||||
fi
|
||||
else
|
||||
config_load sqm
|
||||
config_foreach start_sqm_section
|
||||
fi
|
@ -1,234 +0,0 @@
|
||||
################################################################################
|
||||
# simple.qos (Cero3 Shaper)
|
||||
#
|
||||
# Abstract:
|
||||
# This is a three band fq_codel and ipv6 enabled shaping script for Ethernet
|
||||
# gateways. Compared to the complexity that debloat had become this cleanly
|
||||
# shows a means of going from diffserv marking to prioritization using the
|
||||
# current tools ip(6)tables and tc. We should note that the complexity of
|
||||
# debloat exists for a reason, and it is expected that script is run first to
|
||||
# setup various other parameters such as BQL and ethtool.
|
||||
#
|
||||
# (Assume the debloat script has setup the other interfaces.)
|
||||
#
|
||||
# Notes:
|
||||
# This does the right thing with ipv6 traffic. It also tries to leverage
|
||||
# diffserv to some sane extent. In particular, the 'priority' queue is limited
|
||||
# to 33% of the total, so EF, and IMM traffic cannot starve other types. The
|
||||
# rfc suggested 30%. 30% is probably a lot in today's world.
|
||||
#
|
||||
# References:
|
||||
# This alternate shaper attempts to go for 1/u performance in a clever way
|
||||
# http://git.coverfire.com/?p=linux-qos-scripts.git;a=blob;f=src-3tos.sh;hb=HEAD
|
||||
#
|
||||
################################################################################
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# Copyright (C) 2012-2016
|
||||
# Michael D. Taht, Toke Høiland-Jørgensen, Sebastian Moeller
|
||||
#
|
||||
################################################################################
|
||||
|
||||
. ${SQM_LIB_DIR}/defaults.sh
|
||||
|
||||
################################################################################
|
||||
|
||||
ipt_setup() {
|
||||
|
||||
ipt -t mangle -N QOS_MARK_${IFACE}
|
||||
|
||||
case $QDISC in
|
||||
cake*)
|
||||
sqm_debug "cake does all the diffserv work - no need for iptables rules"
|
||||
;;
|
||||
*)
|
||||
ipt -t mangle -A QOS_MARK_${IFACE} -j MARK --set-mark 0x2/${IPT_MASK}
|
||||
# You can go further with classification but...
|
||||
ipt -t mangle -A QOS_MARK_${IFACE} -m dscp --dscp-class CS1 -j MARK --set-mark 0x3/${IPT_MASK}
|
||||
ipt -t mangle -A QOS_MARK_${IFACE} -m dscp --dscp-class CS6 -j MARK --set-mark 0x1/${IPT_MASK}
|
||||
ipt -t mangle -A QOS_MARK_${IFACE} -m dscp --dscp-class EF -j MARK --set-mark 0x1/${IPT_MASK}
|
||||
ipt -t mangle -A QOS_MARK_${IFACE} -m dscp --dscp-class AF42 -j MARK --set-mark 0x1/${IPT_MASK}
|
||||
ipt -t mangle -A QOS_MARK_${IFACE} -m tos --tos Minimize-Delay -j MARK --set-mark 0x1/${IPT_MASK}
|
||||
;;
|
||||
esac
|
||||
|
||||
# Turn it on. Preserve classification if already performed
|
||||
#
|
||||
#sm: is it correct to do this in $IFACE? Should ingress not be on $DEV? since HTB acts on $DEV?
|
||||
#
|
||||
# ZERO also does not work on $DEV (that is the IFB will still see the
|
||||
# incoming ToS bits whether we squash or not)
|
||||
#
|
||||
# ZERO is still useful to protect internal machines...
|
||||
if [ "$ZERO_DSCP_INGRESS" = "1" ]; then
|
||||
sqm_debug "Squashing differentiated services code points (DSCP) from ingress."
|
||||
ipt -t mangle -I PREROUTING -i $IFACE -m dscp ! --dscp 0 -j DSCP --set-dscp-class be
|
||||
else
|
||||
sqm_debug "Keeping differentiated services code points (DSCP) from ingress."
|
||||
ipt -t mangle -A PREROUTING -i $IFACE -m mark --mark 0x00/${IPT_MASK} -g QOS_MARK_${IFACE}
|
||||
fi
|
||||
|
||||
ipt -t mangle -A POSTROUTING -o $IFACE -m mark --mark 0x00/${IPT_MASK} -g QOS_MARK_${IFACE}
|
||||
|
||||
# The Syn optimization was nice but fq_codel does it for us
|
||||
# ipt -t mangle -A PREROUTING -i s+ -p tcp -m tcp --tcp-flags SYN,RST,ACK SYN -j MARK --set-mark 0x01
|
||||
# Not sure if this will work. Encapsulation is a problem period
|
||||
|
||||
ipt -t mangle -I PREROUTING -i vtun+ -p tcp -j MARK --set-mark 0x2/${IPT_MASK} # tcp tunnels need ordering
|
||||
|
||||
# Emanating from router, do a little more optimization
|
||||
# but don't bother with it too much.
|
||||
|
||||
ipt -t mangle -A OUTPUT -p udp -m multiport --ports 123,53 -j DSCP --set-dscp-class AF42
|
||||
|
||||
#Not clear if the second line is needed
|
||||
#ipt -t mangle -A OUTPUT -o $IFACE -g QOS_MARK_${IFACE}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
cake_egress()
|
||||
{
|
||||
$TC qdisc add dev $IFACE root `get_stab_string` $QDISC bandwidth ${CEIL}kbit `get_cake_lla_string` ${EQDISC_OPTS}
|
||||
}
|
||||
|
||||
egress() {
|
||||
|
||||
CEIL=${UPLINK}
|
||||
PRIO_RATE=`expr $CEIL / 3` # Ceiling for prioirty
|
||||
BE_RATE=`expr $CEIL / 6` # Min for best effort
|
||||
BK_RATE=`expr $CEIL / 6` # Min for background
|
||||
BE_CEIL=`expr $CEIL - 16` # A little slop at the top
|
||||
|
||||
LQ="quantum `get_htb_quantum $IFACE $CEIL ${ESHAPER_QUANTUM_DUR_US}`"
|
||||
BURST="`get_htb_burst $IFACE $CEIL ${ESHAPER_BURST_DUR_US}`"
|
||||
|
||||
SILENT=1 $TC qdisc del dev $IFACE root
|
||||
|
||||
case $QDISC in
|
||||
cake*) cake_egress; return;;
|
||||
esac
|
||||
|
||||
$TC qdisc add dev $IFACE root handle 1: `get_stab_string` htb default 12
|
||||
$TC class add dev $IFACE parent 1: classid 1:1 htb $LQ rate ${CEIL}kbit ceil ${CEIL}kbit $BURST `get_htb_adsll_string`
|
||||
$TC class add dev $IFACE parent 1:1 classid 1:11 htb $LQ rate 128kbit ceil ${PRIO_RATE}kbit prio 1 `get_htb_adsll_string`
|
||||
$TC class add dev $IFACE parent 1:1 classid 1:12 htb $LQ rate ${BE_RATE}kbit ceil ${BE_CEIL}kbit $BURST prio 2 `get_htb_adsll_string`
|
||||
$TC class add dev $IFACE parent 1:1 classid 1:13 htb $LQ rate ${BK_RATE}kbit ceil ${BE_CEIL}kbit $BURST prio 3 `get_htb_adsll_string`
|
||||
|
||||
$TC qdisc add dev $IFACE parent 1:11 handle 110: $QDISC \
|
||||
`get_limit ${ELIMIT}` `get_target "${ETARGET}" ${UPLINK}` `get_ecn ${EECN}` `get_quantum 300` `get_flows ${PRIO_RATE}` ${EQDISC_OPTS}
|
||||
$TC qdisc add dev $IFACE parent 1:12 handle 120: $QDISC \
|
||||
`get_limit ${ELIMIT}` `get_target "${ETARGET}" ${UPLINK}` `get_ecn ${EECN}` `get_quantum 300` `get_flows ${BE_RATE}` ${EQDISC_OPTS}
|
||||
$TC qdisc add dev $IFACE parent 1:13 handle 130: $QDISC \
|
||||
`get_limit ${ELIMIT}` `get_target "${ETARGET}" ${UPLINK}` `get_ecn ${EECN}` `get_quantum 300` `get_flows ${BK_RATE}` ${EQDISC_OPTS}
|
||||
|
||||
# Need a catchall rule
|
||||
|
||||
$TC filter add dev $IFACE parent 1:0 protocol all prio 999 u32 \
|
||||
match ip protocol 0 0x00 flowid 1:12
|
||||
|
||||
# FIXME should probably change the filter here to do pre-nat
|
||||
|
||||
$TC filter add dev $IFACE parent 1:0 protocol ip prio 1 handle 1/${IPT_MASK} fw classid 1:11
|
||||
$TC filter add dev $IFACE parent 1:0 protocol ip prio 2 handle 2/${IPT_MASK} fw classid 1:12
|
||||
$TC filter add dev $IFACE parent 1:0 protocol ip prio 3 handle 3/${IPT_MASK} fw classid 1:13
|
||||
|
||||
# ipv6 support. Note that the handle indicates the fw mark bucket that is looked for
|
||||
|
||||
$TC filter add dev $IFACE parent 1:0 protocol ipv6 prio 4 handle 1/${IPT_MASK} fw classid 1:11
|
||||
$TC filter add dev $IFACE parent 1:0 protocol ipv6 prio 5 handle 2/${IPT_MASK} fw classid 1:12
|
||||
$TC filter add dev $IFACE parent 1:0 protocol ipv6 prio 6 handle 3/${IPT_MASK} fw classid 1:13
|
||||
|
||||
# Arp traffic
|
||||
|
||||
$TC filter add dev $IFACE parent 1:0 protocol arp prio 7 handle 1/${IPT_MASK} fw classid 1:11
|
||||
|
||||
# ICMP traffic - Don't impress your friends. Deoptimize to manage ping floods
|
||||
# better instead
|
||||
|
||||
$TC filter add dev $IFACE parent 1:0 protocol ip prio 8 \
|
||||
u32 match ip protocol 1 0xff flowid 1:13
|
||||
|
||||
$TC filter add dev $IFACE parent 1:0 protocol ipv6 prio 9 \
|
||||
u32 match ip protocol 1 0xff flowid 1:13
|
||||
}
|
||||
|
||||
|
||||
cake_ingress()
|
||||
{
|
||||
CAKEARGS=
|
||||
[ "$IGNORE_DSCP_INGRESS" = "1" ] && CAKEARGS="$CAKEARGS besteffort"
|
||||
$TC qdisc add dev $DEV root `get_stab_string` $QDISC bandwidth ${DOWNLINK}kbit \
|
||||
$CAKEARGS `get_cake_lla_string` ${IQDISC_OPTS}
|
||||
|
||||
$IP link set dev $DEV up
|
||||
|
||||
# redirect all IP packets arriving in $IFACE to $DEV
|
||||
|
||||
$TC filter add dev $IFACE parent ffff: protocol all prio 10 u32 \
|
||||
match u32 0 0 flowid 1:1 action mirred egress redirect dev $DEV
|
||||
}
|
||||
|
||||
ingress() {
|
||||
|
||||
CEIL=$DOWNLINK
|
||||
PRIO_RATE=`expr $CEIL / 3` # Ceiling for prioirty
|
||||
BE_RATE=`expr $CEIL / 6` # Min for best effort
|
||||
BK_RATE=`expr $CEIL / 6` # Min for background
|
||||
BE_CEIL=`expr $CEIL - 16` # A little slop at the top
|
||||
|
||||
LQ="quantum `get_htb_quantum $IFACE $CEIL ${ISHAPER_QUANTUM_DUR_US}`"
|
||||
BURST="`get_htb_burst $IFACE $CEIL ${ISHAPER_BURST_DUR_US}`"
|
||||
|
||||
SILENT=1 $TC qdisc del dev $IFACE handle ffff: ingress
|
||||
$TC qdisc add dev $IFACE handle ffff: ingress
|
||||
|
||||
SILENT=1 $TC qdisc del dev $DEV root
|
||||
|
||||
case $QDISC in
|
||||
cake*) cake_ingress; return ;;
|
||||
esac
|
||||
|
||||
if [ "$IGNORE_DSCP_INGRESS" = "1" ]; then
|
||||
sqm_debug "Do not perform DSCP based filtering on ingress. (1-tier classification)"
|
||||
$TC qdisc add dev $DEV root handle 1: `get_stab_string` htb default 10
|
||||
$TC class add dev $DEV parent 1: classid 1:1 htb $LQ rate ${DOWNLINK}kbit ceil ${DOWNLINK}kbit $BURST `get_htb_adsll_string`
|
||||
$TC class add dev $DEV parent 1:1 classid 1:10 htb $LQ rate ${DOWNLINK}kbit ceil ${DOWNLINK}kbit $BURST prio 0 `get_htb_adsll_string`
|
||||
$TC qdisc add dev $DEV parent 1:10 handle 110: $QDISC \
|
||||
`get_limit ${ILIMIT}` `get_target "${ITARGET}" ${DOWNLINK}` `get_ecn ${IECN}` `get_flows ${DOWNLINK}` ${IQDISC_OPTS}
|
||||
else
|
||||
sqm_debug "Perform DSCP based filtering on ingress. (3-tier classification)"
|
||||
$TC qdisc add dev $DEV root handle 1: `get_stab_string` htb default 12
|
||||
$TC class add dev $DEV parent 1: classid 1:1 htb $LQ rate ${CEIL}kbit ceil ${CEIL}kbit $BURST `get_htb_adsll_string`
|
||||
$TC class add dev $DEV parent 1:1 classid 1:11 htb $LQ rate 32kbit ceil ${PRIO_RATE}kbit prio 1 `get_htb_adsll_string`
|
||||
$TC class add dev $DEV parent 1:1 classid 1:12 htb $LQ rate ${BE_RATE}kbit ceil ${BE_CEIL}kbit $BURST prio 2 `get_htb_adsll_string`
|
||||
$TC class add dev $DEV parent 1:1 classid 1:13 htb $LQ rate ${BK_RATE}kbit ceil ${BE_CEIL}kbit $BURST prio 3 `get_htb_adsll_string`
|
||||
|
||||
$TC qdisc add dev $DEV parent 1:11 handle 110: $QDISC \
|
||||
`get_limit ${ILIMIT}` `get_target "${ITARGET}" ${DOWNLINK}` `get_ecn ${IECN}` `get_quantum 500` `get_flows ${PRIO_RATE}` ${IQDISC_OPTS}
|
||||
$TC qdisc add dev $DEV parent 1:12 handle 120: $QDISC \
|
||||
`get_limit ${ILIMIT}` `get_target "${ITARGET}" ${DOWNLINK}` `get_ecn ${IECN}` `get_quantum 1500` `get_flows ${BE_RATE}` ${IQDISC_OPTS}
|
||||
$TC qdisc add dev $DEV parent 1:13 handle 130: $QDISC \
|
||||
`get_limit ${ILIMIT}` `get_target "${ITARGET}" ${DOWNLINK}` `get_ecn ${IECN}` `get_quantum 300` `get_flows ${BK_RATE}` ${IQDISC_OPTS}
|
||||
|
||||
diffserv $DEV
|
||||
fi
|
||||
|
||||
$IP link set dev $DEV up
|
||||
|
||||
# redirect all IP packets arriving in $IFACE to $DEV
|
||||
|
||||
$TC filter add dev $IFACE parent ffff: protocol all prio 10 u32 \
|
||||
match u32 0 0 flowid 1:1 action mirred egress redirect dev $DEV
|
||||
|
||||
}
|
||||
|
||||
sqm_prepare_script() {
|
||||
do_modules
|
||||
verify_qdisc "htb" || return 1
|
||||
ipt_setup
|
||||
}
|
@ -1 +0,0 @@
|
||||
BW-limited three-tier prioritisation scheme with your qdisc on each queue. (default)
|
@ -1,104 +0,0 @@
|
||||
################################################################################
|
||||
# simplest.qos (Cero3 Simple Shaper)
|
||||
#
|
||||
# Abstract:
|
||||
# This is a single band fq_codel and ipv6 enabled shaping script for Ethernet
|
||||
# gateways. This is nearly the simplest possible. With FQ_CODEL, the sparseness
|
||||
# priority will work pretty well for a casual network. Flow-hashes should not
|
||||
# overlap much with only a few users.
|
||||
#
|
||||
# References:
|
||||
# This alternate shaper attempts to go for 1/u performance in a clever way
|
||||
# http://git.coverfire.com/?p=linux-qos-scripts.git;a=blob;f=src-3tos.sh;hb=HEAD
|
||||
#
|
||||
################################################################################
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# Copyright (C) 2012-2016
|
||||
# Michael D. Taht, Toke Høiland-Jørgensen, Sebastian Moeller
|
||||
#
|
||||
################################################################################
|
||||
|
||||
. ${SQM_LIB_DIR}/defaults.sh
|
||||
|
||||
################################################################################
|
||||
|
||||
cake_egress()
|
||||
{
|
||||
$TC qdisc add dev $IFACE root `get_stab_string` cake bandwidth ${UPLINK}kbit besteffort `get_cake_lla_string` ${EQDISC_OPTS}
|
||||
}
|
||||
|
||||
egress() {
|
||||
|
||||
LQ="quantum `get_htb_quantum $IFACE ${UPLINK} ${ESHAPER_QUANTUM_DUR_US}`"
|
||||
BURST="`get_htb_burst $IFACE ${UPLINK} ${ESHAPER_BURST_DUR_US}`"
|
||||
|
||||
SILENT=1 $TC qdisc del dev $IFACE root
|
||||
|
||||
case $QDISC in
|
||||
cake*) cake_egress; return ;;
|
||||
esac
|
||||
|
||||
$TC qdisc add dev $IFACE root handle 1: `get_stab_string` htb default 10
|
||||
$TC class add dev $IFACE parent 1: classid 1:1 htb $LQ rate ${UPLINK}kbit ceil ${UPLINK}kbit $BURST `get_htb_adsll_string`
|
||||
$TC class add dev $IFACE parent 1:1 classid 1:10 htb $LQ rate ${UPLINK}kbit ceil ${UPLINK}kbit $BURST prio 0 `get_htb_adsll_string`
|
||||
$TC qdisc add dev $IFACE parent 1:10 handle 110: $QDISC \
|
||||
`get_limit ${ELIMIT}` `get_target "${ETARGET}" ${UPLINK}` `get_ecn ${EECN}` `get_flows ${UPLINK}` ${EQDISC_OPTS}
|
||||
|
||||
}
|
||||
|
||||
cake_ingress()
|
||||
{
|
||||
$TC qdisc add dev $DEV root `get_stab_string` cake bandwidth ${DOWNLINK}kbit besteffort `get_cake_lla_string` ${IQDISC_OPTS}
|
||||
$IP link set dev $DEV up
|
||||
|
||||
# redirect all IP packets arriving in $IFACE to $DEV
|
||||
|
||||
$TC filter add dev $IFACE parent ffff: protocol all prio 10 u32 \
|
||||
match u32 0 0 flowid 1:1 action mirred egress redirect dev $DEV
|
||||
}
|
||||
|
||||
ingress() {
|
||||
sqm_debug "ingress"
|
||||
SILENT=1 $TC qdisc del dev $IFACE handle ffff: ingress
|
||||
$TC qdisc add dev $IFACE handle ffff: ingress
|
||||
|
||||
LQ="quantum `get_htb_quantum $IFACE ${DOWNLINK} ${ISHAPER_QUANTUM_DUR_US}`"
|
||||
BURST="`get_htb_burst $IFACE ${DOWNLINK} ${ISHAPER_BURST_DUR_US}`"
|
||||
|
||||
SILENT=1 $TC qdisc del dev $DEV root
|
||||
|
||||
case $QDISC in
|
||||
cake*) cake_ingress; return ;;
|
||||
esac
|
||||
|
||||
$TC qdisc add dev $DEV root handle 1: `get_stab_string` htb default 10
|
||||
$TC class add dev $DEV parent 1: classid 1:1 htb $LQ rate ${DOWNLINK}kbit ceil ${DOWNLINK}kbit $BURST `get_htb_adsll_string`
|
||||
$TC class add dev $DEV parent 1:1 classid 1:10 htb $LQ rate ${DOWNLINK}kbit ceil ${DOWNLINK}kbit $BURST prio 0 `get_htb_adsll_string`
|
||||
|
||||
# FIXME: I'd prefer to use a pre-nat filter but we need to detect if nat is on this interface
|
||||
# AND we need to permute by a random number which we can't do from userspace filters
|
||||
|
||||
# Most high rate flows are REALLY close. This stomps on those harder, but hurts on high rate long distance
|
||||
#$TC qdisc add dev $DEV parent 1:10 handle 110: $QDISC limit $LIMIT $ECN interval 20ms target 3ms `get_flows ${DOWNLINK}`
|
||||
$TC qdisc add dev $DEV parent 1:10 handle 110: $QDISC \
|
||||
`get_limit ${ILIMIT}` `get_target "${ITARGET}" ${DOWNLINK}` `get_ecn ${IECN}` `get_flows ${DOWNLINK}` ${IQDISC_OPTS}
|
||||
|
||||
$IP link set dev $DEV up
|
||||
|
||||
# redirect all IP packets arriving in $IFACE to ifb0
|
||||
|
||||
$TC filter add dev $IFACE parent ffff: protocol all prio 10 u32 \
|
||||
match u32 0 0 flowid 1:1 action mirred egress redirect dev $DEV
|
||||
|
||||
}
|
||||
|
||||
sqm_prepare_script() {
|
||||
do_modules
|
||||
verify_qdisc "htb" || return 1
|
||||
}
|
||||
|
||||
################################################################################
|
@ -1 +0,0 @@
|
||||
Simplest possible configuration: HTB rate limiter with your qdisc attached.
|
@ -1,85 +0,0 @@
|
||||
################################################################################
|
||||
# simplest_tbf.qos (Simple TBF shaper)
|
||||
#
|
||||
# Abstract:
|
||||
# This is a single band fq_codel and ipv6 enabled shaping script for Ethernet
|
||||
# gateways. This is nearly the simplest possible. With FQ_CODEL, the sparseness
|
||||
# priority will work pretty well for a casual network. Flow-hashes should not
|
||||
# overlap much with only a few users.
|
||||
#
|
||||
# Uses TBF instead of HTB as that may give better performance on some
|
||||
# architectures.
|
||||
#
|
||||
# References:
|
||||
# This alternate shaper attempts to go for 1/u performance in a clever way
|
||||
# http://git.coverfire.com/?p=linux-qos-scripts.git;a=blob;f=src-3tos.sh;hb=HEAD
|
||||
#
|
||||
################################################################################
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# Copyright (C) 2012-2017
|
||||
# Michael D. Taht, Toke Høiland-Jørgensen, Sebastian Moeller
|
||||
#
|
||||
################################################################################
|
||||
|
||||
. ${SQM_LIB_DIR}/defaults.sh
|
||||
|
||||
################################################################################
|
||||
|
||||
egress() {
|
||||
|
||||
MTU=$(get_mtu $IFACE)
|
||||
BURST="$(get_burst ${MTU:-1514} ${UPLINK} ${ESHAPER_BURST_DUR_US})"
|
||||
BURST=${BURST:-1514}
|
||||
|
||||
SILENT=1 $TC qdisc del dev $IFACE root
|
||||
|
||||
$TC qdisc add dev $IFACE root handle 1: $(get_stab_string) tbf \
|
||||
rate ${UPLINK}kbit burst $BURST latency 300ms $(get_htb_adsll_string)
|
||||
$TC qdisc add dev $IFACE parent 1: handle 110: $QDISC \
|
||||
$(get_limit ${ELIMIT}) $(get_target "${ETARGET}" ${UPLINK}) \
|
||||
$(get_ecn ${EECN}) $(get_flows ${UPLINK}) ${EQDISC_OPTS}
|
||||
|
||||
}
|
||||
|
||||
ingress() {
|
||||
sqm_debug "ingress"
|
||||
SILENT=1 $TC qdisc del dev $IFACE handle ffff: ingress
|
||||
$TC qdisc add dev $IFACE handle ffff: ingress
|
||||
|
||||
MTU=$(get_mtu $IFACE)
|
||||
BURST="$(get_burst ${MTU:-1514} ${DOWNLINK} ${ISHAPER_BURST_DUR_US})"
|
||||
BURST=${BURST:-1514}
|
||||
|
||||
SILENT=1 $TC qdisc del dev $DEV root
|
||||
|
||||
$TC qdisc add dev $DEV root handle 1: $(get_stab_string) tbf \
|
||||
rate ${DOWNLINK}kbit burst $BURST latency 300ms $(get_htb_adsll_string)
|
||||
$TC qdisc add dev $DEV parent 1: handle 110: $QDISC \
|
||||
$(get_limit ${ILIMIT}) $(get_target "${ITARGET}" ${DOWNLINK}) \
|
||||
$(get_ecn ${IECN}) $(get_flows ${DOWNLINK}) ${IQDISC_OPTS}
|
||||
|
||||
$IP link set dev $DEV up
|
||||
|
||||
# redirect all IP packets arriving in $IFACE to ifb0
|
||||
|
||||
$TC filter add dev $IFACE parent ffff: protocol all prio 10 u32 \
|
||||
match u32 0 0 flowid 1:1 action mirred egress redirect dev $DEV
|
||||
|
||||
}
|
||||
|
||||
sqm_prepare_script() {
|
||||
do_modules
|
||||
verify_qdisc "tbf" || return 1
|
||||
|
||||
case $QDISC in
|
||||
cake*)
|
||||
sqm_warn "Cake is not supported with this script; falling back to FQ-CoDel"
|
||||
QDISC=fq_codel ;;
|
||||
esac
|
||||
}
|
||||
|
||||
################################################################################
|
@ -1,2 +0,0 @@
|
||||
Simplest possible configuration (TBF): TBF rate limiter with your qdisc attached.
|
||||
TBF may give better performance than HTB on some architectures.
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user