diff --git a/rooter/0basicapps/ext-command/Makefile b/rooter/0basicapps/ext-command/Makefile new file mode 100644 index 0000000..828e77a --- /dev/null +++ b/rooter/0basicapps/ext-command/Makefile @@ -0,0 +1,33 @@ +#Owned by DairyMan@Whirlpool +# +#Copyright GNU act. +include $(TOPDIR)/rules.mk + +PKG_NAME:=ext-command +PKG_VERSION:=4.500 +PKG_RELEASE:=1 + +PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool +include $(INCLUDE_DIR)/package.mk + +define Package/ext-command + SECTION:=utils + CATEGORY:=ROOter + SUBMENU:=Basic Applications + TITLE:=support for Command + PKGARCH:=all +endef + +define Package/ext-command/description + Helper scripts to enable command +endef + + +define Build/Compile +endef + +define Package/ext-command/install + $(CP) ./files/* $(1)/ +endef + +$(eval $(call BuildPackage,ext-command)) diff --git a/rooter/0basicapps/ext-command/files/usr/lib/lua/luci/controller/commands.lua b/rooter/0basicapps/ext-command/files/usr/lib/lua/luci/controller/commands.lua new file mode 100644 index 0000000..a9f0640 --- /dev/null +++ b/rooter/0basicapps/ext-command/files/usr/lib/lua/luci/controller/commands.lua @@ -0,0 +1,296 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2012 Jo-Philipp Wich + +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 + +]]-- + +module("luci.controller.commands", package.seeall) + +I18N = require "luci.i18n" +translate = I18N.translate + +function index() + 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 + entry({"admin", "system", "commands"}, firstchild(), _(translate("Custom Commands")), 80) + entry({"admin", "system", "commands", "dashboard"}, template("commands"), _(translate("Dashboard")), 1) + entry({"admin", "system", "commands", "config"}, cbi("commands"), _(translate("Configure")), 2) + entry({"admin", "system", "commands", "script"}, template("cmdedit"), _(translate("Scripts")), 3) + entry({"admin", "system", "commands", "run"}, call("action_run"), nil, 3).leaf = true + entry({"admin", "system", "commands", "download"}, call("action_download"), nil, 3).leaf = true + end + + entry({"admin", "system", "load_script"}, call("action_load_script")) + entry({"admin", "system", "save_script"}, call("action_save_script")) + entry({"admin", "system", "del_script"}, call("action_del_script")) + + entry({"command"}, call("action_public"), nil, 1).leaf = true +end + +--- Decode a given string into arguments following shell quoting rules +--- [[abc \def "foo\"bar" abc'def']] -> [[abc def]] [[foo"bar]] [[abcdef]] +local function parse_args(str) + local args = { } + + local function isspace(c) + if c == 9 or c == 10 or c == 11 or c == 12 or c == 13 or c == 32 then + return c + end + end + + local function isquote(c) + if c == 34 or c == 39 or c == 96 then + return c + end + end + + local function isescape(c) + if c == 92 then + return c + end + end + + local function ismeta(c) + if c == 36 or c == 92 or c == 96 then + return c + end + end + + --- Convert given table of byte values into a Lua string and append it to + --- the "args" table. Segment byte value sequence into chunks of 256 values + --- to not trip over the parameter limit for string.char() + local function putstr(bytes) + local chunks = { } + local csz = 256 + local upk = unpack + local chr = string.char + local min = math.min + local len = #bytes + local off + + for off = 1, len, csz do + chunks[#chunks+1] = chr(upk(bytes, off, min(off + csz - 1, len))) + end + + args[#args+1] = table.concat(chunks) + end + + --- Scan substring defined by the indexes [s, e] of the string "str", + --- perform unquoting and de-escaping on the fly and store the result in + --- a table of byte values which is passed to putstr() + local function unquote(s, e) + local off, esc, quote + local res = { } + + for off = s, e do + local byte = str:byte(off) + local q = isquote(byte) + local e = isescape(byte) + local m = ismeta(byte) + + if e then + esc = true + elseif esc then + if m then res[#res+1] = 92 end + res[#res+1] = byte + esc = false + elseif q and quote and q == quote then + quote = nil + elseif q and not quote then + quote = q + else + if m then res[#res+1] = 92 end + res[#res+1] = byte + end + end + + putstr(res) + end + + --- Find substring boundaries in "str". Ignore escaped or quoted + --- whitespace, pass found start- and end-index for each substring + --- to unquote() + local off, esc, start, quote + for off = 1, #str + 1 do + local byte = str:byte(off) + local q = isquote(byte) + local s = isspace(byte) or (off > #str) + local e = isescape(byte) + + if esc then + esc = false + elseif e then + esc = true + elseif q and quote and q == quote then + quote = nil + elseif q and not quote then + start = start or off + quote = q + elseif s and not quote then + if start then + unquote(start, off - 1) + start = nil + end + else + start = start or off + end + end + + --- If the "quote" is still set we encountered an unfinished string + if quote then + unquote(start, #str) + end + + return args +end + +local function parse_cmdline(cmdid, args) + local uci = require "luci.model.uci".cursor() + if uci:get("luci", cmdid) == "command" then + local cmd = uci:get_all("luci", cmdid) + local argv = parse_args(cmd.command) + local i, v + + if cmd.param == "1" and args then + for i, v in ipairs(parse_args(luci.http.urldecode(args))) do + argv[#argv+1] = v + end + end + + for i, v in ipairs(argv) do + if v:match("[^%w%.%-i/]") then + argv[i] = '"%s"' % v:gsub('"', '\\"') + end + end + + return argv + end +end + +function action_run(...) + local fs = require "nixio.fs" + local argv = parse_cmdline(...) + if argv then + local outfile = os.tmpname() + local errfile = os.tmpname() + + local rv = os.execute(table.concat(argv, " ") .. " >%s 2>%s" %{ outfile, errfile }) + local stdout = fs.readfile(outfile, 1024 * 512) or "" + local stderr = fs.readfile(errfile, 1024 * 512) or "" + + fs.unlink(outfile) + fs.unlink(errfile) + + local binary = not not (stdout:match("[%z\1-\8\14-\31]")) + + luci.http.prepare_content("application/json") + luci.http.write_json({ + command = table.concat(argv, " "), + stdout = not binary and stdout, + stderr = stderr, + exitcode = rv, + binary = binary + }) + else + luci.http.status(404, translate("No such command")) + end +end + +function action_download(...) + local fs = require "nixio.fs" + local argv = parse_cmdline(...) + if argv then + local fd = io.popen(table.concat(argv, " ") .. " 2>/dev/null") + if fd then + local chunk = fd:read(4096) or "" + local name + if chunk:match("[%z\1-\8\14-\31]") then + luci.http.header("Content-Disposition", "attachment; filename=%s" + % fs.basename(argv[1]):gsub("%W+", ".") .. ".bin") + luci.http.prepare_content("application/octet-stream") + else + luci.http.header("Content-Disposition", "attachment; filename=%s" + % fs.basename(argv[1]):gsub("%W+", ".") .. ".txt") + luci.http.prepare_content("text/plain") + end + + while chunk do + luci.http.write(chunk) + chunk = fd:read(4096) + end + + fd:close() + else + luci.http.status(500, translate("Failed to execute command")) + end + else + luci.http.status(404, "No such command") + end +end + +function action_public(cmdid, args) + local uci = require "luci.model.uci".cursor() + if cmdid and + uci:get("luci", cmdid) == "command" and + uci:get("luci", cmdid, "public") == "1" + then + action_download(cmdid, args) + else + luci.http.status(403, translate("Access to command denied")) + end +end + +function action_load_script() + local set = luci.http.formvalue("set") + local rv ={} + local file + + file = io.open(set, "r") + if file ~= nil then + local tmp = file:read("*all") + rv["text"] = tmp + file:close() + else + rv["text"] = translate("No file found") + end + + luci.http.prepare_content("application/json") + luci.http.write_json(rv) +end + +function action_save_script() + local line = luci.http.formvalue("set") + local rv ={} + local file + + s, e = line:find("|") + name = line:sub(1,s-1) + text = line:sub(e+1) + + file = io.open(name, "w") + file:write(text) + file:close() + os.execute("chmod 777 " .. name) + + rv["name"] = name + luci.http.prepare_content("application/json") + luci.http.write_json(rv) +end + +function action_del_script() + local name = luci.http.formvalue("set") + local rv ={} + os.remove(name) + + rv["name"] = name + luci.http.prepare_content("application/json") + luci.http.write_json(rv) +end \ No newline at end of file diff --git a/rooter/0basicapps/ext-command/files/usr/lib/lua/luci/model/cbi/commands.lua b/rooter/0basicapps/ext-command/files/usr/lib/lua/luci/model/cbi/commands.lua new file mode 100644 index 0000000..1359eb2 --- /dev/null +++ b/rooter/0basicapps/ext-command/files/usr/lib/lua/luci/model/cbi/commands.lua @@ -0,0 +1,37 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2012 Jo-Philipp Wich + +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 + +]]-- + +local m, s + +m = Map("luci", translate("Custom Commands"), + translate("This page allows you to configure custom shell commands which can be easily invoked from the web interface.")) + +s = m:section(TypedSection, "command", "") +s.template = "cbi/tblsection" +s.anonymous = true +s.addremove = true + + +s:option(Value, "name", translate("Description"), + translate("A short textual description of the configured command")) + +s:option(Value, "command", translate("Command"), + translate("Command line to execute")) + +s:option(Flag, "param", translate("Custom arguments"), + translate("Allow the user to provide additional command line arguments")) + +s:option(Flag, "public", translate("Public access"), + translate("Allow executing the command and downloading its output without prior authentication")) + +return m diff --git a/rooter/0basicapps/ext-command/files/usr/lib/lua/luci/view/cmdedit.htm b/rooter/0basicapps/ext-command/files/usr/lib/lua/luci/view/cmdedit.htm new file mode 100644 index 0000000..cfd8a53 --- /dev/null +++ b/rooter/0basicapps/ext-command/files/usr/lib/lua/luci/view/cmdedit.htm @@ -0,0 +1,186 @@ +<%+header%> + + + + +
+
+

<%:Script Editing%>

+
<%:Create, Edit and Save Scripts%>
+
+ + + + + + +
<%:Script Name :%>
 
+ + + + + + +
<%:Path to Script :%>
 
+ + + + + +
+ +
+ + + + + + + + + +
 
+ +
+ +
+
+<%+footer%> \ No newline at end of file diff --git a/rooter/0basicapps/ext-command/files/usr/lib/lua/luci/view/commands.htm b/rooter/0basicapps/ext-command/files/usr/lib/lua/luci/view/commands.htm new file mode 100644 index 0000000..83792a9 --- /dev/null +++ b/rooter/0basicapps/ext-command/files/usr/lib/lua/luci/view/commands.htm @@ -0,0 +1,176 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2012 Jo-Philipp Wich + +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 + +-%> + +<% css = [[ + +.commandbox { + height: 12em; + width: 30%; + float: left; + height: 12em; + margin: 5px; + position: relative; +} + +.commandbox h3 { + font-size: 1.5em !important; + line-height: 2em !important; + margin: 0 !important; +} + +.commandbox input[type="text"] { + width: 50% !important; +} + +.commandbox div { + position: absolute; + left: 0; + bottom: 1.5em; +} + +]] -%> + +<%+header%> + + + + +<% + local uci = require "luci.model.uci".cursor() + local commands = { } + + uci:foreach("luci", "command", function(s) commands[#commands+1] = s end) +%> + +
"> +
+

<%:Custom Commands%>

+ +
+ <% local _, command; for _, command in ipairs(commands) do %> +
+

<%=pcdata(command.name)%>

+

<%:Command:%> <%=pcdata(command.command)%>

+ <% if command.param == "1" then %> +

<%:Arguments:%>

+ <% end %> +
+ + + <% if command.public == "1" then %> + + <% end %> +
+
+ <% end %> + +

+ +
+
+ + +
+ +<%+footer%> diff --git a/rooter/0basicapps/ext-command/files/usr/lib/scripts/dummy b/rooter/0basicapps/ext-command/files/usr/lib/scripts/dummy new file mode 100644 index 0000000..c227083 --- /dev/null +++ b/rooter/0basicapps/ext-command/files/usr/lib/scripts/dummy @@ -0,0 +1 @@ +0 \ No newline at end of file diff --git a/rooter/0basicapps/ext-extra/Makefile b/rooter/0basicapps/ext-extra/Makefile new file mode 100644 index 0000000..07a6c59 --- /dev/null +++ b/rooter/0basicapps/ext-extra/Makefile @@ -0,0 +1,35 @@ +#Owned by DairyMan@Whirlpool +# +#Copyright GNU act. +include $(TOPDIR)/rules.mk + +PKG_NAME:=ext-extra +PKG_VERSION:=1.000 +PKG_RELEASE:=1 + +PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool +include $(INCLUDE_DIR)/package.mk + +define Package/ext-extra + SECTION:=utils + CATEGORY:=ROOter + SUBMENU:=Basic Applications + TITLE:=Add Scheduled Reboot + PKGARCH:=all +endef + +define Package/ext-extra/description + Helper scripts to install Scheduled Reboot +endef + + +define Build/Compile +endef + +define Package/ext-extra/install + $(CP) ./files/* $(1)/ + + +endef + +$(eval $(call BuildPackage,ext-extra)) diff --git a/rooter/0basicapps/ext-extra/files/etc/config/schedule b/rooter/0basicapps/ext-extra/files/etc/config/schedule new file mode 100644 index 0000000..95c1155 --- /dev/null +++ b/rooter/0basicapps/ext-extra/files/etc/config/schedule @@ -0,0 +1,7 @@ + +config reboot 'reboot' + option enable '0' + +config timezone 'timezone' + option zonename 'UTC' + diff --git a/rooter/0basicapps/ext-extra/files/usr/lib/lua/luci/controller/schedule.lua b/rooter/0basicapps/ext-extra/files/usr/lib/lua/luci/controller/schedule.lua new file mode 100644 index 0000000..d64b6c6 --- /dev/null +++ b/rooter/0basicapps/ext-extra/files/usr/lib/lua/luci/controller/schedule.lua @@ -0,0 +1,13 @@ +-- Licensed to the public under the Apache License 2.0. + +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.dependent = true +end diff --git a/rooter/0basicapps/ext-extra/files/usr/lib/lua/luci/model/cbi/admin_system/cronnew.lua b/rooter/0basicapps/ext-extra/files/usr/lib/lua/luci/model/cbi/admin_system/cronnew.lua new file mode 100644 index 0000000..0de690c --- /dev/null +++ b/rooter/0basicapps/ext-extra/files/usr/lib/lua/luci/model/cbi/admin_system/cronnew.lua @@ -0,0 +1,29 @@ +-- Copyright 2008 Steven Barth +-- Copyright 2008-2013 Jo-Philipp Wich +-- Licensed to the public under the Apache License 2.0. + +local fs = require "nixio.fs" +local cronfile = "/etc/cronuser" + +f = SimpleForm("crontab", translate("Scheduled Tasks"), translate("This is the system crontab in which scheduled tasks can be defined.")) + +t = f:field(TextValue, "crons") +t.rmempty = true +t.rows = 10 +function t.cfgvalue() + return fs.readfile(cronfile) or "" +end + +function f.handle(self, state, data) + if state == FORM_VALID then + if data.crons then + fs.writefile(cronfile, data.crons:gsub("\r\n", "\n")) + else + fs.writefile(cronfile, "") + end + luci.sys.call("/usr/lib/rooter/luci/croncat.sh") + end + return true +end + +return f diff --git a/rooter/0basicapps/ext-extra/files/usr/lib/lua/luci/model/cbi/schedule.lua b/rooter/0basicapps/ext-extra/files/usr/lib/lua/luci/model/cbi/schedule.lua new file mode 100644 index 0000000..e6ddaa7 --- /dev/null +++ b/rooter/0basicapps/ext-extra/files/usr/lib/lua/luci/model/cbi/schedule.lua @@ -0,0 +1,133 @@ +local utl = require "luci.util" + +local sys = require "luci.sys" +local zones = require "luci.sys.zoneinfo" +local fs = require "nixio.fs" +local conf = require "luci.config" + +os.execute("/usr/lib/rooter/luci/reboot.sh 0") + +m = Map("schedule", translate("Scheduled Reboot"), translate("Schedule a Router Reboot at a Specified Time")) + +m.on_after_save = function(self) + luci.sys.call("/usr/lib/rooter/luci/reboot.sh 1 &") +end + +d1 = m:section(TypedSection, "timezone", " ") + +--o1 = d1:option(DummyValue, "_systime", translate("Local Time : ")) +--o1.template = "admin_system/clock_status" + +o = d1:option(DummyValue, "zonename", translate("Timezone : "), translate("Be sure to set your Timezone correctly in System->System")) + +d = m:section(TypedSection, "reboot", " ") + +c1 = d:option(ListValue, "enable", " "); +c1:value("0", translate("Disabled")) +c1:value("1", translate("Enabled")) +c1.default=0 + +sdhour = d:option(ListValue, "sdhour", translate("Reboot Time :")) +sdhour.rmempty = true +sdhour:value("0", "12:00 AM") +sdhour:value("1", "12:15 AM") +sdhour:value("2", "12:30 AM") +sdhour:value("3", "12:45 AM") +sdhour:value("4", "01:00 AM") +sdhour:value("5", "01:15 AM") +sdhour:value("6", "01:30 AM") +sdhour:value("7", "01:45 AM") +sdhour:value("8", "02:00 AM") +sdhour:value("9", "02:15 AM") +sdhour:value("10", "02:30 AM") +sdhour:value("11", "02:45 AM") +sdhour:value("12", "03:00 AM") +sdhour:value("13", "03:15 AM") +sdhour:value("14", "03:30 AM") +sdhour:value("15", "03:45 AM") +sdhour:value("16", "04:00 AM") +sdhour:value("17", "04:15 AM") +sdhour:value("18", "04:30 AM") +sdhour:value("19", "04:45 AM") +sdhour:value("20", "05:00 AM") +sdhour:value("21", "05:15 AM") +sdhour:value("22", "05:30 AM") +sdhour:value("23", "05:45 AM") +sdhour:value("24", "06:00 AM") +sdhour:value("25", "06:15 AM") +sdhour:value("26", "06:30 AM") +sdhour:value("27", "06:45 AM") +sdhour:value("28", "07:00 AM") +sdhour:value("29", "07:15 AM") +sdhour:value("30", "07:30 AM") +sdhour:value("31", "07:45 AM") +sdhour:value("32", "08:00 AM") +sdhour:value("33", "08:15 AM") +sdhour:value("34", "08:30 AM") +sdhour:value("35", "08:45 AM") +sdhour:value("36", "09:00 AM") +sdhour:value("37", "09:15 AM") +sdhour:value("38", "09:30 AM") +sdhour:value("39", "09:45 AM") +sdhour:value("40", "10:00 AM") +sdhour:value("41", "10:15 AM") +sdhour:value("42", "10:30 AM") +sdhour:value("43", "10:45 AM") +sdhour:value("44", "11:00 AM") +sdhour:value("45", "11:15 AM") +sdhour:value("46", "11:30 AM") +sdhour:value("47", "11:45 AM") +sdhour:value("48", "12:00 PM") +sdhour:value("49", "12:15 PM") +sdhour:value("50", "12:30 PM") +sdhour:value("51", "12:45 PM") +sdhour:value("52", "01:00 PM") +sdhour:value("53", "01:15 PM") +sdhour:value("54", "01:30 PM") +sdhour:value("55", "01:45 PM") +sdhour:value("56", "02:00 PM") +sdhour:value("57", "02:15 PM") +sdhour:value("58", "02:30 PM") +sdhour:value("59", "02:45 PM") +sdhour:value("60", "03:00 PM") +sdhour:value("61", "03:15 PM") +sdhour:value("62", "03:30 PM") +sdhour:value("63", "03:45 PM") +sdhour:value("64", "04:00 PM") +sdhour:value("65", "04:15 PM") +sdhour:value("66", "04:30 PM") +sdhour:value("67", "04:45 PM") +sdhour:value("68", "05:00 PM") +sdhour:value("69", "05:15 PM") +sdhour:value("70", "05:30 PM") +sdhour:value("71", "05:45 PM") +sdhour:value("72", "06:00 PM") +sdhour:value("73", "06:15 PM") +sdhour:value("74", "06:30 PM") +sdhour:value("75", "06:45 PM") +sdhour:value("76", "07:00 PM") +sdhour:value("77", "07:15 PM") +sdhour:value("78", "07:30 PM") +sdhour:value("79", "07:45 PM") +sdhour:value("80", "08:00 PM") +sdhour:value("81", "08:15 PM") +sdhour:value("82", "08:30 PM") +sdhour:value("83", "08:45 PM") +sdhour:value("84", "09:00 PM") +sdhour:value("85", "09:15 PM") +sdhour:value("86", "09:30 PM") +sdhour:value("87", "09:45 PM") +sdhour:value("88", "10:00 PM") +sdhour:value("89", "10:15 PM") +sdhour:value("90", "10:30 PM") +sdhour:value("91", "10:45 PM") +sdhour:value("92", "11:00 PM") +sdhour:value("93", "11:15 PM") +sdhour:value("94", "11:30 PM") +sdhour:value("95", "11:45 PM") + +sdhour:depends("enable", "1") +sdhour.default = "0" + +return m + diff --git a/rooter/0basicapps/ext-extra/files/usr/lib/rooter/luci/croncat.sh b/rooter/0basicapps/ext-extra/files/usr/lib/rooter/luci/croncat.sh new file mode 100644 index 0000000..842f648 --- /dev/null +++ b/rooter/0basicapps/ext-extra/files/usr/lib/rooter/luci/croncat.sh @@ -0,0 +1,36 @@ +#!/bin/sh + +log() { + logger -t "Croncat" "$@" +} + +> /tmp/crontmp +if [ -e /etc/crontabs/root ]; then + while read -r line; do + if [ -n "$line" ]; then + if [ ${line: -1} == ";" ]; then + echo "$line" >> /tmp/crontmp + fi + fi + done < /etc/crontabs/root +fi + +if [ -f /etc/cronuser ]; then + if [ -f /etc/cronbase ]; then + cat /etc/cronbase /etc/cronuser > /etc/crontabs/root + else + cp /etc/cronuser /etc/crontabs/root + fi +else + if [ -f /etc/cronbase ]; then + cp /etc/cronbase /etc/crontabs/root + else + > /etc/crontabs/root + fi +fi +cat /tmp/crontmp /etc/crontabs/root > /tmp/cronroot +cp /tmp/cronroot /etc/crontabs/root +rm /tmp/crontmp +rm /tmp/cronroot + +/etc/init.d/cron restart diff --git a/rooter/0basicapps/ext-extra/files/usr/lib/rooter/luci/reboot.sh b/rooter/0basicapps/ext-extra/files/usr/lib/rooter/luci/reboot.sh new file mode 100644 index 0000000..eac8962 --- /dev/null +++ b/rooter/0basicapps/ext-extra/files/usr/lib/rooter/luci/reboot.sh @@ -0,0 +1,32 @@ +#!/bin/sh + +log() { + logger -t "Schedule Reboot" "$@" +} + +PARM=$1 + +if [ $PARM = "0" ]; then + HO=$(uci get system.@system[-1].zonename) + if [ -z $HO ]; then + HO="UTC" + fi + uci set schedule.timezone.zonename="$HO" + uci commit schedule +fi + +if [ $PARM = "1" ]; then + sleep 5 + EN=$(uci get schedule.reboot.enable) + if [ $EN = "1" ]; then + SDHOUR=$(uci get schedule.reboot.sdhour) + HOUR=`expr $SDHOUR / 4` + let "TH = $HOUR * 4" + let "TMP1 = $SDHOUR - $TH" + let "MIN = $TMP1 * 15" + echo "$MIN $HOUR * * * sleep 70 && touch /etc/banner && reboot -f" > /etc/cronbase + else + rm -f /etc/cronbase + fi + /usr/lib/rooter/luci/croncat.sh +fi diff --git a/rooter/0basicapps/ext-p910nd/Makefile b/rooter/0basicapps/ext-p910nd/Makefile new file mode 100644 index 0000000..9f7dc57 --- /dev/null +++ b/rooter/0basicapps/ext-p910nd/Makefile @@ -0,0 +1,36 @@ +#Owned by DairyMan@Whirlpool +# +#Copyright GNU act. +include $(TOPDIR)/rules.mk + +PKG_NAME:=ext-p910nd +PKG_VERSION:=1.000 +PKG_RELEASE:=1 + +PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool +include $(INCLUDE_DIR)/package.mk + +define Package/ext-p910nd + SECTION:=utils + CATEGORY:=ROOter + SUBMENU:=Basic Applications + DEPENDS:=+p910nd +kmod-usb-printer +kmod-usb-ohci + TITLE:=Install Print Server + PKGARCH:=all +endef + +define Package/ext-p910nd/description + Helper scripts to install print Server +endef + + +define Build/Compile +endef + +define Package/ext-p910nd/install + $(CP) ./files/* $(1)/ + + +endef + +$(eval $(call BuildPackage,ext-p910nd)) diff --git a/rooter/0basicapps/ext-p910nd/files/etc/uci-defaults/40_luci-p910ndx b/rooter/0basicapps/ext-p910nd/files/etc/uci-defaults/40_luci-p910ndx new file mode 100644 index 0000000..80f6d62 --- /dev/null +++ b/rooter/0basicapps/ext-p910nd/files/etc/uci-defaults/40_luci-p910ndx @@ -0,0 +1,11 @@ +#!/bin/sh + +uci -q batch <<-EOF >/dev/null + delete ucitrack.@p910nd[-1] + add ucitrack p910nd + set ucitrack.@p910nd[-1].init=p910nd + commit ucitrack +EOF + +rm -f /tmp/luci-indexcache +exit 0 diff --git a/rooter/0basicapps/ext-p910nd/files/usr/lib/lua/luci/controller/p910ndx.lua b/rooter/0basicapps/ext-p910nd/files/usr/lib/lua/luci/controller/p910ndx.lua new file mode 100644 index 0000000..c6feee8 --- /dev/null +++ b/rooter/0basicapps/ext-p910nd/files/usr/lib/lua/luci/controller/p910ndx.lua @@ -0,0 +1,18 @@ +-- Copyright 2008 Yanira +-- Licensed to the public under the Apache License 2.0. + +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 + end + + local page + + page = entry({"admin", "services", "p910ndx"}, cbi("p910ndx"), _(translate("Print Server")), 60) + page.dependent = true +end diff --git a/rooter/0basicapps/ext-p910nd/files/usr/lib/lua/luci/model/cbi/p910ndx.lua b/rooter/0basicapps/ext-p910nd/files/usr/lib/lua/luci/model/cbi/p910ndx.lua new file mode 100644 index 0000000..12c4a58 --- /dev/null +++ b/rooter/0basicapps/ext-p910nd/files/usr/lib/lua/luci/model/cbi/p910ndx.lua @@ -0,0 +1,59 @@ +--[[ + +LuCI p910nd +(c) 2008 Yanira +(c) 2012 Jo-Philipp Wich + +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 + +]]-- + +local uci = luci.model.uci.cursor_state() +local net = require "luci.model.network" +local m, s, p, b + +m = Map("p910nd", translate("Print Server"), + translatef("Support for USB Printers.")) + +net = net.init(m.uci) + +s = m:section(TypedSection, "p910nd", translate("Settings")) +s.addremove = true +s.anonymous = true + +s:option(Flag, "enabled", translate("enable")) + +s:option(Value, "device", translate("Device")).rmempty = true + +b = s:option(Value, "bind", translate("Interface"), translate("Specifies the interface to listen on.")) +b.template = "cbi/network_netlist" +b.nocreate = true +b.unspecified = true + +function b.cfgvalue(...) + local v = Value.cfgvalue(...) + if v then + return (net:get_status_by_address(v)) + end +end + +function b.write(self, section, value) + local n = net:get_network(value) + if n and n:ipaddr() then + Value.write(self, section, n:ipaddr()) + end +end + +p = s:option(ListValue, "port", translate("Port"), translate("TCP listener port.")) +p.rmempty = true +for i=0,9 do + p:value(i, 9100+i) +end + +s:option(Flag, "bidirectional", translate("Bidirectional mode")) + +return m diff --git a/rooter/0basicapps/usb-storage/Makefile b/rooter/0basicapps/usb-storage/Makefile new file mode 100644 index 0000000..e2b95c2 --- /dev/null +++ b/rooter/0basicapps/usb-storage/Makefile @@ -0,0 +1,38 @@ +#Owned by DairyMan@Whirlpool +# +#Copyright GNU act. +include $(TOPDIR)/rules.mk + +PKG_NAME:=usb-storage +PKG_VERSION:=1.000 +PKG_RELEASE:=1 + +PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool +include $(INCLUDE_DIR)/package.mk + +define Package/usb-storage + SECTION:=utils + CATEGORY:=ROOter + SUBMENU:=Basic Applications + DEPENDS:= +ntfs-3g +fdisk +kmod-usb-storage \ + +kmod-fs-ext4 +kmod-fs-vfat +kmod-nls-cp437 +kmod-nls-iso8859-1 +kmod-nls-utf8 \ + +block-mount +kmod-fs-exfat +kmod-fs-hfs +hd-idle + TITLE:=Install USB Storage + PKGARCH:=all +endef + +define Package/usb-storage/description + Helper scripts to install USB Storage +endef + + +define Build/Compile +endef + +define Package/usb-storage/install + $(CP) ./files/* $(1)/ + + +endef + +$(eval $(call BuildPackage,usb-storage)) diff --git a/rooter/0basicapps/usb-storage/files/etc/config/umount b/rooter/0basicapps/usb-storage/files/etc/config/umount new file mode 100644 index 0000000..ca8f428 --- /dev/null +++ b/rooter/0basicapps/usb-storage/files/etc/config/umount @@ -0,0 +1,2 @@ +config umount 'umount' + option drive '' diff --git a/rooter/0basicapps/usb-storage/files/etc/hotplug.d/block/20-mount b/rooter/0basicapps/usb-storage/files/etc/hotplug.d/block/20-mount new file mode 100644 index 0000000..961a219 --- /dev/null +++ b/rooter/0basicapps/usb-storage/files/etc/hotplug.d/block/20-mount @@ -0,0 +1,68 @@ +#!/bin/sh /etc/rc.common +. /lib/functions.sh + +log() { + logger -t "20-mount" "$@" +} + +blkdev=`dirname $DEVPATH` +if [ `basename $blkdev` != "block" ]; then + device=`basename $DEVPATH` + if echo $device | grep -q "mtdblock"; then + exit 0 + fi + if [ -e /etc/sda_drop ]; then + source /etc/sda_drop + if echo $device | grep -q "$SDA"; then + exit 0 + fi + fi + if [ ! -e /usr/lib/sdcard/sdcard.sh ]; then + /usr/lib/sdcard/sdcard.sh detect + source /tmp/detect.file + if [ $detect = "1" ]; then + if echo $device | grep -q "mmcblk"; then + exit 0 + fi + fi + fi + if echo $device | grep -q "mmcblk"; then + device1="SDCard"${device:8:2} + else + device1=$device + fi + + case "$ACTION" in + add) + mkdir -p /mnt/$device1 + # vfat & ntfs-3g check + if [ `which fdisk` ]; then + isntfs=`fdisk -l | grep $device | grep NTFS` + isvfat=`fdisk -l | grep $device | grep FAT` + isfuse=`lsmod | grep fuse` + isntfs3g=`which ntfs-3g` + else + isntfs="" + isvfat="" + fi + # mount with ntfs-3g if possible, else with default mount + if [ "$isntfs" -a "$isfuse" -a "$isntfs3g" ]; then + ntfs-3g -o nls=utf8 /dev/$device /mnt/$device1 + log "Mount /mnt/$device as NTFS" + elif [ "$isvfat" ]; then + mount -o rw,sync,umask=002,codepage=437,iocharset=iso8859-1 /dev/$device /mnt/$device1 + log "Mount /mnt/$device as FAT" + else + mount -o rw,sync /dev/$device /mnt/$device1 + log "Mount /mnt/$device as other" + fi + + chmod 777 /mnt/$device1 + chown nobody /mnt/$device1 + + if [ -e /usr/lib/sdcard/sdcard.sh ]; then + /usr/lib/sdcard/sdcard.sh add + fi + ;; + esac +fi \ No newline at end of file diff --git a/rooter/0basicapps/usb-storage/files/etc/hotplug.d/block/30-mount b/rooter/0basicapps/usb-storage/files/etc/hotplug.d/block/30-mount new file mode 100644 index 0000000..7a1f933 --- /dev/null +++ b/rooter/0basicapps/usb-storage/files/etc/hotplug.d/block/30-mount @@ -0,0 +1,88 @@ +#!/bin/sh /etc/rc.common +. /lib/functions.sh +# Copyright (C) 2011 OpenWrt.org + +log() { + logger -t "30-mount" "$@" +} + +sanitize() { + sed -e 's/[[:space:]]\+$//; s/[[:space:]]\+/_/g' "$@" +} + +blkdev=`dirname $DEVPATH` +if [ `basename $blkdev` != "block" ]; then + device=`basename $DEVPATH` + if echo $device | grep -q "mtdblock"; then + exit 0 + fi + if [ ! -e /usr/lib/sdcard/sdcard.sh ]; then + /usr/lib/sdcard/sdcard.sh detect + source /tmp/detect.file + if [ $detect = "1" ]; then + if echo $device | grep -q "mmcblk"; then + exit 0 + fi + fi + fi + if echo $device | grep -q "mmcblk"; then + device1="SDCard"${device:8:2} + else + device1=$device + fi + + if [ -e /etc/sda_drop ]; then + source /etc/sda_drop + if echo $device | grep -q "$SDA"; then + exit 0 + fi + fi + + case "$ACTION" in + add) + MT=$(cat /proc/mounts | grep "$device") + if [ -z $MT ]; then + exit 0 + fi + DEVN=${DEVNAME:0:3} + MODEL=$(sanitize "/sys/block/$DEVN/device/model") + if [ -d /etc/ksmbd ]; then + uci delete ksmbd.$device1 + uci set ksmbd.$device1=share + uci set ksmbd.$device1.name=$device1 + uci set ksmbd.$device1.path=/mnt/$device1 + uci set ksmbd.$device1.read_only=no + uci set ksmbd.$device1.guest_ok=yes + uci set ksmbd.$device1.create_mask='0666' + uci set ksmbd.$device1.dir_mask='0777' + uci commit ksmbd + /etc/init.d/ksmbd restart + log "/mnt/$device1 shared as $device1" + else + if [ -d /etc/samba ]; then + uci delete samba.$device1 + uci set samba.$device1=sambashare + uci set samba.$device1.name=$device1 + uci set samba.$device1.path=/mnt/$device1 + uci set samba.$device1.read_only=no + uci set samba.$device1.guest_ok=yes + uci commit samba + /etc/init.d/samba restart + log "/mnt/$device1 shared as $device1" + fi + fi + ;; + remove) + log "remove /mnt/$device1" + if [ -d /etc/ksmbd ]; then + uci delete ksmbd.$device1 + uci commit ksmbd + else + if [ -d /etc/samba ]; then + uci delete samba.$device1 + uci commit samba + fi + fi + ;; + esac +fi diff --git a/rooter/0basicapps/usb-storage/files/etc/hotplug.d/block/99-mount b/rooter/0basicapps/usb-storage/files/etc/hotplug.d/block/99-mount new file mode 100644 index 0000000..5594607 --- /dev/null +++ b/rooter/0basicapps/usb-storage/files/etc/hotplug.d/block/99-mount @@ -0,0 +1,41 @@ +#!/bin/sh /etc/rc.common +. /lib/functions.sh + +log() { + logger -t "99-mount" "$@" +} + + +blkdev=`dirname $DEVPATH` +if [ `basename $blkdev` != "block" ]; then + device=`basename $DEVPATH` + if echo $device | grep -q "mtdblock"; then + exit 0 + fi + + if [ ! -e /usr/lib/sdcard/sdcard.sh ]; then + /usr/lib/sdcard/sdcard.sh detect + source /tmp/detect.file + if [ $detect = "1" ]; then + if echo $device | grep -q "mmcblk"; then + exit 0 + fi + fi + fi + if echo $device | grep -q "mmcblk"; then + device1="SDCard"${device:8:2} + else + device1=$device + fi + + case "$ACTION" in + remove) + log "remove /mnt/$device1" + umount -l /mnt/$device1 + rm -rf /mnt/$device1 + if [ -e /usr/lib/sdcard/sdcard.sh ]; then + /usr/lib/sdcard/sdcard.sh remove + fi + ;; + esac +fi \ No newline at end of file diff --git a/rooter/0basicapps/usb-storage/files/etc/uci-defaults/40_luci-hd_idle b/rooter/0basicapps/usb-storage/files/etc/uci-defaults/40_luci-hd_idle new file mode 100644 index 0000000..92f4356 --- /dev/null +++ b/rooter/0basicapps/usb-storage/files/etc/uci-defaults/40_luci-hd_idle @@ -0,0 +1,11 @@ +#!/bin/sh + +uci -q batch <<-EOF >/dev/null + delete ucitrack.@hd-idle[-1] + add ucitrack hd-idle + set ucitrack.@hd-idle[-1].init=hd-idle + commit ucitrack +EOF + +rm -f /tmp/luci-indexcache +exit 0 diff --git a/rooter/0basicapps/usb-storage/files/etc/umount b/rooter/0basicapps/usb-storage/files/etc/umount new file mode 100644 index 0000000..8292a0f --- /dev/null +++ b/rooter/0basicapps/usb-storage/files/etc/umount @@ -0,0 +1,18 @@ +#!/bin/sh + +log() { + logger -t "Umount" "$@" +} + +sleep 5 +DRV=$(uci get umount.umount.drive) +if [ -z $DRV ]; then + exit 0 +fi + +umount -l /mnt/$DRV + +rm -rf /mnt/$DRV + +uci set umount.umount.drive='' +uci commit umount diff --git a/rooter/0basicapps/usb-storage/files/usr/lib/lua/luci/controller/hd_idle.lua b/rooter/0basicapps/usb-storage/files/usr/lib/lua/luci/controller/hd_idle.lua new file mode 100644 index 0000000..0cd3229 --- /dev/null +++ b/rooter/0basicapps/usb-storage/files/usr/lib/lua/luci/controller/hd_idle.lua @@ -0,0 +1,17 @@ +-- Copyright 2008 Yanira +-- Licensed to the public under the Apache License 2.0. + +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.dependent = true +end diff --git a/rooter/0basicapps/usb-storage/files/usr/lib/lua/luci/controller/umount.lua b/rooter/0basicapps/usb-storage/files/usr/lib/lua/luci/controller/umount.lua new file mode 100644 index 0000000..37bcf31 --- /dev/null +++ b/rooter/0basicapps/usb-storage/files/usr/lib/lua/luci/controller/umount.lua @@ -0,0 +1,11 @@ +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.dependent = true +end diff --git a/rooter/0basicapps/usb-storage/files/usr/lib/lua/luci/model/cbi/hd_idle.lua b/rooter/0basicapps/usb-storage/files/usr/lib/lua/luci/model/cbi/hd_idle.lua new file mode 100644 index 0000000..1c3c18f --- /dev/null +++ b/rooter/0basicapps/usb-storage/files/usr/lib/lua/luci/model/cbi/hd_idle.lua @@ -0,0 +1,28 @@ +-- Copyright 2008 Yanira +-- Licensed to the public under the Apache License 2.0. + +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.")) + +s = m:section(TypedSection, "hd-idle", translate("Settings")) +s.anonymous = true + +s:option(Flag, "enabled", translate("Enable")) + +disk = s:option(Value, "disk", translate("Disk")) +disk.rmempty = true +for dev in nixio.fs.glob("/dev/[sh]d[a-z]") do + disk:value(nixio.fs.basename(dev)) +end + +s:option(Value, "idle_time_interval", translate("Idle-time")).default = 10 +s.rmempty = true +unit = s:option(ListValue, "idle_time_unit", translate("Idle-time unit")) +unit.default = "minutes" +unit:value("minutes", translate("min")) +unit:value("hours", translate("h")) +unit.rmempty = true + +return m diff --git a/rooter/0basicapps/usb-storage/files/usr/lib/lua/luci/model/cbi/umount.lua b/rooter/0basicapps/usb-storage/files/usr/lib/lua/luci/model/cbi/umount.lua new file mode 100644 index 0000000..334fe7f --- /dev/null +++ b/rooter/0basicapps/usb-storage/files/usr/lib/lua/luci/model/cbi/umount.lua @@ -0,0 +1,20 @@ +require("nixio.fs") + +m = Map("umount", "Safely Eject a Drive", + translate("Safely eject a drive from the router")) + +m.on_after_save = function(self) + luci.sys.call("/etc/umount &") +end + +drv = m:section(TypedSection, "umount", translate("Currently Mounted Drives")) +drv.anonymous = true + +disk = drv:option(Value, "drive", translate(" "), translate("Click Save and Apply to eject drive")) +disk.rmempty = true +for dev in nixio.fs.glob("/mnt/[sh]d[a-z][1-9]") do + dv = nixio.fs.basename(dev) + disk:value(nixio.fs.basename(dev)) +end + +return m \ No newline at end of file diff --git a/rooter/0basicapps/usb-storage/files/usr/lib/sdcard/sdcard.sh b/rooter/0basicapps/usb-storage/files/usr/lib/sdcard/sdcard.sh new file mode 100644 index 0000000..257d915 --- /dev/null +++ b/rooter/0basicapps/usb-storage/files/usr/lib/sdcard/sdcard.sh @@ -0,0 +1,88 @@ +#!/bin/sh + +log() { + logger -t "sdcard" "$@" +} + +h721() { + if [ $1 = "add" ]; then + echo "17" > /sys/class/gpio/export + echo "out" > /sys/class/gpio/gpio17/direction + echo 0 > /sys/class/gpio/gpio17/value + else + echo "17" > /sys/class/gpio/export + echo "out" > /sys/class/gpio/gpio17/direction + echo 1 > /sys/class/gpio/gpio17/value +fi +} + +wg1608() { + if [ $1 = "add" ]; then + echo timer > /sys/class/leds/zbt-wg3526:green:signal/trigger + echo 1000 > /sys/class/leds/zbt-wg3526:green:signal/delay_on + echo 0 > /sys/class/leds/zbt-wg3526:green:signal/delay_off + else + echo timer > /sys/class/leds/zbt-wg3526:green:signal/trigger + echo 0 > /sys/class/leds/zbt-wg3526:green:signal/delay_on + echo 1000 > /sys/class/leds/zbt-wg3526:green:signal/delay_off + fi +} + +ws7915() { + if [ $1 = "add" ]; then + echo timer > /sys/class/leds/sys/trigger + echo 1000 > /sys/class/leds/sys/delay_on + echo 0 > /sys/class/leds/sys/delay_off + else + echo timer > /sys/class/leds/sys/trigger + echo 0 > /sys/class/leds/sys/delay_on + echo 1000 > /sys/class/leds/sys/delay_off + fi +} + +ws1688() { + if [ $1 = "add" ]; then + echo timer > /sys/class/leds/usb/trigger + echo 1000 > /sys/class/leds/usb/delay_on + echo 0 > /sys/class/leds/usb/delay_off + else + echo timer > /sys/class/leds/usb/trigger + echo 0 > /sys/class/leds/usb/delay_on + echo 1000 > /sys/class/leds/usb/delay_off + fi +} + +ACTION=$1 +model=$(cat /tmp/sysinfo/model) + +case $ACTION in + "add"|"remove" ) + mod=$(echo $model | grep "H721") + if [ $mod ]; then + h721 $ACTION + fi + mod=$(echo $model | grep "WG1608") + if [ $mod ]; then + wg1608 $ACTION + fi + mod=$(echo $model | grep "WS7915") + if [ $mod ]; then + ws7915 $ACTION + fi + + mod=$(echo $model | grep "WS1688") + if [ $mod ]; then + ws1688 $ACTION + fi + ;; + "detect" ) + mod=$(echo $model | grep "Raspberry") + if [ $mod ]; then + echo 'detect="'"1"'"' > /tmp/detect.file + else + echo 'detect="'"0"'"' > /tmp/detect.file + fi + ;; +esac + + diff --git a/rooter/0basicsupport/ext-buttons/Makefile b/rooter/0basicsupport/ext-buttons/Makefile new file mode 100644 index 0000000..d4ae835 --- /dev/null +++ b/rooter/0basicsupport/ext-buttons/Makefile @@ -0,0 +1,35 @@ +#Owned by DairyMan@Whirlpool +# +#Copyright GNU act. +include $(TOPDIR)/rules.mk + +PKG_NAME:=ext-buttons +PKG_VERSION:=1.000 +PKG_RELEASE:=1 + +PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool +include $(INCLUDE_DIR)/package.mk + +define Package/ext-buttons + SECTION:=utils + CATEGORY:=ROOter + SUBMENU:=Basic Support + TITLE:=Install button support + PKGARCH:=all +endef + +define Package/ext-buttons/description + Helper scripts to install button support +endef + + +define Build/Compile +endef + +define Package/ext-buttons/install + $(CP) ./files/* $(1)/ + + +endef + +$(eval $(call BuildPackage,ext-buttons)) diff --git a/rooter/0basicsupport/ext-buttons/files/etc/btnaction.sh b/rooter/0basicsupport/ext-buttons/files/etc/btnaction.sh new file mode 100644 index 0000000..82a4e4e --- /dev/null +++ b/rooter/0basicsupport/ext-buttons/files/etc/btnaction.sh @@ -0,0 +1,56 @@ +#!/bin/sh + +FUNC=$1 + +reset_short() { + passwd -d root + reboot -f +} + +reset_long() { + mtd -r erase rootfs_data +} + +wifi() { + STATEFILE="/tmp/wifionoff.state" + + if [ $# -eq 1 ]; then + case $1 in + "up"|"on") + STATE=off + ;; + "down"|"off") + STATE=on + ;; + esac + else + if [ ! -e ${STATEFILE} ]; then + STATE=on + else + . ${STATEFILE} + fi + fi + if [ -z ${STATE} ]; then + STATE=on + fi + + if [ ${STATE} == "on" ]; then + /sbin/wifi down + STATE=off + else + /sbin/wifi up + STATE=on + fi + + echo "STATE=${STATE}" > ${STATEFILE} +} + +if [ $FUNC = "reset_short" ]; then + reset_short +fi +if [ $FUNC = "reset_long" ]; then + reset_long +fi +if [ $FUNC = "wifi" ]; then + wifi $2 +fi diff --git a/rooter/0basicsupport/ext-buttons/files/etc/hotplug.d/button/00-button b/rooter/0basicsupport/ext-buttons/files/etc/hotplug.d/button/00-button new file mode 100644 index 0000000..0efab99 --- /dev/null +++ b/rooter/0basicsupport/ext-buttons/files/etc/hotplug.d/button/00-button @@ -0,0 +1,26 @@ +#!/bin/sh +. /lib/functions.sh + +do_button () { + local button + local action + local handler + local min + local max + + config_get button $1 button + config_get action $1 action + config_get handler $1 handler + config_get min $1 min + config_get max $1 max + + [ "$ACTION" = "$action" -a "$BUTTON" = "$button" -a -n "$handler" ] && { + [ -z "$min" -o -z "$max" ] && eval $handler + [ -n "$min" -a -n "$max" ] && { + [ $min -le $SEEN -a $max -ge $SEEN ] && eval $handler + } + } +} + +config_load system +config_foreach do_button button \ No newline at end of file diff --git a/rooter/0basicsupport/ext-buttons/files/etc/hotplug.d/button/10-buttonchk b/rooter/0basicsupport/ext-buttons/files/etc/hotplug.d/button/10-buttonchk new file mode 100644 index 0000000..ea4f499 --- /dev/null +++ b/rooter/0basicsupport/ext-buttons/files/etc/hotplug.d/button/10-buttonchk @@ -0,0 +1,10 @@ +#!/bin/sh + +log() { + logger -t "Button Checker " "$@" +} + +log "Button Name : $BUTTON Action : $ACTION" + +log "$ACTION $SEEN" + diff --git a/rooter/0basicsupport/ext-buttons/files/etc/init.d/buttons b/rooter/0basicsupport/ext-buttons/files/etc/init.d/buttons new file mode 100644 index 0000000..1901e61 --- /dev/null +++ b/rooter/0basicsupport/ext-buttons/files/etc/init.d/buttons @@ -0,0 +1,16 @@ +#!/bin/sh /etc/rc.common +# Copyright (C) 2006 OpenWrt.org + +log() { + logger -t "Buttons" "$@" +} + +START=98 + +start() { + local BTN=$(uci -q get system.@button[-1].button) +} + +stop() { + log "Stopping Buttons" +} diff --git a/rooter/0basicsupport/ext-buttons/files/usr/lib/lua/luci/controller/buttons.lua b/rooter/0basicsupport/ext-buttons/files/usr/lib/lua/luci/controller/buttons.lua new file mode 100644 index 0000000..70fa838 --- /dev/null +++ b/rooter/0basicsupport/ext-buttons/files/usr/lib/lua/luci/controller/buttons.lua @@ -0,0 +1,14 @@ +module("luci.controller.buttons", package.seeall) + +I18N = require "luci.i18n" +translate = I18N.translate + +function index() + local page + 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 + page = entry({"admin", "system", "buttons"}, cbi("buttons/buttons"), _(translate("Buttons")), 65) + page.dependent = true + end +end diff --git a/rooter/0basicsupport/ext-buttons/files/usr/lib/lua/luci/model/cbi/buttons/buttons.lua b/rooter/0basicsupport/ext-buttons/files/usr/lib/lua/luci/model/cbi/buttons/buttons.lua new file mode 100644 index 0000000..4f37569 --- /dev/null +++ b/rooter/0basicsupport/ext-buttons/files/usr/lib/lua/luci/model/cbi/buttons/buttons.lua @@ -0,0 +1,44 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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$ +]]-- + +m = Map("system", translate("Buttons"), + translate("This page allows the configuration of custom button actions")) + +s = m:section(TypedSection, "button", "") +s.anonymous = true +s.addremove = true + +s:option(Value, "button", translate("Name")) + +act = s:option(ListValue, "action", + translate("Action"), + translate("Specifies the button state to handle")) + +act:value("released") +act:value("pressed") +act.default = "released" + +s:option(Value, "handler", + translate("Handler"), + translate("Path to executable which handles the button event")) + +min = s:option(Value, "min", translate("Minimum hold time")) +min.rmempty = true +min:depends("action", "released") + +max = s:option(Value, "max", translate("Maximum hold time")) +max.rmempty = true +max:depends("action", "released") + +return m \ No newline at end of file diff --git a/rooter/0basicsupport/ext-sms/Makefile b/rooter/0basicsupport/ext-sms/Makefile new file mode 100644 index 0000000..3315be2 --- /dev/null +++ b/rooter/0basicsupport/ext-sms/Makefile @@ -0,0 +1,35 @@ +#Owned by DairyMan@Whirlpool +# +#Copyright GNU act. +include $(TOPDIR)/rules.mk + +PKG_NAME:=ext-sms +PKG_VERSION:=1.000 +PKG_RELEASE:=1 + +PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool +include $(INCLUDE_DIR)/package.mk + +define Package/ext-sms + SECTION:=utils + CATEGORY:=ROOter + SUBMENU:=Basic Support + TITLE:=Install SMS support + PKGARCH:=all +endef + +define Package/ext-sms/description + Helper scripts to install SMS on ROOter +endef + + +define Build/Compile +endef + +define Package/ext-sms/install + $(CP) ./files/* $(1)/ + + +endef + +$(eval $(call BuildPackage,ext-sms)) diff --git a/rooter/0basicsupport/ext-sms/files/usr/lib/lua/luci/controller/sms.lua b/rooter/0basicsupport/ext-sms/files/usr/lib/lua/luci/controller/sms.lua new file mode 100644 index 0000000..aa9dc01 --- /dev/null +++ b/rooter/0basicsupport/ext-sms/files/usr/lib/lua/luci/controller/sms.lua @@ -0,0 +1,160 @@ +module("luci.controller.sms", package.seeall) + +I18N = require "luci.i18n" +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 + + 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")) +end + +function trim(s) + return (s:gsub("^%s*(.-)%s*$", "%1")) +end + +function action_send_sms() + if package.path:find(";/usr/lib/sms/?.lua") == nil then + package.path = package.path .. ";/usr/lib/sms/?.lua" + end + smsnum = luci.model.uci.cursor():get("modem", "general", "smsnum") + local set = luci.http.formvalue("set") + local number = trim(string.sub(set, 1, 20)) + local txt = string.sub(set, 21) + local utf8togsm = require "utf8togsm" + utf8togsm.chktxt(txt) + local msg = utf8togsm["msg"] + local dcs = utf8togsm["dcs"] + txt = utf8togsm["txt"] + local rv = {} + local file = nil + local k = 1 + local status + local rfname = "/tmp/smssendstatus0000" + if msg == nil then + os.execute("if [ -e " .. rfname .. " ]; then rm " ..rfname .. "; fi") + os.execute("lua /usr/lib/sms/sendsms.lua " .. smsnum .. " " .. number .. " " .. dcs .. " " .. txt .. " 0000") + os.execute("sleep 3") + repeat + file = io.open(rfname, "r") + if file == nil then + os.execute("sleep 1") + end + k = k + 1 + until k > 25 or file ~=nil + if file == nil then + status = translate('Sending attempt timed out (fail)') + else + status = file:read("*line") + file:close() + os.remove (rfname) + end + else + status = msg + end + rv["status"] = status + luci.http.prepare_content("application/json") + luci.http.write_json(rv) +end + +function action_del_sms() + local set = tonumber(luci.http.formvalue("set")) + if set ~= nil and set > 0 then + set = set - 1; + smsnum = luci.model.uci.cursor():get("modem", "general", "smsnum") + os.execute("/usr/lib/sms/delsms.sh " .. smsnum .. " " .. set) + os.execute("touch /tmp/smswakeup" .. smsnum) + end +end + +function action_check_read() + local rv ={} + local file + local line + smsnum = luci.model.uci.cursor():get("modem", "general", "smsnum") + conn = "Modem #" .. smsnum + rv["conntype"] = conn + support = luci.model.uci.cursor():get("modem", "modem" .. smsnum, "sms") + rv["ready"] = "0" + rv["menable"] = "0" + rv["mslots"] = "0" + if support == "1" then + rv["ready"] = "1" + result = "/tmp/smsresult" .. smsnum .. ".at" + file = io.open(result, "r") + if file ~= nil then + file:close() + file = io.open("/tmp/smstext" .. smsnum, "r") + if file == nil then + rv["ready"] = "3" + else + rv["menable"] = luci.model.uci.cursor():get("modem", "sms", "menable") + rv["mslots"] = luci.model.uci.cursor():get("modem", "sms", "slots") + rv["ready"] = "2" + local tmp = file:read("*line") + rv["used"] = tmp + tmp = file:read("*line") + rv["max"] = tmp + full = nil + + repeat + for j = 1, 4 do + line = file:read("*line") + if line ~= nil then + if j == 3 then + full = full .. string.char(29) + local i = tonumber(line) + for k = 1, i do + line = file:read("*line") + full = full .. line + if k < i then + full = full .. '
' + end + end + else + if full == nil then + full = line + else + full = full .. string.char(29) .. line + end + end + end + end + until line == nil + file:close() + rv["line"] = full + end + end + end + + luci.http.prepare_content("application/json") + luci.http.write_json(rv) +end + +function action_change_sms() + os.execute("/usr/lib/rooter/luci/modemchge.sh sms 1") +end + +function action_change_smsdn() + os.execute("/usr/lib/rooter/luci/modemchge.sh sms 0") +end + +function action_change_smsflag() + local set = tonumber(luci.http.formvalue("set")) + os.execute("/usr/lib/sms/toggle.sh " .. set) +end + diff --git a/rooter/0basicsupport/ext-sms/files/usr/lib/lua/luci/view/rooter/sms.htm b/rooter/0basicsupport/ext-sms/files/usr/lib/lua/luci/view/rooter/sms.htm new file mode 100644 index 0000000..fda6d81 --- /dev/null +++ b/rooter/0basicsupport/ext-sms/files/usr/lib/lua/luci/view/rooter/sms.htm @@ -0,0 +1,525 @@ +<%+header%> + + + + +
+
+

<%:短信收发页面%>

+
<%:通过模块发送和接收文本消息%>
+
+ <%:通信模块信息%> + + + + + + + +
    + + + +
    + <%:收到的短信%> + + + + + + + + + + + + +
    <%:SIM可存放的短信空间 (条)%>
    <%:已使用的SIM短信空间 (条)%>
     
         
        + + + + + + + + + + + + + + + + +
         
        <%:启用模块到SIM卡的短信传输%>
        + +
        <%:模块上的未读信息数量%>
         
           
           
          + + + + + + + + + + + + +
          <%:已读状态%>
          <%:发件人%>
          <%:Date%>
          <%:时间%>
          <%:短信%>
          + + + + + +
          + +
          + + + + + + + +
          <%:短信内容 :%>
             
            + + + + + + + + +
             
            + + <%:短信会话%> + + + + + + + +
            <%:收件人 :%>
             
            + + + + + + +
            + +
            + + + + + + + +
              
            + + + + + + + +
            <%:短信发送状态 :%>
               
              + +
              + +
              +
              +<%+footer%> + diff --git a/rooter/0basicsupport/ext-sms/files/usr/lib/sms/delsms.sh b/rooter/0basicsupport/ext-sms/files/usr/lib/sms/delsms.sh new file mode 100644 index 0000000..5294092 --- /dev/null +++ b/rooter/0basicsupport/ext-sms/files/usr/lib/sms/delsms.sh @@ -0,0 +1,41 @@ +#!/bin/sh + +ROOTER=/usr/lib/rooter + +log() { + logger -t "Delete SMS" "$@" +} + +CURRMODEM=$1 +shift 1 +SLOTS="$@" + +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}" + for SLOT in $SLOTS + do + ATCMDD="AT+CPMS=\"$SMSLOC\";+CMGD=$SLOT" + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + done + 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}" diff --git a/rooter/0basicsupport/ext-sms/files/usr/lib/sms/pack7bit.lua b/rooter/0basicsupport/ext-sms/files/usr/lib/sms/pack7bit.lua new file mode 100644 index 0000000..bbd5661 --- /dev/null +++ b/rooter/0basicsupport/ext-sms/files/usr/lib/sms/pack7bit.lua @@ -0,0 +1,79 @@ +local pack7bit = {} + +function hasbit(x, p) + return x % (p + p) >= p +end + +function bitand(x, y) + local p = 1; local z = 0; local limit = x > y and x or y + while p <= limit do + if hasbit(x, p) and hasbit(y, p) then + z = z + p + end + p = p + p + end + return z +end + +function bitor(x, y) + local p = 1; local z = 0; local limit = x > y and x or y + while p <= limit do + if hasbit(x, p) or hasbit(y, p) then + z = z + p + end + p = p + p + end + return z +end + +function bitright(x, y) + return math.floor(x / 2 ^ y) +end + +function bitleft(x, y) + return x * 2 ^ y +end + +function pack7bit.pack(udl, txt) + maxb = math.ceil((tonumber(udl, 16) / 8) * 7) + udtab = {} + ii = 1 + jj = 1 + kk = 0 + repeat + ch = tonumber(txt:sub(jj, jj + 1), 16) + if ii == 1 then + udtab[kk + 1] = ch + elseif ii == 2 then + udtab[kk] = bitor(bitleft(bitand(ch, 1), 7), udtab[kk]) + udtab[kk + 1] = bitright(bitand(ch, 126), 1) + elseif ii == 3 then + udtab[kk] = bitor(bitleft(bitand(ch, 3), 6), udtab[kk]) + udtab[kk + 1] = bitright(bitand(ch, 124), 2) + elseif ii == 4 then + udtab[kk] = bitor(bitleft(bitand(ch, 7), 5), udtab[kk]) + udtab[kk + 1] = bitright(bitand(ch, 120), 3) + elseif ii == 5 then + udtab[kk] = bitor(bitleft((bitand(ch, 15)), 4), udtab[kk]) + udtab[kk + 1] = bitright(bitand(ch, 112), 4) + elseif ii == 6 then + udtab[kk] = bitor(bitleft(bitand(ch, 31), 3), udtab[kk]) + udtab[kk + 1] = bitright(bitand(ch, 96), 5) + elseif ii == 7 then + udtab[kk] = bitor(bitleft(bitand(ch, 63), 2), udtab[kk]) + udtab[kk + 1] = bitright(bitand(ch, 64), 6) + else + udtab[kk] = bitor(bitleft(ch, 1), udtab[kk]) + ii = 0 + kk = kk - 1 + end + ii = ii + 1 + jj = jj + 2 + kk = kk + 1 + until jj > #txt + for jj = 1, maxb do + udtab[jj] = string.format("%02X", udtab[jj]) + end + pack7bit["pdu"] = table.concat(udtab) +end +return pack7bit diff --git a/rooter/0basicsupport/ext-sms/files/usr/lib/sms/processsms b/rooter/0basicsupport/ext-sms/files/usr/lib/sms/processsms new file mode 100644 index 0000000..8826bb2 --- /dev/null +++ b/rooter/0basicsupport/ext-sms/files/usr/lib/sms/processsms @@ -0,0 +1,168 @@ +#!/bin/sh + +ROOTER=/usr/lib/rooter + +log() { + logger -t "sms process" "$@" +} + +CURRMODEM=$1 + +log "SMS Supported Modem$CURRMODEM" + +COMMPORT="/dev/ttyUSB"$(uci get modem.modem$CURRMODEM.commport) + +LOCKDIR="/tmp/smslock$CURRMODEM" +PIDFILE="${LOCKDIR}/PID" +rm -rf "${LOCKDIR}" + +idV=$(uci -q get modem.modem$CURRMODEM.idV) +idP=$(uci -q get modem.modem$CURRMODEM.idP) +MODEMID="$idV${idP:0:3}" + +ATCMDD="AT+CMGF=0" +OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") +sleep 1 +ATCMDD="AT+CPMS=\"SM\",\"SM\",\"SM\"" +OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") +MAXED=$(echo "$OX" | cut -d, -f2 | grep -o "[0-9]\{1,3\}") +if [ "$MAXED" == "0" -a "$MODEMID" != "119968a" ]; then + ATCMDD="AT+CPMS=\"ME\",\"ME\",\"ME\"" + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + uci set modem.modem$CURRMODEM.smsloc="ME" + SMSLOC="ME" + MEM3="ME" +else + uci set modem.modem$CURRMODEM.smsloc="SM" + SMSLOC="SM" + MEM3="SM" +fi +sleep 1 +uci set modem.modem$CURRMODEM.smsnum=999 +uci commit modem +ATCMDD="AT+CPMS=\"ME\"" +OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") +MESC=$(echo "$OX" | grep -o "+CPMS:.*" | awk -F, '{print $1}' | grep -o "[0-9]\{1,3\}") +METC=$(echo "$OX" | grep -o "+CPMS:.*" | awk -F, '{print $2}' | grep -o "[0-9]\{1,3\}") +MESLOT="0" +MESCc="" +if [ "x$MESC" = "x" ]; then + MESC="0" +fi +if [ "x$METC" = "x" ]; then + METC="0" + MESC="0" + SMSLOC="SM" +fi +uci set modem.sms.slots=$MESC +uci commit modem +sleep 1 + +rm -f /tmp/smsresult$CURRMODEM".at" +> /tmp/smsslots$CURRMODEM +HH=$(date +%H) + +while true; do + SLEEP="20" + while true; do + if mkdir "${LOCKDIR}" &>/dev/null; then + echo "$$" > "${PIDFILE}" + if [ "$METC" != "0" ]; then + ATCMDD="AT+CPMS=\"ME\",\"$SMSLOC\",\"$MEM3\"" + SX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + USED=$(echo "$SX" | cut -d, -f1 | grep -o "[0-9]\{1,3\}") + MESCc="$USED" + MAXED=$(echo "$SX" | cut -d, -f2 | grep -o "[0-9]\{1,3\}") + fi + if [ $SMSLOC == "SM" ]; then + ATCMDD="AT+CPMS=\"SM\",\"$SMSLOC\",\"$MEM3\"" + SX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + USED=$(echo "$SX" | cut -d, -f1 | grep -o "[0-9]\{1,3\}") + MAXED=$(echo "$SX" | cut -d, -f2 | grep -o "[0-9]\{1,3\}") + if [ -n "$MESCc" -a "$MESCc" != "$MESC" ]; then + MESC=$MESCc + uci set modem.sms.slots=$MESC + uci commit modem + fi + if [ $USED == $MAXED -a $MEM3 == "SM" ]; then + ATCMDD="AT+CPMS=\"SM\",\"SM\",\"ME\"" + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + MEM3="ME" + else + if [ $USED != $MAXED -a $MEM3 == "ME" ]; then + ATCMDD="AT+CPMS=\"SM\",\"SM\",\"SM\"" + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + MEM3="SM" + fi + fi + fi + if [ $MAXED -eq 0 ]; then + SLEEP="900" + fi + if [ $USED -eq $(uci get modem.modem$CURRMODEM.smsnum) ] && [ $HH -eq $(date +%H) ]; then + if [ $MEM3 == "SM" -a $USED -lt $MAXED -a $MESC -gt 0 -a $(uci -q get modem.sms.menable) == 1 ]; then + ATCMDD="AT+CPMS=\"ME\";+CMGR=$MESLOT;+CPMS=\"SM\"" + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + Rstat=$(echo "$OX" | grep -o "+CMGR:[^,]\+" | grep -o "[0-3]") + PDU=$(echo "$OX" | grep -o "[0-9A-F]\{30,\}") + PDUL=$(echo "$OX" | grep -o "+CMGR:.*" | grep -o ",[0-9]\{1,\}" | grep -o "[0-9]\{1,3\}") + if [ -n "$PDU" -a -n "$PDUL" -a -n "$Rstat" ]; then + if [ ${#PDUL} -eq 2 ]; then + PDUL="0$PDUL" + fi + ATCMDD="$PDUL,SM,$Rstat,$PDU" + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "smswrite.gcom" "$CURRMODEM" "$ATCMDD") + MREF=$(echo "$OX" | grep -o "[0-9]\{1,3\}") + if [ ${#MREF} -gt 0 ]; then + echo "$MREF" >> /tmp/smsslots$CURRMODEM + ATCMDD="AT+CPMS=\"ME\";+CMGD=$MESLOT;+CPMS=\"SM\"" + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + fi + MESC=$(($MESC - 1)) + uci set modem.sms.slots=$MESC + uci commit modem + SLEEP="5" + fi + MESLOT=$(($MESLOT + 1)) + if [ $MESLOT -gt $METC -o $MESC == "0" ]; then + MESLOT="0" + fi + fi + else + log "Reread SMS Messages on Modem $CURRMODEM" + echo "$SX" > /tmp/smstemp$CURRMODEM + ATCMDD="AT+CMGL=4" + SX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + SX=$(echo "$SX" | sed -e "s/+CMGL:/+CMGL: /g") + echo "$SX" >> /tmp/smstemp$CURRMODEM + uci set modem.modem$CURRMODEM.smsnum=$USED + uci commit modem + mv /tmp/smstemp$CURRMODEM /tmp/smsresult$CURRMODEM.at + lua /usr/lib/sms/smsread.lua $CURRMODEM + HH=$(date +%H) + SLEEP="5" + fi + 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}" + n=1 + until [ $n -ge $SLEEP ] + do + sleep 1 + if [ -e /tmp/smswakeup$CURRMODEM ]; then + rm /tmp/smswakeup$CURRMODEM + n=$(( $n + $SLEEP )) + else + n=$(( $n + 1 )) + fi + done +done diff --git a/rooter/0basicsupport/ext-sms/files/usr/lib/sms/sendsms.lua b/rooter/0basicsupport/ext-sms/files/usr/lib/sms/sendsms.lua new file mode 100644 index 0000000..baee895 --- /dev/null +++ b/rooter/0basicsupport/ext-sms/files/usr/lib/sms/sendsms.lua @@ -0,0 +1,41 @@ +#!/usr/bin/lua + +modem = arg[1] +addr = arg[2] +dcs = arg[3] +txt = arg[4] +suffix = arg[5] + +if package.path:find(";/usr/lib/sms/?.lua") == nil then + package.path = package.path .. ";/usr/lib/sms/?.lua" +end + +local pack7bit = require "pack7bit" + +udl = string.format("%02X", math.floor(#txt / 2)) +da = "81" +if addr:sub(1, 1) == "+" then + da = "91" + addr = addr:sub(2) +elseif addr:sub(1, 1) == "-" then + addr = addr:sub(2) +end +da = string.format("%02X", #addr) .. da +if (#addr % 2) > 0 then + addr = addr .. "F" +end +k = #addr +j = 1 +repeat + da = da .. addr:sub(j + 1, j + 1) .. addr:sub(j, j) + j = j + 2 +until j > k +if dcs == "00" then + pack7bit.pack(udl, txt) + ud = pack7bit["pdu"] +else + ud = txt +end +pdu = "001100" .. da .. "00" .. dcs .. "AD" .. udl .. ud +pdul = string.format("%03d", (math.floor(#pdu / 2) - 1)) +os.execute("/usr/lib/sms/sendsms.sh " .. modem .. " " .. pdul .. "," .. suffix .. "," .. pdu .. " &") diff --git a/rooter/0basicsupport/ext-sms/files/usr/lib/sms/sendsms.sh b/rooter/0basicsupport/ext-sms/files/usr/lib/sms/sendsms.sh new file mode 100644 index 0000000..fad0e9c --- /dev/null +++ b/rooter/0basicsupport/ext-sms/files/usr/lib/sms/sendsms.sh @@ -0,0 +1,10 @@ +#!/bin/sh + +ROOTER=/usr/lib/rooter + +CURRMODEM=$1 +ATCMDD=$2 + +COMMPORT="/dev/ttyUSB"$(uci get modem.modem$CURRMODEM.commport) + +OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "sendsms-at.gcom" "$CURRMODEM" "$ATCMDD") diff --git a/rooter/0basicsupport/ext-sms/files/usr/lib/sms/smsout.lua b/rooter/0basicsupport/ext-sms/files/usr/lib/sms/smsout.lua new file mode 100644 index 0000000..3237ca5 --- /dev/null +++ b/rooter/0basicsupport/ext-sms/files/usr/lib/sms/smsout.lua @@ -0,0 +1,24 @@ +#!/usr/bin/lua + +local modem = arg[1] +local dest = arg[2] +local txt = arg[3] +local pid = arg[4] +local rfname = "/tmp/smssendstatus" .. pid + +if package.path:find(";/usr/lib/sms/?.lua") == nil then + package.path = package.path .. ";/usr/lib/sms/?.lua" +end + +local utf8togsm = require "utf8togsm" +utf8togsm.chktxt(txt) +local msg = utf8togsm["msg"] +local dcs = utf8togsm["dcs"] +txt = utf8togsm["txt"] + +if msg == nil then + os.execute("if [ -e " .. rfname .. " ]; then rm " ..rfname .. "; fi") + os.execute("lua /usr/lib/sms/sendsms.lua " .. modem .. " " .. dest .. " " .. dcs .. " " .. txt .. " " .. pid) +else + os.execute('echo "SMS sending failed - text is too long" > ' .. rfname) +end diff --git a/rooter/0basicsupport/ext-sms/files/usr/lib/sms/smsout.sh b/rooter/0basicsupport/ext-sms/files/usr/lib/sms/smsout.sh new file mode 100644 index 0000000..2c28887 --- /dev/null +++ b/rooter/0basicsupport/ext-sms/files/usr/lib/sms/smsout.sh @@ -0,0 +1,38 @@ +#!/bin/sh + +ROOTER=/usr/lib/rooter + +log() { + logger -t "sms process" "$@" +} + +CURRMODEM=$(uci get modem.general.smsnum) + +DEST="$1" +shift 1 +TXT="$@" +MYPID=$(printf "%05d" $$) +MYPID=$(printf "${MYPID:1:4}") +RESFILE="/tmp/smssendstatus"$MYPID + +lua /usr/lib/sms/smsout.lua $CURRMODEM $DEST "$TXT" $MYPID +sleep 5 +COUNT=0 +XSTATUS=1 +RES="SMS sending failed, timeout reading result" +while [ $COUNT -lt 15 ]; do + if [ -e $RESFILE ]; then + read RES < $RESFILE + if [ "${RES:0:9}" = "SMS sent," ]; then + XSTATUS=0 + fi + COUNT=999 + rm $RESFILE + else + sleep 2 + fi + COUNT=$(($COUNT + 1)) +done +log "$RES" +echo "$RES" +exit $XSTATUS diff --git a/rooter/0basicsupport/ext-sms/files/usr/lib/sms/smsread.lua b/rooter/0basicsupport/ext-sms/files/usr/lib/sms/smsread.lua new file mode 100644 index 0000000..c881724 --- /dev/null +++ b/rooter/0basicsupport/ext-sms/files/usr/lib/sms/smsread.lua @@ -0,0 +1,862 @@ +#!/usr/bin/lua + +senders2delete = {} +deletebinaries = false + +modemn = arg[1] + +local smsresult = "/tmp/smsresult" .. modemn .. ".at" +local smsslots = "/tmp/smsslots" .. modemn +local smstime = "/tmp/smstime" .. modemn +local t = {} +local tptr +local m_pdu_ptr +local m_pdu +local m_smsc +local m_with_udh +local m_report +local m_number +local m_replace +local m_alphabet +local m_dcs +local m_flash +local m_date +local m_time +local m_text +local m_concat +local m_read +local m_index +local g_table1 = {} +local g_table2 = {} + +local max_smsc = 64 +local max_number = 64 +local max_udh_data = 512 +surrogate = 0 + +function reset() + m_smsc = nil + m_with_udh = 0 + m_report = 0 + m_number = nil + m_replace = 0 + m_alphabet = -1 + m_flash = 0 + m_date = nil + m_time = nil + m_text = nil + m_concat = nil +end + +function hasbit(x, p) + return x % (p + p) >= p +end + +function bitor(x, y) + local p = 1; local z = 0; local limit = x > y and x or y + while p <= limit do + if hasbit(x, p) or hasbit(y, p) then + z = z + p + end + p = p + p + end + return z +end + +function bitand(x, y) + local p = 1; local z = 0; local limit = x > y and x or y + while p <= limit do + if hasbit(x, p) and hasbit(y, p) then + z = z + p + end + p = p + p + end + return z +end + +function bitright(x, y) + return math.floor(x / 2 ^ y) +end + +function bitleft(x, y) + return x * 2 ^ y +end + +function ocount(x, y) + local j = 0 + local i = x:find(y, 0) + while i ~= nil do + i = x:find(y, i + 1) + j = j + 1 + end + return j +end + +printf = function(s,...) + if echo == 0 then + io.write(s:format(...)) + else + ss = s:format(...) + os.execute("/usr/lib/rooter/logprint.sh " .. ss) + end +end + +function isxdigit(digit) + if digit == nil then + return 0 + end + if digit >= 48 and digit <= 57 then + return 1 + end + if digit >= 97 and digit <= 102 then + return 1 + end + if digit >= 65 and digit <= 70 then + return 1 + end + return 0 +end + +function isdigit(digit) + if digit >= 48 and digit <= 57 then + return 1 + end + return 0 +end + +function octet2bin(octet) + result = 0 + if octet:byte(1) > 57 then + result = result + octet:byte(1) - 55 + else + result = result + octet:byte(1) - 48 + end + result = result * 16 + if octet:byte(2) > 57 then + result = result + octet:byte(2) - 55 + else + result = result + octet:byte(2) - 48 + end + return result +end + +function octet2bin_check(octet) + if octet:byte(1) == 0 then + return -1 + end + if octet:byte(2) == 0 then + return -2 + end + if isxdigit(octet:byte(1)) == 0 then + return -3 + end + if isxdigit(octet:byte(2)) == 0 then + return -4 + end + return octet2bin(octet) +end + +function swapchars(sstring) + local length = sstring:len() + local xstring = nil + local i = 1 + while i < length do + c1 = sstring:sub(i, i) + c2 = sstring:sub(i+1, i+1) + if xstring == nil then + xstring = c2 .. c1 + else + xstring = xstring .. c2 .. c1 + end + i = i + 2 + end + return xstring +end + +function parseSMSC() + m_pdu_ptr = m_pdu + local length = octet2bin_check(m_pdu_ptr) + if length < 0 then + return -1 + end + if length == 0 then + m_smsc = "" + m_pdu_ptr = m_pdu_ptr:sub(3) + return 1 + end + if length < 2 or length > max_smsc then + return -1 + end + length = (length * 2) - 2 + local mlen = m_pdu:len() + if mlen < (length + 4) then + return -1 + end + m_pdu_ptr = m_pdu_ptr:sub(3) + local addr_type = octet2bin_check(m_pdu_ptr) + if addr_type < 0 then + return -1 + end + if addr_type < 0x80 then + return -1 + end + m_pdu_ptr = m_pdu_ptr:sub(3) + m_smsc = m_pdu_ptr:sub(0, length) + m_smsc = swapchars(m_smsc) + if addr_type < 0x90 then + for j=1, length do + if isxdigit(m_smsc:byte(j)) == 0 then + return -1 + end + end + else + if m_smsc:byte(length) == 70 then + m_smsc = m_smsc:sub(1, length-1) + end + local leng = m_smsc:len() + for j=1,leng do + if isdigit(m_smsc:byte(j)) == 0 then + return -1 + end + end + end + m_pdu_ptr = m_pdu_ptr:sub(length + 1) + return 1 +end + +function explainAddressType(octet_char, octet_int) + local result + if octet_char ~= nil then + result = octet2bin_check(octet_char) + else + result = octet_int + end + return result +end + +function concatinfo(x) + while #x > 9 do + if x:sub(1, 4) == '0003' then + if x:sub(7, 10) ~= '0101' then + m_concat = 'Msg# ' .. tonumber(x:sub(5, 6), 16) + m_concat = m_concat .. ',' .. tonumber(x:sub(9, 10), 16) + m_concat = m_concat .. '/' .. tonumber(x:sub(7, 8), 16) + end + x = "" + elseif x:sub(1, 4) == '0804' then + if x:sub(9, 12) ~= '0101' then + m_concat = 'Msg# ' .. tonumber(x:sub(5, 8), 16) + m_concat = m_concat .. ',' .. tonumber(x:sub(11, 12), 16) + m_concat = m_concat .. '/' .. tonumber(x:sub(9, 10), 16) + end + x = "" + else + local iel = tonumber(x:sub(3, 4), 16) + x = x:sub(5 + iel * 2) + end + end +end + +function pdu2binary(pdu, with_udh) + local skip_octets = 0 + local octetcounter + m_text = '' + local octets = octet2bin_check(pdu) + local last_i = 0 + if octets < 0 then + return -1 + end + if with_udh > 0 then + local pdu2 = pdu:sub(3) + local udhl = tonumber(pdu2:sub(1, 2), 16) + concatinfo(pdu2:sub(3, (udhl + 1) * 2)) + local udhsize = octet2bin_check(pdu2) + if udhsize < 0 then + return -1 + end + skip_octets = udhsize + 1 + end + for octetcounter = 0, (octets - skip_octets - 1) do + local pdu2 = pdu:sub((octetcounter * 2) + 3 + (skip_octets * 2)) + local i = octet2bin_check(pdu2) + if i < 0 then + return -1 + end + if m_alphabet == 2 then + if (2 + octetcounter) % 2 == 0 then + last_i = i + else + m_text = word2utf8(bitor(bitleft(last_i, 8), i), m_text) + end + else + if i < 32 or i > 127 then + i = 0x25A1 + end + m_text = word2utf8(i, m_text) + end + end + return (octets - skip_octets) +end + +function pdu2text(pdu, with_udh) + local result + local octetcounter + local skip_characters = 0 + local binary = 0 + m_text = '' + local septets = octet2bin_check(pdu) + if septets < 0 then + return -1 + end + if with_udh > 0 then + local pdu2 = pdu:sub(3) + local udhl = tonumber(pdu2:sub(1, 2), 16) + concatinfo(pdu2:sub(3, (udhl + 1) * 2)) + local udhsize = octet2bin_check(pdu2) + skip_characters = math.floor((((udhsize+1)*8)+6)/7) + end + local octets = math.floor((septets * 7 + 7) / 8) + local bitposition = 0 + local byteposition + local byteoffset + local i + local g_table_nbr = 1 + octetcounter = 0 + for charcounter=0,septets-1 do + local c = 0 + for bitcounter=0,6 do + byteposition = math.floor(bitposition / 8) + byteoffset = bitposition % 8 + while (byteposition >= octetcounter) and (octetcounter < octets) do + local pdu2 = pdu:sub((octetcounter * 2) + 3) + i = octet2bin_check(pdu2) + if i < 0 then + return -2 + end + binary = i + octetcounter = octetcounter + 1 + end + if bitand(binary, (2^byteoffset)) > 0 then + c = bitor(c, 128) + end + bitposition = bitposition + 1 + c = bitand(math.floor(c / 2), 127) + end + c = gsm2byte(c) + if charcounter >= skip_characters and c ~= 27 then + m_text = word2utf8(c, m_text) + end + end + return 1 +end + +function gsm2byte(ch) + if g_table_nbr == 2 then + if g_table2[ch] == nil then + ch = 63 + else + ch = g_table2[ch] + end + g_table_nbr = 1 + else + if ch == 27 then + g_table_nbr = 2 + else + if g_table1[ch] ~= nil then + ch = g_table1[ch] + end + end + end + return ch +end + +function word2utf8(i, txt) + if surrogate > 0 then + if i >= 0xDC00 and i <= 0xDFFF then + local ii = 0x10000 + bitand(i, 0x3FF) + bitleft(bitand(surrogate, 0x3FF), 10) + txt = txt .. string.char(bitor(0xF0, bitright(bitand(ii, 0x1C0000), 18))) + txt = txt .. string.char(bitor(0x80, bitright(bitand(ii, 0x3F000), 12))) + txt = txt .. string.char(bitor(0x80, bitright(bitand(ii, 0xFC0), 6))) + txt = txt .. string.char(bitor(0x80, bitand(ii, 0x3F))) + else + txt = txt .. string.char(0xe2) .. string.char(0x96) .. string.char(0xa1) + end + surrogate = 0 + elseif i >= 0xD800 and i <= 0xDBFF then + surrogate = i + elseif i >= 0xDC00 and i <= 0xDFFF then + txt = txt .. string.char(0xe2) .. string.char(0x96) .. string.char(0xa1) + elseif i < 0x80 then + txt = txt .. string.char(i) + elseif i < 0x800 then + txt = txt .. string.char(bitor(0xC0, bitright(bitand(i, 0x7C0), 6))) + txt = txt .. string.char(bitor(0x80, bitand(i, 0x3F))) + else + if i == 0x2029 then + txt = txt .. string.char(10) + else + txt = txt .. string.char(bitor(0xE0, bitright(bitand(i, 0xF000), 12))) + txt = txt .. string.char(bitor(0x80, bitright(bitand(i, 0xFC0), 6))) + txt = txt .. string.char(bitor(0x80, bitand(i, 0x3F))) + end + end + return txt +end + +function parseDeliver() + if m_pdu_ptr:len() < 4 then + return 0 + end + local padding = 0 + local length = octet2bin_check(m_pdu_ptr) + local timezone + if length < 0 or length > max_number then + return 0 + end +-- Sender Address + if length == 0 then + m_pdu_ptr = m_pdu_ptr:sub(5) + else + padding = length % 2 + m_pdu_ptr = m_pdu_ptr:sub(3) + local addr_type = explainAddressType(m_pdu_ptr, 0) + if addr_type < 0 then + return 0 + end + if addr_type < 0x80 then + return 0 + end + m_pdu_ptr = m_pdu_ptr:sub(3) + if bitand(addr_type, 112) == 80 then + if m_pdu_ptr:len() < (length + padding) then + return 0 + end + local htmp = string.format("%x", math.floor((length * 4) / 7)) + if htmp:len() < 2 then + htmp = "0" .. htmp + end + htmp = htmp:upper() + local tpdu = htmp .. m_pdu_ptr + local res = pdu2text(tpdu, 0) + if res < 0 then + return 0 + end + m_number = string.gsub(m_text, "\n", " ") + m_text = nil + else + m_number = m_pdu_ptr:sub(1, length + padding + 1) + m_number = swapchars(m_number) + if m_number:byte(length + padding) == 70 then + m_number = m_number:sub(1, length + padding - 1) + end + if addr_type == 145 then + m_number = "+" .. m_number + end + end + end + m_pdu_ptr = m_pdu_ptr:sub(length + padding + 1) + if m_pdu_ptr:len() < 20 then + return 0 + end +-- PID + local byte_buf = octet2bin_check(m_pdu_ptr) + if byte_buf < 0 then + return 0 + end + if bitand(byte_buf, 0xF8) == 0x40 then + m_replace = bitand(byte_buf, 0x07) + end + m_pdu_ptr = m_pdu_ptr:sub(3) +-- Alphabet + byte_buf = octet2bin_check(m_pdu_ptr) + if byte_buf < 0 then + return 0 + end + m_alphabet = math.floor(bitand(byte_buf, 0x0C) / 4) + if m_alphabet == 3 then + return 0 + end + if m_alphabet == 0 then + m_alphabet = -1 + end +-- DCS, Flash Msg + m_dcs = byte_buf + if bitand(byte_buf, 0x10) > 0 then + if bitand(byte_buf, 0x01) > 0 then + m_flash = 1 + end + end + m_pdu_ptr = m_pdu_ptr:sub(3) +-- Date + local str_buf = m_pdu_ptr:sub(2,2) .. m_pdu_ptr:sub(1,1) .. "-" .. m_pdu_ptr:sub(4,4) .. m_pdu_ptr:sub(3,3) .. "-" .. m_pdu_ptr:sub(6,6) .. m_pdu_ptr:sub(5,5) + if (not isdigit(m_pdu_ptr:byte(1))) or (not isdigit(m_pdu_ptr:byte(2))) or (not isdigit(m_pdu_ptr:byte(3))) or (not isdigit(m_pdu_ptr:byte(4))) or (not isdigit(m_pdu_ptr:byte(5))) or (not isdigit(m_pdu_ptr:byte(6))) then + return 0 + end + m_date = str_buf + m_pdu_ptr = m_pdu_ptr:sub(7) +-- Time + str_buf = m_pdu_ptr:sub(2,2) .. m_pdu_ptr:sub(1,1) .. ":" .. m_pdu_ptr:sub(4,4) .. m_pdu_ptr:sub(3,3) .. ":" .. m_pdu_ptr:sub(6,6) .. m_pdu_ptr:sub(5,5) + if (not isdigit(m_pdu_ptr:byte(1))) or (not isdigit(m_pdu_ptr:byte(2))) or (not isdigit(m_pdu_ptr:byte(3))) or (not isdigit(m_pdu_ptr:byte(4))) or (not isdigit(m_pdu_ptr:byte(5))) or (not isdigit(m_pdu_ptr:byte(6))) then + return 0 + end + if tonumber(m_pdu_ptr:sub(8,8), 16) > 7 then + timezone = '-' .. ((tonumber(m_pdu_ptr:sub(8, 8), 16) - 8) .. tonumber(m_pdu_ptr:sub(7, 7), 16)) / 4 + else + timezone = '+' .. (m_pdu_ptr:sub(8, 8) .. tonumber(m_pdu_ptr:sub(7, 7), 16)) / 4 + end + if timezone:sub(-2, -1) == '.0' then + timezone = timezone:sub(1, -3) + end + m_time = str_buf .. ' ' .. timezone .. 'h' + m_pdu_ptr = m_pdu_ptr:sub(7) + if octet2bin_check(m_pdu_ptr) < 0 then + return 0 + end + m_pdu_ptr = m_pdu_ptr:sub(3) + +-- Text + local result = 0 + local bin_udh = 1 + if m_alphabet <= 0 then + result = pdu2text(m_pdu_ptr, m_with_udh) + return result + else + result = pdu2binary(m_pdu_ptr, m_with_udh) + return result + end + return 1 +end + +function parseStatusReport() + if m_pdu_ptr:len() < 6 then + return 0 + end + local messageid = octet2bin_check(m_pdu_ptr) + if messageid < 0 then + return 0 + end + m_pdu_ptr = m_pdu_ptr:sub(3) + local length = octet2bin_check(m_pdu_ptr) + if length < 1 or length > max_number then + return 0 + end + local padding = length % 2 + m_pdu_ptr = m_pdu_ptr:sub(3) + local addr_type = explainAddressType(m_pdu_ptr, 0) + if addr_type < 0x80 then + return 0 + end + m_pdu_ptr = m_pdu_ptr:sub(3) + if bitand(addr_type, 112) == 80 then + if m_pdu_ptr:len() < (length + padding) then + return 0 + end + local htmp = string.format("%x", math.floor((length * 4) / 7)) + if htmp:len() < 2 then + htmp = "0" .. htmp + end + local tpdu = htmp .. m_pdu_ptr + local res = pdu2text(tpdu, 0) + if res < 0 then + return 0 + end + m_number = m_text + m_text = nil + else + m_number = m_pdu_ptr:sub(1, length + padding + 1) + m_number = swapchars(m_number) + if m_number:byte(length + padding) == 70 then + m_number = m_number:sub(1, length + padding - 1) + end + end + m_pdu_ptr = m_pdu_ptr:sub(length + padding + 1) + if m_pdu_ptr:len() < 14 then + return 0 + end +-- Date + local str_buf = m_pdu_ptr:sub(2,2) .. m_pdu_ptr:sub(1,1) .. "-" .. m_pdu_ptr:sub(4,4) .. m_pdu_ptr:sub(3,3) .. "-" .. m_pdu_ptr:sub(6,6) .. m_pdu_ptr:sub(5,5) + if (not isdigit(m_pdu_ptr:byte(1))) or (not isdigit(m_pdu_ptr:byte(2))) or (not isdigit(m_pdu_ptr:byte(3))) or (not isdigit(m_pdu_ptr:byte(4))) or (not isdigit(m_pdu_ptr:byte(5))) or (not isdigit(m_pdu_ptr:byte(6))) then + return 0 + end + m_date = str_buf + m_pdu_ptr = m_pdu_ptr:sub(7) +-- Time + str_buf = m_pdu_ptr:sub(2,2) .. m_pdu_ptr:sub(1,1) .. ":" .. m_pdu_ptr:sub(4,4) .. m_pdu_ptr:sub(3,3) .. ":" .. m_pdu_ptr:sub(6,6) .. m_pdu_ptr:sub(5,5) + if (not isdigit(m_pdu_ptr:byte(1))) or (not isdigit(m_pdu_ptr:byte(2))) or (not isdigit(m_pdu_ptr:byte(3))) or (not isdigit(m_pdu_ptr:byte(4))) or (not isdigit(m_pdu_ptr:byte(5))) or (not isdigit(m_pdu_ptr:byte(6))) then + return 0 + end + m_time = str_buf + m_pdu_ptr = m_pdu_ptr:sub(7) + if octet2bin_check(m_pdu_ptr) < 0 then + return 0 + end + m_pdu_ptr = m_pdu_ptr:sub(3) +-- Discharge Date + local str_buf = m_pdu_ptr:sub(2,2) .. m_pdu_ptr:sub(1,1) .. "-" .. m_pdu_ptr:sub(4,4) .. m_pdu_ptr:sub(3,3) .. "-" .. m_pdu_ptr:sub(6,6) .. m_pdu_ptr:sub(5,5) + if (not isdigit(m_pdu_ptr:byte(1))) or (not isdigit(m_pdu_ptr:byte(2))) or (not isdigit(m_pdu_ptr:byte(3))) or (not isdigit(m_pdu_ptr:byte(4))) or (not isdigit(m_pdu_ptr:byte(5))) or (not isdigit(m_pdu_ptr:byte(6))) then + return 0 + end + local d_date = str_buf + m_pdu_ptr = m_pdu_ptr:sub(7) +-- Time + str_buf = m_pdu_ptr:sub(2,2) .. m_pdu_ptr:sub(1,1) .. ":" .. m_pdu_ptr:sub(4,4) .. m_pdu_ptr:sub(3,3) .. ":" .. m_pdu_ptr:sub(6,6) .. m_pdu_ptr:sub(5,5) + if (not isdigit(m_pdu_ptr:byte(1))) or (not isdigit(m_pdu_ptr:byte(2))) or (not isdigit(m_pdu_ptr:byte(3))) or (not isdigit(m_pdu_ptr:byte(4))) or (not isdigit(m_pdu_ptr:byte(5))) or (not isdigit(m_pdu_ptr:byte(6))) then + return 0 + end + local d_time = str_buf + m_pdu_ptr = m_pdu_ptr:sub(7) + if octet2bin_check(m_pdu_ptr) < 0 then + return 0 + end + m_pdu_ptr = m_pdu_ptr:sub(3) + local status = octet2bin_check(m_pdu_ptr) + if status < 0 then + return 0 + end + m_text = string.format("Discharge Timestamp: %s %s Message ID: %d Status: %d", d_date, d_time, messageid, status) + return 1 +end + +function parse() + local flag = parseSMSC() + if flag ~= 1 then + return 0 + end + local tmp = octet2bin_check(m_pdu_ptr) + if tmp < 0 then + return 0 + end + if bitand(tmp, 0x40) > 0 then + m_with_udh = 1 + end + if bitand(tmp, 0x20) > 0 then + m_report = 1 + end + local type = bitand(tmp, 3) + if type == 0 then + m_pdu_ptr = m_pdu_ptr:sub(3) + local result = parseDeliver() + if result < 1 then + return 0 + end + else + if type == 2 then + m_pdu_ptr = m_pdu_ptr:sub(3) + local result = parseStatusReport() + return result + else + return 0 + end + end + return 1 +end + +function trim(s) + return (s:gsub("^%s*(.-)%s*$", "%1")) +end + +function readpdu(pdu) + m_pdu = pdu + m_pdu_ptr = m_pdu + reset() + local flag = parse() + if flag > 0 then + t[tptr] = m_index + t[tptr+1] = m_read + t[tptr+2] = m_number + if string.find(delsend, gschar .. m_number .. gschar, 1, true) then + delslots = delslots .. m_index .. " " + else + if m_dcs == 245 and deletebinaries then + delslots = delslots .. m_index .. " " + end + end + t[tptr+3] = m_date + t[tptr+4] = m_time + if m_concat ~= nil then + m_text = m_concat .. '\n' .. m_text + end + t[tptr+5] = m_text + tptr = tptr + 6 + end +end + +local max_msg = "0" +local used_msg = "0" +gschar = string.char(29) +delsend = gschar .. table.concat(senders2delete, gschar) .. gschar +delslots = "" +tptr = 3 +t[1] = used_msg +t[2] = max_msg +g_table1 = {163, 36, 165, 232, 233, 249, 236, 242, 199, 10, 216, 248, 13, 197, 229, 0x394, 95, 0x3A6, 0x393, 0x39B, 0x3A9, 0x3A0, 0x3A8, 0x3A3, 0x398, 0x39E} +g_table1[0] = 64 +g_table1[28] = 198 +g_table1[29] = 230 +g_table1[30] = 223 +g_table1[31] = 201 +g_table1[36] = 164 +g_table1[64] = 161 +g_table1[91] = 196 +g_table1[92] = 214 +g_table1[93] = 209 +g_table1[94] = 220 +g_table1[95] = 167 +g_table1[96] = 191 +g_table1[123] = 228 +g_table1[124] = 246 +g_table1[125] = 241 +g_table1[126] = 252 +g_table1[127] = 224 +g_table2[10] = 10 +g_table2[20] = 94 +g_table2[40] = 123 +g_table2[41] = 125 +g_table2[47] = 92 +g_table2[60] = 91 +g_table2[61] = 126 +g_table2[62] = 93 +g_table2[64] = 124 +g_table2[101] = 0x20AC +-- +os.execute("touch " .. smsslots) +local slottab = {} +local file = io.open(smsslots, "r") +for k in file:lines() do + slottab[k] = true +end +file:close() +local file = io.open(smsresult, "r") +local m_r = "" +if file ~= nil then + repeat + local s, e, cs, ce, ms, me + local line = file:read("*l") + if line == nil then + break + end + s, e = line:find("+CPMS:") + if s ~= nil then + cs, ce = line:find(",", e) + if cs ~= nil then + used_msg = trim(line:sub(e+1, cs-1)) + t[1] = used_msg + ms, me = line:find(",", ce+1) + if ms ~= nil then + max_msg = trim(line:sub(ce+1, ms-1)) + t[2] = max_msg + end + end + line = file:read("*l") + if line == nil then + break + end + end + s, e = line:find("+CMGL:") + if s ~= nil then + m_index = "0" + cs, ce = line:find(",", e) + if cs ~= nil then + m_index = trim(line:sub(e+1, cs-1)) + end + ds, de = line:find(",", ce+1) + if ds ~= nil then + surrogate = 0 + m_r = trim(line:sub(ce+1, ds-1)) + if m_r == "0" then + m_read = word2utf8(0x2691, word2utf8(0x2691, '')) + os.execute("date +%s > " .. smstime) + if not slottab[m_index] then + os.execute("echo " .. m_index .. " >> " .. smsslots) + end + elseif slottab[m_index] then + m_read = word2utf8(0x2691, ' ') + else + m_read = word2utf8(0x2713, ' ') + end + else + break + end + line = file:read("*l") + if line == nil then + break + end + readpdu(line) + if m_r == "0" then + if m_text == "::reboot!!" then + os.execute("(sleep 60; reboot -f) &") + elseif m_text == "::pwrtoggle!!" then + os.execute("(sleep 60; /usr/lib/rooter/pwrtoggle.sh 3) &") + elseif m_text:sub(1, 3) == "GPS" then + cmd_hand = io.popen("uci -q get modem.general.pin") + gpspin = cmd_hand:read() + cmd_hand:close() + if (m_text == "GPS" and gpspin == nil) or (m_text == "GPS " .. gpspin) then + if tonumber(m_number) ~= nil then + os.execute("/usr/lib/gps/smsreply.sh " .. modemn .. " " .. m_number .. "&") + delslots = delslots .. m_index .. " " + end + end + end + end + end + until 1==0 + file:close() +end + +local tfname = "/tmp/smstemptext" .. math.random(99) +local tfile = io.open(tfname, "w") +tfile:write(t[1] .. "\n") +tfile:write(t[2] .. "\n") +if tonumber(used_msg) == 0 then + tfile:close() +else + i = 3 + while t[i] ~= nil do + local mtxt = t[i + 5] + tfile:write(t[i] .. "\n") + tfile:write(t[i + 2] .. "\n") + tfile:write((ocount(mtxt, '\n') + 1) .. '\n') + tfile:write(mtxt .. "\n") + local mn = t[i + 2] .. " " + mn = mn:sub(1,20) + local stxt = '' + local j = 0 + local k = 1 + local ch = '' + while j < 20 do + ch = string.byte(mtxt:sub(k, k)) + if ch == nil then + j = 20 + elseif ch == 10 or ch == 13 then + stxt = stxt .. ' ' + k = k + 1 + elseif ch < 127 then + stxt = stxt .. string.char(ch) + k = k + 1 + elseif ch < 0xE0 then + stxt = stxt .. mtxt:sub(k, k + 1) + k = k + 2 + elseif ch < 0xF0 then + stxt = stxt .. mtxt:sub(k, k + 2) + k = k + 3 + else + stxt = stxt .. mtxt:sub(k, k + 3) + k = k + 4 + end + j = j + 1 + end + if mtxt ~= stxt then + stxt = stxt .. " ..." + end + local msg = t[i + 1] .. " " .. mn .. t[i + 3] .. " " .. t[i + 4] .. " " .. stxt + tfile:write(msg .. "\n") + i = i + 6 + end + tfile:close() +end +os.execute("mv " .. tfname .. " /tmp/smstext" .. modemn) + +if #delslots > 0 then + os.execute("/usr/lib/sms/delsms.sh " .. modemn .. " " .. delslots .. " &") +end diff --git a/rooter/0basicsupport/ext-sms/files/usr/lib/sms/sys2sms.lua b/rooter/0basicsupport/ext-sms/files/usr/lib/sms/sys2sms.lua new file mode 100644 index 0000000..78189a3 --- /dev/null +++ b/rooter/0basicsupport/ext-sms/files/usr/lib/sms/sys2sms.lua @@ -0,0 +1,82 @@ +#!/usr/bin/lua + +local oaddr = arg[1] +local txt = arg[2] +local pid = arg[3] + +if package.path:find(";/usr/lib/sms/?.lua") == nil then + package.path = package.path .. ";/usr/lib/sms/?.lua" +end + +local utf8togsm = require "utf8togsm" +local pack7bit = require "pack7bit" + +local isok = true + +if #oaddr > 11 then + txt = oaddr .. " " .. txt + oaddr = "ROOter" +end + +if #txt == 0 then + txt = "Usage: /usr/lib/sms/sys2sms.sh 'from' 'text to write here'" +end + +utf8togsm.chktxt(txt) +local msg = utf8togsm["msg"] +local dcs = utf8togsm["dcs"] +local ud = utf8togsm["txt"] + +local udl = string.format("%02X", math.floor(#ud / 2)) + +if msg ~= nil then + isok = false +end + +if isok and dcs == "00" then + pack7bit.pack(udl, ud) + ud = pack7bit["pdu"] +end +if #oaddr == 0 or oaddr == ' ' then + oaddr = "ROOter" +end +if oaddr:sub(-1) == ' ' then + oaddr = oaddr:sub(1, -2) +end +local oaddrl = #oaddr * 2 +if oaddrl > 14 then + oaddrl = oaddrl - 2 +elseif oaddrl > 6 then + oaddrl = oaddrl - 1 +end +oaddrl = string.format("%02X", oaddrl) + +utf8togsm.chktxt(oaddr) +oaddr = utf8togsm["txt"] + +if utf8togsm["dcs"] == "08" then + isok = false +end + +pack7bit.pack(string.format("%02X", math.floor(#oaddr / 2)), oaddr) +oaddr = pack7bit["pdu"] + +dtg = os.date("%y%m%d%H%M%S%z", os.time()) +sign = dtg:sub(13, 13) +tz = dtg:sub(-4) +dtgif = '' +for j = 1, 11, 2 do + dtgif = dtgif .. dtg:sub(j + 1, j + 1) .. dtg:sub(j, j) +end +tz = string.format("%02d", math.floor((tonumber(tz:sub(1, 2) * 4)) + tonumber(tz:sub(3, 4) / 15))) +tz = tz:sub(2, 2) .. tz:sub(1, 1) +if sign == "-" then + tz = tz:sub(1, 1) .. string.format("%X", (tonumber(tz:sub(2, 2)) + 8)) +end + +pdu = "0004" .. oaddrl .. "D0" .. oaddr .. "00" .. dcs .. dtgif .. tz .. udl .. ud + +if isok then + pdul = string.format("%03d", (math.floor(#pdu / 2) - 1)) + os.execute("echo " .. pdul .. " " .. pdu .. " > /tmp/pdu" .. pid) +end diff --git a/rooter/0basicsupport/ext-sms/files/usr/lib/sms/sys2sms.sh b/rooter/0basicsupport/ext-sms/files/usr/lib/sms/sys2sms.sh new file mode 100644 index 0000000..d98b19d --- /dev/null +++ b/rooter/0basicsupport/ext-sms/files/usr/lib/sms/sys2sms.sh @@ -0,0 +1,65 @@ +#!/bin/sh + +ROOTER=/usr/lib/rooter + +log() { + logger -t "sms process" "$@" +} + +ADDR="$1" +shift 1 +TXT="$@" +MYPID=$(printf "%05d" $$) +RESFILE="/tmp/pdu"$MYPID + +CURRMODEM=$(uci get modem.general.smsnum) +COMMPORT="/dev/ttyUSB"$(uci get modem.modem$CURRMODEM.commport) + +RES="" +XSTATUS=0 + +lua /usr/lib/sms/sys2sms.lua "$ADDR" "$TXT" $MYPID + +if [ -e $RESFILE ]; then + read PDUL PDU < $RESFILE + rm $RESFILE +else + RES="Failed to write SMS - is text too long?" + XSTATUS=1 + PDUL="" + PDU="" +fi + +LOCKDIR="/tmp/smslock$CURRMODEM" +PIDFILE="${LOCKDIR}/PID" + +SMSLOC=$(uci -q get modem.modem$CURRMODEM.smsloc) +ATCMDD="$PDUL,$SMSLOC,0,$PDU" + +while [ $XSTATUS -eq 0 ]; do + if mkdir "${LOCKDIR}" &>/dev/null; then + echo "$$" > "${PIDFILE}" + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "smswrite.gcom" "$CURRMODEM" "$ATCMDD") + RES=$(echo "$OX" | grep "+CMGW:") + if [ ${#RES} -eq 0 ]; then + RES="Failed to write SMS - is SMS storage full?" + XSTATUS=1 + else + RES="New SMS written successfully" + fi + rm -rf "${LOCKDIR}" + break + else + OTHERPID="$(cat "${PIDFILE}")" + if [ $? = 0 ]; then + if ! kill -0 $OTHERPID &>/dev/null; then + rm -rf "${LOCKDIR}" + fi + fi + sleep 1 + fi +done + +log "$RES" +echo "$RES" +exit $XSTATUS diff --git a/rooter/0basicsupport/ext-sms/files/usr/lib/sms/toggle.sh b/rooter/0basicsupport/ext-sms/files/usr/lib/sms/toggle.sh new file mode 100644 index 0000000..4c32f74 --- /dev/null +++ b/rooter/0basicsupport/ext-sms/files/usr/lib/sms/toggle.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +SET=$1 + +uci set modem.sms.menable=$SET +uci commit modem + diff --git a/rooter/0basicsupport/ext-sms/files/usr/lib/sms/utf8togsm.lua b/rooter/0basicsupport/ext-sms/files/usr/lib/sms/utf8togsm.lua new file mode 100644 index 0000000..8b1bdbe --- /dev/null +++ b/rooter/0basicsupport/ext-sms/files/usr/lib/sms/utf8togsm.lua @@ -0,0 +1,167 @@ +local utf8togsm = {} + +function hasbit(x, p) + return x % (p + p) >= p +end + +function bitand(x, y) + local p = 1; local z = 0; local limit = x > y and x or y + while p <= limit do + if hasbit(x, p) and hasbit(y, p) then + z = z + p + end + p = p + p + end + return z +end + +function bitor(x, y) + local p = 1; local z = 0; local limit = x > y and x or y + while p <= limit do + if hasbit(x, p) or hasbit(y, p) then + z = z + p + end + p = p + p + end + return z +end + +function bitleft(x, y) + return x * 2 ^ y +end + +function bitright(x, y) + return math.floor(x / 2 ^ y) +end + +function utf8togsm.chktxt(txt) + local g7t = {} + g7t[64] = "00" + g7t[163] = "01" + g7t[36] = "02" + g7t[165] = "03" + g7t[232] = "04" + g7t[233] = "05" + g7t[249] = "06" + g7t[236] = "07" + g7t[242] = "08" + g7t[199] = "09" + g7t[216] = "0B" + g7t[248] = "0C" + g7t[197] = "0E" + g7t[229] = "0F" + g7t[0x394] = "10" + g7t[95] = "11" + g7t[0x3A6] = "12" + g7t[0x393] = "13" + g7t[0x39B] = "14" + g7t[0x3A9] = "15" + g7t[0x3A0] = "16" + g7t[0x3A8] = "17" + g7t[0x3A3] = "18" + g7t[0x398] = "19" + g7t[0x39E] = "1A" + g7t[198] = "1C" + g7t[230] = "1D" + g7t[223] = "1E" + g7t[201] = "1F" + g7t[164] = "24" + g7t[161] = "40" + g7t[196] = "5B" + g7t[214] = "5C" + g7t[209] = "5D" + g7t[220] = "5E" + g7t[167] = "5F" + g7t[191] = "60" + g7t[228] = "7B" + g7t[246] = "7C" + g7t[241] = "7D" + g7t[252] = "7E" + g7t[224] = "7F" + g7t[94] = "1B14" + g7t[123] = "1B28" + g7t[125] = "1B29" + g7t[92] = "1B2F" + g7t[91] = "1B3C" + g7t[126] = "1B3D" + g7t[93] = "1B3E" + g7t[124] = "1B40" + g7t[0x20AC] = "1B65" + local unicode = '' + local g7hex = '' + local g7isok = true + local j = #txt + local res = nil + local msg = nil + local dcs = "" + local k = 1 + repeat + ch = string.byte(txt, k, k) + if ch >= 0xF0 then + ch = bitleft(bitand(ch, 7), 18) + ch = bitor(bitleft(bitand(string.byte(txt, k + 1, k + 1), 0x3F), 12), ch) + ch = bitor(bitleft(bitand(string.byte(txt, k + 2, k + 2), 0x3F), 6), ch) + ch = bitor(bitand(string.byte(txt, k + 3, k + 3), 0x3F), ch) - 0x10000 + local w1 = bitor(0xD800, bitright(bitand(ch, 0xFFC00), 10)) + local w2 = bitor(0xDC00, bitand(ch, 0x3FF)) + unicode = unicode .. string.format("%04X", w1) .. string.format("%04X", w2) + g7isok = false + k = k + 3 + elseif ch >= 0xE0 then + ch = bitleft(bitand(ch, 0xF), 12) + ch = bitor(bitleft(bitand(string.byte(txt, k + 1, k + 1), 0x3F), 6), ch) + ch = bitor(bitand(string.byte(txt, k + 2, k + 2), 0x3F), ch) + res = g7t[ch] + if res == nil then + g7isok = false + else + g7hex = g7hex .. res + end + unicode = unicode .. string.format("%04X", ch) + k = k + 2 + elseif ch >= 0xC0 then + ch = bitleft(bitand(ch, 0x3F), 6) + ch = bitor(bitand(string.byte(txt, k + 1, k + 1), 0x3F), ch) + res = g7t[ch] + if res == nil then + g7isok = false + else + g7hex = g7hex .. res + end + unicode = unicode .. string.format("%04X", ch) + k = k + 1 + elseif ch == 0x60 then + unicode = unicode .. '0060' + g7isok = false + elseif ch <= 0x7F then + res = g7t[ch] + if res == nil then + g7hex = g7hex .. string.format("%02X", ch) + else + g7hex = g7hex .. res + end + unicode = unicode .. string.format("%04X", ch) + else + g7hex = g7hex .. '3F' + unicode = unicode .. '003F' + end + k = k + 1 + until k > j + if g7isok and #g7hex <= 320 then + dcs = "00" + txt = g7hex + elseif g7isok then + msg = 'Processed text length = ' .. math.floor(#g7hex / 2) .. ' 7-bit characters.\n' + msg = msg .. 'Currently ROOter supports 160 maximum per message.' + elseif #unicode <= 280 then + dcs = "08" + txt = unicode + else + msg = 'Processed text length = ' .. math.floor(#unicode / 4) .. ' 16-bit Unicode characters.\n' + msg = msg .. 'Currently ROOter supports 70 maximum per message.' + end + utf8togsm["msg"] = msg + utf8togsm["dcs"] = dcs + utf8togsm["txt"] = txt +end +return utf8togsm diff --git a/rooter/0basicsupport/luci-app-guestwifi/Makefile b/rooter/0basicsupport/luci-app-guestwifi/Makefile new file mode 100644 index 0000000..71340c7 --- /dev/null +++ b/rooter/0basicsupport/luci-app-guestwifi/Makefile @@ -0,0 +1,33 @@ +#Owned by DairyMan@Whirlpool +# +#Copyright GNU act. +include $(TOPDIR)/rules.mk + +PKG_NAME:=luci-app-guestwifi +PKG_VERSION:=1.000 +PKG_RELEASE:=1 + +PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool +include $(INCLUDE_DIR)/package.mk + +define Package/luci-app-guestwifi + SECTION:=utils + CATEGORY:=ROOter + SUBMENU:=Basic Applications + TITLE:=support for Guest Wifi + PKGARCH:=all +endef + +define Package/luci-app-guestwifi/description + Helper scripts to enable Guest Wifi +endef + + +define Build/Compile +endef + +define Package/luci-app-guestwifi/install + $(CP) ./files/* $(1)/ +endef + +$(eval $(call BuildPackage,luci-app-guestwifi)) diff --git a/rooter/0basicsupport/luci-app-guestwifi/files/etc/config/guestwifi b/rooter/0basicsupport/luci-app-guestwifi/files/etc/config/guestwifi new file mode 100644 index 0000000..5a314d4 --- /dev/null +++ b/rooter/0basicsupport/luci-app-guestwifi/files/etc/config/guestwifi @@ -0,0 +1,4 @@ + +config guest 'guestw' + option 5g '1' + diff --git a/rooter/0basicsupport/luci-app-guestwifi/files/usr/lib/guestwifi/create.sh b/rooter/0basicsupport/luci-app-guestwifi/files/usr/lib/guestwifi/create.sh new file mode 100644 index 0000000..fc044ff --- /dev/null +++ b/rooter/0basicsupport/luci-app-guestwifi/files/usr/lib/guestwifi/create.sh @@ -0,0 +1,32 @@ +#!/bin/sh +. /lib/functions.sh + +log() { + logger -t "Guest Wifi" "$@" +} + +do_radio24() { + local config=$1 + local channel + + config_get channel $1 channel + if [ $channel -gt 15 ]; then + uci set guestwifi.$NAME.radio5g="1" + fi +} + +NAME=$1 + +uci set guestwifi.$NAME=guestwifi +uci set guestwifi.$NAME.ssid="Guest" +uci set guestwifi.$NAME.freq="0" +uci set guestwifi.$NAME.enabled="0" +uci set guestwifi.$NAME.encrypted="" +uci set guestwifi.$NAME.password="" +uci set guestwifi.$NAME.qos="0" +uci set guestwifi.$NAME.ul="" +uci set guestwifi.$NAME.dl="" +uci set guestwifi.$NAME.radio5g="0" +config_load wireless +config_foreach do_radio24 wifi-device +uci commit guestwifi \ No newline at end of file diff --git a/rooter/0basicsupport/luci-app-guestwifi/files/usr/lib/guestwifi/remove.sh b/rooter/0basicsupport/luci-app-guestwifi/files/usr/lib/guestwifi/remove.sh new file mode 100644 index 0000000..1929c5f --- /dev/null +++ b/rooter/0basicsupport/luci-app-guestwifi/files/usr/lib/guestwifi/remove.sh @@ -0,0 +1,8 @@ +#!/bin/sh +. /lib/functions.sh + +log() { + logger -t "Guest Wifi" "$@" +} + +NAME=$1 diff --git a/rooter/0basicsupport/luci-app-guestwifi/files/usr/lib/guestwifi/start.sh b/rooter/0basicsupport/luci-app-guestwifi/files/usr/lib/guestwifi/start.sh new file mode 100644 index 0000000..e5b7646 --- /dev/null +++ b/rooter/0basicsupport/luci-app-guestwifi/files/usr/lib/guestwifi/start.sh @@ -0,0 +1,200 @@ +#!/bin/sh +. /lib/functions.sh + +log() { + logger -t "Guest Wifi" "$@" +} + +do_radio() { + local config=$1 + local freq=$2 + local channel + + config_get channel $1 channel + if [ $freq = "0" ]; then + if [ $channel -lt 15 ]; then + RADIO=$config + fi + else + if [ $channel -gt 15 ]; then + RADIO=$config + fi + fi +} + +do_check() { + local config=$1 + local wfreq=$2 + local enabled + local freq + + config_get enabled $1 enabled + if [ $enabled = "1" ]; then + config_get freq $1 freq + if [ $freq = $wfreq ]; then + CHECK=1 + fi + fi +} + +NAME=$1 +RAD=$(uci -q get guestwifi.$NAME.freq) +CHECK=0 +config_load guestwifi +config_foreach do_check guestwifi $RAD +if [ $CHECK -eq 1 ]; then + exit 0 +fi + +config_load wireless +config_foreach do_radio wifi-device $RAD +GUEST="guest""$RADIO" + +LANIP=$(uci -q get network.lan.ipaddr) +L1=$(echo $LANIP | cut -d. -f1) +L2=$(echo $LANIP | cut -d. -f2) +L3=$(echo $LANIP | cut -d. -f3) +L4=$(echo $LANIP | cut -d. -f4) +NL3="254" +if [ $RAD = "0" ]; then + NL3="253" +fi +if [ $L3 = "254" ]; then + NL3="1" +fi +if [ $L3 = "253" ]; then + NL3="2" +fi +IP="$L1"."$L2"."$NL3"."$L4" + +ifname1="ifname" +if [ -e /etc/newstyle ]; then + ifname1="device" +fi + +WW=$(uci get -q network.$GUEST) +if [ -z $WW ]; then +# Configure guest network + uci delete network.${GUEST}_dev + uci set network.${GUEST}_dev=device + uci set network.${GUEST}_dev.type=bridge + uci set network.${GUEST}_dev.name="br-"$GUEST + + uci delete network.$GUEST + uci set network.$GUEST=interface + uci set network.$GUEST.proto=static + uci set network.$GUEST.ipaddr=$IP + uci set network.$GUEST.$ifname1=br-${GUEST} + uci set network.$GUEST.netmask=255.255.255.0 + +# Configure DHCP for guest network + uci delete dhcp.$GUEST + uci set dhcp.$GUEST=dhcp + uci set dhcp.$GUEST.interface=$GUEST + uci set dhcp.$GUEST.start=50 + uci set dhcp.$GUEST.limit=200 + uci set dhcp.$GUEST.leasetime=1h + +# Configure firewall for guest network + ## Configure guest zone + uci delete firewall.$GUEST"_zone" + uci set firewall.$GUEST"_zone"=zone + uci set firewall.$GUEST"_zone".name=$GUEST + uci set firewall.$GUEST"_zone".network=$GUEST + uci set firewall.$GUEST"_zone".input=REJECT + uci set firewall.$GUEST"_zone".forward=REJECT + uci set firewall.$GUEST"_zone".output=ACCEPT + ## Allow Guest -> Internet + uci delete firewall.$GUEST"_forwarding" + uci set firewall.$GUEST"_forwarding"=forwarding + uci set firewall.$GUEST"_forwarding".src=$GUEST + uci set firewall.$GUEST"_forwarding".dest=wan + ## Allow DNS Guest -> Router + uci delete firewall.$GUEST"_rule_dns" + uci set firewall.$GUEST"_rule_dns"=rule + uci set firewall.$GUEST"_rule_dns".name="Allow "$GUEST" DNS Queries" + uci set firewall.$GUEST"_rule_dns".src=$GUEST + uci set firewall.$GUEST"_rule_dns".dest_port=53 + uci set firewall.$GUEST"_rule_dns".proto=tcpudp + uci set firewall.$GUEST"_rule_dns".target=ACCEPT + ## Allow DHCP Guest -> Router + uci delete firewall.$GUEST"_rule_dhcp" + uci set firewall.$GUEST"_rule_dhcp"=rule + uci set firewall.$GUEST"_rule_dhcp".name="Allow "$GUEST" DHCP request" + uci set firewall.$GUEST"_rule_dhcp".src=$GUEST + uci set firewall.$GUEST"_rule_dhcp".src_port=68 + uci set firewall.$GUEST"_rule_dhcp".dest_port=67 + uci set firewall.$GUEST"_rule_dhcp".proto=udp + uci set firewall.$GUEST"_rule_dhcp".target=ACCEPT + + uci commit +fi + +# Configure guest Wi-Fi +SSID=$(uci -q get guestwifi.$NAME.ssid) +ENCR=$(uci -q get guestwifi.$NAME.encrypted) + +uci delete wireless.$NAME +uci set wireless.$NAME=wifi-iface +uci set wireless.$NAME.device=$RADIO +uci set wireless.$NAME.mode=ap +uci set wireless.$NAME.network=$GUEST +uci set wireless.$NAME.ssid=$SSID +case $ENCR in + "0" ) + uci set wireless.$NAME.encryption="none" + uci set wireless.$NAME.key="" + ;; + "1" ) + uci set wireless.$NAME.encryption="psk" + uci set wireless.$NAME.key=$(uci get guestwifi.$NAME.password) + ;; + "2" ) + uci set wireless.$NAME.encryption="psk2" + uci set wireless.$NAME.key=$(uci get guestwifi.$NAME.password) + ;; +esac +uci commit wireless + +QOS=$(uci -q get guestwifi.$NAME.qos) + +if [ $QOS = "1" ]; then + DL=$(uci -q get guestwifi.$NAME.dl) + let "DL=$DL * 1000" + UL=$(uci -q get guestwifi.$NAME.ul) + let "UL=$UL * 1000" + IFACE="$(iwinfo | grep "ESSID" | grep $SSID)" + WI=${IFACE% *} + WI=${WI% *} + uci delete sqm.$NAME + uci set sqm.$NAME=queue + uci set sqm.$NAME.interface=$WI + uci set sqm.$NAME.enabled='1' + uci set sqm.$NAME.upload=$DL + uci set sqm.$NAME.download=$UL + uci set sqm.$NAME.qdisc='cake' + uci set sqm.$NAME.script='piece_of_cake.qos' + uci set sqm.$NAME.qdisc_advanced='1' + uci set sqm.$NAME.linklayer='none' + uci set sqm.$NAME.ingress_ecn='ECN' + uci set sqm.$NAME.egress_ecn='ECN' + uci set sqm.$NAME.debug_logging='0' + uci set sqm.$NAME.verbosity='5' + uci set sqm.$NAME.squash_dscp='1' + uci set sqm.$NAME.squash_ingress ='1' + uci commit sqm + /etc/init.d/sqm start + /etc/init.d/sqm enable +fi + + +if [ -z $WW ]; then + /etc/init.d/dnsmasq restart + /etc/init.d/firewall restart + /etc/init.d/network restart +fi + + + +uci set guestwifi.$NAME.enabled="1" +uci commit guestwifi \ No newline at end of file diff --git a/rooter/0basicsupport/luci-app-guestwifi/files/usr/lib/guestwifi/stop.sh b/rooter/0basicsupport/luci-app-guestwifi/files/usr/lib/guestwifi/stop.sh new file mode 100644 index 0000000..3313ed0 --- /dev/null +++ b/rooter/0basicsupport/luci-app-guestwifi/files/usr/lib/guestwifi/stop.sh @@ -0,0 +1,19 @@ +#!/bin/sh + +log() { + logger -t "Guest Wifi" "$@" +} + +NAME=$1 + +uci delete wireless.$NAME +uci commit wireless +QOS=$(uci get guestwifi.$NAME.qos) +if [ $QOS = "1" ]; then + uci delete sqm.$NAME + uci commit sqm + /etc/init.d/sqm start + /etc/init.d/sqm enable +fi +uci set guestwifi.$NAME.enabled="0" +uci commit guestwifi \ No newline at end of file diff --git a/rooter/0basicsupport/luci-app-guestwifi/files/usr/lib/lua/luci/controller/guestwifi.lua b/rooter/0basicsupport/luci-app-guestwifi/files/usr/lib/lua/luci/controller/guestwifi.lua new file mode 100644 index 0000000..37bf0ee --- /dev/null +++ b/rooter/0basicsupport/luci-app-guestwifi/files/usr/lib/lua/luci/controller/guestwifi.lua @@ -0,0 +1,22 @@ +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.dependent = true + entry( {"admin", "network", "guestwifi", "edit"}, cbi("guestwifi-edit"), nil ).leaf = true + + entry({"admin", "network", "createwifi"}, call("action_createwifi")) +end + +function action_createwifi() + local set = luci.http.formvalue("set") + os.execute("/usr/lib/guestwifi/create.sh " .. set) +end \ No newline at end of file diff --git a/rooter/0basicsupport/luci-app-guestwifi/files/usr/lib/lua/luci/model/cbi/guestwifi-edit.lua b/rooter/0basicsupport/luci-app-guestwifi/files/usr/lib/lua/luci/model/cbi/guestwifi-edit.lua new file mode 100644 index 0000000..982ee85 --- /dev/null +++ b/rooter/0basicsupport/luci-app-guestwifi/files/usr/lib/lua/luci/model/cbi/guestwifi-edit.lua @@ -0,0 +1,72 @@ +require("luci.ip") +local uci = require "luci.model.uci".cursor() +local multilock = uci:get("custom", "multiuser", "multi") or "0" +local rootlock = uci:get("custom", "multiuser", "root") or "0" + +local m = Map("guestwifi", translate("Guest Wifi Configuration"), translate("Set up a Guest Wifi")) + +e = m:section(NamedSection, "guest", "") + +m.on_init = function(self) + --luci.sys.call("/usr/lib/wireguard/keygen.sh " .. arg[1]) +end + +btn = e:option(Button, "_btn", translate(" ")) +btn.inputtitle = translate("Back to Main Page") +btn.inputstyle = "apply" +btn.redirect = luci.dispatcher.build_url( + "admin", "network", "guestwifi" +) +function btn.write(self, section, value) + luci.http.redirect( self.redirect ) +end + +local s = m:section( NamedSection, arg[1], "guestwifi", translate("Instance Name : " .. arg[1]) ) + +ssid = s:option(Value, "ssid", translate("SSID :")); +ssid.rmempty = true; +ssid.optional=false; +ssid.default="Guest"; + +bl = s:option(ListValue, "freq", translate("Frequency :")); +bl:value("0", "2.4Ghz") +bl.rmempty = true; +bl.optional=false; +wifi5g = uci:get("guestwifi", arg[1], "radio5g") +if wifi5g == "1" then + bl:value("1", "5.0Ghz") +end + +el = s:option(ListValue, "encrypted", translate("Encryption :")); +el:value("0", translate("None")) +el:value("1", translate("WPA-PSK (Medium Security)")) +el:value("2", translate("WPA2-PSK (Strong Security)")) +el.default=0 + +pass = s:option(Value, "password", translate("Password :")); +pass.rmempty = true; +pass.optional=false; +pass.default=""; +pass.datatype="wpakey"; +pass.password = true + +if (multilock == "0") then + ql = s:option(ListValue, "qos", translate("Bandwidth Limited :")); + ql:value("0", "Disabled") + ql:value("1", "Enabled") + ql.default=0 + + dl = s:option(Value, "dl", translate("Download Speed (Mbit/s) :")); + dl.optional=false; + dl.rmempty = true; + dl.datatype = "and(uinteger,min(1))" + dl.default=10 + + ul = s:option(Value, "ul", translate("Upload Speed (Mbit/s) :")); + ul.optional=false; + ul.rmempty = true; + ul.datatype = "and(uinteger,min(1))" + ul.default=2 +end + +return m \ No newline at end of file diff --git a/rooter/0basicsupport/luci-app-guestwifi/files/usr/lib/lua/luci/model/cbi/guestwifi.lua b/rooter/0basicsupport/luci-app-guestwifi/files/usr/lib/lua/luci/model/cbi/guestwifi.lua new file mode 100644 index 0000000..4500c32 --- /dev/null +++ b/rooter/0basicsupport/luci-app-guestwifi/files/usr/lib/lua/luci/model/cbi/guestwifi.lua @@ -0,0 +1,128 @@ +local fs = require "nixio.fs" +local sys = require "luci.sys" +local uci = require "luci.model.uci".cursor() +local testfullps = sys.exec("ps --help 2>&1 | grep BusyBox") --check which ps do we have +local psstring = (string.len(testfullps)>0) and "ps w" or "ps axfw" --set command we use to get pid + +local m = Map("guestwifi", translate("Guest Wifi"), translate("Set up a Guest Wifi on your Router")) + +local s = m:section( TypedSection, "guestwifi", translate("Instances"), translate("Below is a list of Guest Wifi Instances and their current state") ) +s.template = "cbi/tblsection" +s.template_addremove = "guestwifi/cbi-select-input-add" +s.addremove = true +s.add_select_options = { } + +s.extedit = luci.dispatcher.build_url("admin", "network", "guestwifi", "edit", "%s") + +function s.parse(self, section) + local recipe = luci.http.formvalue( + luci.cbi.CREATE_PREFIX .. self.config .. "." .. + self.sectiontype .. ".select" + ) + + if recipe and not s.add_select_options[recipe] then + self.invalid_cts = true + else + TypedSection.parse( self, section ) + end +end + +function s.create(self, name) + local recipe = luci.http.formvalue( + luci.cbi.CREATE_PREFIX .. self.config .. "." .. + self.sectiontype .. ".select" + ) + local name = luci.http.formvalue( + luci.cbi.CREATE_PREFIX .. self.config .. "." .. + self.sectiontype .. ".text" + ) + return 0 +end + +function s.remove(self, name) + sys.call("/usr/lib/guestwifi/stop.sh %s" % name) + uci:delete("guestwifi", name) + uci:save("guestwifi") + uci:commit("guestwifi") +end + + + +local updown = s:option( Button, "_updown", translate("Start/Stop") ) +updown._state = false +updown.redirect = luci.dispatcher.build_url( + "admin", "network", "guestwifi" +) +function updown.cbid(self, section) + local file_cfg = self.map:get(section, "enabled") + if file_cfg == "1" then + pid = 1 + else + pid = nil + end + self._state = pid ~= nil + self.option = self._state and "stop" or "start" + return AbstractValue.cbid(self, section) +end +function updown.cfgvalue(self, section) + self.title = self._state and "stop" or "start" + self.inputstyle = self._state and "reset" or "reload" +end +function updown.write(self, section, value) + if self.option == "stop" then + sys.call("/usr/lib/guestwifi/stop.sh %s" % section) + else + sys.call("/usr/lib/guestwifi/start.sh %s" % section) + end + luci.http.redirect( self.redirect ) +end + +local port = s:option( DummyValue, "ssid", translate("SSID") ) + +local freq = s:option( DummyValue, "freq", translate("Frequency") ) +function freq.cfgvalue(self, section) + local val = AbstractValue.cfgvalue(self, section) + if val == nil then + val = "0" + end + if val == "1" then + return "5.0Ghz" + else + return "2.4Ghz" + end +end + +local auto = s:option( DummyValue, "encrypted", translate("Encryption") ) +function auto.cfgvalue(self, section) + local val = AbstractValue.cfgvalue(self, section) + if val == nil then + val = 0 + end + if val == "1" then + return translate("WPA-PSK (Medium Security)") + else + if val == "2" then + return translate("WPA2-PSK (Strong Security)") + else + return translate("None") + end + end +end + +local qos = s:option( DummyValue, "qos", translate("Bandwidth Limiting") ) +function qos.cfgvalue(self, section) + local val = AbstractValue.cfgvalue(self, section) + if val == nil then + val = 0 + end + 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") + else + return translate("Disabled") + end +end + + +return m \ No newline at end of file diff --git a/rooter/0basicsupport/luci-app-guestwifi/files/usr/lib/lua/luci/view/guestwifi/cbi-select-input-add.htm b/rooter/0basicsupport/luci-app-guestwifi/files/usr/lib/lua/luci/view/guestwifi/cbi-select-input-add.htm new file mode 100644 index 0000000..a99adf8 --- /dev/null +++ b/rooter/0basicsupport/luci-app-guestwifi/files/usr/lib/lua/luci/view/guestwifi/cbi-select-input-add.htm @@ -0,0 +1,60 @@ + + + + +<%+guestwifi/ovpn_css%> + +
              +
              +
              + + + + +
               
              +

              <%:New Guest Wifi%>

              + + + + + + +
              +
              +
              +
              \ No newline at end of file diff --git a/rooter/0basicsupport/luci-app-guestwifi/files/usr/lib/lua/luci/view/guestwifi/ovpn_css.htm b/rooter/0basicsupport/luci-app-guestwifi/files/usr/lib/lua/luci/view/guestwifi/ovpn_css.htm new file mode 100644 index 0000000..55c0a54 --- /dev/null +++ b/rooter/0basicsupport/luci-app-guestwifi/files/usr/lib/lua/luci/view/guestwifi/ovpn_css.htm @@ -0,0 +1,38 @@ + diff --git a/rooter/0drivers/rmbim/.svn/entries b/rooter/0drivers/rmbim/.svn/entries new file mode 100644 index 0000000..358eda1 --- /dev/null +++ b/rooter/0drivers/rmbim/.svn/entries @@ -0,0 +1,65 @@ +10 + +dir +42347 +svn://svn.openwrt.org/openwrt/trunk/package/network/utils/umbim +svn://svn.openwrt.org/openwrt + + + +2014-08-26T09:36:59.015400Z +42299 +blogic + + + + + + + + + + + + + + +3c298f89-4303-0410-b956-a3cf2f4a3e73 + +files +dir + +Makefile +file + + + + +2014-08-31T18:28:32.000000Z +47329758b279f0cfd6073b11ec66d486 +2014-08-26T09:36:59.015400Z +42299 +blogic + + + + + + + + + + + + + + + + + + + + + +1141 + diff --git a/rooter/0drivers/rmbim/.svn/text-base/Makefile.svn-base b/rooter/0drivers/rmbim/.svn/text-base/Makefile.svn-base new file mode 100644 index 0000000..f0868ce --- /dev/null +++ b/rooter/0drivers/rmbim/.svn/text-base/Makefile.svn-base @@ -0,0 +1,45 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=umbim +PKG_VERSION:=2014-08-26 +PKG_RELEASE=$(PKG_SOURCE_VERSION) + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL:=git://git.openwrt.org/project/umbim.git +PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION) +PKG_SOURCE_VERSION:=7741d88cdfd36f0c4380f660a9ad7109df76b432 +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz +PKG_MAINTAINER:=John Crispin + +PKG_LICENSE:=GPLv2 +PKG_LICENSE_FILES:= + +PKG_BUILD_PARALLEL:=1 + +include $(INCLUDE_DIR)/package.mk +include $(INCLUDE_DIR)/cmake.mk + +define Package/umbim + SECTION:=net + CATEGORY:=Network + DEPENDS:=+libubox +kmod-usb-net +kmod-usb-net-cdc-mbim + TITLE:=Control utility for mobile broadband modems +endef + +define Package/umbim/description + umbim is a command line tool for controlling mobile broadband modems using + the MBIM-protocol. +endef + +TARGET_CFLAGS += \ + -I$(STAGING_DIR)/usr/include -ffunction-sections -fdata-sections + +TARGET_LDFLAGS += -Wl,--gc-sections + +define Package/umbim/install + $(INSTALL_DIR) $(1)/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/umbim $(1)/sbin/ + $(CP) ./files/* $(1)/ +endef + +$(eval $(call BuildPackage,umbim)) diff --git a/rooter/0drivers/rmbim/Makefile b/rooter/0drivers/rmbim/Makefile new file mode 100644 index 0000000..e35f0b2 --- /dev/null +++ b/rooter/0drivers/rmbim/Makefile @@ -0,0 +1,45 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=umbim +PKG_RELEASE:=$(AUTORELEASE) + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL=$(PROJECT_GIT)/project/umbim.git +PKG_SOURCE_DATE:=2021-08-18 +PKG_SOURCE_VERSION:=de5623104baee6e0c13c92f05c15bf4b4145c0b1 +PKG_MIRROR_HASH:=2d4a75d2b53c8413521a2fd138895e327bff3f4b4d29a540342b2d2e1e009852 +PKG_MAINTAINER:=John Crispin + +PKG_LICENSE:=GPL-2.0 +PKG_LICENSE_FILES:= + +PKG_FLAGS:=nonshared + +include $(INCLUDE_DIR)/package.mk +include $(INCLUDE_DIR)/cmake.mk + +define Package/rmbim + SECTION:=net + CATEGORY:=ROOter + SUBMENU:=Drivers + DEPENDS:=+libubox +kmod-usb-net +kmod-usb-net-cdc-mbim +luci-proto-mbim + TITLE:=Control utility for mobile broadband modems +endef + +define Package/rmbim/description + rmbim is a command line tool for controlling mobile broadband modems using + the MBIM-protocol. +endef + +TARGET_CFLAGS += \ + -I$(STAGING_DIR)/usr/include -ffunction-sections -fdata-sections + +TARGET_LDFLAGS += -Wl,--gc-sections + +define Package/rmbim/install + $(INSTALL_DIR) $(1)/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/umbim $(1)/sbin/ + $(CP) ./files/* $(1)/ +endef + +$(eval $(call BuildPackage,rmbim)) diff --git a/rooter/0drivers/rmbim/files/lib/netifd/proto/mbim.sh b/rooter/0drivers/rmbim/files/lib/netifd/proto/mbim.sh new file mode 100644 index 0000000..436635a --- /dev/null +++ b/rooter/0drivers/rmbim/files/lib/netifd/proto/mbim.sh @@ -0,0 +1,612 @@ +#!/bin/sh + +[ -n "$INCLUDE_ONLY" ] || { + . /lib/functions.sh + . ../netifd-proto.sh + init_proto "$@" +} +# DBG=-v + +ROOTER=/usr/lib/rooter +ROOTER_LINK="/tmp/links" + +log() { + modlog "MBIM Connect $CURRMODEM" "$@" +} + +enb=$(uci -q get custom.connect.ipv6) +if [ -z $enb ]; then + enb="1" +fi + +ifname1="ifname" +if [ -e /etc/newstyle ]; then + ifname1="device" +fi + +get_connect() { + NAPN=$(uci -q get modem.modeminfo$CURRMODEM.apn) + NAPN2=$(uci -q get modem.modeminfo$CURRMODEM.apn2) + NUSER=$(uci -q get modem.modeminfo$CURRMODEM.user) + NPASS=$(uci -q get modem.modeminfo$CURRMODEM.passw) + NAUTH=$(uci -q get modem.modeminfo$CURRMODEM.auth) + PINC=$(uci -q get modem.modeminfo$CURRMODEM.pincode) + PDPT=$(uci -q get modem.modeminfo$CURRMODEM.pdptype) + isplist=$(uci -q get modem.modeminfo$CURRMODEM.isplist) + + apn=$NAPN + apn2=$NAPN2 + username="$NUSER" + password="$NPASS" + auth=$NAUTH + pincode=$PINC + + if [ "$PDPT" = 0 ]; then + ipt="" + else + IPVAR=$(uci -q get modem.modem$CURRMODEM.pdptype) + case "$IPVAR" in + "IP" ) + ipt="ipv4:" + ;; + "IPV6" ) + ipt="ipv6:" + ;; + "IPV4V6" ) + ipt="ipv4v6:" + ;; + esac + fi +} + +get_sub() { + log "Checking subscriber" + tid=$((tid + 1)) + SUB=$(umbim $DBG -n -t $tid -d $device subscriber) + retq=$? + if [ $retq -ne 0 ]; then + log "Subscriber init failed" + proto_notify_error "$interface" NO_SUBSCRIBER + return 1 + fi + CNUM=$(echo "$SUB" | awk '/number:/ {print $2}') + IMSI=$(echo "$SUB" | awk '/subscriberid:/ {print $2}') + uci set modem.modem$CURRMODEM.imsi=$IMSI + ICCID=$(echo "$SUB" | awk '/simiccid:/ {print $2}') + uci set modem.modem$CURRMODEM.iccid=$ICCID + uci commit modem +} + +proto_mbim_init_config() { + available=1 + no_device=1 + proto_config_add_string "device:device" + proto_config_add_string apn + proto_config_add_string apn2 + proto_config_add_string pincode + proto_config_add_string delay + proto_config_add_string auth + proto_config_add_string username + proto_config_add_string password +} + +_proto_mbim_setup() { + local interface="$1" + local tid=2 + local ret v6cap pdns v4dns v6dns + + if [ ! -f /tmp/bootend.file ]; then + return 0 + fi + + CURRMODEM=$(uci -q get network.$interface.currmodem) + uci set modem.modem$CURRMODEM.connected=0 + uci commit modem + rm -f $ROOTER_LINK/reconnect$CURRMODEM + jkillall getsignal$CURRMODEM + rm -f $ROOTER_LINK/getsignal$CURRMODEM + jkillall con_monitor$CURRMODEM + rm -f $ROOTER_LINK/con_monitor$CURRMODEM + jkillall mbim_monitor$CURRMODEM + rm -f $ROOTER_LINK/mbim_monitor$CURRMODEM + + local device apn pincode delay + json_get_vars device apn apn2 pincode delay auth username password + + case $auth in + "0" ) + auth= + ;; + "1" ) + auth="pap" + ;; + "2" ) + auth="chap" + ;; + "*" ) + auth= + ;; + esac + + IMEI="Unknown" + IMSI="Unknown" + ICCID="Unknown" + CNUM="*" + CNUMx="*" + + [ -n "$ctl_device" ] && device=$ctl_device + + [ -n "$device" ] || { + log "No control device specified" + proto_notify_error "$interface" NO_DEVICE + proto_set_available "$interface" 0 + return 1 + } + [ -c "$device" ] || { + log "The specified control device does not exist" + proto_notify_error "$interface" NO_DEVICE + proto_set_available "$interface" 0 + return 1 + } + + devname="$(basename "$device")" + devpath="$(readlink -f /sys/class/usbmisc/$devname/device/)" + ifname="$( ls "$devpath"/net )" + + [ -n "$ifname" ] || { + log "Failed to find matching interface" + proto_notify_error "$interface" NO_IFNAME + proto_set_available "$interface" 0 + return 1 + } + + [ -n "$delay" ] && sleep "$delay" + + log "Query radio state" + umbim $DBG -n -d $device radio | grep "off" + STATUS=$? + + [ "$STATUS" -ne 0 ] || { + sleep 1 + log "Setting FCC Auth" + uqmi $DBG -s -m -d $device --fcc-auth + sleep 1 + } + + log "Reading capabilities" + tid=$((tid + 1)) + DCAPS=$(umbim $DBG -n -t $tid -d $device caps) + retq=$? + if [ $retq -ne 0 ]; then + + log "Failed to read modem caps" + tid=$((tid + 1)) + umbim $DBG -t $tid -d "$device" disconnect + proto_notify_error "$interface" PIN_FAILED + return 1 + fi + CUSTOM=$(echo "$DCAPS" | awk '/customdataclass:/ {print $2}') + IMEI=$(echo "$DCAPS" | awk '/deviceid:/ {print $2}') + uci set modem.modem$CURRMODEM.imei=$IMEI + echo 'CUSTOM="'"$CUSTOM"'"' > /tmp/mbimcustom$CURRMODEM + + get_sub + + if [ ! -f /tmp/profile$CURRMODEM ]; then + $ROOTER/connect/get_profile.sh $CURRMODEM + fi + + get_connect + + log "Checking PIN state" + tid=$((tid + 1)) + umbim $DBG -n -t $tid -d $device pinstate + retq=$? + if [ $retq -eq 2 ]; then + log "PIN is required" + if [ ! -z $pincode ]; then + log "Sending PIN" + tid=$((tid + 1)) + umbim $DBG -n -t $tid -d $device unlock "$pincode" 2>/dev/null + retq=$? + if [ $retq -ne 0 ]; then + log "PIN unlock failed" + exit 1 + else + log "PIN unlocked" + sleep 3 + CHKPORT=$(uci get modem.modem$CURRMODEM.commport) + if [ ! -z $CHKPORT ]; then + $ROOTER/common/gettype.sh $CURRMODEM + else + get_sub + fi + fi + else + log "PIN is missing in the profile" + exit 1 + fi + else + log "PIN is not required" + fi + + log "Register with network" + for i in $(seq 30); do + tid=$((tid + 1)) + REG=$(umbim $DBG -n -t $tid -d $device registration) + retq=$? + [ $retq -ne 2 ] && break + sleep 2 + done + if [ $retq != 0 ]; then + if [ $retq != 4 ]; then + log "Subscriber registration failed" + proto_notify_error "$interface" NO_REGISTRATION + return 1 + fi + fi + MCCMNC=$(echo "$REG" | awk '/provider_id:/ {print $2}') + PROV=$(echo "$REG" | awk '/provider_name:/ {print $2}') + MCC=${MCCMNC:0:3} + MNC=${MCCMNC:3} + + tid=$((tid + 1)) + + log "Attach to network" + ATTACH=$(umbim $DBG -n -t $tid -d $device attach) + retq=$? + if [ $retq != 0 ]; then + log "Failed to attach to network" + proto_notify_error "$interface" ATTACH_FAILED + return 1 + fi + UP=$(echo "$ATTACH" | awk '/uplinkspeed:/ {print $2}') + DOWN=$(echo "$ATTACH" | awk '/downlinkspeed:/ {print $2}') + + tid=$((tid + 1)) + + for isp in $isplist + do + NAPN=$(echo $isp | cut -d, -f2) + NPASS=$(echo $isp | cut -d, -f4) + CID=$(echo $isp | cut -d, -f5) + NUSER=$(echo $isp | cut -d, -f6) + NAUTH=$(echo $isp | cut -d, -f7) + if [ "$NPASS" = "nil" ]; then + NPASS="NIL" + fi + if [ "$NUSER" = "nil" ]; then + NUSER="NIL" + fi + if [ "$NAUTH" = "nil" ]; then + NAUTH="0" + fi + apn=$NAPN + username="$NUSER" + password="$NPASS" + auth=$NAUTH + case $auth in + "0" ) + auth="none" + ;; + "1" ) + auth="pap" + ;; + "2" ) + auth="chap" + ;; + "*" ) + auth="none" + ;; + esac + + if [ ! -e /etc/config/isp ]; then + log "Connect to network using $apn" + else + log "Connect to network" + fi + + if [ ! -e /etc/config/isp ]; then + log "$ipt $apn $auth $username $password" + fi + + tidd=0 + tcnt=4 + while ! umbim $DBG -n -t $tid -d $device connect "$ipt""$apn" "$auth" "$username" "$password"; do + tid=$((tid + 1)) + sleep 1; + tidd=$((tidd + 1)) + if [ $tidd -gt $tcnt ]; then + break; + fi + done + if [ $tidd -le $tcnt ]; then + break + fi + done + if [ $tidd -gt $tcnt ]; then + log "Failed to connect to network" + return 1 + fi + + tid=$((tid + 1)) + + log "Get IP config" + CONFIG=$(umbim $DBG -n -t $tid -d $device config) || { + log "config failed" + return 1 + } + + IP=$(echo -e "$CONFIG"|grep "ipv4address"|grep -E -o "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)") + GATE=$(echo -e "$CONFIG"|grep "ipv4gateway"|grep -E -o "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)") + DNS1=$(echo -e "$CONFIG"|grep "ipv4dnsserver"|grep -E -o "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)" |sed -n 1p) + DNS2=$(echo -e "$CONFIG"|grep "ipv4dnsserver"|grep -E -o "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)" |sed -n 2p) + if [ $enb = "1" ]; then + IP6=$(echo "$CONFIG" | awk '/ipv6address:/ {print $2}' | cut -d / -f 1) + DNS3=$(echo "$CONFIG" | awk '/ipv6dnsserver:/ {print $2}' | sed -n 1p) + DNS4=$(echo "$CONFIG" | awk '/ipv6dnsserver:/ {print $2}' | sed -n 2p) + fi + echo "$GATE" > /tmp/mbimgateway + + [ -n "$IP" ] && echo "IP: $IP" + [ -n "$DNS1" ] && echo "DNS1: $DNS1" + [ -n "$DNS2" ] && echo "DNS2: $DNS2" + if [ $enb = "1" ]; then + [ -n "$IP6" ] && echo "IPv6: $IP6" + [ -n "$DNS3" ] && echo "DNS3: $DNS3" + [ -n "$DNS4" ] && echo "DNS4: $DNS4" + fi + + log "Connected, setting IP" + + if [ $enb = "1" ]; then + if [ -n "$IP6" -a -z "$IP" ]; then + log "Running IPv6-only mode" + nat46=1 + fi + + if [[ $(echo "$IP6" | grep -o "^[23]") ]]; then + # Global unicast IP acquired + v6cap=1 + elif + [[ $(echo "$IP6" | grep -o "^[0-9a-fA-F]\{1,4\}:") ]]; then + # non-routable address + v6cap=2 + else + v6cap=0 + fi + fi + + INTER=$(uci get modem.modem$CURRMODEM.inter) + if [ -e /tmp/v4dns$INTER -o -e /tmp/v6dns$INTER ]; then + pdns=1 + if [ -e /tmp/v4dns$INTER ]; then + v4dns=$(cat /tmp/v4dns$INTER 2>/dev/null) + fi + if [ $enb = "1" ]; then + if [ -e /tmp/v6dns$INTER ]; then + v6dns=$(cat /tmp/v6dns$INTER 2>/dev/null) + fi + fi + else + v4dns="$DNS1 $DNS2" + if [ $enb = "1" ]; then + v6dns="$DNS3 $DNS4" + fi + fi + + proto_init_update "$ifname" 1 + + if [ -n "$IP" ]; then + proto_add_ipv4_address $IP "255.255.255.255" + proto_add_ipv4_route "0.0.0.0" 0 + fi + + for DNSV in $(echo "$v4dns"); do + proto_add_dns_server "$DNSV" + done + + if [ $enb = "1" ]; then + if [ "$v6cap" -gt 0 ]; then + # RFC 7278: Extend an IPv6 /64 Prefix to LAN + proto_add_ipv6_address $IP6 128 + if [ "$v6cap" = 1 ]; then + proto_add_ipv6_prefix $IP6/64 + proto_add_ipv6_route "::0" 0 "" "" "" $IP6/64 + for DNSV in $(echo "$v6dns"); do + proto_add_dns_server "$DNSV" + done + fi + fi + fi + + proto_add_data + json_add_string zone wan + proto_close_data + + proto_send_update "$interface" + + if [ $enb = "1" ]; then + if [ "$v6cap" -gt 0 ]; then + local zone="$(fw3 -q network "$interface" 2>/dev/null)" + fi + if [ "$v6cap" = 2 ]; then + log "Adding IPv6 dynamic interface" + json_init + json_add_string name "${interface}_6" + json_add_string ${ifname1} "@$interface" + json_add_string proto "dhcpv6" + json_add_string extendprefix 1 + [ -n "$zone" ] && json_add_string zone "$zone" + [ "$nat46" = 1 ] || json_add_string iface_464xlat 0 + json_add_boolean peerdns 0 + json_add_array dns + for DNSV in $(echo "$v6dns"); do + json_add_string "" "$DNSV" + done + json_close_array + proto_add_dynamic_defaults + json_close_object + ubus call network add_dynamic "$(json_dump)" + elif + [ "$v6cap" = 1 -a "$nat46" = 1 ]; then + log "Adding 464XLAT (CLAT) dynamic interface" + json_init + json_add_string name "CLAT$INTER" + json_add_string proto "464xlat" + json_add_string tunlink "${interface}" + [ -n "$zone" ] && json_add_string zone "$zone" + proto_add_dynamic_defaults + json_close_object + ubus call network add_dynamic "$(json_dump)" + fi + fi + + tid=$((tid + 1)) + uci_set_state network $interface tid "$tid" +# SIGNAL=$(umbim $DBG -n -t $tid -d $device signal) +# CSQ=$(echo "$SIGNAL" | awk '/rssi:/ {print $2}') + + $ROOTER/log/logger "Modem #$CURRMODEM Connected" + log "Modem $CURRMODEM Connected" + + IDP=$(uci get modem.modem$CURRMODEM.idP) + IDV=$(uci get modem.modem$CURRMODEM.idV) + + if [ ! -s /tmp/msimdata$CURRMODEM ]; then + echo $IDV" : "$IDP > /tmp/msimdatax$CURRMODEM + echo "$IMEI" >> /tmp/msimdatax$CURRMODEM + echo "$IMSI" >> /tmp/msimdatax$CURRMODEM + echo "$ICCID" >> /tmp/msimdatax$CURRMODEM + echo "1" >> /tmp/msimdatax$CURRMODEM + mv -f /tmp/msimdatax$CURRMODEM /tmp/msimdata$CURRMODEM + fi + + if [ ! -s /tmp/msimnum$CURRMODEM ]; then + echo "$CNUM" > /tmp/msimnumx$CURRMODEM + echo "$CNUMx" >> /tmp/msimnumx$CURRMODEM + mv -f /tmp/msimnumx$CURRMODEM /tmp/msimnum$CURRMODEM + fi + + uci set modem.modem$CURRMODEM.custom=$CUSTOM + uci set modem.modem$CURRMODEM.provider=$PROV + uci set modem.modem$CURRMODEM.down=$DOWN" kbps Down | " + uci set modem.modem$CURRMODEM.up=$UP" kbps Up" + uci set modem.modem$CURRMODEM.mcc=$MCC + uci set modem.modem$CURRMODEM.mnc=" "$MNC + uci set modem.modem$CURRMODEM.sig="--" + uci set modem.modem$CURRMODEM.sms=0 + uci commit modem + + COMMPORT=$(uci get modem.modem$CURRMODEM.commport) + if [ -z $COMMPORT ]; then + ln -s $ROOTER/mbim/mbimdata.sh $ROOTER_LINK/getsignal$CURRMODEM + else + $ROOTER/sms/check_sms.sh $CURRMODEM & + ln -s $ROOTER/signal/modemsignal.sh $ROOTER_LINK/getsignal$CURRMODEM + # send custom AT startup command + if [ $(uci -q get modem.modeminfo$CURRMODEM.at) -eq "1" ]; then + ATCMDD=$(uci -q get modem.modeminfo$CURRMODEM.atc) + if [ ! -z "${ATCMDD}" ]; then + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + OX=$($ROOTER/common/processat.sh "$OX") + ERROR="ERROR" + if `echo ${OX} | grep "${ERROR}" 1>/dev/null 2>&1` + then + log "Error sending custom AT command: $ATCMDD with result: $OX" + else + log "Sent custom AT command: $ATCMDD with result: $OX" + fi + fi + fi + fi + ln -s $ROOTER/connect/reconnect.sh $ROOTER_LINK/reconnect$CURRMODEM + $ROOTER_LINK/getsignal$CURRMODEM $CURRMODEM $PROT & + ln -s $ROOTER/connect/conmon.sh $ROOTER_LINK/con_monitor$CURRMODEM + $ROOTER_LINK/con_monitor$CURRMODEM $CURRMODEM & + #ln -s $ROOTER/mbim/monitor.sh $ROOTER_LINK/mbim_monitor$CURRMODEM + #$ROOTER_LINK/mbim_monitor$CURRMODEM $CURRMODEM $device & + + uci set modem.modem$CURRMODEM.connected=1 + uci commit modem + + if [ -e $ROOTER/connect/postconnect.sh ]; then + $ROOTER/connect/postconnect.sh $CURRMODEM + fi + + if [ -e $ROOTER/timezone.sh ]; then + TZ=$(uci -q get modem.modeminfo$CURRMODEM.tzone) + if [ "$TZ" = "1" ]; then + $ROOTER/timezone.sh & + fi + fi + CLB=$(uci -q get modem.modeminfo$CURRMODEM.lb) + if [ -e /etc/config/mwan3 ]; then + INTER=$(uci get modem.modeminfo$CURRMODEM.inter) + if [ -z $INTER ]; then + INTER=0 + else + if [ $INTER = 0 ]; then + INTER=$CURRMODEM + fi + fi + ENB=$(uci -q get mwan3.wan$CURRMODEM.enabled) + if [ ! -z $ENB ]; then + if [ $CLB = "1" ]; then + uci set mwan3.wan$INTER.enabled=1 + else + uci set mwan3.wan$INTER.enabled=0 + fi + uci commit mwan3 + /usr/sbin/mwan3 restart + fi + fi + rm -f /tmp/usbwait + + return 0 +} + +proto_mbim_setup() { + + local ret + _proto_mbim_setup $@ + ret=$? + + [ "$ret" = 0 ] || { + log "MBIM bringup failed, retry in 5s" + CPORT=$(uci get modem.modem$CURRMODEM.commport) + ATCMDD="AT+COPS=0" + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + sleep 5 + } + + exit 0 + return $ret +} + +proto_mbim_teardown() { + local interface="$1" + + local device + json_get_vars device + local tid=$(uci_get_state network $interface tid) + + [ -n "$ctl_device" ] && device=$ctl_device + + if [ -n "$device" ]; then + log "Stopping network" + if [ -n "$tid" ]; then + tid=$((tid + 1)) + umbim $DBG -t $tid -d "$device" disconnect + uci_revert_state network $interface tid + else + umbim $DBG -d "$device" disconnect + fi + fi + + proto_init_update "*" 0 + proto_send_update "$interface" + +} + +[ -n "$INCLUDE_ONLY" ] || add_protocol mbim diff --git a/rooter/0drivers/rmbim/files/usr/lib/rooter/mbim/mbimdata.sh b/rooter/0drivers/rmbim/files/usr/lib/rooter/mbim/mbimdata.sh new file mode 100644 index 0000000..41f6f10 --- /dev/null +++ b/rooter/0drivers/rmbim/files/usr/lib/rooter/mbim/mbimdata.sh @@ -0,0 +1,115 @@ +#!/bin/sh + +ROOTER=/usr/lib/rooter +ROOTER_LINK=$ROOTER"/links" + +log() { + logger -t "MBIM Data" "$@" +} + +STARTIMEX=$(date +%s) +MONSTAT= +rm -f /tmp/monstat$CURRMODEM + +build_status() { + CSQ=$signal + if [ $CSQ -ge 0 -a $CSQ -le 31 ]; then + CSQ_PER=$(($CSQ * 100/31)) + CSQ_RSSI=$((2 * CSQ - 113)) + CSQX=$CSQ_RSSI + [ $CSQ -eq 0 ] && CSQ_RSSI="<= "$CSQ_RSSI + [ $CSQ -eq 31 ] && CSQ_RSSI=">= "$CSQ_RSSI + CSQ_PER=$CSQ_PER"%" + CSQ_RSSI=$CSQ_RSSI" dBm" + else + CSQ="-" + CSQ_PER="-" + CSQ_RSSI="-" + fi + echo "-" > /tmp/status$CURRMODEM.file + echo "$CSQ" >> /tmp/status$CURRMODEM.file + echo "$CSQ_PER" >> /tmp/status$CURRMODEM.file + echo "$CSQ_RSSI" >> /tmp/status$CURRMODEM.file + echo "$manuf" >> /tmp/status$CURRMODEM.file + echo "$provider" >> /tmp/status$CURRMODEM.file + echo "$cellmode" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "$mcc" >> /tmp/status$CURRMODEM.file + echo "$mnc" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "$down" >> /tmp/status$CURRMODEM.file + echo "$up" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo " " >> /tmp/status$CURRMODEM.file + echo " " >> /tmp/status$CURRMODEM.file + echo "$MONSTAT" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "$conn" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "MBIM" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file +} + +CURRMODEM=$1 + +conn="Modem #"$CURRMODEM +custom=$(uci get modem.modem$CURRMODEM.custom) +port=$(uci get modem.modem$CURRMODEM.wdm) +netd=$(uci get modem.modem$CURRMODEM.wwan) +manuf=$(uci get modem.modem$CURRMODEM.manuf) +model=$(uci get modem.modem$CURRMODEM.model) +mcc=$(uci get modem.modem$CURRMODEM.mcc) +mnc=$(uci get modem.modem$CURRMODEM.mnc) +up=$(uci get modem.modem$CURRMODEM.up) +down=$(uci get modem.modem$CURRMODEM.down) +provider=$(uci get modem.modem$CURRMODEM.provider) +cellmode=$(uci get modem.modem$CURRMODEM.mode) +if [ $cellmode = "CUSTOM" ]; then + cellmode=$custom +fi +signal=$(uci get modem.modem$CURRMODEM.sig) + +device="/dev/cdc-wdm"$port +netdev="wwan"$netd +manuf=$manuf" "$model + +tid=2 +while [ 1 -eq 1 ]; do + tid=2 + #SIGNAL=$(umbim -n -t $tid -d $device signal) + tid=$((tid + 1)) + #SIGNAL=$(umbim -n -t $tid -d $device signal) + signal=0 + if [ -e /tmp/monstat$CURRMODEM ]; then + source /tmp/monstat$CURRMODEM + fi + if [ -z $MONSTAT ]; then + MONSTAT="Unknown" + fi + build_status + if [ -e /etc/netspeed ]; then + NETSPEED=60 + else + NETSPEED=10 + fi + CURRTIME=$(date +%s) + let ELAPSE=CURRTIME-STARTIMEX + while [ $ELAPSE -lt $NETSPEED ]; do + sleep 2 + CURRTIME=$(date +%s) + let ELAPSE=CURRTIME-STARTIMEX + done + STARTIMEX=$CURRTIME +done diff --git a/rooter/0drivers/rmbim/files/usr/lib/rooter/mbim/monitor.sh b/rooter/0drivers/rmbim/files/usr/lib/rooter/mbim/monitor.sh new file mode 100644 index 0000000..0e84aec --- /dev/null +++ b/rooter/0drivers/rmbim/files/usr/lib/rooter/mbim/monitor.sh @@ -0,0 +1,45 @@ +#!/bin/sh + +. /lib/functions.sh + +ROOTER_LINK="/tmp/links" + +log() { + logger -t "MBIM Monitor" "$@" +} + +CURRMODEM=$1 +DEVICE=$2 + +while :; do + tid=$(uci_get_state network wan$CURRMODEM tid) + tid=$((tid + 1)) + umbim -d $DEVICE -n -t $tid status >/dev/null + retq=$? + uci_toggle_state network wan$CURRMODEM tid $tid + [ $retq -ne 0 ] && break + sleep 10 +done + +case $retq in +2) + error="activation state: activating" + ;; +3) + error="activation state: deactivated" + ;; +4) + error="activation state: deactivating" + ;; +255) + error="MBIM message not long enough" + ;; +esac + +log "Modem $CURRMODEM Connection is Down ($error)" +if [ -f $ROOTER_LINK/reconnect$CURRMODEM ]; then + $ROOTER_LINK/reconnect$CURRMODEM $CURRMODEM & +fi + +# wait to be killed by mbim.sh +sleep 60 diff --git a/rooter/0drivers/rqmi/Makefile b/rooter/0drivers/rqmi/Makefile new file mode 100644 index 0000000..0674e1f --- /dev/null +++ b/rooter/0drivers/rqmi/Makefile @@ -0,0 +1,52 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=uqmi +PKG_RELEASE:=$(AUTORELEASE) + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL=$(PROJECT_GIT)/project/uqmi.git +PKG_SOURCE_DATE:=2022-05-04 +PKG_SOURCE_VERSION:=56cb2d4056fef132ccf78dfb6f3074ae5d109992 +PKG_MIRROR_HASH:=cc832b5318805df8c8387a3650f250dee72d5f1dbda4e4866b5503e186b2210c +PKG_MAINTAINER:=Matti Laakso + +PKG_LICENSE:=GPL-2.0 +PKG_LICENSE_FILES:= + +PKG_FLAGS:=nonshared + +include $(INCLUDE_DIR)/package.mk +include $(INCLUDE_DIR)/cmake.mk + +define Package/rqmi + SECTION:=net + CATEGORY:=ROOter + SUBMENU:=Drivers + DEPENDS:=+libubox +libblobmsg-json +kmod-usb-net +kmod-usb-net-qmi-wwan +wwan + TITLE:=Control utility for mobile broadband modems +endef + +define Package/rqmi/description + uqmi is a command line tool for controlling mobile broadband modems using + the QMI-protocol. +endef + +TARGET_CFLAGS += \ + -I$(STAGING_DIR)/usr/include \ + -ffunction-sections \ + -fdata-sections \ + -Wno-error=dangling-pointer \ + -Wno-error=maybe-uninitialized + +TARGET_LDFLAGS += -Wl,--gc-sections + +CMAKE_OPTIONS += \ + -DDEBUG=1 + +define Package/rqmi/install + $(INSTALL_DIR) $(1)/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/uqmi $(1)/sbin/ + $(CP) ./files/* $(1)/ +endef + +$(eval $(call BuildPackage,rqmi)) diff --git a/rooter/0drivers/rqmi/files/usr/lib/rooter/qmi/connectqmi.sh b/rooter/0drivers/rqmi/files/usr/lib/rooter/qmi/connectqmi.sh new file mode 100644 index 0000000..7dc6d02 --- /dev/null +++ b/rooter/0drivers/rqmi/files/usr/lib/rooter/qmi/connectqmi.sh @@ -0,0 +1,293 @@ +#!/bin/sh + +ROOTER=/usr/lib/rooter + +log() { + modlog "QMI Connect $CURRMODEM" "$@" +} + + . /lib/functions.sh + . /lib/netifd/netifd-proto.sh + +CURRMODEM=$1 +devname=$2 +device=/dev/$2 +auth=$3 +NAPN=$4 +username=$5 +password=$6 +RAW=$7 +DHCP=$8 +pincode=$9 + +enb=$(uci -q get custom.connect.ipv6) +if [ -z $enb ]; then + enb="1" +fi + +ifname1="ifname" +if [ -e /etc/newstyle ]; then + ifname1="device" +fi + +INTER=$(uci -q get modem.modem$CURRMODEM.inter) +interface="wan"$INTER + +case $auth in + "0" ) + auth="none" + ;; + "1" ) + auth="pap" + ;; + "2" ) + auth="chap" + ;; + *) + auth="none" + ;; +esac + +if [ $username = NIL ]; then + username= +fi +if [ $password = NIL ]; then + password= +fi + +ifname="$(ls /sys/class/usbmisc/$devname/device/net/)" + +#while uqmi -s -d "$device" --get-pin-status | grep '"UIM uninitialized"' > /dev/null; do +# sleep 1; +#done + +[ -n "$pincode" ] && { + uqmi -s -d "$device" --verify-pin1 "$pincode" || { + log "Unable to verify PIN" + ret=1 + } +} + +uqmi -s -d "$device" --stop-network 0xffffffff --autoconnect > /dev/null & sleep 5 ; kill -9 $! +uqmi -s -d "$device" --set-device-operating-mode online > /dev/null 2>&1 & sleep 5 ; kill -9 $! + +if [ $RAW -eq 1 ]; then + DATAFORM='"raw-ip"' +else + if [ $idV = 1199 -a $idP = 9055 ]; then + $ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "reset.gcom" "$CURRMODEM" + DATAFORM='"802.3"' + uqmi -s -d "$device" --set-data-format 802.3 + uqmi -s -d "$device" --wda-set-data-format 802.3 + else + log "getting data format" + DATAFORM=$(uqmi -s -d "$device" --wda-get-data-format) + fi +fi + +log "WDA-GET-DATA-FORMAT is $DATAFORM" +if [ "$DATAFORM" = '"raw-ip"' ]; then + [ -f /sys/class/net/$ifname/qmi/raw_ip ] || { + log "Device only supports raw-ip mode but is missing this required driver attribute: /sys/class/net/$ifname/qmi/raw_ip" + ret=1 + } + echo "Y" > /sys/class/net/$ifname/qmi/raw_ip +fi + +log "Query radio state" +uqmi -s -d "$device" --get-signal-info | grep -q "Information unavailable" & sleep 5 ; kill -9 $! +STATUS=$? + +[ "$STATUS" -ne 0 ] || { + sleep 1 + log "Setting FCC Auth" + uqmi -s -d "$device" --fcc-auth & sleep 5 ; kill -9 $! + sleep 1 + } + +uqmi -s -d "$device" --sync > /dev/null 2>&1 & sleep 5 ; kill -9 $! + +#uqmi -s -d "$device" --network-register > /dev/null 2>&1 + +log "Waiting for network registration" +td=0 +while uqmi -s -d "$device" --get-serving-system | grep '"searching"' > /dev/null; do + sleep 5; + tid=$((tid + 1)) + if [ $tid -gt 2 ]; then + uqmi -s -d "$device" --stop-network 0xffffffff --autoconnect > /dev/null & sleep 10 ; kill -9 $! + exit 1 + fi +done + +cid=`uqmi -s -d "$device" --get-client-id wds` +[ $? -ne 0 ] && { + log "Unable to obtain client ID" + ret=1 +} + +uqmi -s -d "$device" --set-client-id wds,"$cid" --set-ip-family ipv4 > /dev/null + +isplist=$(uci -q get modem.modeminfo$CURRMODEM.isplist) +apn2=$(uci -q get modem.modeminfo$CURRMODEM.apn2) +for isp in $isplist + do + NAPN=$(echo $isp | cut -d, -f2) + NPASS=$(echo $isp | cut -d, -f4) + CID=$(echo $isp | cut -d, -f5) + NUSER=$(echo $isp | cut -d, -f6) + NAUTH=$(echo $isp | cut -d, -f7) + if [ "$NPASS" = "nil" ]; then + NPASS="NIL" + fi + if [ "$NUSER" = "nil" ]; then + NUSER="NIL" + fi + if [ "$NAUTH" = "nil" ]; then + NAUTH="0" + fi + username="$NUSER" + password="$NPASS" + auth=$NAUTH + case $auth in + "0" ) + auth="none" + ;; + "1" ) + auth="pap" + ;; + "2" ) + auth="chap" + ;; + "*" ) + auth="none" + ;; + esac + + if [ ! -e /etc/config/isp ]; then + log "Connect to network using $NAPN" + else + log "Connect to network" + fi + + if [ ! -e /etc/config/isp ]; then + log "$NAPN $auth $username $password" + fi + + conn=0 + tidd=0 + tcnt=4 + while true; do + ST=$(uqmi -s -d "$device" --set-client-id wds,"$cid" --start-network ${NAPN:+--apn $NAPN} ${auth:+--auth-type $auth} \ + ${username:+--username $username} ${password:+--password $password}) + log "Connection returned : $ST" + CONN=$(uqmi -s -d "$device" --get-data-status) + log "Status is $CONN" + if [[ $(echo "$CONN" | grep -o "disconnected") ]]; then + sleep 1 + tidd=$((tidd + 1)) + if [ $tidd -gt $tcnt ]; then + break + fi + else + conn=1 + break + fi + done + if [ $conn -eq 1 ]; then + break; + fi + done + +if [[ -z $(echo "$CONN" | grep -o "disconnected") ]]; then + ret=0 + + CONN4=$(uqmi -s -d "$device" --set-client-id wds,"$cid" --get-current-settings) + log "GET-CURRENT-SETTINGS is $CONN4" + + if [ $enb = "1" ]; then + cid6=`uqmi -s -d "$device" --get-client-id wds` + [ $? -ne 0 ] && { + log "Unable to obtain client ID" + ret=1 + } + + uqmi -s -d "$device" --set-client-id wds,"$cid6" --set-ip-family ipv6 > /dev/null + ST6=$(uqmi -s -d "$device" --set-client-id wds,"$cid6" --start-network ${NAPN:+--apn $NAPN} ${auth:+--auth-type $auth} \ + ${username:+--username $username} ${password:+--password $password}) + log "IPv6 Connection returned : $ST6" + CONN6=$(uqmi -s -d "$device" --set-client-id wds,"$cid6" --get-current-settings) + CONF6=$(jsonfilter -s $CONN6 -e '@.ipv6') + if [ -n "$CONF6" ];then + log "IPv6 settings are $CONF6" + touch /tmp/ipv6supp$INTER + else + rm -f /tmp/ipv6supp$INTER + fi + fi + + if [ $DATAFORM = '"raw-ip"' ]; then + log "Handle raw-ip" + json_load "$CONN4" + json_select ipv4 + json_get_vars ip subnet gateway dns1 dns2 + if [ $enb = "1" ]; then + if [ -n "$CONF6" ]; then + json_load "$CONN6" + json_select ipv6 + json_get_var ip_6 ip + json_get_var gateway_6 gateway + json_get_var dns1_6 dns1 + json_get_var dns2_6 dns2 + json_get_var ip_prefix_length ip-prefix-length + fi + fi + + if [ -s /tmp/v4dns$INTER -o -s /tmp/v6dns$INTER ]; then + pdns=1 + if [ -s /tmp/v4dns$INTER ]; then + v4dns=$(cat /tmp/v4dns$INTER 2>/dev/null) + fi + if [ $enb = "1" ]; then + if [ -s /tmp/v6dns$INTER ]; then + v6dns=$(cat /tmp/v6dns$INTER 2>/dev/null) + fi + fi + else + v4dns="$dns1 $dns2" + if [ $enb = "1" ]; then + v6dns="$dns1_6 $dns2_6" + echo "$v6dns" > /tmp/v6dns$INTER + fi + fi + + if [ $DHCP -eq 0 ]; then + log Applying IP settings to wan$INTER + uci delete network.wan$INTER + uci set network.wan$INTER=interface + uci set network.wan$INTER.proto=static + uci set network.wan$INTER.${ifname1}=$ifname + uci set network.wan$INTER.metric=$INTER"0" + uci set network.wan$INTER.ipaddr=$ip/$subnet + uci set network.wan$INTER.gateway='0.0.0.0' + uci set network.wan$INTER.dns="$v4dns" + uci commit network + uci set modem.modem$CURRMODEM.interface=$ifname + uci commit modem + else + proto_init_update "$ifname" 1 + proto_set_keep 1 + proto_add_ipv4_address "$ip" "$subnet" + proto_add_ipv4_route "0.0.0.0" 0 + for DNSV in $(echo "$v4dns"); do + proto_add_dns_server "$DNSV" + done + proto_send_update "$interface" + fi + fi +else + uqmi -s -d "$device" --stop-network 0xffffffff --autoconnect > /dev/null & sleep 10 ; kill -9 $! + ret=1 +fi + +exit $ret diff --git a/rooter/0mesh/mesh-mesh/Makefile b/rooter/0mesh/mesh-mesh/Makefile new file mode 100644 index 0000000..39281b6 --- /dev/null +++ b/rooter/0mesh/mesh-mesh/Makefile @@ -0,0 +1,34 @@ +#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)) diff --git a/rooter/0mesh/mesh-mesh/files/etc/config/batman-adv b/rooter/0mesh/mesh-mesh/files/etc/config/batman-adv new file mode 100644 index 0000000..0b4e014 --- /dev/null +++ b/rooter/0mesh/mesh-mesh/files/etc/config/batman-adv @@ -0,0 +1,16 @@ +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' \ No newline at end of file diff --git a/rooter/0mesh/mesh-mesh/files/etc/config/mesh b/rooter/0mesh/mesh-mesh/files/etc/config/mesh new file mode 100644 index 0000000..959ba5a --- /dev/null +++ b/rooter/0mesh/mesh-mesh/files/etc/config/mesh @@ -0,0 +1,18 @@ + +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' + diff --git a/rooter/0mesh/mesh-mesh/files/etc/hotplug.d/net/99-batman-gw b/rooter/0mesh/mesh-mesh/files/etc/hotplug.d/net/99-batman-gw new file mode 100644 index 0000000..600f70b --- /dev/null +++ b/rooter/0mesh/mesh-mesh/files/etc/hotplug.d/net/99-batman-gw @@ -0,0 +1,34 @@ +#!/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 diff --git a/rooter/0mesh/mesh-mesh/files/etc/init.d/zmesh b/rooter/0mesh/mesh-mesh/files/etc/init.d/zmesh new file mode 100644 index 0000000..68e6158 --- /dev/null +++ b/rooter/0mesh/mesh-mesh/files/etc/init.d/zmesh @@ -0,0 +1,9 @@ +#!/bin/sh /etc/rc.common +# Copyright (C) 2006 OpenWrt.org + +START=99 + +start() { + /usr/lib/mesh/checker.sh +} + diff --git a/rooter/0mesh/mesh-mesh/files/usr/lib/lua/luci/controller/batman.lua b/rooter/0mesh/mesh-mesh/files/usr/lib/lua/luci/controller/batman.lua new file mode 100644 index 0000000..8f2cf83 --- /dev/null +++ b/rooter/0mesh/mesh-mesh/files/usr/lib/lua/luci/controller/batman.lua @@ -0,0 +1,249 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2012 Jo-Philipp Wich + +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 diff --git a/rooter/0mesh/mesh-mesh/files/usr/lib/lua/luci/controller/mesh.lua b/rooter/0mesh/mesh-mesh/files/usr/lib/lua/luci/controller/mesh.lua new file mode 100644 index 0000000..923cec2 --- /dev/null +++ b/rooter/0mesh/mesh-mesh/files/usr/lib/lua/luci/controller/mesh.lua @@ -0,0 +1,76 @@ +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 + diff --git a/rooter/0mesh/mesh-mesh/files/usr/lib/lua/luci/view/batman/batman.htm b/rooter/0mesh/mesh-mesh/files/usr/lib/lua/luci/view/batman/batman.htm new file mode 100644 index 0000000..d23421c --- /dev/null +++ b/rooter/0mesh/mesh-mesh/files/usr/lib/lua/luci/view/batman/batman.htm @@ -0,0 +1,300 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2012 Jo-Philipp Wich + +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%> + + + + + + + + +

              <%:Mesh Status%>

              + +
              + + + + + + +
              Internet Status :
                +
                + +
                + <%:Active Mesh Nodes%> + + + + + + + + + + + +
                <%:Link Quality%><%:MAC-Address%><%:Last Seen%><%:Interface%><%:Next Hop%>

                <%:Collecting data...%>
                +
                + +
                + <%:Other Mesh Nodes with Internet Access%> + + + + + + + + + + + +
                <%:MAC-Address%><%:Speed%><%:Link Quality%><%:Interface%><%:Next Hop%>

                <%:Collecting data...%>
                +
                + +
                + <%:Visualization%> +
                +
                + +<%+footer%> diff --git a/rooter/0mesh/mesh-mesh/files/usr/lib/lua/luci/view/mesh/mesh-setup.htm b/rooter/0mesh/mesh-mesh/files/usr/lib/lua/luci/view/mesh/mesh-setup.htm new file mode 100644 index 0000000..60a652b --- /dev/null +++ b/rooter/0mesh/mesh-mesh/files/usr/lib/lua/luci/view/mesh/mesh-setup.htm @@ -0,0 +1,912 @@ +<%+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 + +-%> + + + +
                +
                +

                Mesh Network Configuration

                +
                + +
                + + + + + + + + + + + + + + + + + + + + + +
                Config Status
                Import Configuration File
                Export Configuration File
                Save Settings
                Apply Settings
                Reload Settings
                No Changes
                + + + +
                + + + +
                + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                Mesh Radio Settings
                Select Backhaul Radio
                + +
                Dedicated Backhaul Radio
                Select Backhaul Channel
                + +
                Select Backhaul Channel
                + +
                Use DFS Channels
                Select Backhaul Channel
                + +
                Use DFS Channels
                Channel Bandwidth
                + +
                Channel Bandwidth
                + +
                Channel Bandwidth
                + +
                Channel Bandwidth
                + +
                + +
                + +
                + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                Mesh Network Settings
                Mesh Network ID
                Network Encrypted
                +
                + +
                + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                Access Point Roaming
                Enable Low Signal Roaming
                Roaming ID
                + + + + + +
                + +
                + +
                + +
                +
                +<%+footer%> \ No newline at end of file diff --git a/rooter/0mesh/mesh-mesh/files/usr/lib/mesh/checker.sh b/rooter/0mesh/mesh-mesh/files/usr/lib/mesh/checker.sh new file mode 100644 index 0000000..9bf3cbf --- /dev/null +++ b/rooter/0mesh/mesh-mesh/files/usr/lib/mesh/checker.sh @@ -0,0 +1,251 @@ +#!/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 diff --git a/rooter/0mesh/mesh-mesh/files/usr/lib/mesh/ping.sh b/rooter/0mesh/mesh-mesh/files/usr/lib/mesh/ping.sh new file mode 100644 index 0000000..c29fbec --- /dev/null +++ b/rooter/0mesh/mesh-mesh/files/usr/lib/mesh/ping.sh @@ -0,0 +1,34 @@ +#!/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 \ No newline at end of file diff --git a/rooter/0mesh/mesh-mesh/files/usr/lib/mesh/radio.sh b/rooter/0mesh/mesh-mesh/files/usr/lib/mesh/radio.sh new file mode 100644 index 0000000..0ba8076 --- /dev/null +++ b/rooter/0mesh/mesh-mesh/files/usr/lib/mesh/radio.sh @@ -0,0 +1,78 @@ +#!/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 + + + diff --git a/rooter/0mesh/mesh-mesh/files/usr/lib/mesh/save.sh b/rooter/0mesh/mesh-mesh/files/usr/lib/mesh/save.sh new file mode 100644 index 0000000..d050c7d --- /dev/null +++ b/rooter/0mesh/mesh-mesh/files/usr/lib/mesh/save.sh @@ -0,0 +1,25 @@ +#!/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 diff --git a/rooter/0mesh/mesh-mesh/files/usr/lib/mesh/savecfg.sh b/rooter/0mesh/mesh-mesh/files/usr/lib/mesh/savecfg.sh new file mode 100644 index 0000000..bd4bf1f --- /dev/null +++ b/rooter/0mesh/mesh-mesh/files/usr/lib/mesh/savecfg.sh @@ -0,0 +1,16 @@ +#!/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 \ No newline at end of file diff --git a/rooter/0mesh/mesh-mesh/files/usr/lib/mesh/startstop.sh b/rooter/0mesh/mesh-mesh/files/usr/lib/mesh/startstop.sh new file mode 100644 index 0000000..2cd290a --- /dev/null +++ b/rooter/0mesh/mesh-mesh/files/usr/lib/mesh/startstop.sh @@ -0,0 +1,8 @@ +#!/bin/sh +. /lib/functions.sh + +log() { + logger -t "Start Mesh" "$@" +} + +/usr/lib/mesh/checker.sh 1 \ No newline at end of file diff --git a/rooter/0mesh/mesh-mesh/files/www/luci-static/resources/dracula/dracula_graffle.js b/rooter/0mesh/mesh-mesh/files/www/luci-static/resources/dracula/dracula_graffle.js new file mode 100644 index 0000000..9832727 --- /dev/null +++ b/rooter/0mesh/mesh-mesh/files/www/luci-static/resources/dracula/dracula_graffle.js @@ -0,0 +1 @@ +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].xj[n].x)&&(0!=m&&5!=n||j[m].y>j[n].y)&&(1!=m&&4!=n||j[m].ye.width-20?c-e.width+20:0),g=a.clientY-(d<20?d-20:d>e.height-20?d-e.height+20:0);e.isDrag.set.translate(f-Math.round(e.isDrag.dx),g-Math.round(e.isDrag.dy));for(var h in e.graph.edges)e.graph.edges[h].connection&&e.graph.edges[h].connection.draw();e.isDrag.dx=f,e.isDrag.dy=g}},f.onmouseup=function(){e.isDrag&&e.isDrag.set.animate({"fill-opacity":.6},500),e.isDrag=!1},this.draw()},Graph.Renderer.Raphael.prototype={translate:function(a){return[(a[0]-this.graph.layoutMinX)*this.factorX+this.radius,(a[1]-this.graph.layoutMinY)*this.factorY+this.radius]},rotate:function(a,b,c){var d=b*Math.cos(c),e=b*Math.sin(c);return[a[0]+d,a[1]+e]},draw:function(){this.factorX=(this.width-2*this.radius)/(this.graph.layoutMaxX-this.graph.layoutMinX),this.factorY=(this.height-2*this.radius)/(this.graph.layoutMaxY-this.graph.layoutMinY);for(a in this.graph.nodes)this.drawNode(this.graph.nodes[a]);for(var a=0;ab&&(b=e),ed&&(d=f),fk&&(i=k),i<-k&&(i=-k),j>k&&(j=k),j<-k&&(j=-k),h.layoutPosX+=i,h.layoutPosY+=j,h.layoutForceX=0,h.layoutForceY=0}},layoutRepulsive:function(a,b){if("undefined"!=typeof a&&"undefined"!=typeof b){var c=b.layoutPosX-a.layoutPosX,d=b.layoutPosY-a.layoutPosY,e=c*c+d*d;if(e<.01){c=.1*Math.random()+.1,d=.1*Math.random()+.1;var e=c*c+d*d}var f=Math.sqrt(e);if(fthis.maxRepulsiveForceDistance&&(g=this.maxRepulsiveForceDistance,f=g*g);var h=(f-this.k*this.k)/this.k;void 0==a.attraction&&(a.attraction=1),h*=.5*Math.log(a.attraction)+1,c.layoutForceX-=h*d/g,c.layoutForceY-=h*e/g,b.layoutForceX+=h*d/g,b.layoutForceY+=h*e/g}},Graph.Layout.Ordered=function(a,b){this.graph=a,this.order=b,this.layout()},Graph.Layout.Ordered.prototype={layout:function(){this.layoutPrepare(),this.layoutCalcBounds()},layoutPrepare:function(a){for(i in this.graph.nodes){var b=this.graph.nodes[i];b.layoutPosX=0,b.layoutPosY=0}var c=0;for(i in this.order){var b=this.order[i];b.layoutPosX=c,b.layoutPosY=Math.random(),c++}},layoutCalcBounds:function(){var a=1/0,b=-(1/0),c=1/0,d=-(1/0);for(i in this.graph.nodes){var e=this.graph.nodes[i].layoutPosX,f=this.graph.nodes[i].layoutPosY;e>b&&(b=e),ed&&(d=f),f

                ";if(ag.childNodes[m]!=2){return null;}}an.svg=!(an.vml=an.type=="VML");aT[aY]=an[aY];an._id=0;an._oid=0;an.fn={};an.is=function(e,d){d=aZ.call(d);return((d=="object"||d=="undefined")&&typeof e==d)||(e==null&&d=="null")||aZ.call(aw.call(e).slice(8,-1))==d;};an.setWindow=function(d){au=d;L=au.document;};var aD=function(e){if(an.vml){var d=/^\s+|\s+$/g;aD=aj(function(R){var S;R=(R+at)[aP](d,at);try{var a0=new ActiveXObject("htmlfile");a0.write("");a0.close();S=a0.body;}catch(a2){S=createPopup().document.body;}var i=S.createTextRange();try{S.style.color=R;var a1=i.queryCommandValue("ForeColor");a1=((a1&255)<<16)|(a1&65280)|((a1&16711680)>>>16);return"#"+("000000"+a1[aA](16)).slice(-6);}catch(a2){return"none";}});}else{var E=L.createElement("i");E.title="Rapha\xebl Colour Picker";E.style.display="none";L.body[aL](E);aD=aj(function(i){E.style.color=i;return L.defaultView.getComputedStyle(E,at).getPropertyValue("color");});}return aD(e);};an.hsb2rgb=aj(function(a3,a1,a7){if(an.is(a3,"object")&&"h" in a3&&"s" in a3&&"b" in a3){a7=a3.b;a1=a3.s;a3=a3.h;}var R,S,a8;if(a7==0){return{r:0,g:0,b:0,hex:"#000"};}if(a3>1||a1>1||a7>1){a3/=255;a1/=255;a7/=255;}var a0=~~(a3*6),a4=(a3*6)-a0,E=a7*(1-a1),e=a7*(1-(a1*a4)),a9=a7*(1-(a1*(1-a4)));R=[a7,e,E,E,a9,a7,a7][a0];S=[a9,a7,a7,e,E,E,a9][a0];a8=[E,E,a9,a7,a7,e,E][a0];R*=255;S*=255;a8*=255;var a5={r:R,g:S,b:a8},d=(~~R)[aA](16),a2=(~~S)[aA](16),a6=(~~a8)[aA](16);d=d[aP](aU,"0");a2=a2[aP](aU,"0");a6=a6[aP](aU,"0");a5.hex="#"+d+a2+a6;return a5;},an);an.rgb2hsb=aj(function(d,e,a1){if(an.is(d,"object")&&"r" in d&&"g" in d&&"b" in d){a1=d.b;e=d.g;d=d.r;}if(an.is(d,"string")){var a3=an.getRGB(d);d=a3.r;e=a3.g;a1=a3.b;}if(d>1||e>1||a1>1){d/=255;e/=255;a1/=255;}var a0=g(d,e,a1),i=aI(d,e,a1),R,E,S=a0;if(i==a0){return{h:0,s:0,b:a0};}else{var a2=(a0-i);E=a2/a0;if(d==a0){R=(e-a1)/a2;}else{if(e==a0){R=2+((a1-d)/a2);}else{R=4+((d-e)/a2);}}R/=6;R<0&&R++;R>1&&R--;}return{h:R,s:E,b:S};},an);var aE=/,?([achlmqrstvxz]),?/gi;an._path2string=function(){return this.join(",")[aP](aE,"$1");};function aj(E,e,d){function i(){var R=Array[aY].slice.call(arguments,0),a0=R[az]("\u25ba"),S=i.cache=i.cache||{},a1=i.count=i.count||[];if(S[Q](a0)){return d?d(S[a0]):S[a0];}a1[m]>=1000&&delete S[a1.shift()];a1[f](a0);S[a0]=E[aW](e,R);return d?d(S[a0]):S[a0];}return i;}an.getRGB=aj(function(d){if(!d||!!((d=d+at).indexOf("-")+1)){return{r:-1,g:-1,b:-1,hex:"none",error:1};}if(d=="none"){return{r:-1,g:-1,b:-1,hex:"none"};}!(({hs:1,rg:1})[Q](d.substring(0,2))||d.charAt()=="#")&&(d=aD(d));var S,i,E,a2,a3,a0=d.match(x);if(a0){if(a0[2]){a2=G(a0[2].substring(5),16);E=G(a0[2].substring(3,5),16);i=G(a0[2].substring(1,3),16);}if(a0[3]){a2=G((a3=a0[3].charAt(3))+a3,16);E=G((a3=a0[3].charAt(2))+a3,16);i=G((a3=a0[3].charAt(1))+a3,16);}if(a0[4]){a0=a0[4][z](/\s*,\s*/);i=W(a0[0]);E=W(a0[1]);a2=W(a0[2]);}if(a0[5]){a0=a0[5][z](/\s*,\s*/);i=W(a0[0])*2.55;E=W(a0[1])*2.55;a2=W(a0[2])*2.55;}if(a0[6]){a0=a0[6][z](/\s*,\s*/);i=W(a0[0]);E=W(a0[1]);a2=W(a0[2]);return an.hsb2rgb(i,E,a2);}if(a0[7]){a0=a0[7][z](/\s*,\s*/);i=W(a0[0])*2.55;E=W(a0[1])*2.55;a2=W(a0[2])*2.55;return an.hsb2rgb(i,E,a2);}a0={r:i,g:E,b:a2};var e=(~~i)[aA](16),R=(~~E)[aA](16),a1=(~~a2)[aA](16);e=e[aP](aU,"0");R=R[aP](aU,"0");a1=a1[aP](aU,"0");a0.hex="#"+e+R+a1;return a0;}return{r:-1,g:-1,b:-1,hex:"none",error:1};},an);an.getColor=function(e){var i=this.getColor.start=this.getColor.start||{h:0,s:1,b:e||0.75},d=this.hsb2rgb(i.h,i.s,i.b);i.h+=0.075;if(i.h>1){i.h=0;i.s-=0.2;i.s<=0&&(this.getColor.start={h:0,s:1,b:i.b});}return d.hex;};an.getColor.reset=function(){delete this.start;};an.parsePathString=aj(function(d){if(!d){return null;}var i={a:7,c:6,h:1,l:2,m:2,q:4,s:4,t:2,v:1,z:0},e=[];if(an.is(d,"array")&&an.is(d[0],"array")){e=av(d);}if(!e[m]){(d+at)[aP](/([achlmqstvz])[\s,]*((-?\d*\.?\d*(?:e[-+]?\d+)?\s*,?\s*)+)/ig,function(R,E,a1){var a0=[],S=aZ.call(E);a1[aP](/(-?\d*\.?\d*(?:e[-+]?\d+)?)\s*,?\s*/ig,function(a3,a2){a2&&a0[f](+a2);});while(a0[m]>=i[S]){e[f]([E][aS](a0.splice(0,i[S])));if(!i[S]){break;}}});}e[aA]=an._path2string;return e;});an.findDotsAtSegment=function(e,d,be,bc,a0,R,a2,a1,a8){var a6=1-a8,a5=aM(a6,3)*e+aM(a6,2)*3*a8*be+a6*3*a8*a8*a0+aM(a8,3)*a2,a3=aM(a6,3)*d+aM(a6,2)*3*a8*bc+a6*3*a8*a8*R+aM(a8,3)*a1,ba=e+2*a8*(be-e)+a8*a8*(a0-2*be+e),a9=d+2*a8*(bc-d)+a8*a8*(R-2*bc+d),bd=be+2*a8*(a0-be)+a8*a8*(a2-2*a0+be),bb=bc+2*a8*(R-bc)+a8*a8*(a1-2*R+bc),a7=(1-a8)*e+a8*be,a4=(1-a8)*d+a8*bc,E=(1-a8)*a0+a8*a2,i=(1-a8)*R+a8*a1,S=(90-ab.atan((ba-bd)/(a9-bb))*180/ab.PI);(ba>bd||a91){bi=ab.sqrt(by)*bi;bg=ab.sqrt(by)*bg;}var E=bi*bi,br=bg*bg,bt=(a4==S?-1:1)*ab.sqrt(ab.abs((E*br-E*bn*bn-br*bo*bo)/(E*bn*bn+br*bo*bo))),bd=bt*bi*bn/bg+(a9+a8)/2,bc=bt*-bg*bo/bi+(bE+bD)/2,a3=ab.asin(((bE-bc)/bg).toFixed(7)),a2=ab.asin(((bD-bc)/bg).toFixed(7));a3=a9a2){a3=a3-R*2;}if(!S&&a2>a3){a2=a2-R*2;}}else{a3=bb[0];a2=bb[1];bd=bb[2];bc=bb[3];}var a7=a2-a3;if(ab.abs(a7)>bf){var be=a2,bh=a8,a5=bD;a2=a3+bf*(S&&a2>a3?1:-1);a8=bd+bi*ab.cos(a2);bD=bc+bg*ab.sin(a2);bm=K(a8,bD,bi,bg,ba,0,S,bh,a5,[a2,be,bd,bc]);}a7=a2-a3;var a1=ab.cos(a3),bC=ab.sin(a3),a0=ab.cos(a2),bB=ab.sin(a2),bp=ab.tan(a7/4),bs=4/3*bi*bp,bq=4/3*bg*bp,bz=[a9,bE],bx=[a9+bs*bC,bE-bq*a1],bw=[a8+bs*bB,bD-bq*a0],bu=[a8,bD];bx[0]=2*bz[0]-bx[0];bx[1]=2*bz[1]-bx[1];if(bb){return[bx,bw,bu][aS](bm);}else{bm=[bx,bw,bu][aS](bm)[az]()[z](",");var bk=[];for(var bv=0,bl=bm[m];bv1000000000000&&(a0=0.5);ab.abs(S)>1000000000000&&(S=0.5);if(a0>0&&a0<1){e=M(i,d,R,E,a9,a8,a5,a2,a0);a6[f](e.x);a3[f](e.y);}if(S>0&&S<1){e=M(i,d,R,E,a9,a8,a5,a2,S);a6[f](e.x);a3[f](e.y);}a7=(a8-2*E+d)-(a2-2*a8+E);a4=2*(E-d)-2*(a8-E);a1=d-E;a0=(-a4+ab.sqrt(a4*a4-4*a7*a1))/2/a7;S=(-a4-ab.sqrt(a4*a4-4*a7*a1))/2/a7;ab.abs(a0)>1000000000000&&(a0=0.5);ab.abs(S)>1000000000000&&(S=0.5);if(a0>0&&a0<1){e=M(i,d,R,E,a9,a8,a5,a2,a0);a6[f](e.x);a3[f](e.y);}if(S>0&&S<1){e=M(i,d,R,E,a9,a8,a5,a2,S);a6[f](e.x);a3[f](e.y);}return{min:{x:aI[aW](0,a6),y:aI[aW](0,a3)},max:{x:g[aW](0,a6),y:g[aW](0,a3)}};}),H=aj(function(a9,a4){var R=r(a9),a5=a4&&r(a4),a6={x:0,y:0,bx:0,by:0,X:0,Y:0,qx:null,qy:null},d={x:0,y:0,bx:0,by:0,X:0,Y:0,qx:null,qy:null},a0=function(ba,bb){var i,bc;if(!ba){return["C",bb.x,bb.y,bb.x,bb.y,bb.x,bb.y];}!(ba[0] in {T:1,Q:1})&&(bb.qx=bb.qy=null);switch(ba[0]){case"M":bb.X=ba[1];bb.Y=ba[2];break;case"A":ba=["C"][aS](K[aW](0,[bb.x,bb.y][aS](ba.slice(1))));break;case"S":i=bb.x+(bb.x-(bb.bx||bb.x));bc=bb.y+(bb.y-(bb.by||bb.y));ba=["C",i,bc][aS](ba.slice(1));break;case"T":bb.qx=bb.x+(bb.x-(bb.qx||bb.x));bb.qy=bb.y+(bb.y-(bb.qy||bb.y));ba=["C"][aS](aK(bb.x,bb.y,bb.qx,bb.qy,ba[1],ba[2]));break;case"Q":bb.qx=ba[1];bb.qy=ba[2];ba=["C"][aS](aK(bb.x,bb.y,ba[1],ba[2],ba[3],ba[4]));break;case"L":ba=["C"][aS](aX(bb.x,bb.y,ba[1],ba[2]));break;case"H":ba=["C"][aS](aX(bb.x,bb.y,ba[1],bb.y));break;case"V":ba=["C"][aS](aX(bb.x,bb.y,bb.x,ba[1]));break;case"Z":ba=["C"][aS](aX(bb.x,bb.y,bb.X,bb.Y));break;}return ba;},e=function(ba,bb){if(ba[bb][m]>7){ba[bb].shift();var bc=ba[bb];while(bc[m]){ba.splice(bb++,0,["C"][aS](bc.splice(0,6)));}ba.splice(bb,1);a7=g(R[m],a5&&a5[m]||0);}},E=function(be,bd,bb,ba,bc){if(be&&bd&&be[bc][0]=="M"&&bd[bc][0]!="M"){bd.splice(bc,0,["M",ba.x,ba.y]);bb.bx=0;bb.by=0;bb.x=be[bc][1];bb.y=be[bc][2];a7=g(R[m],a5&&a5[m]||0);}};for(var a2=0,a7=g(R[m],a5&&a5[m]||0);a23){return{container:1,x:arguments[0],y:arguments[1],width:arguments[2],height:arguments[3]};}}},aG=function(d,i){var e=this;for(var E in i){if(i[Q](E)&&!(E in d)){switch(typeof i[E]){case"function":(function(R){d[E]=d===e?R:function(){return R[aW](e,arguments);};})(i[E]);break;case"object":d[E]=d[E]||{};aG.call(this,d[E],i[E]);break;default:d[E]=i[E];break;}}}},ak=function(d,e){d==e.top&&(e.top=d.prev);d==e.bottom&&(e.bottom=d.next);d.next&&(d.next.prev=d.prev);d.prev&&(d.prev.next=d.next);},Y=function(d,e){if(e.top===d){return;}ak(d,e);d.next=null;d.prev=e.top;e.top.next=d;e.top=d;},k=function(d,e){if(e.bottom===d){return;}ak(d,e);d.next=e.bottom;d.prev=null;e.bottom.prev=d;e.bottom=d;},A=function(e,d,i){ak(e,i);d==i.top&&(i.top=e);d.next&&(d.next.prev=e);e.next=d.next;e.prev=d;d.next=e;},aq=function(e,d,i){ak(e,i);d==i.bottom&&(i.bottom=e);d.prev&&(d.prev.next=e);e.prev=d.prev;d.prev=e;e.next=d;},s=function(d){return function(){throw new Error("Rapha\xebl: you are calling to method \u201c"+d+"\u201d of removed object");};},ar=/^r(?:\(([^,]+?)\s*,\s*([^\)]+?)\))?/;if(an.svg){aT[aY].svgns="http://www.w3.org/2000/svg";aT[aY].xlink="http://www.w3.org/1999/xlink";var O=function(d){return +d+(~~d===d)*0.5;},V=function(S){for(var e=0,E=S[m];e0.5)*2-1);aM(a1-0.5,2)+aM(S-0.5,2)>0.25&&(S=ab.sqrt(0.25-aM(a1-0.5,2))*ba+0.5)&&S!=0.5&&(S=S.toFixed(5)-0.00001*ba);}return at;});a7=a7[z](/\s*\-\s*/);if(a4=="linear"){var a0=a7.shift();a0=-W(a0);if(isNaN(a0)){return null;}var R=[0,0,ab.cos(a0*ab.PI/180),ab.sin(a0*ab.PI/180)],a6=1/(g(ab.abs(R[2]),ab.abs(R[3]))||1);R[2]*=a6;R[3]*=a6;if(R[2]<0){R[0]=-R[2];R[2]=0;}if(R[3]<0){R[1]=-R[3];R[3]=0;}}var a3=p(a7);if(!a3){return null;}var e=aJ(a4+"Gradient");e.id="r"+(an._id++)[aA](36);aJ(e,a4=="radial"?{fx:a1,fy:S}:{x1:R[0],y1:R[1],x2:R[2],y2:R[3]});d.defs[aL](e);for(var a2=0,a8=a3[m];a2a1.height)&&(a1.height=a0.y+a0.height-a1.y);(a0.x+a0.width-a1.x>a1.width)&&(a1.width=a0.x+a0.width-a1.x);}}E&&this.hide();return a1;};ax[aY].attr=function(){if(this.removed){return this;}if(arguments[m]==0){var R={};for(var E in this.attrs){if(this.attrs[Q](E)){R[E]=this.attrs[E];}}this._.rt.deg&&(R.rotation=this.rotate());(this._.sx!=1||this._.sy!=1)&&(R.scale=this.scale());R.gradient&&R.fill=="none"&&(R.fill=R.gradient)&&delete R.gradient;return R;}if(arguments[m]==1&&an.is(arguments[0],"string")){if(arguments[0]=="translation"){return t.call(this);}if(arguments[0]=="rotation"){return this.rotate();}if(arguments[0]=="scale"){return this.scale();}if(arguments[0]=="fill"&&this.attrs.fill=="none"&&this.attrs.gradient){return this.attrs.gradient;}return this.attrs[arguments[0]];}if(arguments[m]==1&&an.is(arguments[0],"array")){var d={};for(var e in arguments[0]){if(arguments[0][Q](e)){d[arguments[0][e]]=this.attrs[arguments[0][e]];}}return d;}if(arguments[m]==2){var S={};S[arguments[0]]=arguments[1];aa(this,S);}else{if(arguments[m]==1&&an.is(arguments[0],"object")){aa(this,arguments[0]);}}return this;};ax[aY].toFront=function(){if(this.removed){return this;}this.node.parentNode[aL](this.node);var d=this.paper;d.top!=this&&Y(this,d);return this;};ax[aY].toBack=function(){if(this.removed){return this;}if(this.node.parentNode.firstChild!=this.node){this.node.parentNode.insertBefore(this.node,this.node.parentNode.firstChild);k(this,this.paper);var d=this.paper;}return this;};ax[aY].insertAfter=function(d){if(this.removed){return this;}var e=d.node;if(e.nextSibling){e.parentNode.insertBefore(this.node,e.nextSibling);}else{e.parentNode[aL](this.node);}A(this,d,this.paper);return this;};ax[aY].insertBefore=function(d){if(this.removed){return this;}var e=d.node;e.parentNode.insertBefore(this.node,e);aq(this,d,this.paper);return this;};var P=function(e,d,S,R){d=O(d);S=O(S);var E=aJ("circle");e.canvas&&e.canvas[aL](E);var i=new ax(E,e);i.attrs={cx:d,cy:S,r:R,fill:"none",stroke:"#000"};i.type="circle";aJ(E,i.attrs);return i;};var aF=function(i,d,a1,e,S,a0){d=O(d);a1=O(a1);var R=aJ("rect");i.canvas&&i.canvas[aL](R);var E=new ax(R,i);E.attrs={x:d,y:a1,width:e,height:S,r:a0||0,rx:a0||0,ry:a0||0,fill:"none",stroke:"#000"};E.type="rect";aJ(R,E.attrs);return E;};var ai=function(e,d,a0,S,R){d=O(d);a0=O(a0);var E=aJ("ellipse");e.canvas&&e.canvas[aL](E);var i=new ax(E,e);i.attrs={cx:d,cy:a0,rx:S,ry:R,fill:"none",stroke:"#000"};i.type="ellipse";aJ(E,i.attrs);return i;};var o=function(i,a0,d,a1,e,S){var R=aJ("image");aJ(R,{x:d,y:a1,width:e,height:S,preserveAspectRatio:"none"});R.setAttributeNS(i.xlink,"href",a0);i.canvas&&i.canvas[aL](R);var E=new ax(R,i);E.attrs={x:d,y:a1,width:e,height:S,src:a0};E.type="image";return E;};var X=function(e,d,S,R){var E=aJ("text");aJ(E,{x:d,y:S,"text-anchor":"middle"});e.canvas&&e.canvas[aL](E);var i=new ax(E,e);i.attrs={x:d,y:S,"text-anchor":"middle",text:R,font:j.font,stroke:"none",fill:"#000"};i.type="text";aa(i,i.attrs);return i;};var aV=function(e,d){this.width=e||this.width;this.height=d||this.height;this.canvas[v]("width",this.width);this.canvas[v]("height",this.height);return this;};var w=function(){var E=ao[aW](null,arguments),i=E&&E.container,e=E.x,a0=E.y,R=E.width,d=E.height;if(!i){throw new Error("SVG container not found.");}var S=aJ("svg");R=R||512;d=d||342;aJ(S,{xmlns:"http://www.w3.org/2000/svg",version:1.1,width:R,height:d});if(i==1){S.style.cssText="position:absolute;left:"+e+"px;top:"+a0+"px";L.body[aL](S);}else{if(i.firstChild){i.insertBefore(S,i.firstChild);}else{i[aL](S);}}i=new aT;i.width=R;i.height=d;i.canvas=S;aG.call(i,i,an.fn);i.clear();return i;};aT[aY].clear=function(){var d=this.canvas;while(d.firstChild){d.removeChild(d.firstChild);}this.bottom=this.top=null;(this.desc=aJ("desc"))[aL](L.createTextNode("Created with Rapha\xebl"));d[aL](this.desc);d[aL](this.defs=aJ("defs"));};aT[aY].remove=function(){this.canvas.parentNode&&this.canvas.parentNode.removeChild(this.canvas);for(var d in this){this[d]=s(d);}};}if(an.vml){var aH=function(a8){var a5=/[ahqstv]/ig,a0=r;(a8+at).match(a5)&&(a0=H);a5=/[clmz]/g;if(a0==r&&!(a8+at).match(a5)){var e={M:"m",L:"l",C:"c",Z:"x",m:"t",l:"r",c:"v",z:"x"},R=/([clmz]),?([^clmz]*)/gi,S=/-?[^,\s-]+/g;var a4=(a8+at)[aP](R,function(a9,bb,i){var ba=[];i[aP](S,function(bc){ba[f](O(bc));});return e[bb]+ba;});return a4;}var a6=a0(a8),E,a4=[],d;for(var a2=0,a7=a6[m];a21&&(e=1);a7.opacity=e;}a8.fill&&(a7.on=true);if(a7.on==null||a8.fill=="none"){a7.on=false;}if(a7.on&&a8.fill){var i=a8.fill.match(c);if(i){a7.src=i[1];a7.type="tile";}else{a7.color=an.getRGB(a8.fill).hex;a7.src=at;a7.type="solid";if(an.getRGB(a8.fill).error&&(bd.type in {circle:1,ellipse:1}||(a8.fill+at).charAt()!="r")&&b(bd,a8.fill)){a9.fill="none";a9.gradient=a8.fill;}}}ba&&a6[aL](a7);var R=(a6.getElementsByTagName("stroke")&&a6.getElementsByTagName("stroke")[0]),bb=false;!R&&(bb=R=ah("stroke"));if((a8.stroke&&a8.stroke!="none")||a8["stroke-width"]||a8["stroke-opacity"]!=null||a8["stroke-dasharray"]||a8["stroke-miterlimit"]||a8["stroke-linejoin"]||a8["stroke-linecap"]){R.on=true;}(a8.stroke=="none"||R.on==null||a8.stroke==0||a8["stroke-width"]==0)&&(R.on=false);R.on&&a8.stroke&&(R.color=an.getRGB(a8.stroke).hex);var e=((+a9["stroke-opacity"]+1||2)-1)*((+a9.opacity+1||2)-1),a4=(W(a8["stroke-width"])||1)*0.75;e<0&&(e=0);e>1&&(e=1);a8["stroke-width"]==null&&(a4=a9["stroke-width"]);a8["stroke-width"]&&(R.weight=a4);a4&&a4<1&&(e*=a4)&&(R.weight=1);R.opacity=e;a8["stroke-linejoin"]&&(R.joinstyle=a8["stroke-linejoin"]||"miter");R.miterlimit=a8["stroke-miterlimit"]||8;a8["stroke-linecap"]&&(R.endcap=a8["stroke-linecap"]=="butt"?"flat":a8["stroke-linecap"]=="square"?"square":"round");if(a8["stroke-dasharray"]){var a5={"-":"shortdash",".":"shortdot","-.":"shortdashdot","-..":"shortdashdotdot",". ":"dot","- ":"dash","--":"longdash","- .":"dashdot","--.":"longdashdot","--..":"longdashdotdot"};R.dashstyle=a5[Q](a8["stroke-dasharray"])?a5[a8["stroke-dasharray"]]:at;}bb&&a6[aL](R);}if(bd.type=="text"){var a0=bd.paper.span.style;a9.font&&(a0.font=a9.font);a9["font-family"]&&(a0.fontFamily=a9["font-family"]);a9["font-size"]&&(a0.fontSize=a9["font-size"]);a9["font-weight"]&&(a0.fontWeight=a9["font-weight"]);a9["font-style"]&&(a0.fontStyle=a9["font-style"]);bd.node.string&&(bd.paper.span.innerHTML=(bd.node.string+at)[aP](/"));bd.W=a9.w=bd.paper.span.offsetWidth;bd.H=a9.h=bd.paper.span.offsetHeight;bd.X=a9.x;bd.Y=a9.y+O(bd.H/2);switch(a9["text-anchor"]){case"start":bd.node.style["v-text-align"]="left";bd.bbx=O(bd.W/2);break;case"end":bd.node.style["v-text-align"]="right";bd.bbx=-O(bd.W/2);break;default:bd.node.style["v-text-align"]="center";break;}}};var b=function(d,a1){d.attrs=d.attrs||{};var a2=d.attrs,a4=d.node.getElementsByTagName("fill"),S="linear",a0=".5 .5";d.attrs.gradient=a1;a1=(a1+at)[aP](ar,function(a6,a7,i){S="radial";if(a7&&i){a7=W(a7);i=W(i);aM(a7-0.5,2)+aM(i-0.5,2)>0.25&&(i=ab.sqrt(0.25-aM(a7-0.5,2))*((i>0.5)*2-1)+0.5);a0=a7+am+i;}return at;});a1=a1[z](/\s*\-\s*/);if(S=="linear"){var e=a1.shift();e=-W(e);if(isNaN(e)){return null;}}var R=p(a1);if(!R){return null;}d=d.shape||d.node;a4=a4[0]||ah("fill");if(R[m]){a4.on=true;a4.method="none";a4.type=(S=="radial")?"gradientradial":"gradient";a4.color=R[0].color;a4.color2=R[R[m]-1].color;var a5=[];for(var E=0,a3=R[m];E');};}catch(af){ah=function(d){return L.createElement("<"+d+' xmlns="urn:schemas-microsoft.com:vml" class="rvml">');};}var w=function(){var i=ao[aW](null,arguments),d=i.container,a2=i.height,a3,e=i.width,a1=i.x,a0=i.y;if(!d){throw new Error("VML container not found.");}var R=new aT,S=R.canvas=L.createElement("div"),E=S.style;e=e||512;a2=a2||342;e==+e&&(e+="px");a2==+a2&&(a2+="px");R.width=1000;R.height=1000;R.coordsize="1000 1000";R.coordorigin="0 0";R.span=L.createElement("span");R.span.style.cssText="position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline;";S[aL](R.span);E.cssText=an.format("width:{0};height:{1};position:absolute;clip:rect(0 {0} {1} 0);overflow:hidden",e,a2);if(d==1){L.body[aL](S);E.left=a1+"px";E.top=a0+"px";}else{d.style.width=e;d.style.height=a2;if(d.firstChild){d.insertBefore(S,d.firstChild);}else{d[aL](S);}}aG.call(R,R,an.fn);return R;};aT[aY].clear=function(){this.canvas.innerHTML=at;this.span=L.createElement("span");this.span.style.cssText="position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline;";this.canvas[aL](this.span);this.bottom=this.top=null;};aT[aY].remove=function(){this.canvas.parentNode.removeChild(this.canvas);for(var d in this){this[d]=s(d);}};}if((/^Apple|^Google/).test(navigator.vendor)&&!(navigator.userAgent.indexOf("Version/4.0")+1)){aT[aY].safari=function(){var d=this.rect(-99,-99,this.width+99,this.height+99);setTimeout(function(){d.remove();});};}else{aT[aY].safari=function(){};}var ae=(function(){if(L.addEventListener){return function(R,i,e,d){var E=function(S){return e.call(d,S);};R.addEventListener(i,E,false);return function(){R.removeEventListener(i,E,false);return true;};};}else{if(L.attachEvent){return function(S,E,i,e){var R=function(a0){return i.call(e,a0||au.event);};S.attachEvent("on"+E,R);var d=function(){S.detachEvent("on"+E,R);return true;};return d;};}}})();for(var ac=F[m];ac--;){(function(d){ax[aY][d]=function(e){if(an.is(e,"function")){this.events=this.events||[];this.events.push({name:d,f:e,unbind:ae(this.shape||this.node,d,e,this)});}return this;};ax[aY]["un"+d]=function(E){var i=this.events,e=i[m];while(e--){if(i[e].name==d&&i[e].f==E){i[e].unbind();i.splice(e,1);!i.length&&delete this.events;return this;}}return this;};})(F[ac]);}ax[aY].hover=function(e,d){return this.mouseover(e).mouseout(d);};ax[aY].unhover=function(e,d){return this.unmouseover(e).unmouseout(d);};aT[aY].circle=function(d,i,e){return P(this,d||0,i||0,e||0);};aT[aY].rect=function(d,R,e,i,E){return aF(this,d||0,R||0,e||0,i||0,E||0);};aT[aY].ellipse=function(d,E,i,e){return ai(this,d||0,E||0,i||0,e||0);};aT[aY].path=function(d){d&&!an.is(d,"string")&&!an.is(d[0],"array")&&(d+=at);return q(an.format[aW](an,arguments),this);};aT[aY].image=function(E,d,R,e,i){return o(this,E||"about:blank",d||0,R||0,e||0,i||0);};aT[aY].text=function(d,i,e){return X(this,d||0,i||0,e||at);};aT[aY].set=function(d){arguments[m]>1&&(d=Array[aY].splice.call(arguments,0,arguments[m]));return new T(d);};aT[aY].setSize=aV;aT[aY].top=aT[aY].bottom=null;aT[aY].raphael=an;function u(){return this.x+am+this.y;}ax[aY].scale=function(a6,a5,E,e){if(a6==null&&a5==null){return{x:this._.sx,y:this._.sy,toString:u};}a5=a5||a6;!+a5&&(a5=a6);var ba,a8,a9,a7,bm=this.attrs;if(a6!=0){var a4=this.getBBox(),a1=a4.x+a4.width/2,R=a4.y+a4.height/2,bl=a6/this._.sx,bk=a5/this._.sy;E=(+E||E==0)?E:a1;e=(+e||e==0)?e:R;var a3=~~(a6/ab.abs(a6)),a0=~~(a5/ab.abs(a5)),be=this.node.style,bo=E+(a1-E)*bl,bn=e+(R-e)*bk;switch(this.type){case"rect":case"image":var a2=bm.width*a3*bl,bd=bm.height*a0*bk;this.attr({height:bd,r:bm.r*aI(a3*bl,a0*bk),width:a2,x:bo-a2/2,y:bn-bd/2});break;case"circle":case"ellipse":this.attr({rx:bm.rx*a3*bl,ry:bm.ry*a0*bk,r:bm.r*aI(a3*bl,a0*bk),cx:bo,cy:bn});break;case"path":var bg=ad(bm.path),bh=true;for(var bj=0,bc=bg[m];bjS){if(e&&!a8.start){a6=an.findDotsAtSegment(a5,a4,E[1],E[2],E[3],E[4],E[5],E[6],(S-a3)/a1);R+=["C",a6.start.x,a6.start.y,a6.m.x,a6.m.y,a6.x,a6.y];if(a0){return R;}a8.start=R;R=["M",a6.x,a6.y+"C",a6.n.x,a6.n.y,a6.end.x,a6.end.y,E[5],E[6]][az]();a3+=a1;a5=+E[5];a4=+E[6];continue;}if(!d&&!e){a6=an.findDotsAtSegment(a5,a4,E[1],E[2],E[3],E[4],E[5],E[6],(S-a3)/a1);return{x:a6.x,y:a6.y,alpha:a6.alpha};}}a3+=a1;a5=+E[5];a4=+E[6];}R+=E;}a8.end=R;a6=d?a3:e?a8:an.findDotsAtSegment(a5,a4,E[1],E[2],E[3],E[4],E[5],E[6],1);a6.alpha&&(a6={x:a6.x,y:a6.y,alpha:a6.alpha});return a6;};},n=aj(function(E,d,a0,S,a6,a5,a4,a3){var R={x:0,y:0},a2=0;for(var a1=0;a1<1.01;a1+=0.01){var e=M(E,d,a0,S,a6,a5,a4,a3,a1);a1&&(a2+=ab.sqrt(aM(R.x-e.x,2)+aM(R.y-e.y,2)));R=e;}return a2;});var ap=aB(1),C=aB(),J=aB(0,1);ax[aY].getTotalLength=function(){if(this.type!="path"){return;}return ap(this.attrs.path);};ax[aY].getPointAtLength=function(d){if(this.type!="path"){return;}return C(this.attrs.path,d);};ax[aY].getSubpath=function(i,e){if(this.type!="path"){return;}if(ab.abs(this.getTotalLength()-e)<0.000001){return J(this.attrs.path,i).end;}var d=J(this.attrs.path,e,1);return i?J(d,i).end:d;};an.easing_formulas={linear:function(d){return d;},"<":function(d){return aM(d,3);},">":function(d){return aM(d-1,3)+1;},"<>":function(d){d=d*2;if(d<1){return aM(d,3)/2;}d-=2;return(aM(d,3)+2)/2;},backIn:function(e){var d=1.70158;return e*e*((d+1)*e-d);},backOut:function(e){e=e-1;var d=1.70158;return e*e*((d+1)*e+d)+1;},elastic:function(i){if(i==0||i==1){return i;}var e=0.3,d=e/4;return aM(2,-10*i)*ab.sin((i-d)*(2*ab.PI)/e)+1;},bounce:function(E){var e=7.5625,i=2.75,d;if(E<(1/i)){d=e*E*E;}else{if(E<(2/i)){E-=(1.5/i);d=e*E*E+0.75;}else{if(E<(2.5/i)){E-=(2.25/i);d=e*E*E+0.9375;}else{E-=(2.625/i);d=e*E*E+0.984375;}}}return d;}};var I={length:0},aR=function(){var a2=+new Date;for(var be in I){if(be!="length"&&I[Q](be)){var bj=I[be];if(bj.stop){delete I[be];I[m]--;continue;}var a0=a2-bj.start,bb=bj.ms,ba=bj.easing,bf=bj.from,a7=bj.diff,E=bj.to,a6=bj.t,a9=bj.prev||0,a1=bj.el,R=bj.callback,a8={},d;if(a0255?255:(d<0?0:d);},t=function(d,i){if(d==null){return{x:this._.tx,y:this._.ty,toString:u};}this._.tx+=+d;this._.ty+=+i;switch(this.type){case"circle":case"ellipse":this.attr({cx:+d+this.attrs.cx,cy:+i+this.attrs.cy});break;case"rect":case"image":case"text":this.attr({x:+d+this.attrs.x,y:+i+this.attrs.y});break;case"path":var e=ad(this.attrs.path);e[0][1]+=+d;e[0][2]+=+i;this.attr({path:e});break;}return this;};ax[aY].animateWith=function(e,i,d,R,E){I[e.id]&&(i.start=I[e.id].start);return this.animate(i,d,R,E);};ax[aY].animateAlong=ay();ax[aY].animateAlongBack=ay(1);function ay(d){return function(E,i,e,S){var R={back:d};an.is(e,"function")?(S=e):(R.rot=e);E&&E.constructor==ax&&(E=E.attrs.path);E&&(R.along=E);return this.animate(R,i,S);};}ax[aY].onAnimation=function(d){this._run=d||0;return this;};ax[aY].animate=function(be,a5,a4,E){if(an.is(a4,"function")||!a4){E=a4||null;}var a9={},e={},a2={};for(var a6 in be){if(be[Q](a6)){if(Z[Q](a6)){a9[a6]=this.attr(a6);(a9[a6]==null)&&(a9[a6]=j[a6]);e[a6]=be[a6];switch(Z[a6]){case"along":var bc=ap(be[a6]),a7=C(be[a6],bc*!!be.back),R=this.getBBox();a2[a6]=bc/a5;a2.tx=R.x;a2.ty=R.y;a2.sx=a7.x;a2.sy=a7.y;e.rot=be.rot;e.back=be.back;e.len=bc;be.rot&&(a2.r=W(this.rotate())||0);break;case"number":a2[a6]=(e[a6]-a9[a6])/a5;break;case"colour":a9[a6]=an.getRGB(a9[a6]);var a8=an.getRGB(e[a6]);a2[a6]={r:(a8.r-a9[a6].r)/a5,g:(a8.g-a9[a6].g)/a5,b:(a8.b-a9[a6].b)/a5};break;case"path":var S=H(a9[a6],e[a6]);a9[a6]=S[0];var a3=S[1];a2[a6]=[];for(var bb=0,a1=a9[a6][m];bb)[^>]*$|^#([\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
                a"; +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="";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-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=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=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-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;j0){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":function(g,h){var l=typeof h==="string";if(l&&!/\W/.test(h)){h=h.toLowerCase();for(var m=0,q=g.length;m=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 hl[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=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";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=""; +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="

                ";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="
                ";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=0===d})};c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,f=0,e=this.length;f0)for(var j=d;j0},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-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=/"},F={option:[1,""],legend:[1,"
                ","
                "],thead:[1,"","
                "],tr:[2,"","
                "],td:[3,"","
                "],col:[2,"","
                "],area:[1,"",""],_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
                ","
                "];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;b0||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;e0?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]===""&&!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=//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("
                ").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").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=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.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); diff --git a/rooter/0mesh/mesh-mesh/files/www/luci-static/resources/protocol/batadv.js b/rooter/0mesh/mesh-mesh/files/www/luci-static/resources/protocol/batadv.js new file mode 100644 index 0000000..837ba18 --- /dev/null +++ b/rooter/0mesh/mesh-mesh/files/www/luci-static/resources/protocol/batadv.js @@ -0,0 +1,8 @@ +'use strict'; +'require network'; + +return network.registerProtocol('batadv', { + getI18n: function() { + return _('Batman'); + } +}); diff --git a/rooter/0mesh/mesh-mesh/files/www/luci-static/resources/protocol/batadv_hardif.js b/rooter/0mesh/mesh-mesh/files/www/luci-static/resources/protocol/batadv_hardif.js new file mode 100644 index 0000000..545e63d --- /dev/null +++ b/rooter/0mesh/mesh-mesh/files/www/luci-static/resources/protocol/batadv_hardif.js @@ -0,0 +1,8 @@ +'use strict'; +'require network'; + +return network.registerProtocol('batadv_hardif', { + getI18n: function() { + return _('Mesh'); + } +}); diff --git a/rooter/0mesh/mesh-wpad/Makefile b/rooter/0mesh/mesh-wpad/Makefile new file mode 100644 index 0000000..dcb961e --- /dev/null +++ b/rooter/0mesh/mesh-wpad/Makefile @@ -0,0 +1,29 @@ +#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)) diff --git a/rooter/0optionalapps/bwallocate/Makefile b/rooter/0optionalapps/bwallocate/Makefile new file mode 100644 index 0000000..183c85d --- /dev/null +++ b/rooter/0optionalapps/bwallocate/Makefile @@ -0,0 +1,34 @@ +#Owned by DairyMan@Whirlpool +# +#Copyright GNU act. +include $(TOPDIR)/rules.mk + +PKG_NAME:=bwallocate +PKG_VERSION:=4.500 +PKG_RELEASE:=1 + +PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool +include $(INCLUDE_DIR)/package.mk + +define Package/bwallocate + SECTION:=utils + CATEGORY:=ROOter + SUBMENU:=Optional Applications + DEPENDS:=+ext-throttle +msmtp + TITLE:=Install scripts for Bandwidth Allocation + PKGARCH:=all +endef + +define Package/bwallocate/description + Install scripts for Bandwidth Allocation +endef + + +define Build/Compile +endef + +define Package/bwallocate/install + $(CP) ./files/* $(1)/ +endef + +$(eval $(call BuildPackage,bwallocate)) diff --git a/rooter/0optionalapps/bwallocate/files/etc/init.d/textbwint b/rooter/0optionalapps/bwallocate/files/etc/init.d/textbwint new file mode 100644 index 0000000..b74e85a --- /dev/null +++ b/rooter/0optionalapps/bwallocate/files/etc/init.d/textbwint @@ -0,0 +1,14 @@ +#!/bin/sh /etc/rc.common + +START=88 + +log() { + logger -t "TEXTING" "$@" +} + +start() +{ + uci set bwmon.general.enabled="1" + uci commit bwmon + /usr/lib/bwmon/textbw.sh & +} diff --git a/rooter/0optionalapps/bwallocate/files/usr/lib/lua/luci/controller/bwallocate.lua b/rooter/0optionalapps/bwallocate/files/usr/lib/lua/luci/controller/bwallocate.lua new file mode 100644 index 0000000..a26d6fd --- /dev/null +++ b/rooter/0optionalapps/bwallocate/files/usr/lib/lua/luci/controller/bwallocate.lua @@ -0,0 +1,22 @@ +module("luci.controller.bwallocate", package.seeall) + +I18N = require "luci.i18n" +translate = I18N.translate + +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 + local lock1 = luci.model.uci.cursor():get("custom", "bwallocate", "lock") + if lock1 == "1" then + if (multilock == "1" and rootlock == "1") then + entry({"admin", "adminmenu", "bwmenu"}, cbi("fullmenu/bwmenu"), translate("Bandwidth Allocation"), 6) + else + entry({"admin", "adminmenu", "bwmenu"}, cbi("fullmenu/bwmenu"), translate("---Bandwidth Allocation"), 6) + end + end + end + end +end \ No newline at end of file diff --git a/rooter/0optionalapps/bwallocate/files/usr/lib/lua/luci/model/cbi/fullmenu/bwmenu.lua b/rooter/0optionalapps/bwallocate/files/usr/lib/lua/luci/model/cbi/fullmenu/bwmenu.lua new file mode 100644 index 0000000..4b4d4ab --- /dev/null +++ b/rooter/0optionalapps/bwallocate/files/usr/lib/lua/luci/model/cbi/fullmenu/bwmenu.lua @@ -0,0 +1,267 @@ +local utl = require "luci.util" + +m = Map("custom", translate("Bandwidth Allocation"), translate("Set Maximum Bandwidth Usage before Internet blockage")) + +m.on_after_save = function(self) + luci.sys.call("/usr/lib/bwmon/allocate.sh 0 &") +end + +s = m:section(TypedSection, "bwallocate", translate("Allocation Settings")) +s.anonymous = true +s.addremove = false + +s:option(Flag, "enabled", translate("Allocation Enabled : ")) + +maxim = s:option(Value, "allocate", translate("Maximum Bandwidth in GB : "), translate("Maximum amount of bandwidth that can be used before Internet is affected")); +maxim.rmempty = true; +maxim.optional=false; +maxim.default="1000"; +maxim.datatype = "and(uinteger,min(1))" + +rollover = s:option(ListValue, "rollover", translate("Rollover Day : "), translate("Day of the month when bandwidth usage resets")) +rollover.rmempty = true +rollover:value("1", "1st") +rollover:value("2", "2nd") +rollover:value("3", "3rd") +rollover:value("4", "4th") +rollover:value("5", "5th") +rollover:value("6", "6th") +rollover:value("7", "7th") +rollover:value("8", "8th") +rollover:value("9", "9th") +rollover:value("10", "10th") +rollover:value("11", "11th") +rollover:value("12", "12th") +rollover:value("13", "13th") +rollover:value("14", "14th") +rollover:value("15", "15th") +rollover:value("16", "16th") +rollover:value("17", "17th") +rollover:value("18", "18th") +rollover:value("19", "19th") +rollover:value("20", "20th") +rollover:value("21", "21th") +rollover:value("22", "22th") +rollover:value("23", "23th") +rollover:value("24", "24th") +rollover:value("25", "25th") +rollover:value("26", "26th") +rollover:value("27", "27th") +rollover:value("28", "28th") +rollover.default = "1" + +act = s:option(ListValue, "action", translate("Internet Action : "), translate("Action taken when allocation is exceeded")) +act.rmempty = true +act:value("0", "Internet Blocked") +act:value("1", "Internet Throttled") +act.default = "0" + +down = s:option(Value, "down", translate("Download Speed in Mbps :")); +down.optional=false; +down.rmempty = true; +down.datatype = "and(uinteger,min(1),max(999))" +down:depends("action", "1") +down.default = "5" + +up = s:option(Value, "up", translate("Upload Speed in Mbps :")); +up.optional=false; +up.rmempty = true; +up.datatype = "and(uinteger,min(1),max(999))" +up:depends("action", "1") +up.default = "2" + +s = m:section(TypedSection, "texting", translate("Text/Email Settings")) +s.anonymous = true +s.addremove = false + +aact = s:option(ListValue, "text", translate("Enable : "), translate("Enable Sending Text or Email Information")) +aact.rmempty = true +aact:value("0", "No") +aact:value("1", "Yes") +aact.default = "0" + + +pph = s:option(Value, "ident", translate("Identifier :")); +pph.optional=false; +pph.rmempty = true; +pph:depends("text", "1") +pph.default = "xxx" + + + +ct = s:option(ListValue, "method", translate("Criteria : "), translate("Criteria used to determine when to send information")) +ct.rmempty = true +ct:value("0", translate("By Specified Time Interval")) +ct:value("1", translate("By Amount Used")) +ct:value("2", translate("By Percentage Used")) +ct.default = "0" +ct:depends("text", "1") + +sdhour = s:option(ListValue, "time", translate("Sending Time :"), translate("Time to send information")) +sdhour.rmempty = true +sdhour:value("0", "12:00 AM") +sdhour:value("1", "12:15 AM") +sdhour:value("2", "12:30 AM") +sdhour:value("3", "12:45 AM") +sdhour:value("4", "01:00 AM") +sdhour:value("5", "01:15 AM") +sdhour:value("6", "01:30 AM") +sdhour:value("7", "01:45 AM") +sdhour:value("8", "02:00 AM") +sdhour:value("9", "02:15 AM") +sdhour:value("10", "02:30 AM") +sdhour:value("11", "02:45 AM") +sdhour:value("12", "03:00 AM") +sdhour:value("13", "03:15 AM") +sdhour:value("14", "03:30 AM") +sdhour:value("15", "03:45 AM") +sdhour:value("16", "04:00 AM") +sdhour:value("17", "04:15 AM") +sdhour:value("18", "04:30 AM") +sdhour:value("19", "04:45 AM") +sdhour:value("20", "05:00 AM") +sdhour:value("21", "05:15 AM") +sdhour:value("22", "05:30 AM") +sdhour:value("23", "05:45 AM") +sdhour:value("24", "06:00 AM") +sdhour:value("25", "06:15 AM") +sdhour:value("26", "06:30 AM") +sdhour:value("27", "06:45 AM") +sdhour:value("28", "07:00 AM") +sdhour:value("29", "07:15 AM") +sdhour:value("30", "07:30 AM") +sdhour:value("31", "07:45 AM") +sdhour:value("32", "08:00 AM") +sdhour:value("33", "08:15 AM") +sdhour:value("34", "08:30 AM") +sdhour:value("35", "08:45 AM") +sdhour:value("36", "09:00 AM") +sdhour:value("37", "09:15 AM") +sdhour:value("38", "09:30 AM") +sdhour:value("39", "09:45 AM") +sdhour:value("40", "10:00 AM") +sdhour:value("41", "10:15 AM") +sdhour:value("42", "10:30 AM") +sdhour:value("43", "10:45 AM") +sdhour:value("44", "11:00 AM") +sdhour:value("45", "11:15 AM") +sdhour:value("46", "11:30 AM") +sdhour:value("47", "11:45 AM") +sdhour:value("48", "12:00 PM") +sdhour:value("49", "12:15 PM") +sdhour:value("50", "12:30 PM") +sdhour:value("51", "12:45 PM") +sdhour:value("52", "01:00 PM") +sdhour:value("53", "01:15 PM") +sdhour:value("54", "01:30 PM") +sdhour:value("55", "01:45 PM") +sdhour:value("56", "02:00 PM") +sdhour:value("57", "02:15 PM") +sdhour:value("58", "02:30 PM") +sdhour:value("59", "02:45 PM") +sdhour:value("60", "03:00 PM") +sdhour:value("61", "03:15 PM") +sdhour:value("62", "03:30 PM") +sdhour:value("63", "03:45 PM") +sdhour:value("64", "04:00 PM") +sdhour:value("65", "04:15 PM") +sdhour:value("66", "04:30 PM") +sdhour:value("67", "04:45 PM") +sdhour:value("68", "05:00 PM") +sdhour:value("69", "05:15 PM") +sdhour:value("70", "05:30 PM") +sdhour:value("71", "05:45 PM") +sdhour:value("72", "06:00 PM") +sdhour:value("73", "06:15 PM") +sdhour:value("74", "06:30 PM") +sdhour:value("75", "06:45 PM") +sdhour:value("76", "07:00 PM") +sdhour:value("77", "07:15 PM") +sdhour:value("78", "07:30 PM") +sdhour:value("79", "07:45 PM") +sdhour:value("80", "08:00 PM") +sdhour:value("81", "08:15 PM") +sdhour:value("82", "08:30 PM") +sdhour:value("83", "08:45 PM") +sdhour:value("84", "09:00 PM") +sdhour:value("85", "09:15 PM") +sdhour:value("86", "09:30 PM") +sdhour:value("87", "09:45 PM") +sdhour:value("88", "10:00 PM") +sdhour:value("89", "10:15 PM") +sdhour:value("90", "10:30 PM") +sdhour:value("91", "10:45 PM") +sdhour:value("92", "11:00 PM") +sdhour:value("93", "11:15 PM") +sdhour:value("94", "11:30 PM") +sdhour:value("95", "11:45 PM") +sdhour:depends("text", "1") +sdhour.default = "48" + +xct = s:option(ListValue, "days", translate("Interval : "), translate("Number of days between sending information")) +xct.rmempty = true +xct:value("1", translate("Every Day")) +xct:value("2", translate("Every 2 Days")) +xct:value("5", translate("Every 5 Days")) +xct:value("10", translate("Every 10 Days")) +xct:value("15", translate("Every 15 Days")) +xct.default = "5" +xct:depends("method", "0") + +xxct = s:option(ListValue, "increment", translate("Increment : "), translate("Amount Used between sending information")) +xxct.rmempty = true +xxct:value("50", translate("Every 50 GB")) +xxct:value("75", translate("Every 75 GB")) +xxct:value("100", translate("Every 100 GB")) +xxct.default = "50" +xxct:depends("method", "1") + +ph1 = s:option(ListValue, "percent", translate("Percentage Used :")); +ph1.optional=false; +ph1.rmempty = true; +ph1:value("10", translate("10%")) +ph1:value("20", translate("20%")) +ph1:value("30", translate("30%")) +ph1:value("40", translate("40%")) +ph1:value("50", translate("50%")) +ph1:value("60", translate("60%")) +ph1:value("70", translate("70%")) +ph1:value("80", translate("80%")) +ph1:value("90", translate("90%")) +ph1:depends("method", "2") +ph1.default = "90" + +--b3 = s:option(DummyValue, "blank", " "); + +btn = s:option(Button, "_btn", translate(" ")) +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") +end + +b4 = s:option(DummyValue, "blank", " "); + +ct = s:option(ListValue, "tore", translate("Sending Method : "), translate("Method used to send information")) +ct.rmempty = true +ct:value("0", translate("By Text")) +ct:value("1", translate("By Email")) +ct.default = "0" +ct:depends("text", "1") + +ph = s:option(Value, "phone", translate("Phone Number :")); +ph.optional=false; +ph.rmempty = true; +ph.datatype = "phonedigit" +ph:depends("tore", "0") +ph.default = "12223334444" + +ph1 = s:option(Value, "email", translate("Email Address :")); +ph1.optional=false; +ph1.rmempty = true; +ph1:depends("tore", "1") +ph1.default = "jdoe@domain.com" + + +return m \ No newline at end of file diff --git a/rooter/0optionalapps/bwmon/Makefile b/rooter/0optionalapps/bwmon/Makefile new file mode 100644 index 0000000..c413b2f --- /dev/null +++ b/rooter/0optionalapps/bwmon/Makefile @@ -0,0 +1,35 @@ +#Owned by DairyMan@Whirlpool +# +#Copyright GNU act. +include $(TOPDIR)/rules.mk + +PKG_NAME:=bwmon +PKG_VERSION:=1.000 +PKG_RELEASE:=1 + +PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool +include $(INCLUDE_DIR)/package.mk + +define Package/bwmon + SECTION:=utils + CATEGORY:=ROOter + SUBMENU:=Optional Applications + TITLE:=Install Bandwidth Monitor + PKGARCH:=all +endef + +define Package/bwmon/description + Helper scripts to install Bandwidth Monitor on ROOter +endef + + +define Build/Compile +endef + +define Package/bwmon/install + $(CP) ./files/* $(1)/ + + +endef + +$(eval $(call BuildPackage,bwmon)) diff --git a/rooter/0optionalapps/bwmon/files/etc/config/bwmon b/rooter/0optionalapps/bwmon/files/etc/config/bwmon new file mode 100644 index 0000000..9d45a80 --- /dev/null +++ b/rooter/0optionalapps/bwmon/files/etc/config/bwmon @@ -0,0 +1,9 @@ + +config general 'general' + option external '0' + option backup '30' + option enabled '1' + + +config bwwan 'bwwan' + option wan '0' \ No newline at end of file diff --git a/rooter/0optionalapps/bwmon/files/etc/init.d/bwmon b/rooter/0optionalapps/bwmon/files/etc/init.d/bwmon new file mode 100644 index 0000000..925a8ea --- /dev/null +++ b/rooter/0optionalapps/bwmon/files/etc/init.d/bwmon @@ -0,0 +1,18 @@ +#!/bin/sh /etc/rc.common +# Copyright (C) 2006 OpenWrt.org + +START=60 + +start() { + WX=$(uci -q get custom.bwallocate.lock) + if [ "$WX" = "1" ]; then + uci set bwmon.general.enabled=$enable + uci commit bwmon + fi + /usr/lib/bwmon/wrtbwmon.sh & + /usr/lib/bwmon/create.sh & +} + +stop() { + rmdir -f /tmp/WRTbmon +} \ No newline at end of file diff --git a/rooter/0optionalapps/bwmon/files/lib/upgrade/keep.d/bwmon b/rooter/0optionalapps/bwmon/files/lib/upgrade/keep.d/bwmon new file mode 100644 index 0000000..c664559 --- /dev/null +++ b/rooter/0optionalapps/bwmon/files/lib/upgrade/keep.d/bwmon @@ -0,0 +1 @@ +/usr/lib/bwmon/data/ diff --git a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/allocate.sh b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/allocate.sh new file mode 100644 index 0000000..58b4c22 --- /dev/null +++ b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/allocate.sh @@ -0,0 +1,21 @@ +#!/bin/sh + +log() { + logger -t "allocate" "$@" +} + +amount=$1 + +if [ $amount != "0" ]; then + uci set custom.bwallocate.allocate=$amount + uci commit custom +else + sleep 3 +fi +result=`ps | grep -i "create_data.lua" | grep -v "grep" | wc -l` +while [ $result -ge 1 ]; do + sleep 2 + result=`ps | grep -i "create_data.lua" | grep -v "grep" | wc -l` +done + +lua /usr/lib/bwmon/create_data.lua diff --git a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/amtleft.lua b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/amtleft.lua new file mode 100644 index 0000000..ee530db --- /dev/null +++ b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/amtleft.lua @@ -0,0 +1,30 @@ +#!/usr/bin/lua + +function ltrim(s) + return s:match'^%s*(.*)' +end + +function calc(total) + if total < 1000 then + tstr = string.format("%.2f", total) + tfm = " K" + else + if total < 1000000 then + tstr = string.format("%.2f", total/1000) + tfm = " MB" + else + tstr = string.format("%.2f", total/1000000) + tfm = " GB" + end + end + str = tstr .. tfm + return ltrim(str) +end + +aamt = arg[1] +uamt = arg[2] +amt = aamt - uamt +amts = calc(amt) +tfile = io.open("/tmp/amtleft", "w") +tfile:write(amts, "\n") +tfile:close() \ No newline at end of file diff --git a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/backup-daily.lua b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/backup-daily.lua new file mode 100644 index 0000000..c9f579e --- /dev/null +++ b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/backup-daily.lua @@ -0,0 +1,61 @@ +#!/usr/bin/lua + +dailyUsageDB = arg[1] + +bw = {} +maclist = {} + +file = io.open(dailyUsageDB, "r") +i = 0 +repeat + line = file:read("*line") + if line == nil then + break + end + s, e = line:find("\"mac\":\"") + bs, be = line:find("\"", e+1) + mac = line:sub(e+1, bs-1) + if bw[mac] == nil then + maclist[i] = mac + i = i + 1 + bw[mac] = {} + bw[mac]['down'] = 0 + bw[mac]['offdown'] = 0 + bw[mac]['up'] = 0 + bw[mac]['offup'] = 0 + end + s, e = line:find("\"down\":\"") + bs, be = line:find("\"", e+1) + down = tonumber(line:sub(e+1, bs-1)) + bw[mac]['down'] = bw[mac]['down'] + down + s, e = line:find("\"up\":\"") + bs, be = line:find("\"", e+1) + up = tonumber(line:sub(e+1, bs-1)) + bw[mac]['up'] = bw[mac]['up'] + up + s, e = line:find("\"offdown\":\"") + bs, be = line:find("\"", e+1) + offdown = tonumber(line:sub(e+1, bs-1)) + bw[mac]['offdown'] = bw[mac]['offdown'] + offdown + s, e = line:find("\"offup\":\"") + bs, be = line:find("\"", e+1) + offup = tonumber(line:sub(e+1, bs-1)) + bw[mac]['offup'] = bw[mac]['offup'] + offup + s, e = line:find("\"ip\":\"") + bs, be = line:find("\"", e+1) + bw[mac]['ip'] = line:sub(e+1, bs-1) + s, e = line:find("\"name\":\"") + bs, be = line:find("\"", e+1) + bw[mac]['name'] = line:sub(e+1, bs-1) +until 1==0 +file:close() + +j=0 +file = io.open(dailyUsageDB .. ".bk", "w") +while maclist[j] ~= nil do + mac = maclist[j] + dline = "\"mac\":\"" .. mac .. "\",\"down\":\"" .. bw[mac]['down'] .. "\",\"up\":\"" .. bw[mac]['up'] .. "\",\"offdown\":\"0\",\"offup\":\"0\",\"ip\":\"" .. bw[mac]['ip'] .. "\",\"name\":\"" .. bw[mac]['name'] .. "\"" + file:write(dline, "\n") + j = j + 1 +end +file:close() + diff --git a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/backup-mon.lua b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/backup-mon.lua new file mode 100644 index 0000000..5d8e883 --- /dev/null +++ b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/backup-mon.lua @@ -0,0 +1,81 @@ +#!/usr/bin/lua + +monthUsageDB = arg[1] + +tfile = io.open(monthUsageDB .. ".bk", "w") +tfile:close() + +file = io.open(monthUsageDB, "r") + +repeat + line = file:read("*line") + if line == nil then + break + end + s, e = line:find("start day") + if s ~= nil then + maclist = {} + bw = {} + i = 0 + startday = line + repeat + line = file:read("*line") + if line == nil then + break + end + s, e = line:find("end day") + if s ~= nil then + endday = line + break + end + s, e = line:find("\"mac\":\"") + bs, be = line:find("\"", e+1) + mac = line:sub(e+1, bs-1) + if bw[mac] == nil then + maclist[i] = mac + i = i + 1 + bw[mac] = {} + bw[mac]['down'] = 0 + bw[mac]['offdown'] = 0 + bw[mac]['up'] = 0 + bw[mac]['offup'] = 0 + end + s, e = line:find("\"down\":\"") + bs, be = line:find("\"", e+1) + down = tonumber(line:sub(e+1, bs-1)) + bw[mac]['down'] = bw[mac]['down'] + down + s, e = line:find("\"up\":\"") + bs, be = line:find("\"", e+1) + up = tonumber(line:sub(e+1, bs-1)) + bw[mac]['up'] = bw[mac]['up'] + up + s, e = line:find("\"offdown\":\"") + bs, be = line:find("\"", e+1) + offdown = tonumber(line:sub(e+1, bs-1)) + bw[mac]['offdown'] = bw[mac]['offdown'] + offdown + s, e = line:find("\"offup\":\"") + bs, be = line:find("\"", e+1) + offup = tonumber(line:sub(e+1, bs-1)) + bw[mac]['offup'] = bw[mac]['offup'] + offup + s, e = line:find("\"ip\":\"") + bs, be = line:find("\"", e+1) + bw[mac]['ip'] = line:sub(e+1, bs-1) + s, e = line:find("\"name\":\"") + bs, be = line:find("\"", e+1) + bw[mac]['name'] = line:sub(e+1, bs-1) + until 1==0 + -- day data + j=0 + tfile = io.open(monthUsageDB .. ".bk", "a") + tfile:write(startday, "\n") + while maclist[j] ~= nil do + mac = maclist[j] + dline = "\"mac\":\"" .. mac .. "\",\"down\":\"" .. bw[mac]['down'] .. "\",\"up\":\"" .. bw[mac]['up'] .. "\",\"offdown\":\"0\",\"offup\":\"0\",\"ip\":\"" .. bw[mac]['ip'] .. "\",\"name\":\"" .. bw[mac]['name'] .. "\"" + tfile:write(dline, "\n") + j = j + 1 + end + tfile:write(endday, "\n") + tfile:close() + end + +until 1==0 +file:close() \ No newline at end of file diff --git a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/backup.sh b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/backup.sh new file mode 100644 index 0000000..dba2368 --- /dev/null +++ b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/backup.sh @@ -0,0 +1,51 @@ +#!/bin/sh + +log() { + logger -t "wrtbwmon" "$@" +} + +# parameters +# +btype=$1 +cDay=$2 +monthlyUsageDB=$3 +dailyUsageDB=$4 +monthlyUsageBack=$5 +dailyUsageBack=$6 +pDay=$7 + +/usr/lib/bwmon/backup-daily.lua $dailyUsageDB +/usr/lib/bwmon/backup-mon.lua $monthlyUsageDB +cp -f $monthlyUsageDB".bk" $monthlyUsageDB +cp -f $dailyUsageDB".bk" $dailyUsageDB + +echo "start day $cDay" >> $monthlyUsageDB".bk" +cat $dailyUsageDB".bk" >> $monthlyUsageDB".bk" +echo "end day $cDay" >> $monthlyUsageDB".bk" + +enb=$(uci -q get bwmon.general.enabled) + +if [ $btype = "backup" ]; then + if [ "$enb" = "1" ]; then + cp -f $monthlyUsageDB".bk" $monthlyUsageBack + cp -f $dailyUsageDB".bk" $dailyUsageBack + fi +else + if [ $btype = "daily" ]; then + cp -f $monthlyUsageDB".bk" $monthlyUsageDB + if [ "$enb" = "1" ]; then + cp -f $monthlyUsageDB".bk" $monthlyUsageBack + fi + fi +fi + +rm -f $dailyUsageDB".bk" + +bwday=$(uci -q get modem.modeminfo1.bwday) +if [ ! -z "$bwday" ]; then + if [ $bwday = $pDay -a $bwday != "0" ]; then + if [ -e /usr/lib/bwmon/sendsms ]; then + /usr/lib/bwmon/sendsms.sh + fi + fi +fi \ No newline at end of file diff --git a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/block b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/block new file mode 100644 index 0000000..ba7fb02 --- /dev/null +++ b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/block @@ -0,0 +1,28 @@ +#!/bin/sh + +internet_block() +{ + enable=$1 + iptables -w -S ACCOUNTING_BLOCK > /tmp/iptables.block.$$ + if [ "$enable" = 1 ] + then + # insert the block rule + check=$(cat /tmp/iptables.block.$$ | grep -e "-m comment --comment internet_block -j DROP") + if [ -z "$check" ] + then + iptables -w -I ACCOUNTING_BLOCK -m comment --comment internet_block -j DROP 2>/dev/null + fi + else + # remove the block rule + count=$(cat /tmp/iptables.block.$$ | grep -e "-m comment --comment internet_block -j DROP" | wc -l) + for i in $(seq 1 $count) + do + iptables -w -D ACCOUNTING_BLOCK -m comment --comment internet_block -j DROP 2>/dev/null + done + fi + + rm -rf /tmp/iptables.block.$$ +} + +internet_block $1 + diff --git a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/change.sh b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/change.sh new file mode 100644 index 0000000..003fec7 --- /dev/null +++ b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/change.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +log() { + logger -t "wrtbwmon" "$@" +} + +enable=$1 + +WX=$(uci -q get custom.bwallocate.lock) +if [ "$WX" = "1" ]; then + enable="1" +fi +uci set bwmon.general.enabled=$enable +uci commit bwmon diff --git a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/chksms.sh b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/chksms.sh new file mode 100644 index 0000000..20b3376 --- /dev/null +++ b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/chksms.sh @@ -0,0 +1,21 @@ +#!/bin/sh + +ROOTER=/usr/lib/rooter +ROOTER_LINK="/tmp/links" + +CURRMODEM=1 + +rm -f /tmp/texting +CPORT=$(uci -q get modem.modem$CURRMODEM.commport) +if [ -z $CPORT ]; then + return +fi +OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "smschk.gcom" "$CURRMODEM") +ERROR="ERROR" +if `echo ${OX} | grep "${ERROR}" 1>/dev/null 2>&1` +then + return +fi +echo "0" > /tmp/texting +uci set modem.general.smsnum='1' +uci commit modem \ No newline at end of file diff --git a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/cleanup.lua b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/cleanup.lua new file mode 100644 index 0000000..2c5d764 --- /dev/null +++ b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/cleanup.lua @@ -0,0 +1,32 @@ +#!/usr/bin/lua + +filepost = "-mac_data.js" +dirname = '/usr/lib/bwmon/data' + +function clean() + nummon = 0 + months = {} + f = io.popen('/bin/ls ' .. dirname) + for name in f:lines() do + s, e = name:find(filepost) + if s ~= nil then + nummon = nummon + 1 + months[nummon] = dirname .. "/" .. name + end + end + f:close() + + count = 1 + if nummon > 0 then + for i=nummon,1,-1 do + if count > 3 then + os.execute("rm -f " .. months[i]) + end + count = count + 1 + end + end +end + +clean() +dirname = '/tmp/bwmon/data' +clean() \ No newline at end of file diff --git a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/create.sh b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/create.sh new file mode 100644 index 0000000..348d873 --- /dev/null +++ b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/create.sh @@ -0,0 +1,16 @@ +#!/bin/sh + +log() { + logger -t "createdata" "$@" +} + +lua /usr/lib/bwmon/create_data.lua +sleep 60 +while [ true ] +do + result=`ps | grep -i "create_data.lua" | grep -v "grep" | wc -l` + if [ $result -lt 1 ]; then + lua /usr/lib/bwmon/create_data.lua + fi + sleep 60 +done \ No newline at end of file diff --git a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/create_data.lua b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/create_data.lua new file mode 100644 index 0000000..fc3fba8 --- /dev/null +++ b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/create_data.lua @@ -0,0 +1,193 @@ +#!/usr/bin/lua + +dirname = '/tmp/bwmon/data' +filepost = "-mac_data.js.bk" +bw = {} +maclist = {} +devices = {} +totaldevices = 0 +totaldown = 0 +totalup = 0 +total = 0 + +printf = function(s,...) + local ss = s:format(...) + os.execute("/usr/lib/rooter/logprint.sh " .. ss) +end + +function ltrim(s) + return s:match'^%s*(.*)' +end + +function calc(total) + if total < 1000 then + tstr = string.format("%.2f", total) + tfm = " K" + else + if total < 1000000 then + tstr = string.format("%.2f", total/1000) + tfm = " MB" + else + tstr = string.format("%.2f", total/1000000) + tfm = " GB" + end + end + str = tstr .. tfm + return ltrim(str) +end + +function monthly(datafile) + file = io.open(datafile, "r") + i = 0 + dayx = 0 + repeat + line = file:read("*line") + if line == nil then + break + end + s, e = line:find("start day") + if s ~= nil then + dayx = dayx + 1 + repeat + line = file:read("*line") + s, e = line:find("end day") + if s ~= nil then + break + end + s, e = line:find("\"mac\":\"") + bs, be = line:find("\"", e+1) + mac = line:sub(e+1, bs-1) + if bw[mac] == nil then + maclist[i] = mac + i = i + 1 + bw[mac] = {} + bw[mac]['down'] = 0 + bw[mac]['offdown'] = 0 + bw[mac]['up'] = 0 + bw[mac]['offup'] = 0 + end + s, e = line:find("\"down\":\"") + bs, be = line:find("\"", e+1) + down = tonumber(line:sub(e+1, bs-1)) + bw[mac]['down'] = bw[mac]['down'] + down + s, e = line:find("\"up\":\"") + bs, be = line:find("\"", e+1) + up = tonumber(line:sub(e+1, bs-1)) + bw[mac]['up'] = bw[mac]['up'] + up + s, e = line:find("\"offdown\":\"") + bs, be = line:find("\"", e+1) + offdown = tonumber(line:sub(e+1, bs-1)) + bw[mac]['offdown'] = bw[mac]['offdown'] + offdown + s, e = line:find("\"offup\":\"") + bs, be = line:find("\"", e+1) + offup = tonumber(line:sub(e+1, bs-1)) + bw[mac]['offup'] = bw[mac]['offup'] + offup + s, e = line:find("\"ip\":\"") + bs, be = line:find("\"", e+1) + bw[mac]['ip'] = line:sub(e+1, bs-1) + s, e = line:find("\"name\":\"") + bs, be = line:find("\"", e+1) + bw[mac]['name'] = line:sub(e+1, bs-1) + until 1==0 + end + until 1==0 + file:close() + return dayx +end + +function totals(bw, maclist, dayz) + totaldown = 0 + totalup = 0 + utotaldown = 0 + utotalup = 0 + j=0 + while maclist[j] ~= nil do + totaldown = totaldown + bw[maclist[j]]['down'] + totalup = totalup + bw[maclist[j]]['up'] + utotaldown = utotaldown + bw[maclist[j]]['offdown'] + utotalup = utotalup + bw[maclist[j]]['offup'] + j = j + 1 + end + total = totalup + totaldown + ptotal = (total / dayz) * 30 +end + +function showdevices(bw, maclist) + k = 0 + while maclist[k] ~= nil do + k = k + 1 + end + if k > 0 then + j = 0 + while maclist[j] ~= nil do + dtot = bw[maclist[j]]['down'] + bw[maclist[j]]['up'] + devices[j] = bw[maclist[j]]['ip'] .."|" .. maclist[j] + devices[j] = devices[j] .. "|" .. calc(bw[maclist[j]]['down']) .. "|" .. calc(bw[maclist[j]]['up']) + devices[j] = devices[j] .. "|" .. calc(dtot) .. "|" .. bw[maclist[j]]['name'] + j = j + 1 + end + end + totaldevices = j +end + +os.execute("echo 0 > /tmp/lockbw") +dataname = nil +f = io.popen('/bin/ls ' .. dirname) +for name in f:lines() do + s, e = name:find(filepost) + if s ~= nil then + dataname = dirname .. "/" .. name + end +end +f:close() + +if dataname ~= nil then + days = monthly(dataname) + totals(bw, maclist, days) + tfile = io.open("/tmp/bwdata", "w") + tfile:write(days, "\n") + tfile:write(tostring(total), "\n") + tfile:write(calc(total), "\n") + tfile:write(tostring(totaldown), "\n") + tfile:write(calc(totaldown), "\n") + tfile:write(tostring(totalup), "\n") + tfile:write(calc(totalup), "\n") + tfile:write(tostring(ptotal), "\n") + tfile:write(calc(ptotal), "\n") + -- + -- allocated bandwidth in K + -- + bwallo='rm -f /tmp/bwallo; x=$(uci -q get custom.bwallocate.allocate); echo $x >> /tmp/bwallo; x=$(uci -q get custom.bwallocate.password); echo $x >> /tmp/bwallo' + os.execute(bwallo) + file = io.open("/tmp/bwallo", "r") + if file == nil then + allo = 1000000000 + passw = "password" + else + allos = file:read("*line") + allo = tonumber(allos) * 1000000 + passw = file:read("*line") + file:close() + end + tfile:write(tostring(allo), "\n") + tfile:write(calc(allo), "\n") + tfile:write(passw, "\n") + + showdevices(bw, maclist) + tfile:write(tostring(totaldevices), "\n") + if totaldevices > 0 then + for i=0, totaldevices-1 do + tfile:write(devices[i], "\n") + end + end + tfile:close() +else + tfile = io.open("/tmp/bwdata", "w") + tfile:write("0\n") + tfile:write("0\n") + tfile:close() +end +os.execute("rm -f /tmp/lockbw") +os.execute("/usr/lib/bwmon/excede.sh " .. tostring(total) .. " " .. tostring(allo) .. " " .. tostring(ptotal)) +os.execute("/usr/lib/bwmon/savetot.sh \"" .. calc(total) .. "\"") +os.execute("/usr/lib/bwmon/perday.lua") diff --git a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/data/placeholder b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/data/placeholder new file mode 100644 index 0000000..c227083 --- /dev/null +++ b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/data/placeholder @@ -0,0 +1 @@ +0 \ No newline at end of file diff --git a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/datainc.lua b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/datainc.lua new file mode 100644 index 0000000..6ef57c4 --- /dev/null +++ b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/datainc.lua @@ -0,0 +1,21 @@ +#!/usr/bin/lua + +prev = arg[1] -- previous increment in GB +incr = arg[2] -- fixed increment in GB +used = arg[3] -- amt used in Kb + +used = used / 1000000 -- used in GB +current = prev + incr +running = "0" +if used >= current then + while used >= (current + incr) do + current = current + incr + end + prev = current + running = "1" +end + +tfile = io.open("/tmp/bwinc", "w") +tfile:write("prev=\"", prev, "\"\n") +tfile:write("runn=\"", running, "\"") +tfile:close() \ No newline at end of file diff --git a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/dataper.lua b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/dataper.lua new file mode 100644 index 0000000..d5d0527 --- /dev/null +++ b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/dataper.lua @@ -0,0 +1,16 @@ +#!/usr/bin/lua + +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 +running = "0" +if percent >= per then + running = "1" +end + +tfile = io.open("/tmp/bwper", "w") +tfile:write("runn=\"", running, "\"") +tfile:close() \ No newline at end of file diff --git a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/dotext.sh b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/dotext.sh new file mode 100644 index 0000000..651c410 --- /dev/null +++ b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/dotext.sh @@ -0,0 +1,82 @@ +#!/bin/sh +. /lib/functions.sh + +log() { + logger -t "TEXTING" "$@" +} + +getbw() { + alloc=$(uci -q get custom.bwallocate.allocate)"000000" + if [ -e /tmp/bwdata ]; then + while IFS= read -r line; do + days=$line + if [ $days = '0' ]; then + used="0" + return + fi + read -r line + used=$line + read -r line + useda=$line + return + done < /tmp/bwdata + else + used="0" + useda="0.00 K" + fi +} + +sendmsg() { + getbw + /usr/lib/bwmon/amtleft.lua $alloc $used + bwleft=$(cat /tmp/amtleft) + + #ident=$(uci -q get custom.texting.ident) + ident=$(uci -q get modem.modem1.iccid) + if [ -z "$ident" ]; then + ident="Unknown User" + fi + message="$ident has used $useda bandwidth and has $bwleft of bandwidth left" + + tore=$(uci -q get custom.texting.tore) + if [ $tore = '0' ]; then + phone=$(uci -q get custom.texting.phone) + /usr/lib/bwmon/chksms.sh + if [ -e /tmp/texting ]; then + /usr/lib/sms/smsout.sh "$phone" "$message" + log "$phone $message" + else + log "$message not sent. No SMS." + fi + else + email=$(uci -q get custom.texting.email) + + host=$(uci -q get custom.texting.smtp) + user=$(uci -q get custom.texting.euser) + pass=$(uci -q get custom.texting.epass) + + STEMP="/tmp/eemail" + MSG="/usr/lib/bwmon/msmtprc" + DST="/etc/msmtprc" + rm -f $STEMP + cp $MSG $STEMP + sed -i -e "s!#HOST#!$host!g" $STEMP + sed -i -e "s!#USER#!$user!g" $STEMP + sed -i -e "s!#PASS#!$pass!g" $STEMP + mv $STEMP $DST + + STEMP="/tmp/emailmsg" + MSG="/usr/lib/bwmon/message" + rm -f $STEMP + cp $MSG $STEMP + sed -i -e "s!#EMAIL#!$email!g" $STEMP + sed -i -e "s!#MESSAGE#!$message!g" $STEMP + sed -i -e "s!#IDENT#!$ident!g" $STEMP + mess=$(cat /tmp/emailmsg) + echo -e "$mess" | msmtp --read-envelope-from --read-recipients + log "$email $message" + fi + +} + +sendmsg \ No newline at end of file diff --git a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/editemail.sh b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/editemail.sh new file mode 100644 index 0000000..61c4ec3 --- /dev/null +++ b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/editemail.sh @@ -0,0 +1,29 @@ +#!/bin/sh + +log() { + logger -t "edit email" "$@" +} + +host=$(uci -q get custom.texting.smtp) +if [ -z $host ]; then + exit 0 +fi +user=$(uci -q get custom.texting.euser) +if [ -z $user ]; then + exit 0 +fi +pass=$(uci -q get custom.texting.epass) +if [ -z $pass ]; then + exit 0 +fi + +STEMP="/tmp/eemail" +MSG="/usr/lib/bwmon/msmtprc" +DST="/etc/msmtprc" +rm -f $STEMP +cp $MSG $STEMP +sed -i -e "s!#HOST#!$host!g" $STEMP +sed -i -e "s!#USER#!$user!g" $STEMP +sed -i -e "s!#PASS#!$pass!g" $STEMP +mv $STEMP $DST + \ No newline at end of file diff --git a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/excede.sh b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/excede.sh new file mode 100644 index 0000000..5c9af09 --- /dev/null +++ b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/excede.sh @@ -0,0 +1,94 @@ +#!/bin/sh +. /lib/functions.sh + +log() { + logger -t "excede BW " "$@" +} + +do_throttle() { + local config=$1 + local limit + + config_get name $1 name + config_get limit $1 limit + config_get throttle $1 throttle + let kamt=limit*1000000 + if [ $amt -gt $kamt ]; then + if [ $limit -gt $baselimit ]; then + speed=$throttle + level=$name + baselimit=$limit + fi + fi +} + +lock=$(uci -q get custom.bwallocate.lock) +if [ $lock = "1" ]; then + enb=$(uci -q get custom.bwallocate.enabled) + if [ $enb = '1' ]; then + allocate=$2 + total=$1 + /usr/lib/bwmon/block 0 + action=$(uci -q get custom.bwallocate.action) + if [ -z $action ]; then + action=0 + fi + if [ ! -e /usr/lib/throttle/throttle.sh ]; then + action=0 + fi + if [ $action != "2" ]; then + if [ $total -gt $allocate ]; then + if [ $action = "0" ]; then + if [ -e /etc/nodogsplash/control ]; then + /etc/nodogsplash/control block + else + /usr/lib/bwmon/block 1 + fi + else + down=$(uci -q get custom.bwallocate.down) + if [ -z $down ]; then + down=5 + fi + up=$(uci -q get custom.bwallocate.up) + if [ -z $up ]; then + up=2 + fi + /usr/lib/throttle/throttle.sh start $down $up + fi + else + if [ -e /usr/lib/throttle/throttle.sh ]; then + /usr/lib/throttle/throttle.sh stop + fi + if [ -e /etc/nodogsplash/control ]; then + /etc/nodogsplash/control unblock + fi + /usr/lib/bwmon/block 0 + fi + else + meth=$(uci -q get custom.bwallocate.meth) + if [ -z $meth ]; then + meth="0" + fi + if [ $meth = "0" ]; then + amt=$total + else + amt=$3 + fi + speed="0" + baselimit="0" + config_load custom + config_foreach do_throttle throttle + if [ $speed != "0" ]; then + /usr/lib/bwmon/float.lua "$speed" + source /tmp/float + /usr/lib/throttle/throttle.sh start $SPEED $SPEED 1 + log "Throttled to $speed Mbps" + else + if [ -e /usr/lib/throttle/throttle.sh ]; then + /usr/lib/throttle/throttle.sh stop + fi + fi + + fi + fi +fi \ No newline at end of file diff --git a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/external.sh b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/external.sh new file mode 100644 index 0000000..9b11296 --- /dev/null +++ b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/external.sh @@ -0,0 +1,24 @@ +#!/bin/sh + +log() { + logger -t "wrtbwmon" "$@" +} + +external=$1 + +ext=$(uci -q get bwmon.general.external) + +if [ "$ext" = "$external" ]; then + exit 0 +else + uci set bwmon.general.external=$external + uci commit bwmon + PID=$(ps |grep "wrtbwmon.sh" | grep -v grep |head -n 1 | awk '{print $1}') + PID1=$(ps |grep "create.sh" | grep -v grep |head -n 1 | awk '{print $1}') + if [ ! -z "$PID" ]; then + kill -9 $PID + kill -9 $PID1 + fi + /usr/lib/bwmon/wrtbwmon.sh & + /usr/lib/bwmon/create.sh & +fi \ No newline at end of file diff --git a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/float.lua b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/float.lua new file mode 100644 index 0000000..4c40f3e --- /dev/null +++ b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/float.lua @@ -0,0 +1,9 @@ +#!/usr/bin/lua + +val = arg[1] + +retval = val * 1000 + +local tfile = io.open("/tmp/float", "w") +tfile:write("SPEED=\"", retval, "\"") +tfile:close() \ No newline at end of file diff --git a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/message b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/message new file mode 100644 index 0000000..509a0e4 --- /dev/null +++ b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/message @@ -0,0 +1,4 @@ +From: Broadband Usage +To: #EMAIL# +Subject: Broadband Usage +#MESSAGE# diff --git a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/msmtprc b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/msmtprc new file mode 100644 index 0000000..4b8a3f8 --- /dev/null +++ b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/msmtprc @@ -0,0 +1,12 @@ +account default +host #HOST# +port 587 +auto_from off +from #USER# +aliases /etc/aliases +tls on +tls_starttls on +tls_trust_file /etc/ssl/certs/ca-certificates.crt +auth on +user #USER# +password #PASS# \ No newline at end of file diff --git a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/perday.lua b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/perday.lua new file mode 100644 index 0000000..1f133ef --- /dev/null +++ b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/perday.lua @@ -0,0 +1,204 @@ +#!/usr/bin/lua + +function ltrim(s) + return s:match'^%s*(.*)' +end + +function calc(total) + if total < 1000 then + tstr = string.format("%.2f", total) + tfm = " K" + else + if total < 1000000 then + tstr = string.format("%.2f", total/1000) + tfm = " MB" + else + tstr = string.format("%.2f", total/1000000) + tfm = " GB" + end + end + str = tstr .. tfm + return ltrim(str) +end + +local function bubblesort(a) + repeat + local swapped = false + for i = 1, table.getn(a) do + if a[i - 1] < a[i] then + a[i], a[i - 1] = a[i - 1], a[i] + swapped = true + end -- if + end -- for + until swapped == false +end + +function ConBytes(line) + local s, e, bs, be + s, e = line:find(" ") + bs, be = line:find("K", e+1) + if bs == nil then + bs, be = line:find("MB", e+1) + if bs == nil then + val = tonumber(line:sub(1, e-1)) * 1000000 + else + val = tonumber(line:sub(1, e-1)) * 1000 + end + else + val = tonumber(line:sub(1, e-1)) + end + return val +end + +dirname = '/usr/lib/bwmon/data' +filepost = "-mac_data.js" +monthly = dirname .. "/monthly.data" +daylist = {} +dayline = {} +monlist = {} +monline = {} + +dataname = nil +f = io.popen('/bin/ls ' .. dirname) +for name in f:lines() do + s, e = name:find(filepost) + if s ~= nil then + dataname = name + end +end +f:close() + +if dataname ~= nil then + yearmon = dataname:sub(1, 7) + datafile = dirname .. "/" .. dataname + file = io.open(datafile, "r") + i = 0 + repeat + line = file:read("*line") + if line == nil then + break + end + s, e = line:find("start day") + if s ~= nil then + day = line:sub(e+1) + nday = tonumber(day) + day= tostring(nday) + if nday < 10 then + day = "0" .. day + end + yearmonday = yearmon .. "-" .. day + + daydwn = 0 + dayup = 0 + repeat + line = file:read("*line") + s, e = line:find("end day") + if s ~= nil then + dayt = dayup + daydwn + if dayt > 0 then + daylist[i] = yearmonday + i = i + 1 + dayline[yearmonday] = {} + dayline[yearmonday]['down'] = daydwn + dayline[yearmonday]['up'] = dayup + dayline[yearmonday]['total'] = dayup + daydwn + end + break + end + s, e = line:find("\"down\":\"") + bs, be = line:find("\"", e+1) + daydwn = daydwn + tonumber(line:sub(e+1, bs-1)) + s, e = line:find("\"up\":\"") + bs, be = line:find("\"", e+1) + dayup = dayup + tonumber(line:sub(e+1, bs-1)) + until 1==0 + end + until 1==0 + + if i > 0 then + tfile = io.open(monthly, "r") + if tfile == nil then + for j = 0,i-1 + do + lin = daylist[j] + monlist[j] = lin + monline[lin] = {} + dwn = calc(dayline[lin]['down']) + up = calc(dayline[lin]['up']) + total = calc(dayline[lin]['total']) + dataline = lin .. "|" .. dwn .. "|" .. up .. "|" .. total + monline[lin]['data'] = dataline + end + k = i + else + k = 0 + ksize = tfile:read("*line") + kdwn = tfile:read("*line") + kup = tfile:read("*line") + ktotal = tfile:read("*line") + repeat + line = tfile:read("*line") + if line == nil then + break + end + ymd = line:sub(1,10) + monlist[k] = ymd + k = k + 1 + monline[ymd] = {} + monline[ymd]['data'] = line + until 1==0 + tfile:close() + + for j = 0,i-1 + do + lin = daylist[j] + if monline[lin] == nil then + monlist[k] = lin + k = k + 1 + monline[lin] = {} + end + dwn = calc(dayline[lin]['down']) + up = calc(dayline[lin]['up']) + total = calc(dayline[lin]['total']) + dataline = lin .. "|" .. dwn .. "|" .. up .. "|" .. total + monline[lin]['data'] = dataline + end + end + + bubblesort(monlist) + + tfile = io.open(monthly, "w") + if k > 30 then + k = 30 + end + tfile:write(tostring(k), "\n") + fdown = 0 + fup = 0 + ftotal = 0 + for j = 0,k-1 + do + lin = monlist[j] + dataline = monline[lin]['data'] + s, e = dataline:find("|") + if s ~= nil then + bs, be = dataline:find("|", e+1) + fdown = ConBytes(dataline:sub(e+1, be-1)) + fdown + s, e = dataline:find("|", be+1) + fup = ConBytes(dataline:sub(be+1, e-1)) + fup + ftotal = ConBytes(dataline:sub(e+1)) + ftotal + end + end + tfile:write(calc(fdown), "\n") + tfile:write(calc(fup), "\n") + tfile:write(calc(ftotal), "\n") + for j = 0,k-1 + do + lin = monlist[j] + dataline = monline[lin]['data'] + tfile:write(dataline, "\n") + end + tfile:close() + end + + file:close() +end \ No newline at end of file diff --git a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/process.sh b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/process.sh new file mode 100644 index 0000000..42e38b6 --- /dev/null +++ b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/process.sh @@ -0,0 +1,20 @@ +#!/bin/sh + +log() { + logger -t "BWmon Process" "$@" +} + +running=0 +if [ -e "/tmp/WRTbmon" ]; then + running=1 +fi + +sleep 5 + +if [ $running = 0 ]; then + log "Enable BandWidthMonitor" + /usr/lib/bwmon/wrtbwmon.sh & +fi + + + diff --git a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/rollover.sh b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/rollover.sh new file mode 100644 index 0000000..648b9d6 --- /dev/null +++ b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/rollover.sh @@ -0,0 +1,11 @@ +#!/bin/sh + +log() { + logger -t "Rollover" "$@" +} + +amount=$1 + +uci set custom.bwallocate.rollover=$amount +uci set custom.bwallocate.persent="0" +uci commit custom diff --git a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/savetot.sh b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/savetot.sh new file mode 100644 index 0000000..1a780ba --- /dev/null +++ b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/savetot.sh @@ -0,0 +1,10 @@ +#!/bin/sh + +log() { + logger -t "save total" "$@" +} + +total=$1 + +uci set custom.bwday.bwday="$total" +uci commit custom \ No newline at end of file diff --git a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/sendsms.sh b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/sendsms.sh new file mode 100644 index 0000000..3fc4ff4 --- /dev/null +++ b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/sendsms.sh @@ -0,0 +1,39 @@ +#!/bin/sh + +log() { + logger -t "sendsms" "$@" +} + +chksms() { + CURRMODEM=1 + rm -f /tmp/texting + CPORT=$(uci -q get modem.modem$CURRMODEM.commport) + if [ -z $CPORT ]; then + return + fi + SMS_OK=$(uci -q get modem.modem$CURRMODEM.sms) + if [ "$SMS_OK" != "1" ]; then + return + fi + echo "0" > /tmp/texting +} + +delay=$(uci -q get modem.modeminfo$CURRMODEM.delay) +if [ "$delay" -gt 0 ]; then + cnt=1 + while true; do + sleep 3600 + let cnt=cnt+1 + if [ $cnt -gt $delay ]; then + break + fi + done +fi +total=$(uci -q get.custom.bwday.bwday) +chksms +phone=$(uci -q get modem.modeminfo$CURRMODEM.bwphone) +if [ (! -z "$phone") -o ("$phone" != "0") ]; then + if [ -e /tmp/texting ]; then + /usr/lib/sms/smsout.sh "$phone" "$total" + fi +fi diff --git a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/textbw.sh b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/textbw.sh new file mode 100644 index 0000000..5d9d589 --- /dev/null +++ b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/textbw.sh @@ -0,0 +1,153 @@ +#!/bin/sh +. /lib/functions.sh + +log() { + logger -t "TEXTING" "$@" +} + +checktime() { + SHOUR=$(uci -q get custom.texting.time) + EHOUR=`expr $SHOUR + 1` + if [ $EHOUR -gt 95 ]; then + EHOUR=0 + fi + HOUR=`expr $SHOUR / 4` + let "TH = $HOUR * 4" + let "TMP1 = $SHOUR - $TH" + let "MIN = $TMP1 * 15" + shour=$HOUR + smin=$MIN + + HOUR=`expr $EHOUR / 4` + let "TH = $HOUR * 4" + let "TMP1 = $EHOUR - $TH" + let "MIN = $TMP1 * 15" + ehour=$HOUR + emin=$MIN + + chour=$(date +%H) + cmin=$(date +%M) + if [ $shour -gt $chour ]; then + flag="0" + else + if [ $shour -eq $chour ]; then + if [ $smin -le $cmin ]; then + flag="1" + else + flag="0" + fi + else + flag="1" + fi + fi + + if [ $flag = "1" ]; then + if [ $ehour -lt $chour ]; then + flag="0" + else + if [ $ehour -eq $chour ]; then + if [ $emin -lt $cmin ]; then + flag="0" + else + flag="1" + fi + else + flag="1" + fi + fi + fi + echo $flag +} + +getbw() { + alloc=$(uci -q get custom.bwallocate.allocate)"000000" + if [ -e /tmp/bwdata ]; then + while IFS= read -r line; do + days=$line + if [ $days = '0' ]; then + used="0" + return + fi + read -r line + used=$line + return + done < /tmp/bwdata + else + used="0" + fi +} + +checkamt() { + istime=$(checktime) + if [ $istime = '1' ]; then + incr=$(uci -q get custom.texting.increment) + getbw + /usr/lib/bwmon/datainc.lua $prev $incr $used + source /tmp/bwinc + uci set custom.texting.used=$prev + uci commit custom + echo $runn + else + echo "0" + fi +} + +checkper() { + istime=$(checktime) + if [ $istime = '1' ]; then + prev=$(uci -q get custom.texting.used) + per=$(uci -q get custom.bwallocate.percent) + persent=$(uci -q get custom.bwallocate.persent) + if [ "$persent" != "1" ]; then + getbw + /usr/lib/bwmon/dataper.lua $alloc $per $used + source /tmp/bwper + if [ $runn = "1" ]; then + uci set custom.bwallocate.persent="1" + uci commit custom + fi + echo $runn + else + echo "0" + fi + else + echo "0" + fi +} + +delay=900 +while true +do + EN=$(uci -q get custom.bwallocate.enabled) + if [ $EN = "1" ]; then + MT=$(uci -q get custom.texting.method) + if [ $MT = '0' ]; then + days=$(uci -q get custom.texting.days) + daysdate=$( date +%d ) + daysdate="${daysdate#"${daysdate%%[!0]*}"}" + remain=$((daysdate % days)) + if [ $remain -eq 0 ]; then + running=$(checktime) + else + running="0" + fi + else + if [ $MT = '1' ]; then + running=$(checkamt) + else + running=$(checkper) + fi + fi + if [ $running = "1" ]; then + EN=$(uci -q get custom.texting.text) + if [ $EN = "1" ]; then + /usr/lib/bwmon/dotext.sh + sleep $delay + fi + else + sleep $delay + fi + else + sleep $delay + fi +done \ No newline at end of file diff --git a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/wrtbwmon.sh b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/wrtbwmon.sh new file mode 100644 index 0000000..55e3924 --- /dev/null +++ b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/wrtbwmon.sh @@ -0,0 +1,508 @@ +#!/bin/sh + +setbackup() { + extn=$(uci -q get bwmon.general.external) + if [ "$extn" = "0" ]; then + backPath=/usr/lib/bwmon/data/ + else + if [ -e "$extn""/" ]; then + backPath=$extn"/data/" + else + backPath=/usr/lib/bwmon/data/ + uci set bwmon.general.external="0" + uci commit bwmon + fi + fi + if [ ! -e "$backpath" ]; then + mkdir -p $backPath + fi +} + +LAN_TYPE=$(uci get network.lan.ipaddr | awk -F. ' { print $1"."$2 }') +LEASES_FILE=/tmp/dhcp.leases +lockDir=/tmp/WRTbmon + +ifname="ifname" +source /etc/openwrt_release +twone=$(echo "$DISTRIB_RELEASE" | grep "21.02") +if [ ! -z "$twone" ]; then + ifname="device" +fi + + +[ ! -d "$lockDir" ] && mkdir "$lockDir" +basePath="/tmp/bwmon/" +mkdir -p $basePath"data" +dataPath=$basePath"data/" +setbackup +lockDir1=/tmp/wrtbwmon1.lock +lockDir=/tmp/wrtbwmon.lock +mkdir -p "$lockDir" +pidFile=$lockDir/pid +STARTIMEX=$(date +%s) +STARTIMEY=$(date +%s) +STARTIMEZ=$(date +%s) +cYear=$(date +%Y) +cDay=$(date +%d) +cMonth=$(date +%m) +setup_time=60 +update_time=60 +bs=$(uci -q get bwmon.general.backup) +let "bs=$bs*60" +backup_time=$bs +pause=30 +unlimited="peak" + +networkFuncs=/lib/functions/network.sh +uci=`which uci 2>/dev/null` +nslookup=`which nslookup 2>/dev/null` +nvram=`which nvram 2>/dev/null` +binDir=/usr/sbin +chains='INPUT OUTPUT FORWARD' +DEBUG= +interfaces='eth0' # in addition to detected WAN +DB="/tmp/usage.db" +mode= + +log() { + logger -t "wrtbwmon" "$@" +} + +header="#mac,ip,iface,in,out,total,first_date,last_date" + +createDbIfMissing() +{ + [ ! -f "$DB" ] && rm -f $DB;echo $header > "$DB" +} + +checkWAN() +{ + [ -z "$wan" ] && return +} + +lookup() +{ + MAC=$1 + IP=$2 + userDB=$3 + for USERSFILE in $userDB /tmp/dhcp.leases /tmp/dnsmasq.conf /etc/dnsmasq.conf /etc/hosts; do + [ -e "$USERSFILE" ] || continue + case $USERSFILE in + /tmp/dhcp.leases ) + USER=$(grep -i "$MAC" $USERSFILE | cut -f4 -s -d' ') + ;; + /etc/hosts ) + USER=$(grep "^$IP " $USERSFILE | cut -f2 -s -d' ') + ;; + * ) + USER=$(grep -i "$MAC" "$USERSFILE" | cut -f2 -s -d,) + ;; + esac + [ "$USER" = "*" ] && USER= + [ -n "$USER" ] && break + done + if [ -n "$DO_RDNS" -a -z "$USER" -a "$IP" != "NA" -a -n "$nslookup" ]; then + USER=`$nslookup $IP $DNS | awk '!/server can/{if($4){print $4; exit}}' | sed -re 's/[.]$//'` + fi + [ -z "$USER" ] && USER=${MAC} + echo $USER +} + +detectIF() +{ + if [ -f "$networkFuncs" ]; then + IF=`. $networkFuncs; network_get_device netdev $1; echo $netdev` + [ -n "$IF" ] && echo $IF && return + fi + + if [ -n "$uci" -a -x "$uci" ]; then + IF=`$uci get network.${1}.$ifname 2>/dev/null` + [ $? -eq 0 -a -n "$IF" ] && echo $IF && return + fi + + if [ -n "$nvram" -a -x "$nvram" ]; then + IF=`$nvram get ${1}_$ifname 2>/dev/null` + [ $? -eq 0 -a -n "$IF" ] && echo $IF && return + fi +} + +detectLAN() +{ + [ -e /sys/class/net/br-lan ] && echo br-lan && return + lan=$(detectIF lan) + [ -n "$lan" ] && echo $lan && return +} + +detectWAN() +{ + [ -n "$WAN_IF" ] && echo $WAN_IF && return + wan=$(detectIF wan) + [ -n "$wan" ] && echo $wan && return + wan=$(ip route show 2>/dev/null | grep default | sed -re '/^default/ s/default.*dev +([^ ]+).*/\1/') + [ -n "$wan" ] && echo $wan && return + [ -f "$networkFuncs" ] && wan=$(. $networkFuncs; network_find_wan wan; echo $wan) + [ -n "$wan" ] && echo $wan && return +} + +lock() +{ + attempts=0 + while [ $attempts -lt 10 ]; do + mkdir $lockDir1 2>/dev/null && break + attempts=$((attempts+1)) + pid=`cat $pidFile 2>/dev/null` + if [ -n "$pid" ]; then + if [ -d "/proc/$pid" ]; then + [ -n "$DEBUG" ] && echo "WARNING: Lockfile detected but process $(cat $pidFile) does not exist !" + rm -rf $lockDir1 + else + sleep 1 + fi + fi + done + mkdir $lockDir1 2>/dev/null + echo $$ > $pidFile + [ -n "$DEBUG" ] && echo $$ "got lock after $attempts attempts" + trap '' INT +} + +unlock() +{ + rm -rf $lockDir1 + [ -n "$DEBUG" ] && echo $$ "released lock" + trap "rm -f /tmp/*_$$.tmp; kill $$" INT +} + +# chain +newChain() +{ + chain=$1 + # Create the RRDIPT_$chain chain (it doesn't matter if it already exists). + iptables -t mangle -N RRDIPT_$chain 2> /dev/null + + # Add the RRDIPT_$chain CHAIN to the $chain chain if not present + iptables -t mangle -C $chain -j RRDIPT_$chain 2>/dev/null + if [ $? -ne 0 ]; then + [ -n "$DEBUG" ] && echo "DEBUG: iptables chain misplaced, recreating it..." + iptables -t mangle -I $chain -j RRDIPT_$chain + fi +} + +# chain tun +newRuleIF() +{ + chain=$1 + IF=$2 + + #!@todo test + if [ "$chain" = "OUTPUT" ]; then + cmd="iptables -t mangle -o $IF -j RETURN" + eval $cmd " -C RRDIPT_$chain 2>/dev/null" || eval $cmd " -A RRDIPT_$chain" + elif [ "$chain" = "INPUT" ]; then + cmd="iptables -t mangle -i $IF -j RETURN" + eval $cmd " -C RRDIPT_$chain 2>/dev/null" || eval $cmd " -A RRDIPT_$chain" + fi +} + +accounting(){ + LAN_IFACE="br-lan" + WAN_IFACE=$1 + LAN_IP=$(uci -q get network.lan.ipaddr) + SERVER_IP=$(echo $LAN_IP | cut -d . -f 1,2,3).0 + INTERNAL_NETMASK="$SERVER_IP/24" + + # create the ACCOUNTING chains + iptables -w -N ACCOUNTING_BLOCK 2> /dev/null + iptables -w -N ACCOUNTING_IN 2> /dev/null + iptables -w -N ACCOUNTING_OUT 2> /dev/null + check=0 + # check if accounting rule for ethernet wan not exist, add it + checks=$(iptables -w -L FORWARD -v -n | grep "ACCOUNTING" | grep "$WAN_IFACE") + [ -z "$checks" ] && check=1 + + # check if jumps to the ACCOUNTING chains are still at the start of the FORWARD chain + iptables -w -L FORWARD --line-numbers -n | grep "ACCOUNTING" | grep "^1 " + if [ $? -ne 0 -o "$check" = "1" ]; then + # remove old jump rules + iptables -w -D FORWARD $(iptables -w -L FORWARD --line-numbers | grep ACCOUNTING | grep -m 1 -o "[0-9]*") + while [ $? -eq 0 ]; do + iptables -w -D FORWARD $(iptables -w -L FORWARD --line-numbers | grep ACCOUNTING | grep -m 1 -o "[0-9]*") + done + # insert new jump rules at start of FORWARD chain + if [ -n "$WAN_IFACE" ] + then + iptables -w -I FORWARD -i ${WAN_IFACE} -j ACCOUNTING_IN + iptables -w -I FORWARD -o ${WAN_IFACE} -j ACCOUNTING_OUT + fi + iptables -w -I FORWARD -j ACCOUNTING_BLOCK + fi + + #For each host in the ARP table + grep ${LAN_IFACE} /proc/net/arp | while read IP TYPE FLAGS MAC MASK IFACE + do + #Add iptables rules (if non existing). + iptables -w -nL ACCOUNTING_IN | grep "${IP} " > /dev/null + if [ $? -ne 0 ]; then + iptables -w -I ACCOUNTING_IN -d ${IP} -s ${INTERNAL_NETMASK} -j RETURN + iptables -w -I ACCOUNTING_IN -d ${IP} ! -s ${INTERNAL_NETMASK} -j RETURN + fi + + iptables -w -nL ACCOUNTING_OUT | grep "${IP} " > /dev/null + if [ $? -ne 0 ]; then + iptables -w -I ACCOUNTING_OUT -s ${IP} -d ${INTERNAL_NETMASK} -j RETURN + iptables -w -I ACCOUNTING_OUT -s ${IP} ! -d ${INTERNAL_NETMASK} -j RETURN + fi + done +} + +setup() +{ + for chain in $chains; do + newChain $chain + done + + wan=$(detectWAN) + checkWAN + wan1=$(detectIF wan1) + wan2=$(detectIF wan2) + C1=$(uci -q get modem.modem1.connected) + C2=$(uci -q get modem.modem2.connected)$C1 + if [ ! -z $C2 ]; then + interfaces="$wan1 $wan2" + WW=$(uci -q get bwmon.bwwan.wan) + if [ "$WW" = "1" ]; then + interfaces=$interfaces $wan" wwan" + fi + else + WW=$(uci -q get bwmon.bwwan.wan) + if [ "$WW" = "1" ]; then + interfaces="$wan wwan" + else + return + fi + fi + + # track local data + for chain in INPUT OUTPUT; do + for interface in $interfaces; do + [ -n "$interface" ] && [ -e "/sys/class/net/$interface" ] && newRuleIF $chain $interface + #if [ -e /etc/bwlock ]; then + accounting $interface + #fi + done + done + + # this will add rules for hosts in arp table + update $dailyUsageDB + + rm -f /tmp/*_$$.tmp +} + +update() +{ + createDbIfMissing + checkWAN + PERTOTAL=0 + + > /tmp/iptables_$$.tmp + lock + # only zero our own chains + for chain in $chains; do + iptables -nvxL RRDIPT_$chain -t mangle -Z >> /tmp/iptables_$$.tmp + done + # the iptables and readDB commands have to be separate. Otherwise, + # they will fight over iptables locks + awk -v mode="$mode" -v interfaces=\""$interfaces"\" -f $binDir/readDB.awk \ + $DB \ + /proc/net/arp \ + /tmp/iptables_$$.tmp + + while read L1 + do + MAC=$(echo ${L1} | cut -f1 -d, ) + if [ $MAC != "#mac" ]; then + MAC=$(echo ${L1} | cut -f1 -d, ) + IP=$(echo ${L1} | cut -f2 -d, ) + IN=$(echo ${L1} | cut -f4 -d, ) + IN=$((${IN}/1000)) + OUT=$(echo ${L1} | cut -f5 -d, ) + OUT=$((${OUT}/1000)) + TOTAL=$(echo ${L1} | cut -f6 -d, ) + TOTAL=$((${TOTAL}/1000)) + let PERTOTAL=PERTOTAL+TOTAL + if [ $TOTAL -gt 0 -a $IP != "NA" ]; then + for USERSFILE in /tmp/dhcp.leases /tmp/dnsmasq.conf /etc/dnsmasq.conf /etc/hosts; do + [ -e "$USERSFILE" ] || continue + case $USERSFILE in + /tmp/dhcp.leases ) + NAME=$(grep -i "$MAC" $USERSFILE | cut -f4 -s -d' ') + ;; + /etc/hosts ) + NAME=$(grep "^$IP " $USERSFILE | cut -f2 -s -d' ') + ;; + * ) + NAME=$(grep -i "$MAC" "$USERSFILE" | cut -f2 -s -d,) + ;; + esac + [ "$NAME" = "*" ] && NAME= + [ -n "$NAME" ] && break + done + if [ -z $NAME ]; then + NAME="*" + fi + + echo "\"mac\":\""${MAC}"\"","\"down\":\""${IN}"\"","\"up\":\""${OUT}"\"","\"offdown\":\""0"\"","\"offup\":\""0"\"","\"ip\":\""${IP}"\"","\"name\":\""${NAME}"\"" >> ${1} + fi + fi + done < $DB + if [ -e /usr/lib/bwmon/period.sh ]; then + /usr/lib/bwmon/period.sh "$PERTOTAL" + fi + unlock +} + + +createFiles() +{ + while [ -e /tmp/lockbw ]; do + sleep 1 + done + echo "0" > /tmp/lockbw + while [ ! -e $backPath*"mac_data.js" ]; do + valid=$(cat /var/state/dnsmasqsec) + st=$(echo "$valid" | grep "ntpd says time is valid") + if [ ! -z "$st" ]; then + break + fi + sleep 10 + done + dailyUsageDB="$dataPath$cYear-$cMonth-$cDay-daily_data.js" + dailyUsageBack="$backPath$cYear-$cMonth-$cDay-daily_data.js" + if [ ! -f $dailyUsageBack ]; then + rm -f $backPath*"daily_data.js" + touch $dailyUsageDB + touch $dailyUsageBack + else + cp -f $dailyUsageBack $dailyUsageDB + fi + monthlyUsageDB="$dataPath$cYear-$cMonth-mac_data.js" + monthlyUsageBack="$backPath$cYear-$cMonth-mac_data.js" + if [ -f $monthlyUsageBack ]; then + cp -f $monthlyUsageBack $monthlyUsageDB".bk" + sed "/start day $cDay/,/end day $cDay/d" $monthlyUsageDB".bk" > $monthlyUsageDB + cp -f $monthlyUsageBack $monthlyUsageDB".bk" + else + rm -f $backPath*"mac_data.js" + touch $monthlyUsageDB + touch $monthlyUsageBack + /usr/lib/bwmon/backup.sh "backup" $cDay $monthlyUsageDB $dailyUsageDB $monthlyUsageBack $dailyUsageBack + fi + rm -f /tmp/lockbw +} + +shutDown() +{ + while [ -e /tmplockbw ]; do + sleep 1 + done + echo "0" > /tmp/lockbw + /usr/lib/bwmon/backup.sh "backup" $cDay $monthlyUsageDB $dailyUsageDB $monthlyUsageBack $dailyUsageBack + lua /usr/lib/bwmon/cleanup.lua + rm -f /tmp/lockbw +} + +checkSetup() +{ + CURRTIME=$(date +%s) + let ELAPSE=CURRTIME-STARTIMEX + if [ $ELAPSE -gt $setup_time ]; then + STARTIMEX=$CURRTIME + setup + /usr/lib/bwmon/backup.sh "setup" $cDay $monthlyUsageDB $dailyUsageDB $monthlyUsageBack $dailyUsageBack + fi +} + +checkUpdate() +{ + CURRTIME=$(date +%s) + let ELAPSE=CURRTIME-STARTIMEY + if [ $ELAPSE -gt $update_time ]; then + STARTIMEY=$CURRTIME + update $dailyUsageDB $unlimited + fi +} + +checkBackup() +{ + CURRTIME=$(date +%s) + let ELAPSE=CURRTIME-STARTIMEZ + bs=$(uci -q get bwmon.general.backup) + let "bs=$bs*60" + backup_time=$bs + if [ $ELAPSE -gt $backup_time ]; then + STARTIMEZ=$CURRTIME + shutDown + fi +} + +checkTime() +{ + while [ -e /tmplockbw ]; do + sleep 1 + done + echo "0" > /tmp/lockbw + pDay=$(date +%d) + pYear=$(date +%Y) + pMonth=$(date +%m) + if [ "$cDay" -ne "$pDay" ]; then + /usr/lib/bwmon/backup.sh "daily" $cDay $monthlyUsageDB $dailyUsageDB $monthlyUsageBack $dailyUsageBack + + cDay=$pDay + cMonth=$pMonth + cYear=$pYear + monthlyUsageBack="$backPath$cYear-$cMonth-mac_data.js" + if [ ! -e $monthlyUsageBack ]; then + rm -f $backPath*"mac_data.js" + fi + rm -f $dataPath[[:digit:]][[:digit:]][[:digit:]][[:digit:]]"-"[[:digit:]][[:digit:]]"-"[[:digit:]][[:digit:]]-daily_data.js + rm -f $backPath[[:digit:]][[:digit:]][[:digit:]][[:digit:]]"-"[[:digit:]][[:digit:]]"-"[[:digit:]][[:digit:]]-daily_data.js + roll=$(uci -q get custom.bwallocate.rollover) + [ -z $roll ] && roll=1 + if [ "$roll" -eq "$pDay" ]; then + rm -f $monthlyUsageDB + rm -f $backPath*"mac_data.js" + monthlyUsageDB="$dataPath$cYear-$cMonth-mac_data.js" + monthlyUsageBack="$backPath$cYear-$cMonth-mac_data.js" + touch $monthlyUsageDB + uci set custom.texting.used='0' + uci commit custom + if [ -e /usr/lib/bwmon/periodreset.sh ]; then + /usr/lib/bwmon/periodreset.sh + fi + fi + rm -f $dailyUsageDB + rm -f $backPath*"daily_data.js" + dailyUsageDB="$dataPath$cYear-$cMonth-$cDay-daily_data.js" + touch $dailyUsageDB + dailyUsageBack="$backPath$cYear-$cMonth-$cDay-daily_data.js" + fi + rm -f /tmp/lockbw +} + +createFiles +setup +while [ -d $lockDir ]; do + checkSetup + checkTime + checkBackup + n=0 + while [ true ] ; do + n=$(($n + 1)) + if [ ! -d "$lockDir" ]; then + shutDown + exit 0 + fi + [ "$n" -gt "$pause" ] && break; + sleep 1 + done +done diff --git a/rooter/0optionalapps/bwmon/files/usr/lib/lua/luci/controller/bwmon.lua b/rooter/0optionalapps/bwmon/files/usr/lib/lua/luci/controller/bwmon.lua new file mode 100644 index 0000000..ac269e8 --- /dev/null +++ b/rooter/0optionalapps/bwmon/files/usr/lib/lua/luci/controller/bwmon.lua @@ -0,0 +1,119 @@ +module("luci.controller.bwmon", package.seeall) + +I18N = require "luci.i18n" +translate = I18N.translate + +function index() + local page + entry({"admin", "nlbw"}, firstchild(), translate("Bandwidth Monitor"), 80).dependent=false + page = entry({"admin", "nlbw", "bwmon"}, template("bwmon/bwmon"), translate("ROOter Bandwidth Monitor"), 70) + page.dependent = true + + entry({"admin", "nlbw", "check_bw"}, call("action_check_bw")) + entry({"admin", "nlbw", "change_bw"}, call("action_change_bw")) + entry({"admin", "nlbw", "change_roll"}, call("action_change_roll")) + entry({"admin", "nlbw", "change_enable"}, call("action_change_enable")) + entry({"admin", "nlbw", "change_bwenable"}, call("action_change_bwenable")) + entry({"admin", "nlbw", "change_backup"}, call("action_change_backup")) + entry({"admin", "nlbw", "change_external"}, call("action_change_external")) + entry({"admin", "nlbw", "change_bwwan"}, call("action_change_bwwan")) +end + +function action_check_bw() + local rv = {} + local maclist = {} + + file = io.open("/tmp/bwdata", "r") + if file ~= nil then + rv['days'] = file:read("*line") + if rv['days'] ~= "0" then + rv['total'] = file:read("*line") + rv['ctotal'] = file:read("*line") + rv['totaldown'] = file:read("*line") + rv['ctotaldown'] = file:read("*line") + rv['totalup'] = file:read("*line") + rv['ctotalup'] = file:read("*line") + rv['ptotal'] = file:read("*line") + rv['cptotal'] = file:read("*line") + rv['atotal'] = file:read("*line") + rv['catotal'] = file:read("*line") + rv['password'] = file:read("*line") + j = file:read("*line") + if j == nil then + j = 0 + end + rv['macsize'] = j + if j ~=0 then + for i=0, j-1 do + maclist[i] = file:read("*line") + end + rv['maclist'] = maclist + end + end + file:close() + else + rv['days'] = 0 + end + 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" then + rv['lock'] = luci.model.uci.cursor():get("custom", "bwallocate", "lock") + else + if rootlock == "0" then + rv['lock'] = "1" + else + rv['lock'] = "0" + end + end + rv['rollover'] = luci.model.uci.cursor():get("custom", "bwallocate", "rollover") + rv['enabled'] = luci.model.uci.cursor():get("custom", "bwallocate", "enabled") + rv['bwenabled'] = luci.model.uci.cursor():get("bwmon", "general", "enabled") + rv['backup'] = luci.model.uci.cursor():get("bwmon", "general", "backup") + rv['external'] = luci.model.uci.cursor():get("bwmon", "general", "external") + rv['bwwan'] = luci.model.uci.cursor():get("bwmon", "bwwan", "wan") + + luci.http.prepare_content("application/json") + luci.http.write_json(rv) +end + +function action_change_bw() + local set = luci.http.formvalue("set") + os.execute("/usr/lib/bwmon/allocate.sh " .. set) + +end + +function action_change_roll() + local set = luci.http.formvalue("set") + os.execute("/usr/lib/bwmon/rollover.sh " .. set) + +end + +function action_change_enable() + local set = luci.http.formvalue("set") + os.execute("uci set custom.bwallocate.enabled=" .. set .. "; uci commit custom") + +end + +function action_change_bwenable() + local set = luci.http.formvalue("set") + os.execute("/usr/lib/bwmon/change.sh " .. set) + +end + +function action_change_backup() + local set = luci.http.formvalue("set") + os.execute("uci set bwmon.general.backup=" .. set .. "; uci commit bwmon") + +end + +function action_change_external() + local set = luci.http.formvalue("set") + os.execute("/usr/lib/bwmon/external.sh " .. set) + +end + +function action_change_bwwan() + local set = luci.http.formvalue("set") + os.execute("uci set bwmon.bwwan.wan=" .. set .. "; uci commit bwmon") + +end \ No newline at end of file diff --git a/rooter/0optionalapps/bwmon/files/usr/lib/lua/luci/view/bwmon/bwmon.htm b/rooter/0optionalapps/bwmon/files/usr/lib/lua/luci/view/bwmon/bwmon.htm new file mode 100644 index 0000000..2664efd --- /dev/null +++ b/rooter/0optionalapps/bwmon/files/usr/lib/lua/luci/view/bwmon/bwmon.htm @@ -0,0 +1,610 @@ +<%+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 + +-%> + + + + +
                +
                +

                <%:Bandwidth Monitor%>

                +
                +

                <%:Note : Bandwidth Monitor will not turn on until there is Internet Available%>

                + + + +
                + <%:Extra Internet Sources%> + + + + + + + + +
                <%:Include WAN and Hotspot%>
                +
                + +
                + <%:Data Backup Configuration%> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                <%:Enable Data Backup%>
                <%:Backup Interval in Minutes%>
                +
                <%:Backup Storage Location%>
                + +
                + +
                + <%:Total Bandwidth%> + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                <%:Total Amount of Bandwidth used this Month : %>
                <%:Estimated Bandwidth to be used this Month : %>
                <%:Rollover Day : %>
                +
                + + + + + +
                + +
                + <%:Report%> + + + + + + + + + + + + + + + + + +
                <%:Number of Days in Reporting Period : %>
                <%:Total Amount of Download Bandwidth : %>
                <%:Total Amount of Upload Bandwidth : %>
                + + + + + + +
                + +
                + + + + + + + + + +
                <%:IP Address%>
                <%:Name%>
                <%:MAC Address%>
                <%:Bandwidth Down%>
                <%:Bandwidth Up%>
                <%:Bandwidth Total%>
                + + + +
                +
                + +
                +
                +<%+footer%> \ No newline at end of file diff --git a/rooter/0optionalapps/bwmon/files/usr/sbin/readDB.awk b/rooter/0optionalapps/bwmon/files/usr/sbin/readDB.awk new file mode 100644 index 0000000..cb57377 --- /dev/null +++ b/rooter/0optionalapps/bwmon/files/usr/sbin/readDB.awk @@ -0,0 +1,157 @@ +#!/usr/bin/awk + +function inInterfaces(host){ + return(interfaces ~ "(^| )"host"($| )") +} + +function newRule(arp_ip, + ipt_cmd){ + # checking for existing rules shouldn't be necessary if newRule is + # always called after db is read, arp table is read, and existing + # iptables rules are read. + ipt_cmd="iptables -t mangle -j RETURN -s " arp_ip + system(ipt_cmd " -C RRDIPT_FORWARD 2>/dev/null || " ipt_cmd " -A RRDIPT_FORWARD") + ipt_cmd="iptables -t mangle -j RETURN -d " arp_ip + system(ipt_cmd " -C RRDIPT_FORWARD 2>/dev/null || " ipt_cmd " -A RRDIPT_FORWARD") +} + +function total(i){ + return(bw[i "/in"] + bw[i "/out"]) +} + +function date( cmd, d){ + cmd="date +%d-%m-%Y_%H:%M:%S" + cmd | getline d + close(cmd) + #!@todo could start a process with "while true; do date ...; done" + return(d) +} + +BEGIN { + od="" + fid=1 + debug=0 + rrd=0 +} + +/^#/ { # get DB filename + FS="," + dbFile=FILENAME + next +} + +# data from database; first file +FNR==NR { #!@todo this doesn't help if the DB file is empty. + if($2 == "NA") + #!@todo could get interface IP here + n=$1 + else + n=$2 + + hosts[n] = "" # add this host/interface to hosts + mac[n] = $1 + ip[n] = $2 + inter[n] = $3 + bw[n "/in"] = $4 + bw[n "/out"] = $5 + firstDate[n] = $7 + lastDate[n] = $8 + next +} + +# not triggered on the first file +FNR==1 { + FS=" " + fid++ #!@todo use fid for all files; may be problematic for empty files + next +} + +# arp: ip hw flags hw_addr mask device +fid==2 { + #!@todo regex match IPs and MACs for sanity + arp_ip = $1 + arp_flags = $3 + arp_mac = $4 + arp_dev = $6 + if(arp_flags != "0x0" && !(arp_ip in ip)){ + if(debug) + print "new host:", arp_ip, arp_flags > "/dev/stderr" + hosts[arp_ip] = "" + mac[arp_ip] = arp_mac + ip[arp_ip] = arp_ip + inter[arp_ip] = arp_dev + bw[arp_ip "/in"] = bw[arp_ip "/out"] = 0 + firstDate[arp_ip] = lastDate[arp_ip] = date() + } + next +} + +#!@todo could use mangle chain totals or tailing "unnact" rules to +# account for data for new hosts from their first presence on the +# network to rule creation. The "unnact" rules would have to be +# maintained at the end of the list, and new rules would be inserted +# at the top. + +# skip line +# read the chain name and deal with the data accordingly +fid==3 && $1 == "Chain"{ + rrd=$2 ~ /RRDIPT_.*/ + next +} + +fid==3 && rrd && (NF < 9 || $1=="pkts"){ next } + +fid==3 && rrd { # iptables input + if($6 != "*"){ + m=$6 + n=m "/out" + } else if($7 != "*"){ + m=$7 + n=m "/in" + } else if($8 != "0.0.0.0/0"){ + m=$8 + n=m "/out" + } else { # $9 != "0.0.0.0/0" + m=$9 + n=m "/in" + } + + # remove host from array; any hosts left in array at END get new + # iptables rules + + #!@todo this deletes a host if any rule exists; if only one + # directional rule is removed, this will not remedy the situation + delete hosts[m] + + if($2 > 0){ # counted some bytes + if(mode == "diff" || mode == "noUpdate") + print n, $2 + if(mode!="noUpdate"){ + if(inInterfaces(m)){ # if label is an interface + if(!(m in mac)){ # if label was not in db (also not in + # arp table, but interfaces won't be + # there anyway) + firstDate[m] = date() + mac[m] = inter[m] = m + ip[m] = "NA" + bw[m "/in"]=bw[m "/out"]= 0 + } + } + bw[n]+=$2 + lastDate[m] = date() + } + } +} + +END { + if(mode=="noUpdate") exit + close(dbFile) + system("rm -f " dbFile) + print "#mac,ip,iface,in,out,total,first_date,last_date" > dbFile + OFS="," + for(i in mac) + print mac[i], ip[i], inter[i], bw[i "/in"], bw[i "/out"], total(i), firstDate[i], lastDate[i] > dbFile + close(dbFile) + # for hosts without rules + for(host in hosts) if(!inInterfaces(host)) newRule(host) +} \ No newline at end of file diff --git a/rooter/0optionalapps/ext-autoapn/Makefile b/rooter/0optionalapps/ext-autoapn/Makefile new file mode 100644 index 0000000..ef5fbc4 --- /dev/null +++ b/rooter/0optionalapps/ext-autoapn/Makefile @@ -0,0 +1,33 @@ +#Owned by DairyMan@Whirlpool +# +#Copyright GNU act. +include $(TOPDIR)/rules.mk + +PKG_NAME:=ext-autoapn +PKG_VERSION:=1.000 +PKG_RELEASE:=1 + +PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool +include $(INCLUDE_DIR)/package.mk + +define Package/ext-autoapn + SECTION:=utils + CATEGORY:=ROOter + SUBMENU:=Optional Applications + TITLE:=support for Automatic APN + PKGARCH:=all +endef + +define Package/ext-autoapn/description + Helper scripts to enable Automatic APN +endef + + +define Build/Compile +endef + +define Package/ext-autoapn/install + $(CP) ./files/* $(1)/ +endef + +$(eval $(call BuildPackage,ext-autoapn)) diff --git a/rooter/0optionalapps/ext-autoapn/files/usr/lib/autoapn/apn.data b/rooter/0optionalapps/ext-autoapn/files/usr/lib/autoapn/apn.data new file mode 100644 index 0000000..88afe61 --- /dev/null +++ b/rooter/0optionalapps/ext-autoapn/files/usr/lib/autoapn/apn.data @@ -0,0 +1,2198 @@ +00101,phone,AT&TPHONETESTSIM,nil,1,nil,nil +001010,VZWINTERNET,TestInternet,nil,1,nil,nil +20201,internet,CosmoteWirelessInternet,nil,1,nil,nil +20205,internet.vodafone.gr,VfMobileInternet,nil,1,nil,nil +20209,myq,QInternet,nil,1,nil,nil +20210,gint.b-online.gr,WindInternet,nil,1,nil,nil +20402,internet.tele2.nl,Tele2GPRS,nil,1,nil,nil +20403,internet.mvno.mobi,MVNONL,mvno,1,mvno,1 +20404,mobiledata,JumpRoam,nil,1,nil,0 +20404,iot.truphone.com,Truphone,nil,1,nil,nil +20404,live.vodafone.com,VodafoneNL,vodafone,1,vodafone,1 +20404,VZWINTERNET,EHRPD-VZWRoamingInternet,nil,3,nil,nil +20408,iot.truphone.com,Truphone,nil,1,nil,nil +20404,internet.cs4glte.com,CSpireinternational,cs3g,1,Uniroam@inet.cs.com,3 +20404,admin.cs4glte.com,CSpireinternational,nil,1,nil,nil +20404,tethering.cs4glte.com,CSpireinternational,nil,1,nil,nil +20408,KPN4G.nl,KPN/Hi4GLTEMobielinternet,nil,1,nil,nil +20408,portalmmm.nl,KPN/HiMobielInternet,nil,1,nil,nil +20408,internet.mvno.mobi,MVNONL,mvno,1,mvno,1 +20408,rabo,RaboMobielInt.,nil,1,nil,nil +20404,net.hotm,HOTmobileInternet,nil,1,nil,nil +20412,internet,TelfortInternet,nil,1,nil,nil +20416,internet,T-MobileInternet,nil,1,nil,1 +20416,internet.ben,BenInternetAbonnee,nil,1,nil,nil +20416,basic.internet.ben.data,BenInternetPrePaid,nil,1,nil,nil +20420,internet,T-MobileInternet,nil,1,nil,1 +20433,iot.truphone.com,Truphone,nil,1,nil,nil +20601,INTERNET.PROXIMUS.BE,PxInternet,nil,1,nil,nil +20601,telenetwap.be,TelenetInternet,nil,1,nil,nil +20601,iijmio.jp,IIJmio(TypeI/Roaming),iij,1,mio@iij,3 +20601,vmobile.jp,vmobile.jp(Roaming),vmobile,1,vmobile@jp,3 +20605,telenetwap.be,TelenetInternet,nil,1,nil,nil +20610,mworld.be,MobistarInternet,nil,1,nil,nil +20610,netgprs.com,netgprs.com,tsl,1,tsl,nil +20620,gprs.base.be,BASEWAP,base,1,base,1 +20628,bicsapn,BICSInternet,nil,1,nil,nil +20801,orange,OrangeWorld,orange,1,orange,1 +20801,orange-mib,OrangeEntreprise,orange,1,orange,2 +20801,orange.fr,OrangeInternet,orange,1,orange,0 +20801,ofnew.fr,CarrefourWAP,orange,1,orange,1 +20801,coriolis,Coriolis,nil,1,nil,nil +20809,sl2sfr,SFRwebphone,nil,1,nil,nil +20809,websfr,SFRoptionmodem,nil,1,nil,nil +20809,pda.newcomobile.com,BeAliv,nil,1,nil,nil +20809,iot.truphone.com,Truphone,nil,1,nil,nil +20809,coriolis,Coriolis,nil,1,nil,nil +20810,sl2sfr,SFRwebphone,nil,1,nil,nil +20810,websfr,SFRoptionModem,nil,1,nil,0 +20810,fnetnrj,NRJWEB,nil,1,nil,nil +20810,internetnrj,INTERNETNRJ,nil,1,nil,0 +20810,wap65,AuchanWAP,nil,1,nil,nil +20810,wap66,WAPLeclercMobile,nil,1,nil,nil +20810,fnetcoriolis,CoriolisWAP,nil,1,nil,nil +20810,internetcoriolis,CoriolisWEB,nil,1,nil,0 +20810,wapdebitel,WEBLaPosteMobile,nil,1,nil,nil +20810,wap68,DartySurf&Mails,nil,1,nil,nil +20810,internet68,KeyyoMobileInternet,nil,1,nil,0 +20810,wap68,KeyyoMobileWap,nil,1,nil,0 +20810,wap66,WAPRegloMobile,nil,1,nil,0 +20812,iot.truphone.com,Truphone,nil,1,nil,nil +20815,free,Free,nil,1,nil,nil +20815,free.re,FreeReInt,nil,1,nil,nil +20815,iliad,IliadInt,nil,1,nil,nil +20817,bornsip,Legos,nil,1,nil,nil +20820,mmsbouygtel.com,BouyguesTelecom,nil,1,nil,nil +20822,mobiledata,mobiledata,nil,1,nil,nil +20822,netgprs.com,netgprs.com,tsl,1,tsl,nil +20823,virgin-mobile.fr,Virginmobile,nil,1,nil,nil +20826,fnetnrj,NRJWEB,nil,1,nil,nil +20827,coriolis,Coriolis,nil,1,nil,nil +21401,airtelwap.es,Internetmóvil,wap125,1,wap@wap,1 +21401,airtelnet.es,INTERNET,vodafone,1,vodafone,1 +21402,altecom.net,ALTECOM,nil,1,nil,nil +21402,fibracat.cat,FIBRACAT,nil,1,nil,nil +21403,orangeworld,OrangeInternetMóvil,orange,1,orange,1 +21403,internet,OrangeInternetPC,orange,1,orange,0 +21403,internet.euskaltel.mobi,EuskaltelInternet,EUSKALTEL,1,CLIENTE,1 +21403,CARREFOURINTERNET,Carrefour,nil,1,nil,1 +21403,internettph,HappyInternet,nil,1,nil,nil +21403,internet.racc.net,RACCINTERNET,RACC,1,CLIENTERACC,nil +21403,internetmas,MASMovilInternet,nil,1,nil,nil +21403,ibercominternet,IbercomInternet,nil,1,nil,nil +21403,jazzinternet,jazzinternet,nil,1,nil,nil +21404,internet,YoigoInternet,nil,1,nil,nil +21405,tuenti.com,Tuenti,tuenti,1,tuenti,1 +21405,inet.es,INETRoaming,nil,1,nil,nil +21406,airtelnet.es,INTERNETGPRS,vodafone,1,vodafone,nil +21406,internet.euskaltel.mobi,EuskaltelInternet,EUSKALTEL,1,CLIENTE,1 +21406,internet.mundo-r.com,InternetR,nil,1,nil,1 +21406,internet.telecable.es,TeleCableInternet,telecable,1,telecable,1 +21406,gprs.eroskimovil.es,EroskiMovilGPRS,wap125,1,wap@wap,1 +21406,gprs.pepephone.com,DUN,nil,1,nil,0 +21406,gprsmov.pepephone.com,Internet,nil,1,nil,0 +21407,telefonica.es,Movistar,telefonica,1,telefonica,1 +21407,jazzinternet,JazztelInternet,nil,1,nil,nil +21407,movistar.es,Conexióompartida,MOVISTAR,1,MOVISTAR,1 +21407,internet.t-2.net,T-2,nil,1,nil,nil +21408,internet.euskaltel.mobi,EuskaltelInternet,EUSKALTEL,1,CLIENTE,1 +21416,internet.telecable.es,TeleCableInternet,telecable,1,telecable,nil +21418,internet.ono.com,ONOInternet,nil,1,nil,nil +21419,orangeworld,internetsimyo,orange,1,orange,1 +21421,jazzinternet,jazzinternet,nil,1,nil,nil +21427,iot.truphone.com,Truphone,nil,1,nil,nil +21432,tuenti.com,Tuenti,tuenti,1,tuenti,3 +21434,inet.es,INETInternet,nil,1,nil,nil +21601,online,TelenorOnline,nil,1,nil,nil +21601,net,DjuiceNET,nil,1,nil,0 +21601,wap,DjuiceWAP,nil,1,nil,0 +21630,internet.telekom,T-MobileH,nil,1,nil,1 +21670,internet.vodafone.net,VodafoneInternet,nil,1,nil,0 +21670,wap.vodafone.net,VodafoneLive!,vodawap,1,vodawap,1 +21670,vitamax.internet.vodafone.net,VodafoneInternetVitaMAX,nil,1,nil,nil +21670,vitamax.wap.vodafone.net,VodafoneLive!VitaMAX,vodawap,1,vodawap,1 +21803,wap.eronet.ba,HTEronetWAP,nil,1,nil,nil +21803,gprs.eronet.ba,HTEronetGPRS,nil,1,nil,nil +21805,3g1,m,nil,1,nil,nil +21890,active.bhmobile.ba,BHMobileInternet,nil,1,nil,nil +21901,internet.ht.hr,T-MobileInternet,nil,1,nil,1 +21901,web.htgprs,bonbonInternet,nil,1,nil,1 +21902,internet.tele2.hr,Tele2,nil,1,nil,nil +21910,data.vip.hr,Broadband,38591,1,38591,1 +22001,internet,Telenorinternet,gprs,1,telenor,1 +22002,internet,TelenorMNEinternet,gprs,1,gprs,nil +22003,gprswap,mt,064,1,mts,1 +22003,gprsinternet,MTSInternetRS,064,1,mts,0 +22004,tmcg-wnw,T-MobileInternet,38267,1,38267,nil +20404,pda.stm.sk.ca,SaskTel,nil,1,nil,nil +20465,agms,agms,nil,1,nil,nil +22005,vipmobile,VipGPRS,vipmobile,1,vipmobile,1 +22201,wap.tim.it,TIMWAP,nil,1,nil,nil +22201,ibox.tim.it,TIMDUN(IT),nil,1,nil,0 +22201,internet.windmobile.ca,Internet,nil,1,nil,nil +22201,modem.iusacellgsm.mx,Modem,iusacellgsm,1,iusacellgsm,0 +22201,web.iusacellgsm.mx,Internet,iusacellgsm,1,iusacellgsm,0 +22201,web.noverca.it,NOVERCAWEB,nil,1,nil,0 +22210,mobile.vodafone.it,Acc.Internetdacell,nil,1,nil,nil +22210,web.omnitel.it,TetheringInternet,nil,1,nil,0 +22210,wap.postemobile.it,PosteMobile,nil,1,nil,0 +22210,internet.postemobile.it,PosteMobile(DUN),nil,1,nil,0 +22210,mobile.erg.it,ErgMobileWAP,nil,1,nil,0 +22250,iliad,Iliad,nil,1,nil,nil +22254,data.plintron.it,Plintron,nil,1,nil,1 +22288,internet.wind,WINDWEB,nil,1,nil,nil +22288,internet.windmobile.ca,Internet,nil,1,nil,nil +22299,tre.it,3,nil,1,nil,nil +22299,apn.fastweb.it,FastwebWEB,nil,1,nil,nil +22601,live.vodafone.com,Vodafonelive!,vodafone,1,live,1 +22601,live.pre.vodafone.com,Vodafonelive!PRE,vodafone,1,live,0 +22603,broadband,CosmoteConnectMobile,nil,1,nil,nil +22603,wnw,web'n'walk,wnw,1,wnw,1 +22605,internet,Digi.Mobil,nil,1,nil,1 +22606,broadband,CosmoteConnectMobile,nil,1,nil,nil +22606,wnw,web'n'walk,wnw,1,wnw,nil +22610,net,OrangeInternet,nil,1,nil,nil +22801,gprs.swisscom.ch,SwisscomServices,nil,1,nil,nil +22802,internet,Sunriselive,nil,1,nil,nil +22803,internet,OrangeInternet,nil,1,nil,nil +22803,netgprs.com,netgprs.com,tsl,1,tsl,nil +23001,internet.t-mobile.cz,T-MobileCZ,wap,1,wap,1 +23002,internet,O2internet,nil,1,nil,nil +23003,internet,Internet,nil,1,nil,nil +23101,internet,OrangeSK,nil,1,nil,nil +23101,orangewap,OrangeWorld,wap,1,wap,1 +23102,internet,T-Mobileinternet,nil,1,nil,1 +23106,o2internet,O2internet,nil,1,nil,nil +23201,a1.net,live!,ppp,1,ppp@a1plus.at,1 +23203,internet.t-mobile.at,T-MobileLTE,tm,1,t-mobile,1 +23205,drei.at,Planet3,nil,1,nil,nil +23207,web,tele.ringweb,web,1,web@telering.at,1 +23210,drei.at,Planet3,nil,1,nil,nil +23211,bob.at,data.bob,ppp,1,data@bob.at,1 +23212,web.yesss.at,yesss!,nil,1,nil,nil +23222,data.plintron.at,Plintron,nil,1,nil,1 +23401,internet,UBIQUISYS,nil,1,nil,nil +23402,mobile.o2.co.uk,O2MOBILEWEB,O2web,1,O2web,nil +23408,internet.btonephone.com,BTOnePhoneInternet,nil,1,nil,nil +23410,mobile.o2.co.uk,O2MobileWeb,password,1,o2web,nil +23410,payandgo.o2.co.uk,O2Pay&Go,password,1,payandgo,nil +23410,prepay.tesco-mobile.com,TESCO,password,1,tescowap,1 +23410,giffgaff.com,giffgaff,password,1,giffgaff,1 +23410,mobiledata,JumpUK,nil,1,nil,0 +23411,mobile.o2.co.uk,O2MOBILEWEB,O2web,1,O2web,nil +23415,wap.vodafone.co.uk,VodafoneUK,wap,1,wap,1 +23415,pp.vodafone.co.uk,VodafoneUKPrepay,wap,1,wap,1 +23415,asdamobiles.co.uk,ASDAWAP,wap,1,wap,1 +23415,payg.talkmobile.co.uk,TalkmobPAYGWAP,wap,1,wap,1 +23415,talkmobile.co.uk,TalkmobWAP,wap,1,wap,1 +23415,mobile.talktalk.co.uk,TalkTalkWAP,nil,1,nil,nil +23415,payg.mobilebysainsburys.co.uk,Sainsbury'sPAYG,nil,1,nil,1 +23415,uk.lebara.mobi,LebaraInternet,wap,1,wap,1 +23420,three.co.uk,3,nil,1,nil,nil +23420,3hotspot,3Hotspot,nil,1,nil,0 +23426,data.lycamobile.co.uk,Lycamobile,plus,1,lmuk,1 +23430,goto.virginmobile.uk,VirginMediaMobileInternet,nil,1,user,1 +23430,everywhere,EEInternet,secure,1,eesecure,1 +23430,internet.btonephone.com,BTOnePhoneInternet,nil,1,nil,nil +23433,tslpaygnet,Internet,nil,1,nil,0 +23433,everywhere,EEInternet,secure,1,eesecure,1 +23425,iot.truphone.com,Truphone,nil,1,nil,nil +23439,Jump,Jump,nil,1,nil,nil +23439,gamma.co.uk,GammaData,nil,1,nil,nil +23450,pepper,pepperWEB(Jersey),nil,1,nil,nil +23455,internet,C&WGuernseyInternet,nil,1,nil,nil +23458,3gpronto,3GHSDPA,nil,1,nil,nil +23458,web.manxpronto.net,ManxTelecomContractWEB,gprs,1,gprs,nil +23486,everywhere,EEInternet,secure,1,eesecure,1 +23594,3hotspot,3hotspot,nil,1,nil,0 +23594,three.co.uk,3,nil,1,nil,nil +23801,internet,DKTDC,nil,1,nil,0 +23801,internet,TDCInternet,nil,1,nil,nil +23801,wap,TELMOREWAP,nil,1,nil,0 +23802,Internet,TelenorInternet,nil,1,nil,nil +23806,data.tre.dk,3,nil,1,nil,nil +23820,www.internet.mtelia.dk,TeliaSurfPort,nil,1,nil,nil +23820,webSP,CallmeInternet,nil,1,nil,nil +23830,web.orange.dk,OrangeDE,nil,1,nil,nil +23877,Internet,TelenorInternet,nil,1,nil,nil +24001,online.telia.se,Telia,nil,1,nil,nil +24001,halebop.telia.se,HalebopInternet,nil,1,nil,nil +24002,data.tre.se,3,nil,1,nil,nil +24004,data.tre.se,3,nil,1,nil,nil +24005,4g.tele2.se,Tele2Internet,nil,1,nil,nil +24005,internet.tele2.se,Tele2Internet3G,nil,1,nil,nil +24005,online.telia.se,Telia,nil,1,nil,nil +24005,halebop.telia.se,HalebopInternet,nil,1,nil,nil +24006,internet,Internet,nil,1,nil,nil +24007,4g.tele2.se,Tele2Internet,nil,1,nil,nil +24007,internet.tele2.se,Tele2Internet3G,nil,1,nil,nil +24007,internet.tele2.no,Tele2Internet,wap,1,wap,1 +24007,Jump,Jump,nil,1,nil,nil +24007,gamma.co.uk,GammaData,nil,1,nil,nil +24008,internet.telenor.se,TelenorSE,nil,1,nil,nil +24009,com4,Com4,nil,1,nil,nil +24010,data.springmobil.se,Springdata,nil,1,nil,nil +240017,halebop.telia.se,HalebopInternet,nil,1,nil,nil +24024,4g.tele2.se,Tele2Internet,nil,1,nil,nil +24024,internet.tele2.se,Tele2Internet3G,nil,1,nil,nil +24201,internet.ventelo.no,VenteloInternett,nil,1,nil,nil +24201,telenor,Telenor,nil,1,nil,nil +24202,netcom,NetCom,nil,1,nil,nil +24204,internet.tele2.no,Tele2Internet,nil,1,nil,nil +24205,internet,NwNInternet,nil,1,nil,nil +24209,com4,Com4,nil,1,nil,nil +24403,internet,DNAInternet,nil,1,nil,nil +24404,internet,DNAInternet,nil,1,nil,nil +24405,internet,ElisaInternet,nil,1,nil,nil +24405,internet.saunalahti,SaunalahtiInternet,nil,1,nil,nil +24410,internet.song.fi,TDCInternet,songnet,1,song@internet,nil +24412,internet,DNAInternet,nil,1,nil,nil +24412,dnapro.fi,DNAProInternet,nil,1,nil,1 +24412,inet.tdc.fi,TDCInternetFinland,nil,1,nil,1 +24413,internet,DNAInternet,nil,1,nil,nil +24421,internet.saunalahti,SaunalahtiInternet,nil,1,nil,nil +24491,internet,SONERAInternet,nil,1,nil,nil +24601,omnitel,OmnitelInternet,omni,1,omni,1 +24602,wap,BiteInternet,nil,1,nil,nil +24608,mezon,Mezon,nil,1,nil,nil +24603,internet.tele2.lt,Tele2InternetLT,nil,1,nil,nil +246081,VZW800,Test800,nil,3,nil,nil +246081,VZWINTERNET,TestInternet,nil,3,nil,3 +246081,VZWINTERNET,TestInternet,nil,3,nil,nil +24681,VZW800,Test800,nil,3,nil,nil +24681,VZWINTERNET,TestInternet,nil,3,nil,3 +24681,VZWINTERNET,TestInternet,nil,3,nil,nil +24701,internet.lmt.lv,LMTInternet,nil,1,nil,nil +24702,internet.tele2.lv,Tele2LVInternet,nil,1,nil,nil +24705,internet,BiteLVInternet,nil,1,nil,nil +24705,wap,BiteLVWAP,nil,1,nil,nil +24801,internet.emt.ee,EMTInternet,nil,1,nil,nil +24801,wap.emt.ee,EMTWAP,nil,1,nil,nil +24801,send.ee,Send,nil,1,nil,nil +24802,internet,ElisaInternet,nil,1,nil,nil +24802,wap,ElisaWAP,nil,1,nil,nil +24803,internet.tele2.ee,Tele2Internet,nil,1,nil,nil +25001,internet.mts.ru,MTSInternet,mts,1,mts,1 +25002,internet,MegafonInternet,nil,1,nil,nil +25011,yota.ru,YOTAInternet,nil,1,nil,nil +25020,internet.tele2.ru,TELE2Internet,nil,1,nil,nil +25028,vodalte.ru,VODAinternet,nil,1,nil,nil +25062,m.tinkoff,TinkoffMobile,nil,1,nil,nil +25099,internet.beeline.ru,BeelineInternet,beeline,1,beeline,1 +25501,internet,MTS-internet,nil,1,nil,nil +25502,internet.beeline.ua,Beeline-internet,nil,1,nil,nil +25503,www.kyivstar.net,KyivstarInternet,internet,1,igprs,1 +25503,www.djuice.com.ua,DjuiceInternet,nil,1,nil,nil +25506,internet,Life,nil,1,nil,nil +25507,3g.utel.ua,UtelInternet,nil,1,nil,nil +25701,web.velcom.by,VelcomInternet,nil,1,nil,1 +25702,mts,MTSInternet,mts,1,mts,1 +25704,internet.life.com.by,life,nil,1,nil,1 +25901,wap.orange.md,Orange_Internet_GPRS,nil,1,nil,nil +25902,internet,MoldcellInternet,nil,1,nil,nil +25905,internet3g.unite.md,UniteInternetPrePay,nil,1,nil,nil +25905,internet.unite.md,UniteInternetPostPay,nil,1,nil,nil +26001,plus,PlusInternet,nil,1,nil,nil +26002,internet,T-mobile.pl,nil,1,nil,nil +26002,heyah.pl,heyahinternet,nil,1,nil,nil +26003,Internet,OrangeInternet,internet,1,internet,1 +26006,internet,PlayInternet,nil,1,nil,nil +26033,iot.truphone.com,Truphone,nil,1,nil,nil +26044,rebtel,Rebtel,nil,1,nil,nil +26201,internet.telekom,TelekomInternet,telekom,1,telekom,1 +26202,web.vodafone.de,VodafoneDE,nil,1,nil,nil +26202,home.vodafone.de,VodafoneDE,nil,1,nil,nil +26203,internet.eplus.de,E-PlusInternet,internet,1,eplus,1 +26207,internet,o2Internet,nil,1,nil,nil +26207,pinternet.interkom.de,o2InternetPrepaid,nil,1,nil,nil +26207,webmobil1,TchiboInternet,nil,1,nil,nil +26242,iot.truphone.com,Truphone,nil,1,nil,nil +26801,net2.vodafone.pt,VodafoneNet2,vodafone,1,vodafone,1 +26801,internet.vodafone.pt,vodafonePdun,nil,1,nil,0 +26803,umts,PortalOptimus,nil,1,nil,nil +26803,modem,OptimusHotSpot,nil,1,nil,nil +26806,internet,tmninternet,nil,1,nil,nil +27001,wap.pt.lu,LUXGSMWAP,wap,1,wap,nil +27002,internet,MTXC,nil,1,nil,nil +27077,internet,TangoWAP,tango,1,tango,nil +27077,netgprs.com,netgprs.com,tsl,1,tsl,nil +27099,orange.lu,Orange,nil,1,nil,nil +27201,live.vodafone.com,VodafoneIE,nil,1,nil,nil +27201,hs.vodafone.ie,VodafoneMISP,vodafone,1,vodafone,0 +27202,3iot.com,3Ireland,nil,1,nil,nil +27202,internet,3Ireland,nil,1,nil,0 +27203,data.mymeteor.ie,MeteorData,wap,1,my,1 +27205,3ireland.ie,3Ireland,nil,1,nil,nil +27211,tescomobile.liffeytelecom.com,Tesco,nil,1,nil,nil +27401,internet,SiminnInternet,nil,1,nil,nil +27402,gprs.is,VodafoneInternet,nil,1,nil,nil +27403,gprs.is,VodafoneInternet,nil,1,nil,0 +27411,net.nova.is,NetNova,nil,1,nil,nil +27801,internet,VodafoneMT,internet,1,internet,nil +28001,cytamobile,CYTA,nil,1,nil,nil +28010,internet,MTNInternet,nil,1,nil,nil +28020,ip.primetel,PrimeTel,nil,1,nil,nil +28401,inet-gprs.mtel.bg,MTel,nil,1,nil,nil +28403,internet.vivacom.bg,VIVACOMInternet,vivacom,1,vivacom,1 +28405,telenorbg,TelenorInternet,nil,1,nil,0 +28411,bulsat.com,bulsatcom,nil,1,nil,nil +28413,apn.maxtelecom.bg,MAXTELECOM,nil,1,nil,nil +28601,internet,TURKCELLINTERNET,nil,1,nil,nil +28602,internet,Vodafoneinternet,nil,1,nil,1 +28603,internet,AVEAINTERNET,nil,1,nil,1 +29001,internet,TeleInternet,nil,1,nil,nil +29340,internet.simobil.si,Si.mobilGPRS,internet,1,simobil,1 +29341,internet,MobilniInternet,internet,1,mobitel,1 +29364,internet.t-2.net,T2,nil,1,nil,nil +29370,internet.tusmobil.si,TusmobilInternet,internet,1,tusmobil,1 +29370,telemach.net,TelemachInternet,nil,1,nil,nil +29401,internet,T-MobileMKInternet,t-mobile,1,internet,nil +29402,Internet,Cosmofon,Internet,1,Internet,nil +29403,vipoperator,Internet,vipoperator,1,vipoperator,nil +29505,em,EMnify,nil,1,nil,nil +29509,em,EMnify,nil,1,nil,nil +29509,bicsapn,BICS,nil,1,nil,nil +29702,tmcg-wnw,T-MobileInternet,38267,1,38267,nil +302220,sp.telus.com,TELUS,nil,1,nil,nil +302220,isp.telus.com,TELUSTether,nil,1,nil,nil +302220,sp.koodo.com,Koodo,nil,1,nil,nil +302220,sp.mb.com,MobileInternet,nil,1,nil,nil +302220,isp.mb.com,TetheredMobileInternet,nil,1,nil,nil +302221,isp.telus.com,TELUSISP,nil,1,nil,nil +302221,sp.koodo.com,Koodo,nil,1,nil,nil +302221,isp.mb.com,TetheredPCMobile,nil,1,nil,nil +302320,wap.davewireless.com,MOWAP,nil,1,nil,nil +302270,wisp.mobi.eastlink.ca,Internet,nil,1,nil,nil +302370,ltedata.apn,FidoTethering,nil,1,nil,nil +302370,ltemobile.apn,FidoInternet,nil,1,nil,nil +302370,sp.mts,MTS,nil,1,nil,nil +302370,internet.mts,MTSTetheringS,nil,1,nil,nil +302490,internet.windmobile.ca,Internet,nil,1,nil,nil +302500,media.ng,Media,nil,1,nil,nil +302510,media.ng,Media,nil,1,nil,nil +302520,media.ng,Media,nil,1,nil,nil +302610,pda.bell.ca,BellMobility,nil,1,nil,nil +302610,ota.bell.ca,BellMobility,nil,1,nil,nil +302660,sp.mts,MTS,nil,1,nil,nil +302660,internet.mts,MTSTethering,nil,1,nil,nil +302720,ltemobile.apn,RogersLTE,nil,1,nil,nil +302720,chatrweb.apn,chatr,nil,1,nil,nil +302720,chatrisp.apn,ChatrTethering,nil,1,nil,nil +302720,ltedata.apn,TbaytelTethering,nil,1,nil,nil +302780,pda.stm.sk.ca,SaskTel,nil,1,nil,nil +310000,VZWINTERNET,Bluewire,nil,3,nil,nil +310020,union.wap.com,UnionWirelessData,nil,1,nil,nil +310004,internet,Verizon,nil,3,nil,3 +310028,VZWINTERNET,ALUTest-SIMInternet,nil,3,nil,nil +310030,private.centennialwireless.com,Internet,priv,1,privuser,nil +310032,VZWINTERNET,Itewire,nil,3,nil,nil +310035,VZWINTERNET,Etex,nil,3,nil,nil +310040,VZWINTERNET,Mta,nil,3,nil,nil +310050,VZWINTERNET,Alaskacomm,nil,3,nil,nil +310066,internet,U.S.Cellular,*,1,*,nil +310080,corrgprs,CorrWap,nil,1,nil,nil +310090,isp,Internet,nil,1,nil,nil +310100,isp.plateau,PLATWEB,nil,1,nil,nil +310120,sprint,Sprint,nil,1,nil,nil +310120,otasn,OTA,nil,1,nil,nil +310120,cinet.spcs,SPCSGlobal,nil,1,nil,nil +310130,VZWINTERNET,Carolinawest,nil,3,nil,nil +310150,ndo,internet,nil,1,nil,nil +310160,fast.t-mobile.com,T-MobileUS160,nil,1,nil,nil +310160,pcweb.tmobile.com,T-MobileUS160DUN,none,1,none,nil +310160,fast.metropcs.com,MetroPCS160,nil,1,nil,nil +310170,isp.cingular,DataConnect,nil,1,nil,nil +310180,internet.wcc.net,WCW-INTERNET,mmsc,1,13257630000,nil +310200,fast.t-mobile.com,T-MobileUS200,nil,1,nil,nil +310200,pcweb.tmobile.com,T-MobileUS200DUN,none,1,none,nil +310200,fast.metropcs.com,MetroPCS200,nil,1,nil,nil +310210,fast.t-mobile.com,T-MobileUS210,nil,1,nil,nil +310210,pcweb.tmobile.com,T-MobileUS210DUN,none,1,none,nil +310210,fast.metropcs.com,MetroPCS210,nil,1,nil,nil +310220,fast.t-mobile.com,T-MobileUS220,nil,1,nil,nil +310220,pcweb.tmobile.com,T-MobileUS220DUN,none,1,none,nil +310220,fast.metropcs.com,MetroPCS220,nil,1,nil,nil +310230,fast.t-mobile.com,T-MobileUS230,nil,1,nil,nil +310230,pcweb.tmobile.com,T-MobileUS230DUN,none,1,none,nil +310230,fast.metropcs.com,MetroPCS230,nil,1,nil,nil +310240,fast.t-mobile.com,T-MobileUS240,nil,1,nil,nil +310240,pcweb.tmobile.com,T-MobileUS240DUN,none,1,none,nil +310240,fast.metropcs.com,MetroPCS240,nil,1,nil,nil +310250,fast.t-mobile.com,T-MobileUS250,nil,1,nil,nil +310250,pcweb.tmobile.com,T-MobileUS250DUN,none,1,none,nil +310250,fast.metropcs.com,MetroPCS250,nil,1,nil,nil +310260,fast.t-mobile.com,T-MobileGPRS,nil,1,nil,nil +310260,h2g2,ProjectFi-T,none,1,none,nil +310260,fast.metropcs.com,MetroPCS260,nil,1,nil,nil +310260,simple,SIMPLE,nil,1,nil,nil +310260,wap.tracfone,TFWAP,nil,1,nil,nil +310260,wholesale,ConsumerCellular,nil,1,nil,nil +310270,fast.t-mobile.com,T-MobileUS270,nil,1,nil,nil +310270,pcweb.tmobile.com,T-MobileUS270DUN,none,1,none,nil +310270,fast.metropcs.com,MetroPCS270,nil,1,nil,nil +310280,agms,agms,nil,1,nil,nil +310300,fast.t-mobile.com,T-MobileUS300,nil,1,nil,nil +310300,pcweb.tmobile.com,T-MobileUS300DUN,none,1,none,nil +310300,fast.metropcs.com,MetroPCS300,nil,1,nil,nil +310310,fast.t-mobile.com,T-MobileUS310,nil,1,nil,nil +310310,pcweb.tmobile.com,T-MobileUS310DUN,none,1,none,nil +310310,fast.metropcs.com,MetroPCS310,nil,1,nil,nil +310320,isp.cellularoneaz.net,CellularOneNEAZISP,nil,1,nil,nil +310330,VZWINTERNET,Alltel2,nil,3,nil,nil +310360,VZWINTERNET,Pioneer,nil,3,nil,nil +310380,proxy,Cingular380ATT,nil,1,nil,nil +310380,agms.nl.gmm,AGMSGlobal,nil,1,nil,nil +310410,broadband,ATTNextgenphone,nil,1,nil,nil +310410,phone,ATTPhone,nil,1,nil,nil +310410,wap.cingular,ATTWAP,nil,1,nil,nil +310410,PRODATA,DefenseMobile,nil,1,nil,nil +310410,tfdata,TFDATA,nil,1,nil,nil +310420,wap.gocbw.com,CBWData,nil,1,nil,nil +310430,VZWINTERNET,Gci,nil,3,nil,nil +310450,internet.vedge.com,ViaeroConnect,nil,1,nil,nil +310470,isp.cingular,DataConnect,nil,1,nil,nil +310470,wap.cingular,MediaNet,CINGULAR1,1,WAP@CINGULARGPRS.COM,nil +310470,admin.4g.ntelos.com,nTelosOta,nil,1,nil,nil +310470,internet.4g.ntelos.com,nTelosWireless,nil,1,nil,nil +310470,tethering.4g.ntelos.com,nTelosTether,nil,1,nil,nil +310480,isp.cingular,DataConnect,nil,1,nil,nil +310480,wap.cingular,MediaNet,CINGULAR1,1,WAP@CINGULARGPRS.COM,nil +310490,fast.t-mobile.com,T-MobileUS490,nil,1,nil,nil +310490,pcweb.tmobile.com,T-MobileUS490DUN,none,1,none,nil +310490,fast.metropcs.com,MetroPCS490,nil,1,nil,nil +310530,fast.t-mobile.com,T-MobileUS530,nil,1,nil,nil +310530,pcweb.tmobile.com,T-MobileUS530DUN,none,1,none,nil +310530,fast.metropcs.com,MetroPCS530,nil,1,nil,nil +310560,nxtgenphone,ATTNextgenphone,nil,1,nil,nil +310570,internet,CellularOneSmartphone,nil,1,nil,nil +310580,VZWINTERNET,Inland,nil,3,nil,nil +310590,fast.t-mobile.com,T-MobileUS590,nil,1,nil,nil +310590,pcweb.tmobile.com,T-MobileUS590DUN,none,1,none,nil +310590,fast.metropcs.com,MetroPCS590,nil,1,nil,nil +310600,VZWINTERNET,Cellcom,nil,3,nil,nil +310610,internet.epictouch,EpicINT,nil,1,nil,nil +310640,fast.t-mobile.com,T-MobileUS640,nil,1,nil,nil +310640,pcweb.tmobile.com,T-MobileUS640DUN,none,1,none,nil +310640,fast.metropcs.com,MetroPCS640,nil,1,nil,nil +310660,fast.t-mobile.com,T-MobileUS660,nil,1,nil,nil +310660,pcweb.tmobile.com,T-MobileUS660DUN,none,1,none,nil +310660,fast.metropcs.com,MetroPCS660,nil,1,nil,nil +31069,iot.truphone.com,Truphone,nil,1,nil,nil +310720,internet.com,RogersInternet,nil,1,nil,nil +310750,VZWINTERNET,Appalachian,nil,3,nil,nil +310770,i2.iwireless.com,Web2,nil,1,nil,nil +310770,wap1.iwireless.com,Web1,nil,1,nil,nil +310800,fast.t-mobile.com,T-MobileUS800,nil,1,nil,nil +310800,pcweb.tmobile.com,T-MobileUS800DUN,none,1,none,nil +310800,fast.metropcs.com,MetroPCS800,nil,1,nil,nil +310840,isp,Internet,nil,1,nil,nil +310880,wapdtcw.com,DTCdtcwap,nil,1,nil,nil +310900,VZWINTERNET,Midrivers,nil,3,nil,nil +310910,wap.firstcellular.com,WOW_WAP,nil,1,nil,nil +310920,VZWINTERNET,Jamesvalley,nil,3,nil,nil +310930,VZWINTERNET,CopperValley,nil,3,nil,nil +310960,VZWINTERNET,Nntcwire,nil,3,nil,nil +311050,VZWINTERNET,Thumbcellular,nil,3,nil,nil +311070,VZWINTERNET,Elementmobile,nil,3,nil,nil +311080,PINE,PINEWAP,nil,1,nil,nil +311140,VZWINTERNET,Sprocket,nil,3,nil,nil +311190,isp.cellular1.net,ISP,nil,1,nil,nil +311190,broadband.cellular1.net,Tether,nil,1,nil,nil +311210,internet.farmerswireless.com,FarmersGPRS,nil,1,nil,nil +311220,usccinternet,U.S.Cellular,nil,1,nil,nil +311221,usccinternet,U.S.Cellular,nil,1,nil,nil +311222,usccinternet,U.S.Cellular,nil,1,nil,nil +311223,usccinternet,U.S.Cellular,nil,1,nil,nil +311224,usccinternet,U.S.Cellular,nil,1,nil,nil +311225,usccinternet,U.S.Cellular,nil,1,nil,nil +311226,usccinternet,U.S.Cellular,nil,1,nil,nil +311227,usccinternet,U.S.Cellular,nil,1,nil,nil +311228,usccinternet,U.S.Cellular,nil,1,nil,nil +311229,usccinternet,U.S.Cellular,nil,1,nil,nil +311230,admin.cs4glte.com,CSpireota,nil,1,nil,nil +311230,internet.cs4glte.com,CSpireinternet,nil,1,nil,nil +311230,tethering.cs4glte.com,CSpiretether,nil,1,nil,nil +311310,VZWINTERNET,Leaco,nil,3,nil,nil +311340,VZWINTERNET,Illinoisvalley,nil,3,nil,nil +311350,VZWINTERNET,Nemont,nil,3,nil,nil +311370,web.gci,GCIWEB,nil,1,nil,nil +311370,web.acs,ACSWEB,nil,1,nil,nil +311410,VZWINTERNET,Chatmobrsa2,nil,3,nil,nil +311420,VZWINTERNET,Northwestcell,nil,3,nil,nil +311430,VZWINTERNET,Chatmobrsa1,nil,3,nil,nil +311440,VZWINTERNET,Bluegrass,nil,3,nil,nil +311450,VZWINTERNET,Ptci,nil,3,nil,nil +311500,wap,24-7WAP,nil,1,nil,nil +311530,mms.mymobiletxt.com,Blaze,nil,1,nil,nil +311530,wap.mymobiletxt.com,DuetInternet,nil,1,nil,nil +311580,usccinternet,U.S.Cellular,nil,1,nil,nil +311581,usccinternet,U.S.Cellular,nil,1,nil,nil +311582,usccinternet,U.S.Cellular,nil,1,nil,nil +311583,usccinternet,U.S.Cellular,nil,1,nil,nil +311584,usccinternet,U.S.Cellular,nil,1,nil,nil +311585,usccinternet,U.S.Cellular,nil,1,nil,nil +311586,usccinternet,U.S.Cellular,nil,1,nil,nil +311587,usccinternet,U.S.Cellular,nil,1,nil,nil +311588,usccinternet,U.S.Cellular,nil,1,nil,nil +311589,usccinternet,U.S.Cellular,nil,1,nil,nil +311600,VZWINTERNET,Cox,nil,3,nil,nil +311610,VZWINTERNET,Srtcomm,nil,3,nil,nil +311650,VZWINTERNET,Unitedwireless,nil,3,nil,nil +311670,VZWINTERNET,Pinebelt,nil,3,nil,nil +311740,akcell.mobi,TelAlaskaCellular,nil,1,nil,nil +311750,CdmaNai,Cleartalk,nil,1,nil,3 +311750,home.netamerica.com,ClearTalkLTE,nil,1,nil,nil +311910,mymn4g.net,MobileNation,nil,1,nil,nil +311920,VZWINTERNET,Charitonvalley,nil,3,nil,nil +311930,internet.syringawireless.com,SyringaWireless,nil,1,nil,nil +312420,admin.lte.ntwls.com,NexTechOta,nil,1,nil,nil +312420,internet.lte.ntwls.com,NexTechWireless,nil,1,nil,nil +312420,modem.lte.ntwls.com,NexTechTether,nil,1,nil,nil +312570,BlueHotspot,BlueWireless,wirelessblue,1,%M@dun.bluehandset.com,nil +330000,VZWINTERNET,Openmobile,nil,3,nil,nil +330110,lte.claropr.com,PuertoRico,nil,1,nil,1 +334020,internet.itelcel.com,Internet,webgprs2002,1,webgprs,1 +33403,internet.movistar.mx,MovistarINTERNET,movistar,1,movistar,1 +334030,internet.movistar.mx,MovistarINTERNET,movistar,1,movistar,1 +334050,web.iusacellgsm.mx,IusacellInternet,iusacellgsm,1,iusacellgsm,nil +33450,modem.iusacellgsm.mx,Modem,iusacellgsm,1,iusacellgsm,1 +334090,location.nexteldata.com.mx,Localización,nil,1,nil,0 +334090,modem.nexteldata.com.mx,Internet,nil,1,nil,0 +334090,wap.nexteldata.com.mx,Navegación,nil,1,nil,0 +33805,web,INTERNETDigicel,nil,1,nil,nil +338050,web,INTERNETDigicel,nil,1,nil,nil +33818,internet,LimeInternetPostpaid,nil,1,nil,nil +33818,ppinternet,LimeInternetPrepaid,nil,1,nil,nil +338180,internet,LimeInternetPostpaid,nil,1,nil,nil +338180,ppinternet,LimeInternetPrepaid,nil,1,nil,nil +338070,internet.ideasclaro.com.jm,ClaroWeb,nil,1,nil,1 +338180,internet,LimeInternetPostpaid,nil,1,nil,1 +34001,orangeweb,OrangeWorldCaraïbe,orange,1,orange,nil +34001,orangeweb,Orangeweb,orange,1,orange,1 +34020,web.digicelfr.com,DigicelWeb,nil,1,nil,nil +34260,internet,LimeInternetPostpaid,nil,1,nil,nil +342600,internet,Barbado,nil,1,nil,1 +34492,internet,LimeInternetPostpaid,nil,1,nil,nil +344920,internet,Antigua,nil,1,nil,1 +34614,internet,LimeInternetPostpaid,nil,1,nil,nil +346140,internet,CaymanIslands,nil,1,nil,1 +34817,internet,LimeInternetPostpaid,nil,1,nil,nil +34877,wap.digicelbvi.com,Bvi,nil,1,nil,1 +34877,wap.digicelbvi.com,Bvi,wapbvi,1,wapbvi,1 +348170,internet,Bvi,nil,1,nil,1 +35211,internet,LimeInternetPostpaid,nil,1,nil,nil +352110,internet,Grenada,nil,1,nil,1 +35486,internet,LimeInternetPostpaid,nil,1,nil,nil +354860,internet,Monserrat,nil,1,nil,1 +35611,internet,LimeInternetPostpaid,nil,1,nil,nil +356110,internet,StKittsAndNevis,nil,1,nil,1 +35811,internet,LimeInternetPostpaid,nil,1,nil,nil +36011,internet,LimeInternetPostpaid,nil,1,nil,nil +358110,internet,StLucia,nil,1,nil,1 +360110,internet,StVincent,nil,1,nil,1 +36269,web.digicelcuracao.com,Curacao,nil,1,nil,1 +36269,wap,Curacao,nil,1,nil,1 +36302,web.digicelaruba.com,INTERNETAruba,nil,1,nil,1 +363020,web.digicelaruba.com,INTERNETAruba,nil,1,nil,1 +36449,pda.newcomobile.com,BeAliv,nil,1,nil,nil +36584,internet,LimeInternetPostpaid,nil,1,nil,nil +365840,internet,Anguilla,nil,1,nil,1 +36611,internet,LimeInternetPostpaid,nil,1,nil,nil +366110,internet,Dominica,nil,1,nil,1 +36801,internet,Internet,nil,1,nil,nil +37001,orangeinternet,OrangeInternet(LTE),nil,1,nil,nil +37001,orangenet.com.do,Orangenet(3G),nil,1,nil,nil +37002,internet.ideasclaro.com.do,InternetMóvilClaro,nil,1,nil,nil +370020,internet.ideasclaro.com.do,InternetMóvilClaro,nil,1,nil,nil +37004,edge.viva.net.do,VivaEdge(GSM),viva,1,viva,1 +37202,wap.digicelha.com,Haiti,nil,1,nil,1 +37202,wap.digicelha.com,Haiti,wap01ha,1,wapha,1 +37203,natcom,NATCOMINTERNET,nil,1,nil,nil +37412,internet,Bmobileinternet,nil,1,nil,1 +374120,internet,Bmobileinternet,nil,1,nil,1 +374121,internet,Bmobileinternet,nil,1,nil,1 +374122,internet,Bmobileinternet,nil,1,nil,1 +374123,internet,Bmobileinternet,nil,1,nil,1 +374124,internet,Bmobileinternet,nil,1,nil,1 +374125,internet,Bmobileinternet,nil,1,nil,1 +374126,internet,Bmobileinternet,nil,1,nil,1 +374127,internet,Bmobileinternet,nil,1,nil,1 +374128,internet,Bmobileinternet,nil,1,nil,1 +374129,internet,Bmobileinternet,nil,1,nil,1 +37413,web.digiceltt.com,INTERNETTrinidad,nil,1,nil,1 +374130,web.digiceltt.com,INTERNETTrinidad,nil,1,nil,1 +37635,internet,LimeInternetPostpaid,nil,1,nil,nil +376350,internet,TurksAndCaicos,nil,1,nil,1 +40001,default,Azercell,nil,1,nil,nil +40002,default,Bakcell,nil,1,nil,nil +40003,default,FONEX,nil,1,nil,nil +40004,default,NarMobile,nil,1,nil,nil +40101,internet.beeline.kz,BeelineInternet,beeline,1,@internet.beeline,1 +40101,internet.dos.kz,DOSInternet,nil,1,nil,nil +40102,internet,KcellInternet,nil,1,nil,nil +40107,internet,ALTELINTERNET,nil,1,nil,nil +40177,internet,Tele2Internet,nil,1,nil,nil +40211,default,B-Mobile,nil,1,nil,nil +40277,ticlnet,TashiCell,nil,1,nil,nil +40401,portalnmms,Vodafonelive,nil,1,nil,nil +40401,www,Vodafonemobileconnect,nil,1,nil,nil +40402,airtelfun.com,AIRTELLIVE,nil,1,nil,nil +40402,airtelgprs.com,MobileOffice,nil,1,nil,nil +40403,airtelgprs.com,MobileOffice,nil,1,nil,nil +40403,airtelfun.com,AIRTELLIVE,nil,1,nil,nil +40404,internet,Idea_Internet,nil,1,nil,nil +40404,imis,IDEAGPRS,nil,1,nil,nil +40405,www,Vodafonemobileconnect,nil,1,nil,nil +40405,portalnmms,Vodafonelive,nil,1,nil,nil +40407,internet,Idea_Internet,nil,1,nil,nil +40407,imis,IDEAGPRS,nil,1,nil,nil +40409,smartnet,RelianceNet,nil,1,nil,nil +40409,smartwap,RelianceWAP,nil,1,nil,1 +40410,airtelgprs.com,MobileOffice,nil,1,nil,nil +40410,airtelfun.com,AIRTELLIVE,nil,1,nil,nil +40411,www,Vodafonemobileconnect,nil,1,nil,nil +40411,portalnmms,Vodafonelive,nil,1,nil,nil +40412,internet,Idea_Internet,nil,1,nil,nil +40412,imis,IDEAGPRS,nil,1,nil,nil +40413,www,Vodafonemobileconnect,nil,1,nil,nil +40413,portalnmms,Vodafonelive,nil,1,nil,nil +40414,internet,Idea_Internet,nil,1,nil,nil +40414,imis,IDEAGPRS,nil,1,nil,nil +40415,www,Vodafonemobileconnect,nil,1,nil,nil +40415,portalnmms,Vodafonelive,nil,1,nil,nil +40416,airtelgprs.com,MobileOffice,nil,1,nil,nil +40416,airtelfun.com,AIRTELLIVE,nil,1,nil,nil +40417,aircelwebpost,Aircel-GPRS-Postpaid,nil,1,nil,nil +40417,aircelwappost,PocketInternet-Postpaid,nil,1,nil,nil +40417,aircelwap,PocketInternet-Prepaid,nil,1,nil,nil +40417,aircelweb,Aircel-GPRS-Prepaid,nil,1,nil,nil +40417,aircelgprs,AircelInternet(40417),nil,1,nil,nil +40418,smartnet,RelianceNet,nil,1,nil,nil +40418,smartwap,RelianceWAP,nil,1,nil,1 +40418,rcomnet,RelianceInternet(40418),nil,1,nil,nil +40419,internet,Idea_Internet,nil,1,nil,nil +40419,imis,IDEAGPRS,nil,1,nil,nil +40420,www,Vodafonemobileconnect,nil,1,nil,nil +40420,portalnmms,Vodafonelive,nil,1,nil,nil +40421,www,LoopMobile,nil,1,nil,nil +40422,internet,Idea_Internet,nil,1,nil,nil +40422,imis,IDEAGPRS,nil,1,nil,nil +40424,internet,Idea_Internet,nil,1,nil,nil +40424,imis,IDEAGPRS,nil,1,nil,nil +40425,aircelwebpost,Aircel-GPRS-Postpaid,nil,1,nil,nil +40425,aircelwappost,PocketInternet-Postpaid,nil,1,nil,nil +40425,aircelwap,PocketInternet-Prepaid,nil,1,nil,nil +40425,aircelweb,Aircel-GPRS-Prepaid,nil,1,nil,nil +40425,aircelgprs,AircelInternet(40425),nil,1,nil,nil +40427,www,Vodafonemobileconnect,nil,1,nil,nil +40427,portalnmms,Vodafonelive,nil,1,nil,nil +40428,aircelwebpost,Aircel-GPRS-Postpaid,nil,1,nil,nil +40428,aircelwappost,PocketInternet-Postpaid,nil,1,nil,nil +40428,aircelwap,PocketInternet-Prepaid,nil,1,nil,nil +40428,aircelweb,Aircel-GPRS-Prepaid,nil,1,nil,nil +40428,aircelgprs,AircelInternet(40428),nil,1,nil,nil +40429,aircelwebpost,Aircel-GPRS-Postpaid,nil,1,nil,nil +40429,myaircelpost,PocketInternet-Postpaid,nil,1,nil,nil +40429,myaircel,PocketInternet-Prepaid,nil,1,nil,nil +40429,aircelweb,Aircel-GPRS-Prepaid,nil,1,nil,nil +40429,aircelgprs,AircelInternet(40429),nil,1,nil,nil +40429,aircelwap,AircelWAP(40429),nil,1,nil,nil +40430,www,Vodafonemobileconnect,nil,1,nil,nil +40430,portalnmms,Vodafonelive,nil,1,nil,nil +40431,airtelgprs.com,MobileOffice,nil,1,nil,nil +40431,airtelfun.com,AIRTELLIVE,nil,1,nil,nil +40433,aircelwebpost,Aircel-GPRS-Postpaid,nil,1,nil,nil +40433,myaircelpost,PocketInternet-Postpaid,nil,1,nil,nil +40433,myaircel,PocketInternet-Prepaid,nil,1,nil,nil +40433,aircelweb,Aircel-GPRS-Prepaid,nil,1,nil,nil +40433,aircelgprs,AircelInternet(40433),nil,1,nil,nil +40433,aircelwap,AircelWAP(40433),nil,1,nil,nil +40434,bsnlnet,bsnlnet,nil,1,nil,1 +40434,bsnllive,bsnllive,nil,1,nil,nil +40435,aircelwebpost,Aircel-GPRS-Postpaid,nil,1,nil,nil +40435,aircelwappost,PocketInternet-Postpaid,nil,1,nil,nil +40435,aircelwap,PocketInternet-Prepaid,nil,1,nil,nil +40435,aircelweb,Aircel-GPRS-Prepaid,nil,1,nil,nil +40435,aircelgprs,AircelInternet(40435),nil,1,nil,nil +40436,smartnet,RelianceNet,nil,1,nil,nil +40436,smartwap,RelianceWAP,nil,1,nil,1 +40436,rcomnet,RelianceInternet(40436),nil,1,nil,nil +40437,aircelwebpost,Aircel-GPRS-Postpaid,nil,1,nil,nil +40437,aircelwappost,PocketInternet-Postpaid,nil,1,nil,nil +40437,aircelwap,PocketInternet-Prepaid,nil,1,nil,nil +40437,aircelweb,Aircel-GPRS-Prepaid,nil,1,nil,nil +40437,aircelgprs,AircelInternet(40437),nil,1,nil,nil +40438,bsnlnet,bsnlnet,nil,1,nil,nil +40438,bsnllive,bsnllive,nil,1,nil,nil +40440,airtelgprs.com,MobileOffice,nil,1,nil,nil +40440,airtelfun.com,AIRTELLIVE,nil,1,nil,nil +40441,aircelgprs.po,Aircel-GPRS-Postpaid,nil,1,nil,nil +40441,aircelgprs.pr,Aircel-GPRS-Prepaid,nil,1,nil,nil +40441,aircelwap.po,PocketInternet-Postpaid,nil,1,nil,nil +40441,aircelwap.pr,PocketInternet-Prepaid,nil,1,nil,nil +40441,aircelgprs,AircelInternet(40441),nil,1,nil,nil +40441,aircelwap,AircelWAP(40441),nil,1,nil,nil +40442,aircelgprs.po,Aircel-GPRS-Postpaid,nil,1,nil,nil +40442,aircelgprs.pr,Aircel-GPRS-Prepaid,nil,1,nil,nil +40442,aircelwap.po,PocketInternet-Postpaid,nil,1,nil,nil +40442,aircelwap.pr,PocketInternet-Prepaid,nil,1,nil,nil +40442,aircelgprs,AircelInternet(40442),nil,1,nil,nil +40443,www,Vodafonemobileconnect,nil,1,nil,nil +40443,portalnmms,Vodafonelive,nil,1,nil,nil +40444,internet,Idea_Internet,nil,1,nil,nil +40444,imis,IDEAGPRS,nil,1,nil,nil +40445,airtelgprs.com,MobileOffice,nil,1,nil,nil +40445,airtelfun.com,AIRTELLIVE,nil,1,nil,nil +40446,www,Vodafonemobileconnect,nil,1,nil,nil +40446,portalnmms,Vodafonelive,nil,1,nil,nil +40449,airtelgprs.com,MobileOffice,nil,1,nil,nil +40449,airtelfun.com,AIRTELLIVE,nil,1,nil,nil +40450,smartnet,RelianceNet,nil,1,nil,nil +40450,smartwap,RelianceWAP,nil,1,nil,1 +40451,bsnlnet,bsnlnet,nil,1,nil,nil +40451,bsnllive,bsnllive,nil,1,nil,nil +40452,smartnet,RelianceNet,nil,1,nil,nil +40452,smartwap,RelianceWAP,nil,1,nil,1 +40453,bsnlnet,bsnlnet,nil,1,nil,nil +40453,bsnllive,bsnllive,nil,1,nil,nil +40454,bsnlnet,bsnlnet,nil,1,nil,nil +40454,bsnllive,bsnllive,nil,1,nil,nil +40455,bsnlnet,bsnlnet,nil,1,nil,nil +40455,bsnllive,bsnllive,nil,1,nil,nil +40456,internet,Idea_Internet,nil,1,nil,nil +40456,imis,IDEAGPRS,nil,1,nil,nil +40457,bsnlnet,bsnlnet,nil,1,nil,nil +40457,bsnllive,bsnllive,nil,1,nil,nil +40458,bsnlnet,bsnlnet,nil,1,nil,nil +40458,bsnllive,bsnllive,nil,1,nil,nil +40459,bsnlnet,bsnlnet,nil,1,nil,nil +40459,bsnllive,bsnllive,nil,1,nil,nil +40460,www,Vodafonemobileconnect,nil,1,nil,nil +40460,portalnmms,Vodafonelive,nil,1,nil,nil +40462,bsnlnet,bsnlnet,nil,1,nil,nil +40462,bsnllive,bsnllive,nil,1,nil,nil +40464,bsnlnet,bsnlnet,nil,1,nil,nil +40464,bsnllive,bsnllive,nil,1,nil,nil +40466,bsnlnet,bsnlnet,nil,1,nil,nil +40466,bsnllive,bsnllive,nil,1,nil,nil +40467,smartnet,RelianceNet,nil,1,nil,nil +40467,smartwap,RelianceWAP,nil,1,nil,1 +40468,mtnl.net,MTNL,mtnl123,1,mtnl,0 +40469,mtnl.net,MTNL,mtnl123,1,mtnl,0 +40470,airtelgprs.com,MobileOffice,nil,1,nil,nil +40470,airtelfun.com,AIRTELLIVE,nil,1,nil,nil +40471,bsnlnet,bsnlnet,nil,1,nil,nil +40471,bsnllive,bsnllive,nil,1,nil,nil +40472,bsnlnet,bsnlnet,nil,1,nil,nil +40472,bsnllive,bsnllive,nil,1,nil,nil +40473,bsnlnet,bsnlnet,nil,1,nil,nil +40473,bsnllive,bsnllive,nil,1,nil,nil +40474,bsnlnet,bsnlnet,nil,1,nil,nil +40474,bsnllive,bsnllive,nil,1,nil,nil +40475,bsnlnet,bsnlnet,nil,1,nil,nil +40475,bsnllive,bsnllive,nil,1,nil,nil +40476,bsnlnet,bsnlnet,nil,1,nil,nil +40476,bsnllive,bsnllive,nil,1,nil,nil +40477,bsnlnet,bsnlnet,nil,1,nil,nil +40477,bsnllive,bsnllive,nil,1,nil,nil +40478,internet,Idea_Internet,nil,1,nil,nil +40478,imis,IDEAGPRS,nil,1,nil,nil +40479,bsnlnet,bsnlnet,nil,1,nil,nil +40479,bsnllive,bsnllive,nil,1,nil,nil +40480,bsnlnet,bsnlnet,nil,1,nil,nil +40480,bsnllive,bsnllive,nil,1,nil,nil +40481,bsnlnet,bsnlnet,nil,1,nil,nil +40481,bsnllive,bsnllive,nil,1,nil,nil +40482,internet,Idea_Internet,nil,1,nil,nil +40482,imis,IDEAGPRS,nil,1,nil,nil +40483,smartnet,RelianceNet,nil,1,nil,nil +40483,smartwap,RelianceWAP,nil,1,nil,1 +40484,www,Vodafonemobileconnect,nil,1,nil,nil +40484,portalnmms,Vodafonelive,nil,1,nil,nil +40485,smartnet,RelianceNet,nil,1,nil,nil +40485,smartwap,RelianceWAP,nil,1,nil,1 +40486,www,Vodafonemobileconnect,nil,1,nil,nil +40486,portalnmms,Vodafonelive,nil,1,nil,nil +40487,internet,Idea_Internet,nil,1,nil,nil +40487,imis,IDEAGPRS,nil,1,nil,nil +40488,www,Vodafonemobileconnect,nil,1,nil,nil +40488,portalnmms,Vodafonelive,nil,1,nil,nil +40489,internet,Idea_Internet,nil,1,nil,nil +40489,imis,IDEAGPRS,nil,1,nil,nil +40490,airtelgprs.com,MobileOffice,nil,1,nil,nil +40490,airtelfun.com,AIRTELLIVE,nil,1,nil,nil +40491,aircelwebpost,Aircel-GPRS-Postpaid,nil,1,nil,nil +40491,aircelwappost,PocketInternet-Postpaid,nil,1,nil,nil +40491,aircelwap,PocketInternet-Prepaid,nil,1,nil,nil +40491,aircelweb,Aircel-GPRS-Prepaid,nil,1,nil,nil +40492,airtelgprs.com,MobileOffice,nil,1,nil,nil +40492,airtelfun.com,AIRTELLIVE,nil,1,nil,nil +40493,airtelgprs.com,MobileOffice,nil,1,nil,nil +40493,airtelfun.com,AIRTELLIVE,nil,1,nil,nil +40494,airtelgprs.com,MobileOffice,nil,1,nil,nil +40494,airtelfun.com,AIRTELLIVE,nil,1,nil,nil +40495,airtelgprs.com,MobileOffice,nil,1,nil,nil +40495,airtelfun.com,AIRTELLIVE,nil,1,nil,nil +40496,airtelgprs.com,MobileOffice,nil,1,nil,nil +40496,airtelfun.com,AIRTELLIVE,nil,1,nil,nil +40497,airtelgprs.com,MobileOffice,nil,1,nil,nil +40497,airtelfun.com,AIRTELLIVE,nil,1,nil,nil +40498,airtelgprs.com,MobileOffice,nil,1,nil,nil +40498,airtelfun.com,AIRTELLIVE,nil,1,nil,nil +40501,rcomnet,Netconnect,nil,1,nil,nil +40501,rcomwap,RelianceMbWorld,nil,1,nil,nil +40503,rcomnet,Netconnect,nil,1,nil,nil +40503,rcomwap,RelianceMbWorld,nil,1,nil,nil +40504,rcomnet,Netconnect,nil,1,nil,nil +40504,rcomwap,RelianceMbWorld,nil,1,nil,nil +40505,rcomnet,Netconnect,nil,1,nil,nil +40505,rcomwap,RelianceMbWorld,nil,1,nil,nil +40506,rcomnet,Netconnect,nil,1,nil,nil +40506,rcomwap,RelianceMbWorld,nil,1,nil,nil +40507,rcomnet,Netconnect,nil,1,nil,nil +40507,rcomwap,RelianceMbWorld,nil,1,nil,nil +40508,rcomnet,Netconnect,nil,1,nil,nil +40508,rcomwap,RelianceMbWorld,nil,1,nil,nil +40509,rcomnet,Netconnect,nil,1,nil,nil +40509,rcomwap,RelianceMbWorld,nil,1,nil,nil +40510,rcomnet,Netconnect,nil,1,nil,nil +40510,rcomwap,RelianceMbWorld,nil,1,nil,nil +40511,rcomnet,Netconnect,nil,1,nil,nil +40511,rcomwap,RelianceMbWorld,nil,1,nil,nil +40512,rcomnet,Netconnect,nil,1,nil,nil +40512,rcomwap,RelianceMbWorld,nil,1,nil,nil +40513,rcomnet,Netconnect,nil,1,nil,nil +40513,rcomwap,RelianceMbWorld,nil,1,nil,nil +40514,rcomnet,Netconnect,nil,1,nil,nil +40514,rcomwap,RelianceMbWorld,nil,1,nil,nil +40515,rcomnet,Netconnect,nil,1,nil,nil +40515,rcomwap,RelianceMbWorld,nil,1,nil,nil +40517,rcomnet,Netconnect,nil,1,nil,nil +40517,rcomwap,RelianceMbWorld,nil,1,nil,nil +40518,rcomnet,Netconnect,nil,1,nil,nil +40518,rcomwap,RelianceMbWorld,nil,1,nil,nil +40519,rcomnet,Netconnect,nil,1,nil,nil +40519,rcomwap,RelianceMbWorld,nil,1,nil,nil +40520,rcomnet,Netconnect,nil,1,nil,nil +40520,rcomwap,RelianceMbWorld,nil,1,nil,nil +40521,rcomnet,Netconnect,nil,1,nil,nil +40521,rcomwap,RelianceMbWorld,nil,1,nil,nil +40522,rcomnet,Netconnect,nil,1,nil,nil +40522,rcomwap,RelianceMbWorld,nil,1,nil,nil +40523,rcomnet,Netconnect,nil,1,nil,nil +40523,rcomwap,RelianceMbWorld,nil,1,nil,nil +405025,TATA.DOCOMO.DIVE.IN,TATADOCOMODIVE-IN,nil,1,nil,nil +405025,TATA.DOCOMO.INTERNET,TATADOCOMOINTERNET,nil,1,nil,nil +405026,TATA.DOCOMO.INTERNET,TATADOCOMOINTERNET,nil,1,nil,nil +405026,TATA.DOCOMO.DIVE.IN,TATADOCOMODIVE-IN,nil,1,nil,nil +405027,TATA.DOCOMO.INTERNET,TATADOCOMOINTERNET,nil,1,nil,nil +405027,TATA.DOCOMO.DIVE.IN,TATADOCOMODIVE-IN,nil,1,nil,nil +405028,TATA.DOCOMO.INTERNET,TATADOCOMOINTERNET,nil,1,nil,nil +405028,TATA.DOCOMO.DIVE.IN,TATADOCOMODIVE-IN,nil,1,nil,nil +405029,TATA.DOCOMO.INTERNET,TATADOCOMOINTERNET,nil,1,nil,nil +405029,TATA.DOCOMO.DIVE.IN,TATADOCOMODIVE-IN,nil,1,nil,nil +405030,TATA.DOCOMO.INTERNET,TATADOCOMOINTERNET,nil,1,nil,nil +405030,TATA.DOCOMO.DIVE.IN,TATADOCOMODIVE-IN,nil,1,nil,nil +405031,TATA.DOCOMO.INTERNET,TATADOCOMOINTERNET,nil,1,nil,nil +405031,TATA.DOCOMO.DIVE.IN,TATADOCOMODIVE-IN,nil,1,nil,nil +405032,TATA.DOCOMO.INTERNET,TATADOCOMOINTERNET,nil,1,nil,nil +405032,TATA.DOCOMO.DIVE.IN,TATADOCOMODIVE-IN,nil,1,nil,nil +405033,TATA.DOCOMO.INTERNET,TATADOCOMOINTERNET,nil,1,nil,nil +405033,TATA.DOCOMO.DIVE.IN,TATADOCOMODIVE-IN,nil,1,nil,nil +405034,TATA.DOCOMO.INTERNET,TATADOCOMOINTERNET,nil,1,nil,nil +405034,TATA.DOCOMO.DIVE.IN,TATADOCOMODIVE-IN,nil,1,nil,nil +405035,TATA.DOCOMO.INTERNET,TATADOCOMOINTERNET,nil,1,nil,nil +405035,TATA.DOCOMO.DIVE.IN,TATADOCOMODIVE-IN,nil,1,nil,nil +405036,TATA.DOCOMO.INTERNET,TATADOCOMOINTERNET,nil,1,nil,nil +405036,TATA.DOCOMO.DIVE.IN,TATADOCOMODIVE-IN,nil,1,nil,nil +405037,TATA.DOCOMO.INTERNET,TATADOCOMOINTERNET,nil,1,nil,nil +405037,TATA.DOCOMO.DIVE.IN,TATADOCOMODIVE-IN,nil,1,nil,nil +405038,TATA.DOCOMO.INTERNET,TATADOCOMOINTERNET,nil,1,nil,nil +405038,TATA.DOCOMO.DIVE.IN,TATADOCOMODIVE-IN,nil,1,nil,nil +405039,TATA.DOCOMO.INTERNET,TATADOCOMOINTERNET,nil,1,nil,nil +405039,TATA.DOCOMO.DIVE.IN,TATADOCOMODIVE-IN,nil,1,nil,nil +405040,TATA.DOCOMO.INTERNET,TATADOCOMOINTERNET,nil,1,nil,nil +405040,TATA.DOCOMO.DIVE.IN,TATADOCOMODIVE-IN,nil,1,nil,nil +405041,TATA.DOCOMO.INTERNET,TATADOCOMOINTERNET,nil,1,nil,nil +405041,TATA.DOCOMO.DIVE.IN,TATADOCOMODIVE-IN,nil,1,nil,nil +405042,TATA.DOCOMO.INTERNET,TATADOCOMOINTERNET,nil,1,nil,nil +405042,TATA.DOCOMO.DIVE.IN,TATADOCOMODIVE-IN,nil,1,nil,nil +405043,TATA.DOCOMO.INTERNET,TATADOCOMOINTERNET,nil,1,nil,nil +405043,TATA.DOCOMO.DIVE.IN,TATADOCOMODIVE-IN,nil,1,nil,nil +405044,TATA.DOCOMO.INTERNET,TATADOCOMOINTERNET,nil,1,nil,nil +405044,TATA.DOCOMO.DIVE.IN,TATADOCOMODIVE-IN,nil,1,nil,nil +405045,TATA.DOCOMO.INTERNET,TATADOCOMOINTERNET,nil,1,nil,nil +405045,TATA.DOCOMO.DIVE.IN,TATADOCOMODIVE-IN,nil,1,nil,nil +405046,TATA.DOCOMO.INTERNET,TATADOCOMOINTERNET,nil,1,nil,nil +405046,TATA.DOCOMO.DIVE.IN,TATADOCOMODIVE-IN,nil,1,nil,nil +405047,TATA.DOCOMO.INTERNET,TATADOCOMOINTERNET,nil,1,nil,nil +405047,TATA.DOCOMO.DIVE.IN,TATADOCOMODIVE-IN,nil,1,nil,nil +40551,airtelgprs.com,MobileOffice,nil,1,nil,nil +40551,airtelfun.com,AIRTELLIVE,nil,1,nil,nil +40552,airtelgprs.com,MobileOffice,nil,1,nil,nil +40552,airtelfun.com,AIRTELLIVE,nil,1,nil,nil +40553,airtelgprs.com,MobileOffice,nil,1,nil,nil +40553,airtelfun.com,AIRTELLIVE,nil,1,nil,nil +40554,airtelgprs.com,MobileOffice,nil,1,nil,nil +40554,airtelfun.com,AIRTELLIVE,nil,1,nil,nil +40555,airtelgprs.com,MobileOffice,nil,1,nil,nil +40555,airtelfun.com,AIRTELLIVE,nil,1,nil,nil +40556,airtelgprs.com,MobileOffice,nil,1,nil,nil +40556,airtelfun.com,AIRTELLIVE,nil,1,nil,nil +40566,www,Vodafonemobileconnect,nil,1,nil,nil +40566,portalnmms,Vodafonelive,nil,1,nil,nil +40567,www,Vodafonemobileconnect,nil,1,nil,nil +40567,portalnmms,Vodafonelive,nil,1,nil,nil +40570,internet,Idea_Internet,nil,1,nil,nil +40570,imis,IDEAGPRS,nil,1,nil,nil +405750,www,Vodafonemobileconnect,nil,1,nil,nil +405750,portalnmms,Vodafonelive,nil,1,nil,nil +405751,www,Vodafonemobileconnect,nil,1,nil,nil +405751,portalnmms,Vodafonelive,nil,1,nil,nil +405752,www,Vodafonemobileconnect,nil,1,nil,nil +405752,portalnmms,Vodafonelive,nil,1,nil,nil +405753,www,Vodafonemobileconnect,nil,1,nil,nil +405753,portalnmms,Vodafonelive,nil,1,nil,nil +405754,www,Vodafonemobileconnect,nil,1,nil,nil +405754,portalnmms,Vodafonelive,nil,1,nil,nil +405755,www,Vodafonemobileconnect,nil,1,nil,nil +405755,portalnmms,Vodafonelive,nil,1,nil,nil +405756,www,Vodafonemobileconnect,nil,1,nil,nil +405756,portalnmms,Vodafonelive,nil,1,nil,nil +405799,internet,Idea_Internet,nil,1,nil,nil +405799,imis,IDEAGPRS,nil,1,nil,nil +405800,aircelgprs,Aircel-GPRS,nil,1,nil,nil +405800,aircelwap,PocketInternet,nil,1,nil,nil +405801,aircelgprs,Aircel-GPRS,nil,1,nil,nil +405801,aircelwap,PocketInternet,nil,1,nil,nil +405802,aircelgprs,Aircel-GPRS,nil,1,nil,nil +405802,aircelwap,PocketInternet,nil,1,nil,nil +405803,aircelgprs,Aircel-GPRS,nil,1,nil,nil +405803,aircelwap,PocketInternet,nil,1,nil,nil +405804,aircelgprs,Aircel-GPRS,nil,1,nil,nil +405804,aircelwap,PocketInternet,nil,1,nil,nil +405805,aircelgprs,Aircel-GPRS,nil,1,nil,nil +405805,aircelwap,PocketInternet,nil,1,nil,nil +405806,aircelgprs,Aircel-GPRS,nil,1,nil,nil +405806,aircelwap,PocketInternet,nil,1,nil,nil +405807,aircelgprs,Aircel-GPRS,nil,1,nil,nil +405807,aircelwap,PocketInternet,nil,1,nil,nil +405808,aircelgprs,Aircel-GPRS,nil,1,nil,nil +405808,aircelwap,PocketInternet,nil,1,nil,nil +405809,aircelgprs,Aircel-GPRS,nil,1,nil,nil +405809,aircelwap,PocketInternet,nil,1,nil,nil +405810,aircelgprs,Aircel-GPRS,nil,1,nil,nil +405810,aircelwap,PocketInternet,nil,1,nil,nil +405811,aircelgprs,Aircel-GPRS,nil,1,nil,nil +405811,aircelwap,PocketInternet,nil,1,nil,nil +405812,aircelgprs,Aircel-GPRS,nil,1,nil,nil +405812,aircelwap,PocketInternet,nil,1,nil,nil +405813,uninor,UninorInternet,nil,1,nil,1 +405813,uninor,UninorWap,nil,1,nil,nil +405814,uninor,UninorInternet,nil,1,nil,1 +405814,uninor,UninorWap,nil,1,nil,nil +405815,uninor,UninorInternet,nil,1,nil,1 +405815,uninor,UninorWap,nil,1,nil,nil +405816,uninor,UninorInternet,nil,1,nil,1 +405816,uninor,UninorWap,nil,1,nil,nil +405817,uninor,UninorInternet,nil,1,nil,1 +405817,uninor,UninorWap,nil,1,nil,nil +405818,uninor,UninorInternet,nil,1,nil,1 +405818,uninor,UninorWap,nil,1,nil,nil +405819,uninor,UninorInternet,nil,1,nil,1 +405819,uninor,UninorWap,nil,1,nil,nil +405820,uninor,UninorInternet,nil,1,nil,1 +405820,uninor,UninorWap,nil,1,nil,nil +405821,uninor,UninorInternet,nil,1,nil,1 +405821,uninor,UninorWap,nil,1,nil,nil +405822,uninor,UninorInternet,nil,1,nil,1 +405822,uninor,UninorWap,nil,1,nil,nil +405823,vinternet.com,Videocon,nil,1,nil,nil +405824,vinternet.com,Videocon,nil,1,nil,nil +405825,vinternet.com,Videocon,nil,1,nil,nil +405826,vinternet.com,Videocon,nil,1,nil,nil +405827,vinternet.com,Videocon,nil,1,nil,nil +405828,vinternet.com,Videocon,nil,1,nil,nil +405829,vinternet.com,Videocon,nil,1,nil,nil +405830,vinternet.com,Videocon,nil,1,nil,nil +405831,vinternet.com,Videocon,nil,1,nil,nil +405832,vinternet.com,Videocon,nil,1,nil,nil +405833,vinternet.com,Videocon,nil,1,nil,nil +405834,vinternet.com,Videocon,nil,1,nil,nil +405835,vinternet.com,Videocon,nil,1,nil,nil +405836,vinternet.com,Videocon,nil,1,nil,nil +405837,vinternet.com,Videocon,nil,1,nil,nil +405838,vinternet.com,Videocon,nil,1,nil,nil +405839,vinternet.com,Videocon,nil,1,nil,nil +405840,vinternet.com,Videocon,nil,1,nil,nil +405841,vinternet.com,Videocon,nil,1,nil,nil +405842,vinternet.com,Videocon,nil,1,nil,nil +405843,vinternet.com,Videocon,nil,1,nil,nil +405844,uninor,UninorInternet,nil,1,nil,1 +405844,uninor,UninorWap,nil,1,nil,nil +405845,internet,Idea_Internet,nil,1,nil,nil +405845,imis,IDEAGPRS,nil,1,nil,nil +405846,internet,Idea_Internet,nil,1,nil,nil +405846,imis,IDEAGPRS,nil,1,nil,nil +405847,internet,Idea_Internet,nil,1,nil,nil +405847,imis,IDEAGPRS,nil,1,nil,nil +405848,internet,Idea_Internet,nil,1,nil,nil +405848,imis,IDEAGPRS,nil,1,nil,nil +405849,internet,Idea_Internet,nil,1,nil,nil +405849,imis,IDEAGPRS,nil,1,nil,nil +405850,internet,Idea_Internet,nil,1,nil,nil +405850,imis,IDEAGPRS,nil,1,nil,nil +405851,internet,Idea_Internet,nil,1,nil,nil +405851,imis,IDEAGPRS,nil,1,nil,nil +405852,internet,Idea_Internet,nil,1,nil,nil +405852,imis,IDEAGPRS,nil,1,nil,nil +405853,internet,Idea_Internet,nil,1,nil,nil +405853,imis,IDEAGPRS,nil,1,nil,nil +405854,www,LoopInternet(405854),nil,1,nil,nil +405855,www,LoopInternet(405855),nil,1,nil,nil +405856,www,LoopInternet(405856),nil,1,nil,nil +405857,www,LoopInternet(405857),nil,1,nil,nil +405858,www,LoopInternet(405858),nil,1,nil,nil +405859,www,LoopInternet(405859),nil,1,nil,nil +405860,www,LoopInternet(405860),nil,1,nil,nil +405861,www,LoopInternet(405861),nil,1,nil,nil +405862,www,LoopInternet(405862),nil,1,nil,nil +405863,www,LoopInternet(405863),nil,1,nil,nil +405864,www,LoopInternet(405864),nil,1,nil,nil +405865,www,LoopInternet(405865),nil,1,nil,nil +405866,www,LoopInternet(405866),nil,1,nil,nil +405867,www,LoopInternet(405867),nil,1,nil,nil +405868,www,LoopInternet(405868),nil,1,nil,nil +405869,www,LoopInternet(405869),nil,1,nil,nil +405870,www,LoopInternet(405870),nil,1,nil,nil +405871,www,LoopInternet(405871),nil,1,nil,nil +405872,www,LoopInternet(405872),nil,1,nil,nil +405873,www,LoopInternet(405873),nil,1,nil,nil +405874,www,LoopInternet(405874),nil,1,nil,nil +405875,uninor,UninorInternet,nil,1,nil,1 +405875,uninor,UninorWap,nil,1,nil,nil +405876,uninor,UninorInternet,nil,1,nil,1 +405876,uninor,UninorWap,nil,1,nil,nil +405877,uninor,UninorInternet,nil,1,nil,1 +405877,uninor,UninorWap,nil,1,nil,nil +405878,uninor,UninorInternet,nil,1,nil,1 +405878,uninor,UninorWap,nil,1,nil,nil +405879,uninor,UninorInternet,nil,1,nil,1 +405879,uninor,UninorWap,nil,1,nil,nil +405880,uninor,UninorInternet,nil,1,nil,1 +405880,uninor,UninorWap,nil,1,nil,nil +405881,gprs.stel.in,STEL,nil,1,nil,nil +405882,gprs.stel.in,STEL,nil,1,nil,nil +405883,gprs.stel.in,STEL,nil,1,nil,nil +405884,gprs.stel.in,STEL,nil,1,nil,nil +405885,gprs.stel.in,STEL,nil,1,nil,nil +405886,gprs.stel.in,STEL,nil,1,nil,nil +405908,internet,IDEA,nil,1,nil,nil +405909,internet,IDEA,nil,1,nil,nil +405910,internet,IDEA,nil,1,nil,nil +405911,internet,IDEA,nil,1,nil,nil +405912,internet,Cheers,nil,1,nil,nil +405913,internet,Cheers,nil,1,nil,nil +405914,internet,Cheers,nil,1,nil,nil +405915,internet,Cheers,nil,1,nil,nil +405916,internet,Cheers,nil,1,nil,nil +405917,internet,Cheers,nil,1,nil,nil +405918,internet,Cheers,nil,1,nil,nil +405919,internet,Cheers,nil,1,nil,nil +405920,internet,Cheers,nil,1,nil,nil +405921,internet,Cheers,nil,1,nil,nil +405922,internet,Cheers,nil,1,nil,nil +405923,internet,Cheers,nil,1,nil,nil +405924,internet,Cheers,nil,1,nil,nil +405925,uninor,UninorInternet,nil,1,nil,1 +405925,uninor,UninorWap,nil,1,nil,nil +405926,uninor,UninorInternet,nil,1,nil,1 +405926,uninor,UninorWap,nil,1,nil,nil +405927,uninor,UninorInternet,nil,1,nil,1 +405927,uninor,UninorWap,nil,1,nil,nil +405928,uninor,UninorInternet,nil,1,nil,1 +405928,uninor,UninorWap,nil,1,nil,nil +405929,uninor,UninorInternet,nil,1,nil,1 +405929,uninor,UninorWap,nil,1,nil,nil +405930,internet,Cheers,nil,1,nil,nil +405931,internet,Cheers,nil,1,nil,nil +405932,vinternet.com,Videocon,nil,1,nil,nil +41001,connect.mobilinkworld.com,MobilinkWAPGPRS,Mobilink,1,Mobilink,nil +41003,Ufone.internet,UfoneWAP,nil,1,nil,nil +41004,zonginternet,ZONGWAP,nil,1,nil,nil +41006,internet,TelenorWAP,nil,1,nil,nil +41007,Wap.warid,WaridWAP,nil,1,nil,nil +410310,att.mvno,ConsumerCellular,nil,1,nil,nil +41201,default,AWCC,nil,1,nil,nil +41220,default,Roshan,nil,1,nil,nil +41240,default,MTN,nil,1,nil,nil +41250,default,Etisalat,nil,1,nil,nil +41301,default,Mobitel,nil,1,nil,nil +41302,default,Dialog,nil,1,nil,nil +41303,default,Etisalat,nil,1,nil,nil +41305,default,Airtel,nil,1,nil,nil +41308,default,Hutch,nil,1,nil,nil +41401,default,MPT,nil,1,nil,nil +41405,Internet,OoredooInternet,nil,1,nil,nil +41501,internet.mic1.com.lb,AlfaInternet,mic1,1,mic1,nil +41501,wap.mic1.com.lb,Alfawap,mic1,1,mic1,nil +41503,touch,touch,nil,1,nil,nil +41503,wap,touch_WAP,nil,1,nil,nil +41601,zain,ZainJOInternet,zain,1,zain,1 +41601,Zain,ZainJOStreaming,zain,1,zain,1 +41603,net,Umniahinternet,nil,1,nil,nil +41603,wap,UmniahWAP,nil,1,nil,nil +416770,net.orange.jo,OrangeInternet,net,1,net,1 +416770,wap.orange.jo,OrangeWAP,wap,1,wap,1 +41677,net.orange.jo,OrangeInternet,net,1,net,1 +41677,wap.orange.jo,OrangeWAP,wap,1,wap,1 +41701,net.syriatel.com,SyriatelNet,nil,1,nil,nil +41702,internet,MTNWAP,nil,1,nil,nil +41805,net.asiacell.com,AsiacellInternet,nil,1,nil,nil +41808,default,SanaTel,nil,1,nil,nil +41820,internet,ZAIN-GPRS,atheer,1,atheer,1 +41830,internet,ZAIN-GPRS,atheer,1,atheer,1 +41840,internet.korek.com,Korek9595,nil,1,nil,nil +41840,net.korek.com,Korek9191,korek,1,korek,nil +41845,default,Mobitel,nil,1,nil,nil +41862,default,Itisaluna,nil,1,nil,nil +41892,default,Omnnea,nil,1,nil,nil +41902,pps,MI,pps,1,pps,nil +41902,pps,ZainWAP,pps,1,pps,3 +41903,action.ooredoo.com,OoredooAction,nil,1,nil,1 +41903,mms.ooredoo.com,OoredooMMS,nil,1,nil,1 +41904,viva,VIVA-KW,nil,1,nil,0 +42001,jawalnet.com.sa,STC-GPRS,nil,1,nil,nil +42003,web1,MobilyWEB,nil,1,nil,nil +42003,wap2,Mobilyprepaid-GPRS,nil,1,nil,nil +42003,wap1,Mobilypostpaid-GPRS,nil,1,nil,nil +42003,web2,MobilyWEB2,nil,1,nil,nil +42004,zain,zain-InternetWap,nil,1,nil,0 +42101,default,SabaFon,nil,1,nil,nil +42102,default,MTN,nil,1,nil,nil +42103,default,YemenMobile,nil,1,nil,nil +42104,default,HiTS-UNITEL,nil,1,nil,nil +42202,taif,OmanMobileInternet,taif,1,taif,1 +42203,isp.nawras.com.om,NawrasInternet,test,1,test,1 +42402,etisalat.ae,EtisalatDataPackage,nil,1,nil,1 +42402,etisalat,WeyakWap,nil,1,nil,1 +42403,du,duInternet,nil,1,nil,nil +42501,uwap.orange.co.il,3GPortal,nil,1,nil,nil +42502,sphone,CellcomInternet,nil,1,nil,nil +42503,sphone.pelephone.net.il,SphonePelephone,pcl,1,pcl@3g,2 +42505,wap,JawwalWAP,nil,1,nil,nil +42506,internet,Internet,nil,1,nil,nil +42507,net.hotm,InternetHOTmobile,nil,1,nil,nil +42507,pc.hotm,PCHOTmobile,nil,1,nil,0 +42508,internet.golantelecom.net.il,GolanTelecomInternet,nil,1,nil,nil +42510,uwap.orange.co.il,3GPortal,nil,1,nil,nil +42514,data.youphone.co.il,YouPhone,nil,1,nil,nil +42515,hcminternet,HomeCellularInternet,nil,1,nil,nil +42516,internet.rl,RamiLevi3G,nil,1,nil,nil +42601,internet.batelco.com,BatelcoInternet,nil,1,nil,nil +42601,wap.batelco.com,BatelcoWAP,wap,1,wap,0 +42602,internet,ZainBHInternet,internet,1,internet,0 +42602,wap,ZainBHWAP,wap,1,wap,0 +42604,viva.bh,VIVAGPRS,nil,1,nil,nil +42604,vivawap.bh,VIVAWAP,nil,1,nil,nil +42701,data,Internet,nil,1,nil,1 +42702,web.vodafone.com.qa,Vodainternet,nil,1,nil,nil +42888,default,Unitel,nil,1,nil,nil +42891,default,Skytel,nil,1,nil,nil +42898,default,G.Mobile,nil,1,nil,nil +42899,default,MobiCom,nil,1,nil,nil +42901,default,Namaste/NTMobile,nil,1,nil,nil +42902,default,Ncell,nil,1,nil,nil +42903,default,Sky/C-Phone,nil,1,nil,nil +42904,default,SmartCell,nil,1,nil,nil +43211,mcinet,MCI-GPRS,nil,1,nil,nil +43214,mcinet,MCI-GPRS,nil,1,nil,nil +43219,mcinet,MCI-GPRS,nil,1,nil,nil +43220,rightel,rightel,nil,1,nil,nil +43235,mtnirancell,Irancell-GPRS,nil,1,nil,nil +43270,mcinet,MCI-GPRS,nil,1,nil,nil +43293,mcinet,MCI-GPRS,nil,1,nil,nil +43404,internet.beeline.uz,Beeline-UZBInternet,beeline,1,beeline,1 +43405,internet,UCELLInternet,nil,1,nil,nil +43406,default,PerfectumMobile,nil,1,nil,nil +43407,net.mts.uz,MTS-UZBInternet,mts,1,mts,1 +43601,default,Tcell,nil,1,nil,nil +43602,default,Tcell,nil,1,nil,nil +43603,default,Megafon,nil,1,nil,nil +43604,default,Babilon-M,nil,1,nil,nil +43605,default,Tacom,nil,1,nil,nil +43612,default,Tcell,nil,1,nil,nil +43701,default,Beeline,nil,1,nil,nil +43703,default,Fonex,nil,1,nil,nil +43705,default,MegaCom,nil,1,nil,nil +43709,default,O!,nil,1,nil,nil +43801,default,MTS(BARASHCommunication),nil,1,nil,nil +43802,default,TM-Cell,nil,1,nil,nil +44003,iijmio.jp,IIJmio(TypeI),iij,1,mio@iij,3 +44003,vmobile.jp,vmobile.jp,vmobile,1,vmobile@jp,3 +44010,spmode.ne.jp,sp-mode,nil,1,nil,nil +44010,mopera.net,moperaU,nil,1,nil,nil +44010,bmobile.ne.jp,b-mobileforNexus,bmobile,1,bmobile@nx,3 +44010,iijmio.jp,IIJmio,iij,1,mio@iij,3 +44010,3g-d-2.ocn.ne.jp,OCNモバイルONE(3G),mobile,1,mobileid@ocn,2 +44010,lte-d.ocn.ne.jp,OCNモバイルONE(LTE),mobile,1,mobileid@ocn,2 +44010,ratel.com,RATEL,ratel,1,ratel@ratel.com,3 +44020,plus.acs.jp,Application,ym,1,ym,2 +44020,ratel.com,RATEL,ratel,1,ratel@ratel.com,3 +44051,ratel.com,RATEL,ratel,1,ratel@ratel.com,3 +44051,a.rmobile.jp,Rakuten,0000,1,rakuten@vdm,3 +45005,lte.sktelecom.com,SKTLTEINTERNET,nil,1,nil,nil +45005,web.sktelecom.com,SKT3GINTERNET,nil,1,nil,nil +45005,lte-roaming.sktelecom.com,SKTLTERoaming,nil,1,nil,nil +45005,roaming.sktelecom.com,SKT3GRoaming,nil,1,nil,nil +45011,web.sktelecom.com,SKT3GINTERNET,nil,1,nil,nil +45011,lte-roaming.sktelecom.com,SKTLTERoaming,nil,1,nil,nil +45011,roaming.sktelecom.com,SKT3GRoaming,nil,1,nil,nil +45006,internet.lguplus.co.kr,LGuplus,nil,1,nil,nil +45006,lte-roaming.lguplus.co.kr,LGuplusLTERoaming,nil,1,nil,0 +45006,wroaming.lguplus.co.kr,LGuplusRoaming,nil,1,nil,0 +45008,lte.ktfwing.com,KT,nil,1,nil,nil +45201,m-wap,Mobi-wap-gprs2,mms,1,mms,1 +45202,m3-world,Vina-wap-gprs,mms,1,mms,1 +45204,v-internet,Viettel-wap-gprs1,nil,1,nil,nil +45204,v-wap,Viettel-wap-gprs2,nil,1,nil,nil +45205,internet,Vietnamobile_GPRS3,nil,1,nil,nil +45205,wap,Vietnamobile_GPRS1,nil,1,nil,nil +45207,internet,Gmobile-wap-gprs2,nil,1,nil,nil +45208,e-internet,e-internet,nil,1,nil,nil +45208,e-wap,e-wap,nil,1,nil,nil +45400,mobile,1O1O,nil,1,nil,3 +45400,NWMOBILE,NWMOBILE,nil,1,nil,3 +45402,mobile,1O1O,nil,1,nil,3 +45402,NWMOBILE,NWMOBILE,nil,1,nil,3 +45403,mobile.lte.three.com.hk,3LTE,nil,1,nil,1 +45403,mobile.three.com.hk,3,nil,1,nil,1 +45404,web-g.three.com.hk,3(2G)GPRS,nil,1,nil,nil +45406,SmarTone,SmarTone,nil,1,nil,3 +45408,iot.truphone.com,Truphone,nil,1,nil,nil +45410,hkcsl,one2free,nil,1,nil,3 +45412,cmhk,CMHKData,nil,1,nil,nil +45413,cmhk,CMHKData,nil,1,nil,nil +45415,SmarTone,SmarTone,nil,1,nil,3 +45416,pccw,PCCW-HKT,nil,1,nil,1 +45417,SmarTone,SmarTone,nil,1,nil,3 +45418,mobile,1O1O,nil,1,nil,3 +45418,NWMOBILE,NWMOBILE,nil,1,nil,3 +45419,pccw,PCCW-HKT,nil,1,nil,1 +45500,smartgprs,SmarToneMacau,nil,1,nil,3 +45501,ctm-mobile,CTMData,nil,1,nil,nil +45501,ctmprepaid,CTM(Prepaid),nil,1,nil,nil +45503,mobile.three.com.mo,3Macau,nil,1,nil,1 +45504,ctm-mobile,CTMData,nil,1,nil,nil +45504,ctmprepaid,CTM(Prepaid),nil,1,nil,nil +45505,mobile.three.com.mo,3Macau,nil,1,nil,1 +45601,default,Cellcard,nil,1,nil,nil +45602,default,Smart,nil,1,nil,nil +45604,default,qb,nil,1,nil,nil +45605,default,Star-Cell,nil,1,nil,nil +45606,default,Smart,nil,1,nil,nil +45608,default,Metfone,nil,1,nil,nil +45609,default,Beeline,nil,1,nil,nil +45611,default,Excell,nil,1,nil,nil +45618,default,Cellcard,nil,1,nil,nil +45701,default,LTC,nil,1,nil,nil +45702,default,ETL,nil,1,nil,nil +45703,default,Unitel,nil,1,nil,nil +45708,default,Beeline,nil,1,nil,nil +46000,cmnet,中国移动(ChinaMobile)GPRS,nil,1,nil,nil +46000,cmwap,中国移动(ChinaMobile)WAP,nil,1,nil,nil +46001,3gnet,沃3G连接互联网(ChinaUnicom),nil,1,nil,nil +46001,3gwap,沃3G手机上网(ChinaUnicom),nil,1,nil,nil +46001,uninet,联通2GNET上网(ChinaUnicom),nil,1,nil,nil +46002,cmnet,中国移动(ChinaMobile)GPRS,nil,1,nil,nil +46002,cmwap,中国移动(ChinaMobile)WAP,nil,1,nil,nil +46007,cmnet,中国移动(ChinaMobile)GPRS,nil,1,nil,nil +46008,cmnet,中国移动(ChinaMobile)GPRS,nil,1,nil,nil +46007,cmwap,中国移动(ChinaMobile)WAP,nil,1,nil,nil +46008,cmwap,中国移动(ChinaMobile)WAP,nil,1,nil,nil +46009,3gnet,ChinaUnicom3G,nil,1,nil,nil +46009,3gwap,ChinaUnicomwap,nil,1,nil,nil +46011,ctlte,ctlte,nil,1,nil,0 +46003,ctnet,CTNET,vnet.mobi,1,ctnet@mycdma.cn,3 +46003,ctwap,CTWAP,vnet.mobi,1,ctwap@mycdma.cn,3 +20404,ctnet,CTNET,nil,1,nil,0 +46601,internet,遠傳電信(FarEasTone)(Internet),nil,1,nil,nil +46688,internet,和信電訊(KGT-Online)(Internet),nil,1,nil,nil +46689,vibo,VIBO-vibo,nil,1,nil,nil +46689,internet,TStar-internet,nil,1,nil,nil +46689,viboone,VIBOONE,nil,1,nil,nil +46692,internet,中華電信(Chunghwa)(Internet),nil,1,nil,nil +46693,Internet,台灣大哥大(TWMobile)(Internet),nil,1,nil,nil +46697,Internet,台灣大哥大(TWMobile)(Internet),nil,1,nil,nil +46699,Internet,台灣大哥大(TWMobile)(Internet),nil,1,nil,nil +47001,gpinternet,GP-INTERNET,nil,1,nil,0 +47201,default,Dhiraagu,nil,1,nil,nil +47202,OoredooData,OoredooData,nil,1,nil,nil +50210,diginet,DiGiInternet,nil,1,nil,nil +50212,max4g,MaxisInternet,wap,1,maxis,1 +50213,celcom4g,CelcomInternet,nil,1,nil,nil +502143,diginet,DiGiInternet,nil,1,nil,nil +502145,celcom4g,CelcomInternet,nil,1,nil,nil +502146,diginet,DiGiInternet,nil,1,nil,nil +502148,celcom4g,CelcomInternet,nil,1,nil,nil +50216,diginet,DiGiInternet,nil,1,nil,nil +50217,max4g,MaxisInternet,wap,1,maxis,1 +50218,my3g,UMobileInternet,nil,1,nil,nil +50219,celcom4g,CelcomInternet,nil,1,nil,nil +50501,telstra.wap,TelstraInternet,nil,1,nil,nil +50501,telstra.internet,TelstraTethering,nil,1,nil,nil +50502,yesinternet,OptusYesInternet,nil,1,nil,nil +50503,live.vodafone.com,Vodafonelive!,nil,1,nil,nil +50506,3services,Planet3,nil,1,nil,0 +50507,vfinternet.au,VFInternet,nil,1,nil,nil +50511,Telstra.wap,TelstraInternet,nil,1,nil,nil +50512,3netaccess,3Internet,nil,1,nil,nil +50512,3services,3,nil,1,nil,nil +50538,iot.truphone.com,Truphone,nil,1,nil,nil +50571,Telstra.wap,TelstraInternet,nil,1,nil,nil +50572,Telstra.wap,TelstraInternet,nil,1,nil,nil +50588,vfinternet.au,VFInternet,nil,1,nil,nil +50590,internet,OptusInternet,nil,1,nil,nil +50599,live.vodafone.com,VodafoneLive!,nil,1,nil,nil +51001,indosatgprs,indosatgprs,nil,1,nil,1 +51008,AXIS,AXIS-SNS,nil,1,nil,1 +51008,AXIS,AXISwap,123456,1,axis,1 +51010,internet,internet,nil,1,nil,nil +51010,telkomsel,TSEL-WAP,wap123,1,wap,1 +51011,internet,Internet,nil,1,nil,1 +51021,indosatgprs,Indosat-SNS,nil,1,nil,1 +51021,indosatgprs,IndosatGPRS,indosat,1,indosat,1 +51089,3gprs,3-SNS,nil,1,nil,1 +51089,3gprs,3GPRS,3gprs,1,3gprs,1 +51401,default,Telin,nil,1,nil,nil +51402,default,TimorTelecom,nil,1,nil,nil +51403,default,ViettelTimor-Leste,nil,1,nil,nil +51502,internet.globe.com.ph,myGlobeInternet,nil,1,nil,nil +51502,http.globe.com.ph,myGlobeINET,nil,1,nil,nil +51502,www.globe.com.ph,myGlobeConnect,nil,1,nil,nil +51503,smartlte,SMARTLTE,nil,1,nil,nil +51503,internet,SMARTINTERNET,nil,1,nil,nil +51503,Smart1,SmartGPRS,nil,1,nil,nil +51505,minternet,SunInternet,nil,1,nil,nil +51505,wap,SUNWAPGPRS,nil,1,nil,nil +51505,fbband,SunSBW,nil,1,nil,nil +51518,redinternet,Redinternet,nil,1,nil,nil +52000,internet,CAT3GINTERNET,nil,1,nil,nil +52000,internet,TRUE-HINTERNET,true,1,true,1 +52001,internet,AISInternet,nil,1,nil,0 +52003,internet,AISInternet,nil,1,nil,0 +52004,internet,TRUE-HINTERNET,true,1,true,1 +52005,www.dtac.co.th,dtacInternet,nil,1,nil,nil +52015,internet,TOT3GInternet,nil,1,nil,nil +52018,www.dtac.co.th,dtacInternet,nil,1,nil,nil +52099,internet,TRUEINTERNET,true,1,true,1 +52501,e-ideas,SingTel(PostPaid),nil,1,nil,nil +52501,hicard,SingTel(PrePaid),nil,1,nil,nil +52502,e-ideas,SingTel(PostPaid),nil,1,nil,nil +52502,hicard,SingTel(PrePaid),nil,1,nil,nil +52503,sunsurf,SunsurfMobile,nil,1,nil,nil +52504,sunsurf,SunsurfMobile,nil,1,nil,nil +52505,shwap,SHDataPostpaid,nil,1,nil,nil +52802,default,B-Mobile,nil,1,nil,nil +52811,default,DSTCom,nil,1,nil,nil +53001,vodafone,VFNZInternet,nil,1,nil,nil +53005,Internet,Data,nil,1,nil,nil +53005,wapaccess.co.nz,Default,nil,1,nil,nil +53024,internet,2DegreesInternet,nil,1,nil,nil +53602,default,Digicel,nil,1,nil,nil +53701,default,BeMobile,nil,1,nil,nil +53703,wap.digicelpng.com,PNGWAP,nil,1,nil,nil +53703,internet.digicelpng.com,PNGWEB,nil,1,nil,nil +53703,wap.digicel.com.pg,PapuaNewGuinea,nil,1,nil,1 +53703,em,EMnify,nil,1,nil,nil +53901,default,U-Call,nil,1,nil,nil +53943,default,ShorelineCommunication,nil,1,nil,nil +53988,default,Digicel,nil,1,nil,nil +53988,wap,Tonga,nil,1,nil,1 +54001,default,BREEZE,nil,1,nil,nil +54002,default,BeMobile,nil,1,nil,nil +54100,default,AIL,nil,1,nil,nil +54101,default,SMILE,nil,1,nil,nil +54105,default,Digicel,nil,1,nil,nil +54105,wap,Vanatu,nil,1,nil,1 +54201,default,Vodafone,nil,1,nil,nil +54202,default,Digicel,nil,1,nil,nil +54202,wap,Fiji,nil,1,nil,1 +54411,default,Bluesky,nil,1,nil,nil +54501,default,Kiribati-TSKL,nil,1,nil,nil +54509,default,Kiribati-FrigateNet,nil,1,nil,nil +54601,default,Mobilis,nil,1,nil,nil +54720,default,Vini,nil,1,nil,nil +54801,default,TelecomCook,nil,1,nil,nil +54901,default,Digicel,nil,1,nil,nil +54927,default,Bluesky,nil,1,nil,nil +55001,default,FSMTC,nil,1,nil,nil +55101,default,MINTA,nil,1,nil,nil +55201,default,PNCC,nil,1,nil,nil +55280,default,PalauMobile,nil,1,nil,nil +60201,mobinilweb,MobinilWeb,nil,1,nil,nil +60201,mobinilwap,MobinilWAP,nil,1,nil,nil +60202,internet.vodafone.net,vodafoneinternet,internet,1,internet,3 +60202,wap.vodafone.com.eg,VodafoneWAP,wap,1,wap,3 +60203,etisalat,EtisalatWAP,nil,1,nil,nil +60301,wap,mobiliswap,wap,1,wap,1 +60301,internet,Mobilisinternet,internet,1,internet,1 +60302,djezzy.internet,djezzy.internet,nil,1,nil,nil +60303,internet,Ooredoointernet,nil,1,nil,1 +60400,internet.orange.ma,Internet,nil,1,nil,1 +60400,wap.meditel.ma,Imedia,MEDIWAP,1,MEDIWAP,1 +60401,wap.iamgprs.ma,MobileZone,nil,1,nil,nil +60401,www.iamgprs1.ma,InternetMobile,nil,1,nil,nil +60402,www.wana.ma,WEB,nil,1,nil,nil +60501,weborange,weborange,nil,1,nil,nil +60502,internet.tn,Internet,nil,1,nil,nil +60502,gprs.tn,InternetPortail,gprs,1,gprs,1 +60503,internet.ooredoo.tn,OoredooTNInternet,nil,1,nil,nil +60600,default,Libyana,nil,1,nil,nil +60601,default,Madar,nil,1,nil,nil +60602,default,Al-JeelPhone,nil,1,nil,nil +60603,default,LibyaPhone,nil,1,nil,nil +60606,default,HatefLibya,nil,1,nil,nil +60701,default,Gamcel,nil,1,nil,nil +60702,default,Africel,nil,1,nil,nil +60703,default,Comium,nil,1,nil,nil +60704,default,QCell,nil,1,nil,nil +60801,wap,OrangeWapSN,wap,1,wap,nil +60801,internet,OrangeWebSN,internet,1,internet,nil +60802,web.sentel.com,TigoInternetSN,nil,1,nil,nil +60803,expresso,ExpressoInternetSN,wap,1,wap,nil +60901,default,Mattel,nil,1,nil,nil +60902,default,Chinguitel,nil,1,nil,nil +60910,default,Mauritel,nil,1,nil,nil +61002,internet,Orange3G/4G,internet,1,internet,1 +61002,wap,OrangeWapML,wap,1,wap,nil +61101,default,OrangeS.A.,nil,1,nil,nil +61102,default,Sotelgui,nil,1,nil,nil +61103,default,TelecelGuinee,nil,1,nil,nil +61104,default,MTN,nil,1,nil,nil +61105,default,Cellcom,nil,1,nil,nil +61202,moov,MoovInternetCI,web,1,web,nil +61203,orangeciweb,Oweb,web,1,web,1 +61203,orangeciwap,OWORLDCI,wap,1,wap,nil +61204,gprs.koz.ci,KozInternetCI,web,1,web,nil +61205,web.mtn.ci,MTNInternetCI,vide,1,vide,nil +61301,default,Telmob,nil,1,nil,nil +61302,default,Airtel,nil,1,nil,nil +61303,default,TelecelFaso,nil,1,nil,nil +61404,orange.ne,OrangeInternet,nil,1,nil,nil +61501,default,TogoCell,nil,1,nil,nil +61503,default,Moov,nil,1,nil,nil +61601,default,Libercom,nil,1,nil,nil +61602,default,Moov,nil,1,nil,nil +61603,default,MTN,nil,1,nil,nil +61604,default,BBCOM,nil,1,nil,nil +61605,default,Glo,nil,1,nil,nil +61701,orange,OrangeInternet,nil,1,nil,nil +61801,default,LonestarCell,nil,1,nil,nil +61802,default,Libercell,nil,1,nil,nil +61804,default,Comium,nil,1,nil,nil +61807,Orange,Orange,nil,1,nil,nil +61820,default,LIBTELCO,nil,1,nil,nil +61901,default,Airtel,nil,1,nil,nil +61902,default,Tigo,nil,1,nil,nil +61903,default,Africell,nil,1,nil,nil +61904,default,Comium,nil,1,nil,nil +61905,default,Africell,nil,1,nil,nil +61925,default,Mobitel,nil,1,nil,nil +6200,glowap,Glo,nil,1,nil,0 +62001,internet,MTNInternetGH,nil,1,nil,nil +62002,browse,VodafoneInternetGH,nil,1,nil,nil +62003,web.tigo.com.gh,TigoInternetGH,nil,1,nil,nil +62006,wap,AirtelInternetGH,nil,1,nil,nil +62007,glowap,GloInternetGH,glo,1,glo,1 +62120,internet.ng.zain.com,AirtelInternet,internet,1,internet,1 +62120,wap.ng.zain.com,AirtelWAP,wap,1,wap,1 +62130,web.gprs.mtnnigeria.net,MTNWAP,web,1,web,1 +62150,glosecure,GloDirect,gprs,1,gprs,1 +62160,etisalat,etisalatWAP,nil,1,nil,nil +62201,default,Airtel,nil,1,nil,nil +62202,default,Tawali,nil,1,nil,nil +62203,default,Tigo,nil,1,nil,nil +62204,default,Salam,nil,1,nil,nil +62301,default,CTP,nil,1,nil,nil +62302,default,TC,nil,1,nil,nil +62303,orangeca3g,Internetbrowsing,nil,1,nil,nil +62304,default,Nationlink,nil,1,nil,nil +62501,default,CVMOVEL,nil,1,nil,nil +62502,default,T+,nil,1,nil,nil +62601,default,CSTmovel,nil,1,nil,nil +62701,default,OrangeGQ,nil,1,nil,nil +62703,default,HitsGQ,nil,1,nil,nil +62801,default,Libertis,nil,1,nil,nil +62802,default,Moov,nil,1,nil,nil +62803,default,Airtel,nil,1,nil,nil +62804,default,Azur,nil,1,nil,nil +62901,default,Airtel,nil,1,nil,nil +62910,default,LibertisTelecom,nil,1,nil,nil +63001,vodanet,VodacomInternetCD,nil,1,nil,nil +63089,tigo.web,TigoInternetCD,nil,1,nil,nil +63102,default,UNITEL,nil,1,nil,nil +63104,default,MOVICEL,nil,1,nil,nil +63202,default,Areeba,nil,1,nil,nil +63203,4Gogb,OrangeBissau,nil,1,nil,nil +63207,default,Guinetel,nil,1,nil,nil +63301,default,Cable&Wireless,nil,1,nil,nil +63302,default,MediatechInternational,nil,1,nil,nil +63310,default,Airtel,nil,1,nil,nil +63401,default,ZainSD,nil,1,nil,nil +63402,default,MTN,nil,1,nil,nil +63407,default,SudaniOne,nil,1,nil,nil +63409,default,PrivetNetwork,nil,1,nil,nil +63510,default,MTN,nil,1,nil,nil +63512,default,Rwandatel,nil,1,nil,nil +63513,default,Tigo,nil,1,nil,nil +63514,default,Airtel,nil,1,nil,nil +63601,default,ETH-MTN,nil,1,nil,nil +63701,default,Telesom,nil,1,nil,nil +63704,default,Somafone,nil,1,nil,nil +63710,default,Nationlink,nil,1,nil,nil +63725,default,Hormuud,nil,1,nil,nil +63730,default,Golis,nil,1,nil,nil +63757,default,Unittel,nil,1,nil,nil +63760,default,NationlinkTelecom,nil,1,nil,nil +63771,default,Somtel,nil,1,nil,nil +63782,default,Telcom,nil,1,nil,nil +63801,default,Evatis,nil,1,nil,nil +63902,safaricom,safaricomGPRS,data,1,saf,1 +63903,internet,AirtelInternet,nil,1,nil,nil +63903,ke.celtel.com,Airtel,nil,1,nil,nil +63905,Internet,YuInternet,nil,1,nil,nil +63905,Yuinternet,YuWAP,nil,1,nil,nil +63907,bew.orange.co.ke,OrangeInternet,nil,1,nil,nil +64004,Wap,VodacomWAP,nil,1,nil,nil +64101,internet,AirtelInternetUG,nil,1,nil,nil +64110,yellopix.mtn.co.ug,MTNInternetUG,nil,1,nil,nil +64111,utweb,UTLInternetUG,nil,1,nil,nil +64114,orange.ug,OrangeInternetUG,nil,1,nil,nil +64122,web.waridtel.co.ug,WaridTelecomInternetUG,nil,1,nil,nil +64201,default,Spacetel,nil,1,nil,nil +64202,default,Tempo,nil,1,nil,nil +64203,default,Onatel,nil,1,nil,nil +64207,default,SmartMobile,nil,1,nil,nil +64208,default,HiTsTelecom,nil,1,nil,nil +64282,default,Leo,nil,1,nil,nil +64301,default,mCel,nil,1,nil,nil +64303,default,Movitel,nil,1,nil,nil +64304,default,Vodacom,nil,1,nil,nil +64501,default,Airtel,nil,1,nil,nil +64502,default,MTN,nil,1,nil,nil +64503,default,ZAMTEL,nil,1,nil,nil +64602,orangenet,OrangeMGInternet,nil,1,nil,0 +64700,orangerun,OrangeWorldre,orange,1,orange,nil +64702,onlywap,OnlyWap,only,1,only,1 +64703,free.re,FreeRe,nil,1,nil,nil +64710,sl2sfr,FullInternetSRR,nil,1,nil,nil +64710,wapsfr,GPRSSRR,wap,1,wap,nil +64710,fnetcoriolis,CoriolisWAP,nil,1,nil,nil +64803,default,Telecel,nil,1,nil,nil +64804,default,Econet,nil,1,nil,nil +64901,default,MTC,nil,1,nil,nil +64902,default,switch,nil,1,nil,nil +64903,default,Leo,nil,1,nil,nil +65001,default,TNM,nil,1,nil,nil +65010,default,Airtel,nil,1,nil,nil +65101,internet,VCLInternetGPRS,nil,1,nil,nil +65310,default,SwaziMTN,nil,1,nil,nil +65401,default,HURI-SNPT,nil,1,nil,nil +65501,lte.vodacom.za,LTE.Vodacom,nil,1,nil,nil +65501,internet,Smart.Vodacom,nil,1,nil,nil +65502,internet,TelkomMobileInternet,nil,1,nil,nil +65507,internet,CellCGPRS,nil,1,nil,nil +65507,vdata,VIRGIN_INTERNET_1,nil,1,nil,nil +65510,myMTN,MTNGPRS,mtnwap,1,mtnwap,1 +65701,default,Eritel,nil,1,nil,nil +70267,default,DigiCell,nil,1,nil,nil +70299,default,Smart,nil,1,nil,nil +70401,internet.ideasclaro,InternetCLARO,nil,1,nil,nil +70402,broadband.tigo.gt,BroadbandTIGO,nil,1,nil,nil +70403,internet.movistar.gt,MovistarINTERNET,movistargt,1,movistargt,1 +704030,internet.movistar.gt,MovistarINTERNET,movistargt,1,movistargt,1 +70601,internet.ideasclaro,InternetCLARO,nil,1,nil,nil +70602,web.digicelsv.com,DigicelInternet,nil,1,nil,nil +70603,internet.tigo.sv,InternetTigo,nil,1,nil,nil +70604,internet.movistar.sv,MovistarINTERNET,movistarsv,1,movistarsv,1 +706040,internet.movistar.sv,MovistarINTERNET,movistarsv,1,movistarsv,1 +708001,internet.ideasclaro,InternetClaro,nil,1,nil,nil +70802,internet.tigo.hn,INTERNETTIGO,nil,1,nil,nil +70804,web.digicelhn.com,Honduras,nil,1,nil,1 +70804,wap.digicelhn.com,Honduras,nil,1,nil,1 +708020,internet.tigo.hn,INTERNETTIGO,nil,1,nil,nil +708040,web.digicelhn.com,Honduras,nil,1,nil,1 +71021,internet.ideasalo.ni,EnitelWEB,internet,1,internet,1 +71030,internet.movistar.ni,MovistarINTERNET,movistarni,1,movistarni,1 +710300,internet.movistar.ni,MovistarINTERNET,movistarni,1,movistarni,1 +71073,internet.ideasalo.ni,EnitelWEB,internet,1,internet,1 +710730,internet.ideasalo.ni,EnitelWEB,internet,1,internet,1 +71201,kolbi3g,KOLBI3G,nil,1,nil,nil +71201,kolbi,CostarRica,nil,1,nil,1 +71202,kolbi3g,KOLBI3G,nil,1,nil,nil +71203,internet.ideasclaro,InternetCLAROCR,nil,1,nil,nil +71204,internet.movistar.cr,MovistarINTERNET,movistarcr,1,movistarcr,1 +712019,tm7datos,InternetTuyo,nil,1,nil,nil +712190,tm7datos,InternetTuyo,nil,1,nil,nil +71220,datos.fullmovil.cr,InternetFullmovil,nil,1,nil,nil +71401,apn01.cwpanama.com.pa,Internet,nil,1,nil,nil +71402,internet.movistar.pa,MovistarINTERNET,movistarpa,1,movistarpa,1 +714020,internet.movistar.pa,MovistarINTERNET,movistarpa,1,movistarpa,1 +71403,web.claro.com.pa,WEBClaro,CLAROWEB,1,CLAROWEB,1 +71404,web.digicelpanama.com,DigicelInternet,nil,1,nil,nil +714040,web.digicelpanama.com,Panama,nil,1,nil,1 +71606,movistar.pe,MovistarINTERNET,movistar,1,movistar@datos,1 +71610,claro.pe,CLARODATOS,claro,1,claro,1 +71615,bitel,Bitel-Internet,nil,1,nil,1 +71617,entel.pe,EntelPE,nil,1,nil,0 +71617,location.entel.pe,EntelLocation,nil,1,nil,0 +72201,internet.movil,Quam_WEB,internet,1,internet,1 +72207,wap.gprs.unifon.com.ar,MovistarWAP,wap,1,wap,1 +72207,internet.gprs.unifon.com.ar,Argentina,internet,1,internet,1 +72231,igprs.claro.com.ar,ClaroAR,nil,1,nil,nil +722310,igprs.claro.com.ar,ClaroAR,nil,1,nil,nil +72234,datos.personal.com,PersonalDatos,datos,1,datos,1 +72234,internet.personal.com,Argentina,internet,1,internet,0 +72236,gprs.nuestro.com.ar,Argentina,nil,1,gprs,0 +722340,datos.personal.com,Argentina,adgj,1,gprs,0 +722340,internet.personal.com,Argentina,internet,1,internet,0 +722341,datos.personal.com,PersonalDatos,datos,1,datos,1 +722341,internet.personal.com,Argentina,internet,1,internet,0 +72402,timbrasil.br,TIMConnect,tim,1,tim,1 +72403,timbrasil.br,TIMConnect,tim,1,tim,1 +72404,timbrasil.br,TIMConnect,tim,1,tim,1 +72405,java.claro.com.br,JavaSession,claro,1,claro,nil +72406,zap.vivo.com.br,VivoInternet,vivo,1,vivo,1 +72407,sercomtel.com.br,SCTLGPRS,sercomtel,1,sercomtel,nil +72410,zap.vivo.com.br,VivoInternet,vivo,1,vivo,1 +72411,zap.vivo.com.br,VivoInternet,vivo,1,vivo,1 +72415,sercomtel.com.br,Sercomtel,sercomtel,1,sercomtel,1 +72416,gprs.oi.com.br,OiGPRSInternet,nil,1,nil,nil +72417,internet.br,Surf,nil,1,nil,1 +72419,gprs.telemigcelular.com.br,TelemigCGPRS,celular,1,celular,nil +72423,zap.vivo.com.br,VivoInternet,vivo,1,vivo,1 +72424,gprs.oi.com.br,OI,oi,1,oi,1 +72431,gprs.oi.com.br,OiGPRSInternet,nil,1,nil,nil +72432,ctbc.br,CTBC,1212,1,CTBC,1 +72433,ctbc.br,CTBC,1212,1,CTBC,1 +72434,ctbc.br,CTBC,1212,1,CTBC,1 +72439,wap.nextel3g.net.br,NextelWAP,nil,1,nil,0 +72454,portoconecta.br,PortoSeguroConecta,nil,1,nil,0 +73001,bam.entelpcs.cl,InternetMovil,entelpcs,1,entelpcs,1 +73009,wap.nextelmovil.cl,InternetNextel,nil,1,nil,0 +73010,bam.entelpcs.cl,InternetMovil,entelpcs,1,entelpcs,1 +73002,wap.tmovil.cl,MovistarAPLICACIONES,wap,1,wap,1 +73003,bam.clarochile.cl,BandaAnchaMovil,clarochile,1,clarochile,1 +73007,web.gtdmovil.cl,web,webgtd,1,webgtd,1 +73008,movil.vtr.com,Internet,vtrmovil,1,vtrmovil,2 +73008,wap.vtr.com,Wap,nil,1,nil,0 +73212,internet.movistar.com.co,MovistarINTERNET,movistar,1,movistar,1 +732101,internet.comcel.com.co,COMCEL,COMCELWEB,1,COMCELWEB,1 +732103,web.colombiamovil.com.co,TIGOWEB,nil,1,nil,1 +732103,moviletb.net.co,InternetETB,etb,1,etb,0 +732103,movilexito.net.co,InternetÉxito,nil,1,nil,1 +732103,www.une.net.co,UNE,une,1,une,0 +732111,web.colombiamovil.com.co,TIGOWEB,nil,1,nil,1 +732111,moviletb.net.co,InternetETB,etb,1,etb,0 +732111,movilexito.net.co,InternetÉxito,nil,1,nil,1 +732111,www.une.net.co,UNE,une,1,une,0 +732123,internet.movistar.com.co,MovistarINTERNET,movistar,1,movistar,1 +732123,web.vmc.net.co,VirginMobile,nil,1,nil,1 +732130,lte.avantel.com.co,Avantel,nil,1,nil,0 +732187,internetmovil.etb.net.co,ETB4G,nil,1,nil,0 +73401,internet.digitel.ve,Digitel412,nil,1,nil,nil +73401,gprsweb.digitel.ve,Venezuela,nil,1,nil,1 +73402,internet.digitel.ve,Digitel412,nil,1,nil,nil +73402,gprsweb.digitel.ve,Venezuela,nil,1,nil,1 +73403,internet.digitel.ve,Digitel412,nil,1,nil,nil +73403,gprsweb.digitel.ve,Venezuela,nil,1,nil,1 +73404,internet.movistar.ve,MovistarINTERNET,nil,1,nil,nil +73404,wap.movistar.ve,MovistarWAP,nil,1,nil,nil +73406,int.movilnet.com.ve,MODEM,nil,1,nil,nil +73601,internet.nuevatel.com,VIVA3G,nil,1,nil,1 +73602,wap.movil.com.bo,ENTELWAPGPRS,nil,1,nil,1 +73603,wap.tigo.bo,WAPTIGO,nil,1,nil,1 +73801,default,Digicel,nil,1,nil,nil +73801,wap.digicelgy.com,Guyana,wap,1,wap,1 +73802,default,GT&TCellinkPlus,nil,1,nil,nil +74000,internet.movistar.com.ec,MovistarINTERNET,movistar,1,movistar,1 +74001,internet.claro.com.ec,InternetClaro,nil,1,nil,nil +740010,internet.claro.com.ec,InternetClaro,nil,1,nil,nil +74002,internet3gsp.alegro.net.ec,CNT3G,nil,1,nil,nil +74401,vox.internet,VOXINTERNET,nil,1,nil,1 +74401,vox.wap,Paraguay,nil,1,nil,1 +74402,igprs.claro.com.py,ClaroPY,ctigprs999,1,ctigprs,1 +74404,internet.tigo.py,TIGOPY,nil,1,nil,1 +74405,internet,PersonalDatosPy,personal,1,personal,1 +74602,default,Telesur,nil,1,nil,nil +74603,web.digicelsr.com,Suriname,nil,1,nil,1 +74603,wap.digicelsr.com,Suriname,wap,1,wap,1 +74801,wap,wapANCEL,nil,1,nil,1 +74801,gprs.ancel,gprsANCEL,nil,1,nil,1 +74807,webapn.movistar.com.uy,MovistarINTERNET,movistar,1,movistar,1 +74810,igprs.claro.com.uy,ClaroUY,ctigprs999,1,ctigprs,1 +28310,Internet,OrangeArmeniaInternet,nil,1,nil,1 +65202,internet.orange.co.bw,OrangeWAPBW,nil,1,nil,nil +62402,orangecmgprs,OrangeCM,orange,1,orange,nil +64602,orangeworld,OrangeWorldMG,orange,1,world,nil +90128,ciot.vodafone.com,CIOTVodafone,vodafone,1,vodafone,nil +90137,mobiledata,mobiledata,nil,1,nil,nil +90143,em,EMnify,nil,1,nil,nil +90158,bicsapn,BICSInternet,nil,1,nil,nil +25050,internet.sberbank-tele.com,Sberbank-TelecomInternet,nil,1,nil,nil +20630,web.be,Unleashed,nil,1,nil,nil +22207,web.kenamobile.it,KenaMobileWeb,nil,1,nil,nil +50519,data.lycamobile.com.au,Lycamobile,nil,1,nil,1 +24223,data.lyca-mobile.no,Lycamobile,nil,1,nil,1 +22854,data.lycamobile.ch,Lycamobile,nil,1,nil,1 +23208,data.lycamobile.at,Lycamobile,nil,1,nil,1 +20606,data.lycamobile.be,Lycamobile,nil,1,nil,1 +26243,data.lycamobile.de,Lycamobile,nil,1,nil,1 +23812,data.lycamobile.dk,Lycamobile,nil,1,nil,1 +21425,data.lycamobile.es,Lycamobile,nil,1,nil,1 +20825,data.lycamobile.fr,Lycamobile,nil,1,nil,1 +27213,data.lycamobile.ie,Lycamobile,nil,1,nil,1 +20409,data.lycamobile.nl,Lycamobile,nil,1,nil,1 +26009,data.lycamobile.pl,Lycamobile,nil,1,nil,1 +26804,data.lycamobile.pt,Lycamobile,nil,1,nil,1 +22616,data.lycamobile.ro,Lycamobile,nil,1,nil,1 +24012,data.lycamobile.se,Lycamobile,nil,1,nil,1 +22235,data.lycamobile.it,Lycamobile,nil,1,nil,1 +311960,data.lycamobile.com,Lycamobile,nil,1,nil,1 +64126,data.lycamobile.ug,Lycamobile,nil,1,nil,1 +29404,data.lycamobile.mk,Lycamobile,nil,1,nil,1 +65553,data.lycamobile.co.za,Lycamobile,nil,1,nil,1 +23457,mobile.sky,Internet,nil,1,nil,0 +29701,flat,Internet,nil,1,nil,3 +29701,internet,Internet,nil,1,nil,3 +29702,tmcg-4g,TelekomInternet,38267,1,38267,1 +29703,mtelinternet,mTelInternet,068,1,internet,2 +40421,jionet,Jio,nil,1,nil,3 +404854,jionet,Jio,nil,1,nil,3 +404855,jionet,Jio,nil,1,nil,3 +404856,jionet,Jio,nil,1,nil,3 +404857,jionet,Jio,nil,1,nil,3 +404858,jionet,Jio,nil,1,nil,3 +404859,jionet,Jio,nil,1,nil,3 +404860,jionet,Jio,nil,1,nil,3 +404861,jionet,Jio,nil,1,nil,3 +404862,jionet,Jio,nil,1,nil,3 +404863,jionet,Jio,nil,1,nil,3 +404864,jionet,Jio,nil,1,nil,3 +404865,jionet,Jio,nil,1,nil,3 +404866,jionet,Jio,nil,1,nil,3 +404867,jionet,Jio,nil,1,nil,3 +404868,jionet,Jio,nil,1,nil,3 +404869,jionet,Jio,nil,1,nil,3 +404870,jionet,Jio,nil,1,nil,3 +404871,jionet,Jio,nil,1,nil,3 +404872,jionet,Jio,nil,1,nil,3 +404873,jionet,Jio,nil,1,nil,3 +404874,jionet,Jio,nil,1,nil,3 +22801,shared.m2m.ch,SwisscomM2M,nil,1,nil,0 +27202,Open.internet,3Ireland,nil,1,nil,nil +24008,services.telenor.se,TelenorMobilsurf,nil,1,nil,nil +310410,accessrgn.net,AT&T,nil,1,nil,nil +24603,static.tele2.lt,Tele2,nil,1,nil,nil +24602,bangapro,Bite,nil,1,nil,nil +24601,gprs.fix-ip.omnitel1.net,Telia,nil,1,nil,nil +20404,truphone.com,Truphone,nil,1,nil,nil +20433,truphone.com,Truphone,nil,1,nil,nil +20809,truphone.com,Truphone,nil,1,nil,nil +20812,truphone.com,Truphone,nil,1,nil,nil +21427,truphone.com,Truphone,nil,1,nil,nil +23425,truphone.com,Truphone,nil,1,nil,nil +26033,truphone.com,Truphone,nil,1,nil,nil +26242,truphone.com,Truphone,nil,1,nil,nil +31030,truphone.com,Truphone,nil,1,nil,nil +310300,truphone.com,Truphone,nil,1,nil,nil +45408,truphone.com,Truphone,nil,1,nil,nil +50538,truphone.com,Truphone,nil,1,nil,nil +50502,truphone.com,Truphone,nil,1,nil,nil +20828,datapro,AIF,nil,1,nil,nil +90140,iot.1nce.net,1NCE,nil,1,nil,nil +00101,internet,Amarisoft,nil,1,nil,nil +00101,default,Amarisoft,nil,1,nil,nil +40001,internet,Azercell,nil,1,nil,nil +310004,VZWINTERNET,Verizon,nil,3,nil,nil +310010,VZWINTERNET,Verizon,nil,3,nil,nil +310012,VZWINTERNET,Verizon,nil,3,nil,nil +310013,VZWINTERNET,Verizon,nil,3,nil,nil +310350,VZWINTERNET,Verizon,nil,3,nil,nil +310590,VZWINTERNET,Verizon,nil,3,nil,nil +310591,VZWINTERNET,Verizon,nil,3,nil,nil +310592,VZWINTERNET,Verizon,nil,3,nil,nil +310593,VZWINTERNET,Verizon,nil,3,nil,nil +310594,VZWINTERNET,Verizon,nil,3,nil,nil +310595,VZWINTERNET,Verizon,nil,3,nil,nil +310596,VZWINTERNET,Verizon,nil,3,nil,nil +310597,VZWINTERNET,Verizon,nil,3,nil,nil +310598,VZWINTERNET,Verizon,nil,3,nil,nil +310599,VZWINTERNET,Verizon,nil,3,nil,nil +310820,VZWINTERNET,Verizon,nil,3,nil,nil +310890,VZWINTERNET,Verizon,nil,3,nil,nil +310891,VZWINTERNET,Verizon,nil,3,nil,nil +310892,VZWINTERNET,Verizon,nil,3,nil,nil +310893,VZWINTERNET,Verizon,nil,3,nil,nil +310894,VZWINTERNET,Verizon,nil,3,nil,nil +310895,VZWINTERNET,Verizon,nil,3,nil,nil +310896,VZWINTERNET,Verizon,nil,3,nil,nil +310897,VZWINTERNET,Verizon,nil,3,nil,nil +310898,VZWINTERNET,Verizon,nil,3,nil,nil +310899,VZWINTERNET,Verizon,nil,3,nil,nil +310910,VZWINTERNET,Verizon,nil,3,nil,nil +311110,VZWINTERNET,Verizon,nil,3,nil,nil +311270,VZWINTERNET,Verizon,nil,3,nil,nil +311271,VZWINTERNET,Verizon,nil,3,nil,nil +311272,VZWINTERNET,Verizon,nil,3,nil,nil +311273,VZWINTERNET,Verizon,nil,3,nil,nil +311274,VZWINTERNET,Verizon,nil,3,nil,nil +311275,VZWINTERNET,Verizon,nil,3,nil,nil +311276,VZWINTERNET,Verizon,nil,3,nil,nil +311277,VZWINTERNET,Verizon,nil,3,nil,nil +311278,VZWINTERNET,Verizon,nil,3,nil,nil +311279,VZWINTERNET,Verizon,nil,3,nil,nil +311280,VZWINTERNET,Verizon,nil,3,nil,nil +311281,VZWINTERNET,Verizon,nil,3,nil,nil +311282,VZWINTERNET,Verizon,nil,3,nil,nil +311283,VZWINTERNET,Verizon,nil,3,nil,nil +311284,VZWINTERNET,Verizon,nil,3,nil,nil +311285,VZWINTERNET,Verizon,nil,3,nil,nil +311286,VZWINTERNET,Verizon,nil,3,nil,nil +311287,VZWINTERNET,Verizon,nil,3,nil,nil +311288,VZWINTERNET,Verizon,nil,3,nil,nil +311289,VZWINTERNET,Verizon,nil,3,nil,nil +311390,VZWINTERNET,Verizon,nil,3,nil,nil +311480,VZWINTERNET,Verizon,nil,3,nil,nil +311481,VZWINTERNET,Verizon,nil,3,nil,nil +311482,VZWINTERNET,Verizon,nil,3,nil,nil +311483,VZWINTERNET,Verizon,nil,3,nil,nil +311484,VZWINTERNET,Verizon,nil,3,nil,nil +311485,VZWINTERNET,Verizon,nil,3,nil,nil +311486,VZWINTERNET,Verizon,nil,3,nil,nil +311487,VZWINTERNET,Verizon,nil,3,nil,nil +311488,VZWINTERNET,Verizon,nil,3,nil,nil +311489,VZWINTERNET,Verizon,nil,3,nil,nil +311590,VZWINTERNET,Verizon,nil,3,nil,nil +312040,VZWINTERNET,Verizon,nil,3,nil,nil +312160,VZWINTERNET,Verizon,nil,3,nil,nil +312770,VZWINTERNET,Verizon,nil,3,nil,nil +310010,VZWINTERNET,Verizon,nil,3,nil,nil +310012,VZWINTERNET,Verizon,nil,3,nil,nil +310004,ne01.vzwstatic,Verizon,nil,3,nil,nil +310010,ne01.vzwstatic,Verizon,nil,3,nil,nil +310012,ne01.vzwstatic,Verizon,nil,3,nil,nil +310013,ne01.vzwstatic,Verizon,nil,3,nil,nil +310350,ne01.vzwstatic,Verizon,nil,3,nil,nil +310590,ne01.vzwstatic,Verizon,nil,3,nil,nil +310591,ne01.vzwstatic,Verizon,nil,3,nil,nil +310592,ne01.vzwstatic,Verizon,nil,3,nil,nil +310593,ne01.vzwstatic,Verizon,nil,3,nil,nil +310594,ne01.vzwstatic,Verizon,nil,3,nil,nil +310595,ne01.vzwstatic,Verizon,nil,3,nil,nil +310596,ne01.vzwstatic,Verizon,nil,3,nil,nil +310597,ne01.vzwstatic,Verizon,nil,3,nil,nil +310598,ne01.vzwstatic,Verizon,nil,3,nil,nil +310599,ne01.vzwstatic,Verizon,nil,3,nil,nil +310820,ne01.vzwstatic,Verizon,nil,3,nil,nil +310890,ne01.vzwstatic,Verizon,nil,3,nil,nil +310891,ne01.vzwstatic,Verizon,nil,3,nil,nil +310892,ne01.vzwstatic,Verizon,nil,3,nil,nil +310893,ne01.vzwstatic,Verizon,nil,3,nil,nil +310894,ne01.vzwstatic,Verizon,nil,3,nil,nil +310895,ne01.vzwstatic,Verizon,nil,3,nil,nil +310896,ne01.vzwstatic,Verizon,nil,3,nil,nil +310897,ne01.vzwstatic,Verizon,nil,3,nil,nil +310898,ne01.vzwstatic,Verizon,nil,3,nil,nil +310899,ne01.vzwstatic,Verizon,nil,3,nil,nil +310910,ne01.vzwstatic,Verizon,nil,3,nil,nil +311110,ne01.vzwstatic,Verizon,nil,3,nil,nil +311270,ne01.vzwstatic,Verizon,nil,3,nil,nil +311271,ne01.vzwstatic,Verizon,nil,3,nil,nil +311272,ne01.vzwstatic,Verizon,nil,3,nil,nil +311273,ne01.vzwstatic,Verizon,nil,3,nil,nil +311274,ne01.vzwstatic,Verizon,nil,3,nil,nil +311275,ne01.vzwstatic,Verizon,nil,3,nil,nil +311276,ne01.vzwstatic,Verizon,nil,3,nil,nil +311277,ne01.vzwstatic,Verizon,nil,3,nil,nil +311278,ne01.vzwstatic,Verizon,nil,3,nil,nil +311279,ne01.vzwstatic,Verizon,nil,3,nil,nil +311280,ne01.vzwstatic,Verizon,nil,3,nil,nil +311281,ne01.vzwstatic,Verizon,nil,3,nil,nil +311282,ne01.vzwstatic,Verizon,nil,3,nil,nil +311283,ne01.vzwstatic,Verizon,nil,3,nil,nil +311284,ne01.vzwstatic,Verizon,nil,3,nil,nil +311285,ne01.vzwstatic,Verizon,nil,3,nil,nil +311286,ne01.vzwstatic,Verizon,nil,3,nil,nil +311287,ne01.vzwstatic,Verizon,nil,3,nil,nil +311288,ne01.vzwstatic,Verizon,nil,3,nil,nil +311289,ne01.vzwstatic,Verizon,nil,3,nil,nil +311390,ne01.vzwstatic,Verizon,nil,3,nil,nil +311480,ne01.vzwstatic,Verizon,nil,3,nil,nil +311481,ne01.vzwstatic,Verizon,nil,3,nil,nil +311482,ne01.vzwstatic,Verizon,nil,3,nil,nil +311483,ne01.vzwstatic,Verizon,nil,3,nil,nil +311484,ne01.vzwstatic,Verizon,nil,3,nil,nil +311485,ne01.vzwstatic,Verizon,nil,3,nil,nil +311486,ne01.vzwstatic,Verizon,nil,3,nil,nil +311487,ne01.vzwstatic,Verizon,nil,3,nil,nil +311488,ne01.vzwstatic,Verizon,nil,3,nil,nil +311489,ne01.vzwstatic,Verizon,nil,3,nil,nil +311590,ne01.vzwstatic,Verizon,nil,3,nil,nil +312040,ne01.vzwstatic,Verizon,nil,3,nil,nil +312160,ne01.vzwstatic,Verizon,nil,3,nil,nil +312770,ne01.vzwstatic,Verizon,nil,3,nil,nil +310004,nw01.vzwstatic,Verizon,nil,3,nil,nil +310010,nw01.vzwstatic,Verizon,nil,3,nil,nil +310012,nw01.vzwstatic,Verizon,nil,3,nil,nil +310013,nw01.vzwstatic,Verizon,nil,3,nil,nil +310350,nw01.vzwstatic,Verizon,nil,3,nil,nil +310590,nw01.vzwstatic,Verizon,nil,3,nil,nil +310591,nw01.vzwstatic,Verizon,nil,3,nil,nil +310592,nw01.vzwstatic,Verizon,nil,3,nil,nil +310593,nw01.vzwstatic,Verizon,nil,3,nil,nil +310594,nw01.vzwstatic,Verizon,nil,3,nil,nil +310595,nw01.vzwstatic,Verizon,nil,3,nil,nil +310596,nw01.vzwstatic,Verizon,nil,3,nil,nil +310597,nw01.vzwstatic,Verizon,nil,3,nil,nil +310598,nw01.vzwstatic,Verizon,nil,3,nil,nil +310599,nw01.vzwstatic,Verizon,nil,3,nil,nil +310820,nw01.vzwstatic,Verizon,nil,3,nil,nil +310890,nw01.vzwstatic,Verizon,nil,3,nil,nil +310891,nw01.vzwstatic,Verizon,nil,3,nil,nil +310892,nw01.vzwstatic,Verizon,nil,3,nil,nil +310893,nw01.vzwstatic,Verizon,nil,3,nil,nil +310894,nw01.vzwstatic,Verizon,nil,3,nil,nil +310895,nw01.vzwstatic,Verizon,nil,3,nil,nil +310896,nw01.vzwstatic,Verizon,nil,3,nil,nil +310897,nw01.vzwstatic,Verizon,nil,3,nil,nil +310898,nw01.vzwstatic,Verizon,nil,3,nil,nil +310899,nw01.vzwstatic,Verizon,nil,3,nil,nil +310910,nw01.vzwstatic,Verizon,nil,3,nil,nil +311110,nw01.vzwstatic,Verizon,nil,3,nil,nil +311270,nw01.vzwstatic,Verizon,nil,3,nil,nil +311271,nw01.vzwstatic,Verizon,nil,3,nil,nil +311272,nw01.vzwstatic,Verizon,nil,3,nil,nil +311273,nw01.vzwstatic,Verizon,nil,3,nil,nil +311274,nw01.vzwstatic,Verizon,nil,3,nil,nil +311275,nw01.vzwstatic,Verizon,nil,3,nil,nil +311276,nw01.vzwstatic,Verizon,nil,3,nil,nil +311277,nw01.vzwstatic,Verizon,nil,3,nil,nil +311278,nw01.vzwstatic,Verizon,nil,3,nil,nil +311279,nw01.vzwstatic,Verizon,nil,3,nil,nil +311280,nw01.vzwstatic,Verizon,nil,3,nil,nil +311281,nw01.vzwstatic,Verizon,nil,3,nil,nil +311282,nw01.vzwstatic,Verizon,nil,3,nil,nil +311283,nw01.vzwstatic,Verizon,nil,3,nil,nil +311284,nw01.vzwstatic,Verizon,nil,3,nil,nil +311285,nw01.vzwstatic,Verizon,nil,3,nil,nil +311286,nw01.vzwstatic,Verizon,nil,3,nil,nil +311287,nw01.vzwstatic,Verizon,nil,3,nil,nil +311288,nw01.vzwstatic,Verizon,nil,3,nil,nil +311289,nw01.vzwstatic,Verizon,nil,3,nil,nil +311390,nw01.vzwstatic,Verizon,nil,3,nil,nil +311480,nw01.vzwstatic,Verizon,nil,3,nil,nil +311481,nw01.vzwstatic,Verizon,nil,3,nil,nil +311482,nw01.vzwstatic,Verizon,nil,3,nil,nil +311483,nw01.vzwstatic,Verizon,nil,3,nil,nil +311484,nw01.vzwstatic,Verizon,nil,3,nil,nil +311485,nw01.vzwstatic,Verizon,nil,3,nil,nil +311486,nw01.vzwstatic,Verizon,nil,3,nil,nil +311487,nw01.vzwstatic,Verizon,nil,3,nil,nil +311488,nw01.vzwstatic,Verizon,nil,3,nil,nil +311489,nw01.vzwstatic,Verizon,nil,3,nil,nil +311590,nw01.vzwstatic,Verizon,nil,3,nil,nil +312040,nw01.vzwstatic,Verizon,nil,3,nil,nil +312160,nw01.vzwstatic,Verizon,nil,3,nil,nil +312770,nw01.vzwstatic,Verizon,nil,3,nil,nil +310004,so01.vzwstatic,Verizon,nil,3,nil,nil +310010,so01.vzwstatic,Verizon,nil,3,nil,nil +310012,so01.vzwstatic,Verizon,nil,3,nil,nil +310013,so01.vzwstatic,Verizon,nil,3,nil,nil +310350,so01.vzwstatic,Verizon,nil,3,nil,nil +310590,so01.vzwstatic,Verizon,nil,3,nil,nil +310591,so01.vzwstatic,Verizon,nil,3,nil,nil +310592,so01.vzwstatic,Verizon,nil,3,nil,nil +310593,so01.vzwstatic,Verizon,nil,3,nil,nil +310594,so01.vzwstatic,Verizon,nil,3,nil,nil +310595,so01.vzwstatic,Verizon,nil,3,nil,nil +310596,so01.vzwstatic,Verizon,nil,3,nil,nil +310597,so01.vzwstatic,Verizon,nil,3,nil,nil +310598,so01.vzwstatic,Verizon,nil,3,nil,nil +310599,so01.vzwstatic,Verizon,nil,3,nil,nil +310820,so01.vzwstatic,Verizon,nil,3,nil,nil +310890,so01.vzwstatic,Verizon,nil,3,nil,nil +310891,so01.vzwstatic,Verizon,nil,3,nil,nil +310892,so01.vzwstatic,Verizon,nil,3,nil,nil +310893,so01.vzwstatic,Verizon,nil,3,nil,nil +310894,so01.vzwstatic,Verizon,nil,3,nil,nil +310895,so01.vzwstatic,Verizon,nil,3,nil,nil +310896,so01.vzwstatic,Verizon,nil,3,nil,nil +310897,so01.vzwstatic,Verizon,nil,3,nil,nil +310898,so01.vzwstatic,Verizon,nil,3,nil,nil +310899,so01.vzwstatic,Verizon,nil,3,nil,nil +310910,so01.vzwstatic,Verizon,nil,3,nil,nil +311110,so01.vzwstatic,Verizon,nil,3,nil,nil +311270,so01.vzwstatic,Verizon,nil,3,nil,nil +311271,so01.vzwstatic,Verizon,nil,3,nil,nil +311272,so01.vzwstatic,Verizon,nil,3,nil,nil +311273,so01.vzwstatic,Verizon,nil,3,nil,nil +311274,so01.vzwstatic,Verizon,nil,3,nil,nil +311275,so01.vzwstatic,Verizon,nil,3,nil,nil +311276,so01.vzwstatic,Verizon,nil,3,nil,nil +311277,so01.vzwstatic,Verizon,nil,3,nil,nil +311278,so01.vzwstatic,Verizon,nil,3,nil,nil +311279,so01.vzwstatic,Verizon,nil,3,nil,nil +311280,so01.vzwstatic,Verizon,nil,3,nil,nil +311281,so01.vzwstatic,Verizon,nil,3,nil,nil +311282,so01.vzwstatic,Verizon,nil,3,nil,nil +311283,so01.vzwstatic,Verizon,nil,3,nil,nil +311284,so01.vzwstatic,Verizon,nil,3,nil,nil +311285,so01.vzwstatic,Verizon,nil,3,nil,nil +311286,so01.vzwstatic,Verizon,nil,3,nil,nil +311287,so01.vzwstatic,Verizon,nil,3,nil,nil +311288,so01.vzwstatic,Verizon,nil,3,nil,nil +311289,so01.vzwstatic,Verizon,nil,3,nil,nil +311390,so01.vzwstatic,Verizon,nil,3,nil,nil +311480,so01.vzwstatic,Verizon,nil,3,nil,nil +311481,so01.vzwstatic,Verizon,nil,3,nil,nil +311482,so01.vzwstatic,Verizon,nil,3,nil,nil +311483,so01.vzwstatic,Verizon,nil,3,nil,nil +311484,so01.vzwstatic,Verizon,nil,3,nil,nil +311485,so01.vzwstatic,Verizon,nil,3,nil,nil +311486,so01.vzwstatic,Verizon,nil,3,nil,nil +311487,so01.vzwstatic,Verizon,nil,3,nil,nil +311488,so01.vzwstatic,Verizon,nil,3,nil,nil +311489,so01.vzwstatic,Verizon,nil,3,nil,nil +311590,so01.vzwstatic,Verizon,nil,3,nil,nil +312040,so01.vzwstatic,Verizon,nil,3,nil,nil +312160,so01.vzwstatic,Verizon,nil,3,nil,nil +312770,so01.vzwstatic,Verizon,nil,3,nil,nil +310004,mw01.vzwstatic,Verizon,nil,3,nil,nil +310010,mw01.vzwstatic,Verizon,nil,3,nil,nil +310012,mw01.vzwstatic,Verizon,nil,3,nil,nil +310013,mw01.vzwstatic,Verizon,nil,3,nil,nil +310350,mw01.vzwstatic,Verizon,nil,3,nil,nil +310590,mw01.vzwstatic,Verizon,nil,3,nil,nil +310591,mw01.vzwstatic,Verizon,nil,3,nil,nil +310592,mw01.vzwstatic,Verizon,nil,3,nil,nil +310593,mw01.vzwstatic,Verizon,nil,3,nil,nil +310594,mw01.vzwstatic,Verizon,nil,3,nil,nil +310595,mw01.vzwstatic,Verizon,nil,3,nil,nil +310596,mw01.vzwstatic,Verizon,nil,3,nil,nil +310597,mw01.vzwstatic,Verizon,nil,3,nil,nil +310598,mw01.vzwstatic,Verizon,nil,3,nil,nil +310599,mw01.vzwstatic,Verizon,nil,3,nil,nil +310820,mw01.vzwstatic,Verizon,nil,3,nil,nil +310890,mw01.vzwstatic,Verizon,nil,3,nil,nil +310891,mw01.vzwstatic,Verizon,nil,3,nil,nil +310892,mw01.vzwstatic,Verizon,nil,3,nil,nil +310893,mw01.vzwstatic,Verizon,nil,3,nil,nil +310894,mw01.vzwstatic,Verizon,nil,3,nil,nil +310895,mw01.vzwstatic,Verizon,nil,3,nil,nil +310896,mw01.vzwstatic,Verizon,nil,3,nil,nil +310897,mw01.vzwstatic,Verizon,nil,3,nil,nil +310898,mw01.vzwstatic,Verizon,nil,3,nil,nil +310899,mw01.vzwstatic,Verizon,nil,3,nil,nil +310910,mw01.vzwstatic,Verizon,nil,3,nil,nil +311110,mw01.vzwstatic,Verizon,nil,3,nil,nil +311270,mw01.vzwstatic,Verizon,nil,3,nil,nil +311271,mw01.vzwstatic,Verizon,nil,3,nil,nil +311272,mw01.vzwstatic,Verizon,nil,3,nil,nil +311273,mw01.vzwstatic,Verizon,nil,3,nil,nil +311274,mw01.vzwstatic,Verizon,nil,3,nil,nil +311275,mw01.vzwstatic,Verizon,nil,3,nil,nil +311276,mw01.vzwstatic,Verizon,nil,3,nil,nil +311277,mw01.vzwstatic,Verizon,nil,3,nil,nil +311278,mw01.vzwstatic,Verizon,nil,3,nil,nil +311279,mw01.vzwstatic,Verizon,nil,3,nil,nil +311280,mw01.vzwstatic,Verizon,nil,3,nil,nil +311281,mw01.vzwstatic,Verizon,nil,3,nil,nil +311282,mw01.vzwstatic,Verizon,nil,3,nil,nil +311283,mw01.vzwstatic,Verizon,nil,3,nil,nil +311284,mw01.vzwstatic,Verizon,nil,3,nil,nil +311285,mw01.vzwstatic,Verizon,nil,3,nil,nil +311286,mw01.vzwstatic,Verizon,nil,3,nil,nil +311287,mw01.vzwstatic,Verizon,nil,3,nil,nil +311288,mw01.vzwstatic,Verizon,nil,3,nil,nil +311289,mw01.vzwstatic,Verizon,nil,3,nil,nil +311390,mw01.vzwstatic,Verizon,nil,3,nil,nil +311480,mw01.vzwstatic,Verizon,nil,3,nil,nil +311481,mw01.vzwstatic,Verizon,nil,3,nil,nil +311482,mw01.vzwstatic,Verizon,nil,3,nil,nil +311483,mw01.vzwstatic,Verizon,nil,3,nil,nil +311484,mw01.vzwstatic,Verizon,nil,3,nil,nil +311485,mw01.vzwstatic,Verizon,nil,3,nil,nil +311486,mw01.vzwstatic,Verizon,nil,3,nil,nil +311487,mw01.vzwstatic,Verizon,nil,3,nil,nil +311488,mw01.vzwstatic,Verizon,nil,3,nil,nil +311489,mw01.vzwstatic,Verizon,nil,3,nil,nil +311590,mw01.vzwstatic,Verizon,nil,3,nil,nil +312040,mw01.vzwstatic,Verizon,nil,3,nil,nil +312160,mw01.vzwstatic,Verizon,nil,3,nil,nil +312770,mw01.vzwstatic,Verizon,nil,3,nil,nil +310004,we01.vzwstatic,Verizon,nil,3,nil,nil +310010,we01.vzwstatic,Verizon,nil,3,nil,nil +310012,we01.vzwstatic,Verizon,nil,3,nil,nil +310013,we01.vzwstatic,Verizon,nil,3,nil,nil +310350,we01.vzwstatic,Verizon,nil,3,nil,nil +310590,we01.vzwstatic,Verizon,nil,3,nil,nil +310591,we01.vzwstatic,Verizon,nil,3,nil,nil +310592,we01.vzwstatic,Verizon,nil,3,nil,nil +310593,we01.vzwstatic,Verizon,nil,3,nil,nil +310594,we01.vzwstatic,Verizon,nil,3,nil,nil +310595,we01.vzwstatic,Verizon,nil,3,nil,nil +310596,we01.vzwstatic,Verizon,nil,3,nil,nil +310597,we01.vzwstatic,Verizon,nil,3,nil,nil +310598,we01.vzwstatic,Verizon,nil,3,nil,nil +310599,we01.vzwstatic,Verizon,nil,3,nil,nil +310820,we01.vzwstatic,Verizon,nil,3,nil,nil +310890,we01.vzwstatic,Verizon,nil,3,nil,nil +310891,we01.vzwstatic,Verizon,nil,3,nil,nil +310892,we01.vzwstatic,Verizon,nil,3,nil,nil +310893,we01.vzwstatic,Verizon,nil,3,nil,nil +310894,we01.vzwstatic,Verizon,nil,3,nil,nil +310895,we01.vzwstatic,Verizon,nil,3,nil,nil +310896,we01.vzwstatic,Verizon,nil,3,nil,nil +310897,we01.vzwstatic,Verizon,nil,3,nil,nil +310898,we01.vzwstatic,Verizon,nil,3,nil,nil +310899,we01.vzwstatic,Verizon,nil,3,nil,nil +310910,we01.vzwstatic,Verizon,nil,3,nil,nil +311110,we01.vzwstatic,Verizon,nil,3,nil,nil +311270,we01.vzwstatic,Verizon,nil,3,nil,nil +311271,we01.vzwstatic,Verizon,nil,3,nil,nil +311272,we01.vzwstatic,Verizon,nil,3,nil,nil +311273,we01.vzwstatic,Verizon,nil,3,nil,nil +311274,we01.vzwstatic,Verizon,nil,3,nil,nil +311275,we01.vzwstatic,Verizon,nil,3,nil,nil +311276,we01.vzwstatic,Verizon,nil,3,nil,nil +311277,we01.vzwstatic,Verizon,nil,3,nil,nil +311278,we01.vzwstatic,Verizon,nil,3,nil,nil +311279,we01.vzwstatic,Verizon,nil,3,nil,nil +311280,we01.vzwstatic,Verizon,nil,3,nil,nil +311281,we01.vzwstatic,Verizon,nil,3,nil,nil +311282,we01.vzwstatic,Verizon,nil,3,nil,nil +311283,we01.vzwstatic,Verizon,nil,3,nil,nil +311284,we01.vzwstatic,Verizon,nil,3,nil,nil +311285,we01.vzwstatic,Verizon,nil,3,nil,nil +311286,we01.vzwstatic,Verizon,nil,3,nil,nil +311287,we01.vzwstatic,Verizon,nil,3,nil,nil +311288,we01.vzwstatic,Verizon,nil,3,nil,nil +311289,we01.vzwstatic,Verizon,nil,3,nil,nil +311390,we01.vzwstatic,Verizon,nil,3,nil,nil +311480,we01.vzwstatic,Verizon,nil,3,nil,nil +311481,we01.vzwstatic,Verizon,nil,3,nil,nil +311482,we01.vzwstatic,Verizon,nil,3,nil,nil +311483,we01.vzwstatic,Verizon,nil,3,nil,nil +311484,we01.vzwstatic,Verizon,nil,3,nil,nil +311485,we01.vzwstatic,Verizon,nil,3,nil,nil +311486,we01.vzwstatic,Verizon,nil,3,nil,nil +311487,we01.vzwstatic,Verizon,nil,3,nil,nil +311488,we01.vzwstatic,Verizon,nil,3,nil,nil +311489,we01.vzwstatic,Verizon,nil,3,nil,nil +311590,we01.vzwstatic,Verizon,nil,3,nil,nil +312040,we01.vzwstatic,Verizon,nil,3,nil,nil +312160,we01.vzwstatic,Verizon,nil,3,nil,nil +312770,we01.vzwstatic,Verizon,nil,3,nil,nil +302490,internet.freedommobile.ca,FreedomMobile,nil,1,nil,nil \ No newline at end of file diff --git a/rooter/0optionalapps/ext-blacklist/Makefile b/rooter/0optionalapps/ext-blacklist/Makefile new file mode 100644 index 0000000..0c156e8 --- /dev/null +++ b/rooter/0optionalapps/ext-blacklist/Makefile @@ -0,0 +1,35 @@ +#Owned by DairyMan@Whirlpool +# +#Copyright GNU act. +include $(TOPDIR)/rules.mk + +PKG_NAME:=ext-blacklist +PKG_VERSION:=1.000 +PKG_RELEASE:=1 + +PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool +include $(INCLUDE_DIR)/package.mk + +define Package/ext-blacklist + SECTION:=utils + CATEGORY:=ROOter + SUBMENU:=Optional Applications + TITLE:=Install Mac Blacklisting + PKGARCH:=all +endef + +define Package/ext-blacklistdescription + Helper scripts to install Mac Blacklisting +endef + + +define Build/Compile +endef + +define Package/ext-blacklist/install + $(CP) ./files/* $(1)/ + + +endef + +$(eval $(call BuildPackage,ext-blacklist)) diff --git a/rooter/0optionalapps/ext-blacklist/files/etc/config/blacklist b/rooter/0optionalapps/ext-blacklist/files/etc/config/blacklist new file mode 100644 index 0000000..00fb552 --- /dev/null +++ b/rooter/0optionalapps/ext-blacklist/files/etc/config/blacklist @@ -0,0 +1,4 @@ + +config blacklist 'blacklist' + + diff --git a/rooter/0optionalapps/ext-blacklist/files/usr/lib/blacklist/blacklist.sh b/rooter/0optionalapps/ext-blacklist/files/usr/lib/blacklist/blacklist.sh new file mode 100644 index 0000000..6775a95 --- /dev/null +++ b/rooter/0optionalapps/ext-blacklist/files/usr/lib/blacklist/blacklist.sh @@ -0,0 +1,32 @@ +#!/bin/sh +. /lib/functions.sh + +log() { + logger -t "Blacklist" "$@" +} + +getmac() { + local config=$1 + config_get src_mac $1 src_mac + if [ ! -z $src_mac ]; then + if [ $create = "0" ]; then + uci set firewall.blacklist=rule + uci set firewall.blacklist.src='lan' + uci set firewall.blacklist.target='REJECT' + uci set firewall.blacklist.dest='wan' + uci set firewall.blacklist.name='Blacklist' + create=1 + fi + uci add_list firewall.blacklist.src_mac=$src_mac + fi +} + +sleep 8 +create="0" +uci -q delete firewall.blacklist +config_load blacklist +config_foreach getmac devices +uci commit firewall +/etc/init.d/firewall restart + +exit 0 diff --git a/rooter/0optionalapps/ext-blacklist/files/usr/lib/blacklist/chkblack.sh b/rooter/0optionalapps/ext-blacklist/files/usr/lib/blacklist/chkblack.sh new file mode 100644 index 0000000..4b13613 --- /dev/null +++ b/rooter/0optionalapps/ext-blacklist/files/usr/lib/blacklist/chkblack.sh @@ -0,0 +1,11 @@ +#!/bin/sh + +log() { + logger -t "Blacklist" "$@" +} + + +result=`ps | grep -i "blacklist.sh" | grep -v "grep" | wc -l` +if [ $result -eq 0 ]; then + /usr/lib/blacklist/blacklist.sh & +fi \ No newline at end of file diff --git a/rooter/0optionalapps/ext-blacklist/files/usr/lib/lua/luci/controller/blacklist.lua b/rooter/0optionalapps/ext-blacklist/files/usr/lib/lua/luci/controller/blacklist.lua new file mode 100644 index 0000000..d132021 --- /dev/null +++ b/rooter/0optionalapps/ext-blacklist/files/usr/lib/lua/luci/controller/blacklist.lua @@ -0,0 +1,13 @@ +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) + page.dependent = true + --end +end diff --git a/rooter/0optionalapps/ext-blacklist/files/usr/lib/lua/luci/model/cbi/blacklist.lua b/rooter/0optionalapps/ext-blacklist/files/usr/lib/lua/luci/model/cbi/blacklist.lua new file mode 100644 index 0000000..91fa4e7 --- /dev/null +++ b/rooter/0optionalapps/ext-blacklist/files/usr/lib/lua/luci/model/cbi/blacklist.lua @@ -0,0 +1,21 @@ +require("nixio.fs") + +m = Map("blacklist", translate("Blacklist Devices by Mac Address")) + +m.on_after_save = function(self) + luci.sys.call("/usr/lib/blacklist/chkblack.sh &") +end + +s = m:section(TypedSection, "devices", translate("Blacklisted Devices"), translate("Block these devices from using the Internet")) +s.anonymous = true +s.addremove = true + +o = s:option(Value, "src_mac", translate("Device MAC address")) + o.datatype = "list(macaddr)" + o.placeholder = translate("any") + + luci.sys.net.mac_hints(function(mac, name) + o:value(mac, "%s (%s)" %{ mac, name }) + end) + +return m \ No newline at end of file diff --git a/rooter/0optionalapps/ext-blockport/Makefile b/rooter/0optionalapps/ext-blockport/Makefile new file mode 100644 index 0000000..103fa98 --- /dev/null +++ b/rooter/0optionalapps/ext-blockport/Makefile @@ -0,0 +1,35 @@ +#Owned by DairyMan@Whirlpool +# +#Copyright GNU act. +include $(TOPDIR)/rules.mk + +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-blockport + SECTION:=utils + CATEGORY:=ROOter + SUBMENU:=Optional Applications + TITLE:=Install Port Blocking + PKGARCH:=all +endef + +define Package/ext-blockport/description + Helper scripts to install Port Blocking +endef + + +define Build/Compile +endef + +define Package/ext-blockport/install + $(CP) ./files/* $(1)/ + + +endef + +$(eval $(call BuildPackage,ext-blockport)) diff --git a/rooter/0optionalapps/ext-blockport/files/etc/config/blockport b/rooter/0optionalapps/ext-blockport/files/etc/config/blockport new file mode 100644 index 0000000..8e69716 --- /dev/null +++ b/rooter/0optionalapps/ext-blockport/files/etc/config/blockport @@ -0,0 +1,4 @@ + +config port 'port' + + diff --git a/rooter/0optionalapps/ext-blockport/files/usr/lib/blockport/blockport.sh b/rooter/0optionalapps/ext-blockport/files/usr/lib/blockport/blockport.sh new file mode 100644 index 0000000..6965bc0 --- /dev/null +++ b/rooter/0optionalapps/ext-blockport/files/usr/lib/blockport/blockport.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 + diff --git a/rooter/0optionalapps/ext-blockport/files/usr/lib/lua/luci/controller/blockport.lua b/rooter/0optionalapps/ext-blockport/files/usr/lib/lua/luci/controller/blockport.lua new file mode 100644 index 0000000..57bd9ff --- /dev/null +++ b/rooter/0optionalapps/ext-blockport/files/usr/lib/lua/luci/controller/blockport.lua @@ -0,0 +1,15 @@ +-- Licensed to the public under the Apache License 2.0. + +module("luci.controller.blockport", 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", "blockport"}, cbi("portblk"), _(translate("Port Blocking")), 11) + page.dependent = true + --end +end diff --git a/rooter/0optionalapps/ext-blockport/files/usr/lib/lua/luci/model/cbi/portblk.lua b/rooter/0optionalapps/ext-blockport/files/usr/lib/lua/luci/model/cbi/portblk.lua new file mode 100644 index 0000000..73cd1ea --- /dev/null +++ b/rooter/0optionalapps/ext-blockport/files/usr/lib/lua/luci/model/cbi/portblk.lua @@ -0,0 +1,21 @@ +local utl = require "luci.util" + +local sys = require "luci.sys" +local zones = require "luci.sys.zoneinfo" +local fs = require "nixio.fs" +local conf = require "luci.config" + +m = Map("blockport", translate("Port Blocking"), translate("Block traffic using specific ports")) + +m.on_after_save = function(self) + luci.sys.call("/usr/lib/blockport/blockport.sh &") +end + +s = m:section(TypedSection, "port", translate("Block Port List")) +s.anonymous = true +s.addremove = false + +s:option(DynamicList, "block", translate("Ports")) + + +return m \ No newline at end of file diff --git a/rooter/0optionalapps/ext-domain/Makefile b/rooter/0optionalapps/ext-domain/Makefile new file mode 100644 index 0000000..66e3d59 --- /dev/null +++ b/rooter/0optionalapps/ext-domain/Makefile @@ -0,0 +1,36 @@ +#Owned by DairyMan@Whirlpool +# +#Copyright GNU act. +include $(TOPDIR)/rules.mk + +PKG_NAME:=ext-domain +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 + SECTION:=utils + CATEGORY:=ROOter + SUBMENU:=Optional Applications + DEPENDS:=+dnsmasq-full +ipset + TITLE:=Domain Filter + PKGARCH:=all +endef + +define Package/ext-domain/description + Helper scripts to install Domain Filter on ROOter +endef + + +define Build/Compile +endef + +define Package/ext-domain/install + $(CP) ./files/* $(1)/ + + +endef + +$(eval $(call BuildPackage,ext-domain)) diff --git a/rooter/0optionalapps/ext-domain/files/etc/config/filter b/rooter/0optionalapps/ext-domain/files/etc/config/filter new file mode 100644 index 0000000..5eb7a3b --- /dev/null +++ b/rooter/0optionalapps/ext-domain/files/etc/config/filter @@ -0,0 +1 @@ +config filter filter diff --git a/rooter/0optionalapps/ext-domain/files/etc/init.d/domain b/rooter/0optionalapps/ext-domain/files/etc/init.d/domain new file mode 100644 index 0000000..2e99572 --- /dev/null +++ b/rooter/0optionalapps/ext-domain/files/etc/init.d/domain @@ -0,0 +1,46 @@ +#!/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 +} \ No newline at end of file diff --git a/rooter/0optionalapps/ext-domain/files/usr/lib/domain/filter.sh b/rooter/0optionalapps/ext-domain/files/usr/lib/domain/filter.sh new file mode 100644 index 0000000..1bb349c --- /dev/null +++ b/rooter/0optionalapps/ext-domain/files/usr/lib/domain/filter.sh @@ -0,0 +1,26 @@ +#!/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 \ No newline at end of file diff --git a/rooter/0optionalapps/ext-domain/files/usr/lib/lua/luci/controller/domain.lua b/rooter/0optionalapps/ext-domain/files/usr/lib/lua/luci/controller/domain.lua new file mode 100644 index 0000000..5bca115 --- /dev/null +++ b/rooter/0optionalapps/ext-domain/files/usr/lib/lua/luci/controller/domain.lua @@ -0,0 +1,15 @@ +-- 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 diff --git a/rooter/0optionalapps/ext-domain/files/usr/lib/lua/luci/model/cbi/domainfltr.lua b/rooter/0optionalapps/ext-domain/files/usr/lib/lua/luci/model/cbi/domainfltr.lua new file mode 100644 index 0000000..9c898e5 --- /dev/null +++ b/rooter/0optionalapps/ext-domain/files/usr/lib/lua/luci/model/cbi/domainfltr.lua @@ -0,0 +1,21 @@ +local utl = require "luci.util" + +local sys = require "luci.sys" +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.on_after_save = function(self) + luci.sys.call("/usr/lib/domain/filter.sh &") +end + +s = m:section(TypedSection, "filter", translate("Block List")) +s.anonymous = true +s.addremove = false + +s:option(DynamicList, "ipset", translate("Domain URLs")) + + +return m \ No newline at end of file diff --git a/rooter/0optionalapps/ext-menu/Makefile b/rooter/0optionalapps/ext-menu/Makefile new file mode 100644 index 0000000..0dee3f0 --- /dev/null +++ b/rooter/0optionalapps/ext-menu/Makefile @@ -0,0 +1,35 @@ +#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)) diff --git a/rooter/0optionalapps/ext-menu/files/etc/uci-defaults/63-menu b/rooter/0optionalapps/ext-menu/files/etc/uci-defaults/63-menu new file mode 100644 index 0000000..d5375bd --- /dev/null +++ b/rooter/0optionalapps/ext-menu/files/etc/uci-defaults/63-menu @@ -0,0 +1,10 @@ +#!/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 diff --git a/rooter/0optionalapps/ext-menu/files/usr/lib/fullmenu/full19/firewall.lua b/rooter/0optionalapps/ext-menu/files/usr/lib/fullmenu/full19/firewall.lua new file mode 100644 index 0000000..d761109 --- /dev/null +++ b/rooter/0optionalapps/ext-menu/files/usr/lib/fullmenu/full19/firewall.lua @@ -0,0 +1,28 @@ +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 diff --git a/rooter/0optionalapps/ext-menu/files/usr/lib/fullmenu/full19/luci-mod-status.json b/rooter/0optionalapps/ext-menu/files/usr/lib/fullmenu/full19/luci-mod-status.json new file mode 100644 index 0000000..0dcf6e8 --- /dev/null +++ b/rooter/0optionalapps/ext-menu/files/usr/lib/fullmenu/full19/luci-mod-status.json @@ -0,0 +1,103 @@ +{ + "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" + } + } +} diff --git a/rooter/0optionalapps/ext-menu/files/usr/lib/fullmenu/full19/luci-mod-system.json b/rooter/0optionalapps/ext-menu/files/usr/lib/fullmenu/full19/luci-mod-system.json new file mode 100644 index 0000000..ef21d6e --- /dev/null +++ b/rooter/0optionalapps/ext-menu/files/usr/lib/fullmenu/full19/luci-mod-system.json @@ -0,0 +1,111 @@ +{ + "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" + } + } +} diff --git a/rooter/0optionalapps/ext-menu/files/usr/lib/fullmenu/full19/network.lua b/rooter/0optionalapps/ext-menu/files/usr/lib/fullmenu/full19/network.lua new file mode 100644 index 0000000..b34ec4f --- /dev/null +++ b/rooter/0optionalapps/ext-menu/files/usr/lib/fullmenu/full19/network.lua @@ -0,0 +1,44 @@ +-- Copyright 2008 Steven Barth +-- Copyright 2011-2018 Jo-Philipp Wich +-- 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 diff --git a/rooter/0optionalapps/ext-menu/files/usr/lib/fullmenu/full19/opkg.lua b/rooter/0optionalapps/ext-menu/files/usr/lib/fullmenu/full19/opkg.lua new file mode 100644 index 0000000..29c9a08 --- /dev/null +++ b/rooter/0optionalapps/ext-menu/files/usr/lib/fullmenu/full19/opkg.lua @@ -0,0 +1,117 @@ +-- Copyright 2018 Jo-Philipp Wich +-- 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 diff --git a/rooter/0optionalapps/ext-menu/files/usr/lib/fullmenu/full21/luci-app-firewall.json b/rooter/0optionalapps/ext-menu/files/usr/lib/fullmenu/full21/luci-app-firewall.json new file mode 100644 index 0000000..4672a27 --- /dev/null +++ b/rooter/0optionalapps/ext-menu/files/usr/lib/fullmenu/full21/luci-app-firewall.json @@ -0,0 +1,70 @@ +{ + "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" + } + } +} diff --git a/rooter/0optionalapps/ext-menu/files/usr/lib/fullmenu/full21/luci-app-opkg.json b/rooter/0optionalapps/ext-menu/files/usr/lib/fullmenu/full21/luci-app-opkg.json new file mode 100644 index 0000000..3d06a25 --- /dev/null +++ b/rooter/0optionalapps/ext-menu/files/usr/lib/fullmenu/full21/luci-app-opkg.json @@ -0,0 +1,13 @@ +{ + "admin/system/opkg": { + "title": "Software", + "order": 30, + "action": { + "type": "view", + "path": "opkg" + }, + "depends": { + "acl": [ "luci-app-opkg" ] + } + } +} diff --git a/rooter/0optionalapps/ext-menu/files/usr/lib/fullmenu/full21/luci-mod-network.json b/rooter/0optionalapps/ext-menu/files/usr/lib/fullmenu/full21/luci-mod-network.json new file mode 100644 index 0000000..188c695 --- /dev/null +++ b/rooter/0optionalapps/ext-menu/files/usr/lib/fullmenu/full21/luci-mod-network.json @@ -0,0 +1,98 @@ +{ + "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" ] + } + } +} diff --git a/rooter/0optionalapps/ext-menu/files/usr/lib/fullmenu/full21/luci-mod-status.json b/rooter/0optionalapps/ext-menu/files/usr/lib/fullmenu/full21/luci-mod-status.json new file mode 100644 index 0000000..0f066e6 --- /dev/null +++ b/rooter/0optionalapps/ext-menu/files/usr/lib/fullmenu/full21/luci-mod-status.json @@ -0,0 +1,137 @@ +{ + "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" + } + } +} diff --git a/rooter/0optionalapps/ext-menu/files/usr/lib/fullmenu/full21/luci-mod-system.json b/rooter/0optionalapps/ext-menu/files/usr/lib/fullmenu/full21/luci-mod-system.json new file mode 100644 index 0000000..4022e0c --- /dev/null +++ b/rooter/0optionalapps/ext-menu/files/usr/lib/fullmenu/full21/luci-mod-system.json @@ -0,0 +1,136 @@ +{ + "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" ] + } + } +} diff --git a/rooter/0optionalapps/ext-menu/files/usr/lib/fullmenu/limited19/firewall.lua b/rooter/0optionalapps/ext-menu/files/usr/lib/fullmenu/limited19/firewall.lua new file mode 100644 index 0000000..d761109 --- /dev/null +++ b/rooter/0optionalapps/ext-menu/files/usr/lib/fullmenu/limited19/firewall.lua @@ -0,0 +1,28 @@ +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 diff --git a/rooter/0optionalapps/ext-menu/files/usr/lib/fullmenu/limited19/luci-mod-status.json b/rooter/0optionalapps/ext-menu/files/usr/lib/fullmenu/limited19/luci-mod-status.json new file mode 100644 index 0000000..7e664bf --- /dev/null +++ b/rooter/0optionalapps/ext-menu/files/usr/lib/fullmenu/limited19/luci-mod-status.json @@ -0,0 +1,19 @@ +{ + "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" + } + } +} diff --git a/rooter/0optionalapps/ext-menu/files/usr/lib/fullmenu/limited19/luci-mod-system.json b/rooter/0optionalapps/ext-menu/files/usr/lib/fullmenu/limited19/luci-mod-system.json new file mode 100644 index 0000000..f220775 --- /dev/null +++ b/rooter/0optionalapps/ext-menu/files/usr/lib/fullmenu/limited19/luci-mod-system.json @@ -0,0 +1,45 @@ +{ + "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" + } + } +} diff --git a/rooter/0optionalapps/ext-menu/files/usr/lib/fullmenu/limited19/network.lua b/rooter/0optionalapps/ext-menu/files/usr/lib/fullmenu/limited19/network.lua new file mode 100644 index 0000000..b34ec4f --- /dev/null +++ b/rooter/0optionalapps/ext-menu/files/usr/lib/fullmenu/limited19/network.lua @@ -0,0 +1,44 @@ +-- Copyright 2008 Steven Barth +-- Copyright 2011-2018 Jo-Philipp Wich +-- 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 diff --git a/rooter/0optionalapps/ext-menu/files/usr/lib/fullmenu/limited19/opkg.lua b/rooter/0optionalapps/ext-menu/files/usr/lib/fullmenu/limited19/opkg.lua new file mode 100644 index 0000000..29c9a08 --- /dev/null +++ b/rooter/0optionalapps/ext-menu/files/usr/lib/fullmenu/limited19/opkg.lua @@ -0,0 +1,117 @@ +-- Copyright 2018 Jo-Philipp Wich +-- 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 diff --git a/rooter/0optionalapps/ext-menu/files/usr/lib/fullmenu/limited21/luci-app-firewall.json b/rooter/0optionalapps/ext-menu/files/usr/lib/fullmenu/limited21/luci-app-firewall.json new file mode 100644 index 0000000..4672a27 --- /dev/null +++ b/rooter/0optionalapps/ext-menu/files/usr/lib/fullmenu/limited21/luci-app-firewall.json @@ -0,0 +1,70 @@ +{ + "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" + } + } +} diff --git a/rooter/0optionalapps/ext-menu/files/usr/lib/fullmenu/limited21/luci-mod-network.json b/rooter/0optionalapps/ext-menu/files/usr/lib/fullmenu/limited21/luci-mod-network.json new file mode 100644 index 0000000..188c695 --- /dev/null +++ b/rooter/0optionalapps/ext-menu/files/usr/lib/fullmenu/limited21/luci-mod-network.json @@ -0,0 +1,98 @@ +{ + "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" ] + } + } +} diff --git a/rooter/0optionalapps/ext-menu/files/usr/lib/fullmenu/limited21/luci-mod-status.json b/rooter/0optionalapps/ext-menu/files/usr/lib/fullmenu/limited21/luci-mod-status.json new file mode 100644 index 0000000..5beffdd --- /dev/null +++ b/rooter/0optionalapps/ext-menu/files/usr/lib/fullmenu/limited21/luci-mod-status.json @@ -0,0 +1,38 @@ +{ + "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 } } + } + }, +} diff --git a/rooter/0optionalapps/ext-menu/files/usr/lib/fullmenu/limited21/luci-mod-system.json b/rooter/0optionalapps/ext-menu/files/usr/lib/fullmenu/limited21/luci-mod-system.json new file mode 100644 index 0000000..7ab8bed --- /dev/null +++ b/rooter/0optionalapps/ext-menu/files/usr/lib/fullmenu/limited21/luci-mod-system.json @@ -0,0 +1,60 @@ +{ + "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" ] + } + } +} diff --git a/rooter/0optionalapps/ext-menu/files/usr/lib/fullmenu/setmenu.sh b/rooter/0optionalapps/ext-menu/files/usr/lib/fullmenu/setmenu.sh new file mode 100644 index 0000000..fd5bc31 --- /dev/null +++ b/rooter/0optionalapps/ext-menu/files/usr/lib/fullmenu/setmenu.sh @@ -0,0 +1,34 @@ +#!/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 \ No newline at end of file diff --git a/rooter/0optionalapps/ext-menu/files/usr/lib/lua/luci/controller/fullmenu.lua b/rooter/0optionalapps/ext-menu/files/usr/lib/lua/luci/controller/fullmenu.lua new file mode 100644 index 0000000..20d1494 --- /dev/null +++ b/rooter/0optionalapps/ext-menu/files/usr/lib/lua/luci/controller/fullmenu.lua @@ -0,0 +1,28 @@ +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 \ No newline at end of file diff --git a/rooter/0optionalapps/ext-menu/files/usr/lib/lua/luci/view/fullmenu/fullmenu.htm b/rooter/0optionalapps/ext-menu/files/usr/lib/lua/luci/view/fullmenu/fullmenu.htm new file mode 100644 index 0000000..a08e06d --- /dev/null +++ b/rooter/0optionalapps/ext-menu/files/usr/lib/lua/luci/view/fullmenu/fullmenu.htm @@ -0,0 +1,166 @@ +<%+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 + +-%> + + + +
                +
                +

                <%:Menu Selection%>

                +
                + + + + +
                + + + + + + + + + + + + + + + + + + + + + + +
                <%:Current Menu is Limited.%>
                <%:You must enter a password to change to the full Menu.%>
                + + + + + + + + + + + + + + +
                <%:Current Menu is Full.%>
                <%:You must enter a password to change to the limited Menu.%>
                + +
                + +
                +
                +<%+footer%> \ No newline at end of file diff --git a/rooter/0optionalapps/ext-rspeedtest/Makefile b/rooter/0optionalapps/ext-rspeedtest/Makefile new file mode 100644 index 0000000..5dee477 --- /dev/null +++ b/rooter/0optionalapps/ext-rspeedtest/Makefile @@ -0,0 +1,34 @@ +#Owned by DairyMan@Whirlpool +# +#Copyright GNU act. +include $(TOPDIR)/rules.mk + +PKG_NAME:=ext-rspeedtest +PKG_VERSION:=1.000 +PKG_RELEASE:=1 + +PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool +include $(INCLUDE_DIR)/package.mk + +define Package/ext-rspeedtest + SECTION:=utils + CATEGORY:=ROOter + DEPENDS:=+httping +curl +coreutils +coreutils-date +speedtestpp + SUBMENU:=Optional Applications + TITLE:=support for ROOter SpeedTest + PKGARCH:=all +endef + +define Package/ext-rspeedtest/description + Helper scripts to enable ROOter SpeedTest +endef + + +define Build/Compile +endef + +define Package/ext-rspeedtest/install + $(CP) ./files/* $(1)/ +endef + +$(eval $(call BuildPackage,ext-rspeedtest)) diff --git a/rooter/0optionalapps/ext-rspeedtest/files/usr/lib/lua/luci/controller/rspeedtest.lua b/rooter/0optionalapps/ext-rspeedtest/files/usr/lib/lua/luci/controller/rspeedtest.lua new file mode 100644 index 0000000..6ac5628 --- /dev/null +++ b/rooter/0optionalapps/ext-rspeedtest/files/usr/lib/lua/luci/controller/rspeedtest.lua @@ -0,0 +1,79 @@ +module("luci.controller.rspeedtest", package.seeall) + +I18N = require "luci.i18n" +translate = I18N.translate + +function index() + local page + page = entry({"admin", "speed", "rspeedtest"}, template("speedtest/rspeedtest"), translate("SpeedTest by Ookla"), 72) + page.dependent = true + + entry({"admin", "speed", "closeserver"}, call("action_closeserver")) + entry({"admin", "speed", "stoptest"}, call("action_stoptest")) + entry({"admin", "speed", "getspeed"}, call("action_getspeed")) + entry({"admin", "speed", "getspeeddata"}, call("action_getspeeddata")) +end + +function action_closeserver() + local rv = {} + + os.execute("/usr/lib/speedtest/info.sh") + result = "/tmp/sinfo" + file = io.open(result, "r") + if file ~= nil then + rv["status"] = file:read("*line") + if rv["status"] ~= "0" then + rv["ip"] = file:read("*line") + rv["isp"] = file:read("*line") + rv["city"] = file:read("*line") + rv["prov"] = file:read("*line") + end + file:close() + else + rv["status"] = "0" + end + + luci.http.prepare_content("application/json") + luci.http.write_json(rv) +end + +function action_stoptest() + os.execute("/usr/lib/speedtest/stop.sh") +end + +function action_getspeed() + local rv = {} + + os.execute("/usr/lib/speedtest/getspeed.sh ") + + luci.http.prepare_content("application/json") + luci.http.write_json(rv) +end + +function action_getspeeddata() + local rv = {} + + result = "/tmp/getspeed" + file = io.open(result, "r") + if file ~= nil then + rv["dlsize"] = file:read("*line") + rv["dlelapse"] = file:read("*line") + rv["ulsize"] = file:read("*line") + rv["ulelapse"] = file:read("*line") + file:close() + else + rv["dlsize"] = "0" + rv["ulsize"] = "0" + end + result = "/tmp/spworking" + file = io.open(result, "r") + if file ~= nil then + rv["working"] = file:read("*line") + file:close() + else + rv["working"] = "0" + end + + luci.http.prepare_content("application/json") + luci.http.write_json(rv) +end diff --git a/rooter/0optionalapps/ext-rspeedtest/files/usr/lib/lua/luci/view/speedtest/rspeedtest.htm b/rooter/0optionalapps/ext-rspeedtest/files/usr/lib/lua/luci/view/speedtest/rspeedtest.htm new file mode 100644 index 0000000..a35eaa4 --- /dev/null +++ b/rooter/0optionalapps/ext-rspeedtest/files/usr/lib/lua/luci/view/speedtest/rspeedtest.htm @@ -0,0 +1,259 @@ +<%+header%> +<% + user_icon = resource .. "/img/user.png" + prov_icon = resource .. "/img/prov.png" + load_icon = resource .. "/icons/loading.gif" +%> + + + + +
                + +
                +

                <%:Speed Test by Ookla%>

                +
                <%:An Internet speed test that runs from the router%>
                + + + +
                + + + + + + +
                <%:***Finding Optimal Server***%>
                 
                + + + + + + + + + + +
                 
                 
                + + + + + + + + +
                 
                 
                + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                 
                + + + + + + + + + + + + + + + + + + +
                + +
                + +<%+footer%> \ No newline at end of file diff --git a/rooter/0optionalapps/ext-rspeedtest/files/usr/lib/speedtest/closest.lua b/rooter/0optionalapps/ext-rspeedtest/files/usr/lib/speedtest/closest.lua new file mode 100644 index 0000000..5544048 --- /dev/null +++ b/rooter/0optionalapps/ext-rspeedtest/files/usr/lib/speedtest/closest.lua @@ -0,0 +1,62 @@ +#!/usr/bin/lua + +function trim(s) + return (s:gsub("^%s*(.-)%s*$", "%1")) +end + +ulat = arg[1] +ulon = arg[2] + +url = {} +slat = {} +slon = {} +city = {} +dist = {} +prov = {} + +radius = 6371 + +cnt = 0 +clos = 99999999.99 +index = 0 +file = io.open("/tmp/slist", "r") +if file ~= nil then + repeat + line = file:read("*line") + if line == nil then + break + end + cnt = cnt + 1 + s, e = line:find(" ") + if s ~= nil then + url[cnt] = trim(line:sub(0, s-1)) + cs, ce = line:find(" ", e+1) + slat[cnt] = trim(line:sub(e, cs-1)) + s, e = line:find(" ", ce+1) + slon[cnt] = trim(line:sub(ce, s-1)) + cs, ce = line:find("\"", e+1) + s, e = line:find("\"", ce+1) + city[cnt] = trim(line:sub(ce+1, s-1)) + prov[cnt] = trim(line:sub(e+1)) + + dlat = math.rad(slat[cnt] - ulat) + dlon = math.rad(slon[cnt] - ulon) + a = (math.sin(dlat / 2) * math.sin(dlat / 2) + math.cos(math.rad(ulat)) * math.cos(math.rad(slat[cnt])) * math.sin(dlon / 2) * math.sin(dlon / 2)) + c = 2 * math.atan(math.sqrt(a), math.sqrt(1 - a)) + dist[cnt] = radius * c + + if dist[cnt] < clos then + clos = dist[cnt] + index = cnt + end + end + until 1==0 + file:close() + tfile = io.open("/tmp/close", "w") + tfile:write("CURL=\"", url[index], "\"\n") + tfile:write("CITY=\"", city[index], "\"\n") + tfile:write("PROV=\"", prov[index], "\"") + tfile:close() +end + + diff --git a/rooter/0optionalapps/ext-rspeedtest/files/usr/lib/speedtest/getspeed.sh b/rooter/0optionalapps/ext-rspeedtest/files/usr/lib/speedtest/getspeed.sh new file mode 100644 index 0000000..7583f5b --- /dev/null +++ b/rooter/0optionalapps/ext-rspeedtest/files/usr/lib/speedtest/getspeed.sh @@ -0,0 +1,83 @@ +#!/bin/sh + +log() { + logger -t "Getspeed " "$@" +} + +fixspeed() { + sed 's/\(PROVIDER=[[:blank:]]*\)\(.*\)/\1'\''\2'\''/' /tmp/speed > /tmp/tspeed +} + +echo "0" > /tmp/getspeed +echo "0" >> /tmp/getspeed +echo "0" >> /tmp/getspeed +echo "0" >> /tmp/getspeed +echo "1" > /tmp/spworking + +JITTER="" +LATENCY="" +DOWNLOAD_SPEED="" +UPLOAD_SPEED="" + +while IFS= read -r line +do + read -r line + read -r line + read -r line + read -r line + read -r line + break +done < /tmp/sinfo +url=${line:7:100} +url=$(echo $url" " | tr "/" ",") +url=$(echo "$url" | cut -d, -f1) +rm -f /tmp/speed +speedtest --test-server $url --output text > /tmp/speed & +while [ -z "$JITTER" ] +do + if [ -e /tmp/speed ]; then + fixspeed + if [ -e /tmp/tspeed ]; then + source /tmp/tspeed + fi + fi + sleep 1 +done +echo "$LATENCY" > /tmp/getspeed +echo "$JITTER" >> /tmp/getspeed +echo "0" >> /tmp/getspeed +echo "0" >> /tmp/getspeed +echo "2" > /tmp/spworking + +while [ -z "$DOWNLOAD_SPEED" ] +do + if [ -e /tmp/speed ]; then + fixspeed + if [ -e /tmp/tspeed ]; then + source /tmp/tspeed + fi + fi + sleep 1 +done +echo "$LATENCY" > /tmp/getspeed +echo "$JITTER" >> /tmp/getspeed +echo "$DOWNLOAD_SPEED" >> /tmp/getspeed +echo "0" >> /tmp/getspeed +echo "3" > /tmp/spworking + +while [ -z "$UPLOAD_SPEED" ] +do + if [ -e /tmp/speed ]; then + fixspeed + if [ -e /tmp/tspeed ]; then + source /tmp/tspeed + fi + fi + sleep 1 +done +echo "$LATENCY" > /tmp/getspeed +echo "$JITTER" >> /tmp/getspeed +echo "$DOWNLOAD_SPEED" >> /tmp/getspeed +echo "$UPLOAD_SPEED" >> /tmp/getspeed +echo "0" > /tmp/spworking + diff --git a/rooter/0optionalapps/ext-rspeedtest/files/usr/lib/speedtest/info.sh b/rooter/0optionalapps/ext-rspeedtest/files/usr/lib/speedtest/info.sh new file mode 100644 index 0000000..1232246 --- /dev/null +++ b/rooter/0optionalapps/ext-rspeedtest/files/usr/lib/speedtest/info.sh @@ -0,0 +1,75 @@ +#!/bin/sh + +killprocess() { + proc=$1 + PID=$(ps |grep "$proc" | grep -v grep |head -n 1 | awk '{print $1}') + if [ ! -z $PID ]; then + kill -9 $PID + fi +} + +killprocess "speedtest --test-server" +killprocess "/speedtest/closest.lua" +killprocess "/speedtest/getspeed.sh" +killprocess "/speedtest/servers.lua" + +rm -f /tmp/speed +rm -f /tmp/sinfo +rm -f /tmp/close +rm -f /tmp/getspeed +rm -f /tmp/jpg +rm -f /tmp/pinfo +rm -f /tmp/sinfo +rm -f /tmp/slist +echo "0" > /tmp/getspeed +echo "0" >> /tmp/getspeed +echo "0" >> /tmp/getspeed +echo "0" >> /tmp/getspeed +echo "0" >> /tmp/getspeed +echo "0" > /tmp/spworking +wget -q -O /tmp/client http://speedtest.net/speedtest-config.php +if [ $? = "0" ]; then + RAW=$(cat /tmp/client) + clid=$(echo $RAW" " | grep -o " " | tr -d '"' | tr " " "," | tr "/" "," | tr "=" ",") + ip=$(echo $clid | cut -d, -f3) + ulat=$(echo $clid | cut -d, -f5) + ulon=$(echo $clid | cut -d, -f7) + isp=$(echo $clid | cut -d, -f9) + rm -f /tmp/client + echo "1" > /tmp/sinfo + echo "$ip" >> /tmp/sinfo + echo "$isp" >> /tmp/sinfo + + wget -q -O /tmp/servers http://www.speedtest.net/speedtest-servers-static.php + if [ $? != "0" ]; then + wget -q -O /tmp/servers http://c.speedtest.net/speedtest-servers.php + if [ $? != "0" ]; then + echo "0" > /tmp/sinfo + exit 0 + fi + fi + rm -f /tmp/slist + while IFS= read -r line + do + read -r line + /usr/lib/speedtest/servers.lua "$line" + if [ -e /tmp/server ]; then + source /tmp/server + echo "$URL $LAT $LON "\""$NAME"\"" $SPONSOR" >> /tmp/slist + rm -f /tmp/server + fi + done < /tmp/servers + rm -f /tmp/servers + + /usr/lib/speedtest/closest.lua $ulat $ulon + source /tmp/close + echo "$CITY" >> /tmp/sinfo + echo "$PROV" >> /tmp/sinfo + echo "$CURL" >> /tmp/sinfo + rm -f /tmp/slist + rm -f /tmp/close +else + echo "0" > /tmp/sinfo + exit 0 +fi + diff --git a/rooter/0optionalapps/ext-rspeedtest/files/usr/lib/speedtest/ping.sh b/rooter/0optionalapps/ext-rspeedtest/files/usr/lib/speedtest/ping.sh new file mode 100644 index 0000000..7ec502c --- /dev/null +++ b/rooter/0optionalapps/ext-rspeedtest/files/usr/lib/speedtest/ping.sh @@ -0,0 +1,26 @@ +#!/bin/sh + +rm -f /tmp/pinfo + +echo "0" > /tmp/getspeed +echo "0" >> /tmp/getspeed +echo "0" >> /tmp/getspeed +echo "0" >> /tmp/getspeed +echo "1" > /tmp/spworking +while IFS= read -r line +do + read -r line + read -r line + read -r line + read -r line + read -r line + break +done < /tmp/sinfo + +hp=$(httping -c 3 $line) +pingg=$(echo $hp" " | grep -o "round-trip .\+ ms " | tr " " "," | tr "/" ",") +latency=$(echo $pingg | cut -d, -f7) + +echo "$latency" > /tmp/pinfo +echo "2" > /tmp/spworking + diff --git a/rooter/0optionalapps/ext-rspeedtest/files/usr/lib/speedtest/servers.lua b/rooter/0optionalapps/ext-rspeedtest/files/usr/lib/speedtest/servers.lua new file mode 100644 index 0000000..abc3962 --- /dev/null +++ b/rooter/0optionalapps/ext-rspeedtest/files/usr/lib/speedtest/servers.lua @@ -0,0 +1,46 @@ +#!/usr/bin/lua + +function trim(s) + return (s:gsub("^%s*(.-)%s*$", "%1")) +end + +line = arg[1] +if line == nil then + return +end + +s, e = line:find("url=\"") +if s ~= nil then + cs, ce = line:find("\"", e+1) + url = trim(line:sub(e+1, cs-1)) +else + return +end +s, e = line:find("lat=\"") +if s ~= nil then + cs, ce = line:find("\"", e+1) + lat = trim(line:sub(e+1, cs-1)) +end +s, e = line:find("lon=\"") +if s ~= nil then + cs, ce = line:find("\"", e+1) + lon = trim(line:sub(e+1, cs-1)) +end +s, e = line:find("name=\"") +if s ~= nil then + cs, ce = line:find("\"", e+1) + name = trim(line:sub(e+1, cs-1)) +end +s, e = line:find("sponsor=\"") +if s ~= nil then + cs, ce = line:find("\"", e+1) + sponsor = trim(line:sub(e+1, cs-1)) +end + +tfile = io.open("/tmp/server", "w") +tfile:write("URL=\"", url, "\"\n") +tfile:write("LAT=\"", lat, "\"\n") +tfile:write("LON=\"", lon, "\"\n") +tfile:write("NAME=\"", name, "\"\n") +tfile:write("SPONSOR=\"", sponsor, "\"") +tfile:close() \ No newline at end of file diff --git a/rooter/0optionalapps/ext-rspeedtest/files/usr/lib/speedtest/stop.sh b/rooter/0optionalapps/ext-rspeedtest/files/usr/lib/speedtest/stop.sh new file mode 100644 index 0000000..c95dec0 --- /dev/null +++ b/rooter/0optionalapps/ext-rspeedtest/files/usr/lib/speedtest/stop.sh @@ -0,0 +1,28 @@ +#!/bin/sh + +killprocess() { + proc=$1 + PID=$(pgrep -f "$proc") + if [ ! -z $PID ]; then + kill -9 $PID + fi +} + +killprocess "speedtest --test-server" +killprocess "/speedtest/closest.lua" +killprocess "/speedtest/getspeed.sh" +killprocess "/speedtest/servers.lua" + +flist="/tmp/speed /tmp/sinfo /tmp/close /tmp/getspeed /tmp/jpg /tmp/pinfo /tmp/sinfo /tmp/slist" + +for val in $flist; do + rm -f $val +done + +echo "0" > /tmp/getspeed +echo "0" >> /tmp/getspeed +echo "0" >> /tmp/getspeed +echo "0" >> /tmp/getspeed +echo "0" >> /tmp/getspeed +echo "0" > /tmp/spworking + diff --git a/rooter/0optionalapps/ext-rspeedtest/files/www/luci-static/resources/img/prov.png b/rooter/0optionalapps/ext-rspeedtest/files/www/luci-static/resources/img/prov.png new file mode 100644 index 0000000..715618c Binary files /dev/null and b/rooter/0optionalapps/ext-rspeedtest/files/www/luci-static/resources/img/prov.png differ diff --git a/rooter/0optionalapps/ext-rspeedtest/files/www/luci-static/resources/img/user.png b/rooter/0optionalapps/ext-rspeedtest/files/www/luci-static/resources/img/user.png new file mode 100644 index 0000000..a557423 Binary files /dev/null and b/rooter/0optionalapps/ext-rspeedtest/files/www/luci-static/resources/img/user.png differ diff --git a/rooter/0optionalapps/ext-speedtest/Makefile b/rooter/0optionalapps/ext-speedtest/Makefile new file mode 100644 index 0000000..68a6e47 --- /dev/null +++ b/rooter/0optionalapps/ext-speedtest/Makefile @@ -0,0 +1,34 @@ +#Owned by DairyMan@Whirlpool +# +#Copyright GNU act. +include $(TOPDIR)/rules.mk + +PKG_NAME:=ext-speedtest +PKG_VERSION:=1.000 +PKG_RELEASE:=1 + +PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool +include $(INCLUDE_DIR)/package.mk + +define Package/ext-speedtest + SECTION:=utils + CATEGORY:=ROOter + DEPENDS:=+ext-rspeedtest + SUBMENU:=Optional Applications + TITLE:=support for OpenSpeedTest + PKGARCH:=all +endef + +define Package/ext-speedtest/description + Helper scripts to enable OpenSpeedTest +endef + + +define Build/Compile +endef + +define Package/ext-speedtest/install + $(CP) ./files/* $(1)/ +endef + +$(eval $(call BuildPackage,ext-speedtest)) diff --git a/rooter/0optionalapps/ext-speedtest/files/usr/lib/lua/luci/controller/speedtest.lua b/rooter/0optionalapps/ext-speedtest/files/usr/lib/lua/luci/controller/speedtest.lua new file mode 100644 index 0000000..2c78f99 --- /dev/null +++ b/rooter/0optionalapps/ext-speedtest/files/usr/lib/lua/luci/controller/speedtest.lua @@ -0,0 +1,11 @@ +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) + page.dependent = true +end diff --git a/rooter/0optionalapps/ext-speedtest/files/usr/lib/lua/luci/view/speedtest/speedtest.htm b/rooter/0optionalapps/ext-speedtest/files/usr/lib/lua/luci/view/speedtest/speedtest.htm new file mode 100644 index 0000000..8f731de --- /dev/null +++ b/rooter/0optionalapps/ext-speedtest/files/usr/lib/lua/luci/view/speedtest/speedtest.htm @@ -0,0 +1,45 @@ +<%+header%> + + + +
                +
                +

                <%:Browser Speed Test%>

                +
                <%:A Speed Test using OpenSpeedTest that runs in the browser%>
                + + + + + + + + + +
                + +
                + + + + + +
                + + + +
                +
                +<%+footer%> diff --git a/rooter/0optionalapps/ext-speedtest/files/www/luci-static/speed/css/iconmoon_splash.css b/rooter/0optionalapps/ext-speedtest/files/www/luci-static/speed/css/iconmoon_splash.css new file mode 100644 index 0000000..5254b92 --- /dev/null +++ b/rooter/0optionalapps/ext-speedtest/files/www/luci-static/speed/css/iconmoon_splash.css @@ -0,0 +1,69 @@ +@font-face { + font-family: 'icomoon_splash'; + src: url('../fonts/icomoon_splash.eot?vja16g'); + src: url('../fonts/icomoon_splash.eot?vja16g#iefix') format('embedded-opentype'), + url('../fonts/icomoon_splash.ttf?vja16g') format('truetype'), + url('../fonts/icomoon_splash.woff?vja16g') format('woff'), + url('../fonts/icomoon_splash.svg?vja16g#icomoon_splash') format('svg'); + font-weight: normal; + font-style: normal; +} + +[class^="icon-"], [class*=" icon-"] { + /* use !important to prevent issues with browser extensions that change fonts */ + font-family: 'icomoon_splash' !important; + speak: none; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + + /* Better Font Rendering =========== */ + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + + +.icon-power-off:before { + content: "\f011"; +} +.icon-signal:before { + content: "\f012"; +} +.icon-cog:before { + content: "\f013"; +} +.icon-gear:before { + content: "\f013"; +} +.icon-home:before { + content: "\f015"; +} +.icon-exclamation-triangle:before { + content: "\f071"; +} +.icon-warning:before { + content: "\f071"; +} +.icon-comments:before { + content: "\f086"; +} +.icon-hdd-o:before { + content: "\f0a0"; +} +.icon-plug:before { + content: "\f1e6"; +} +.icon-wifi:before { + content: "\f1eb"; +} +.icon-connection:before { + content: "\e91b"; +} +.icon-podcast:before { + content: "\e91c"; +} +.icon-earth:before { + content: "\e9ca"; +} diff --git a/rooter/0optionalapps/ext-speedtest/files/www/luci-static/speed/css/splash.css b/rooter/0optionalapps/ext-speedtest/files/www/luci-static/speed/css/splash.css new file mode 100644 index 0000000..85af002 --- /dev/null +++ b/rooter/0optionalapps/ext-speedtest/files/www/luci-static/speed/css/splash.css @@ -0,0 +1,341 @@ +/* @override http://src.dev.lo.lo/ROOter/www/luci-static/rooter/css/splash.css */ + +/* + CSS for ROOter splash pages + Copyright Francois Dechery + https://github.com/soif +*/ + +/* @group Splash Pages +--------------------------------------------------*/ + +.rooterSplash{ + padding: 0; + background: #F0F0F0; +} +.rooterPageHead{ + background: #55F; + padding: 10px 5px; + background: rgb(140,140,255); + background: -moz-linear-gradient(top, rgba(140,140,255,1) 0%, rgba(85,85,255,1) 100%); + background: -webkit-linear-gradient(top, rgba(140,140,255,1) 0%,rgba(85,85,255,1) 100%); + background: linear-gradient(to bottom, rgba(140,140,255,1) 0%,rgba(85,85,255,1) 100%); + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#8c8cff', endColorstr='#5555ff',GradientType=0 ); + border-bottom: 1px solid rgba(0,0,0,0.7); + +} +.rooterPageContent{ + border-top: 1px solid rgba(255,255,255,0.8); + border-bottom: 1px solid rgba(0,0,0, 0.1); + padding: 25px 10px; + max-width: 1200px; + margin: auto; +} + +.rooterPageContentBut{ + border-top: 1px solid rgba(255,255,255,0.8); + border-bottom: 1px solid rgba(0,0,0, 0.1); + padding: 25px 10px; + max-width: 600px; + margin: auto; +} + +.rooterHeadTitle{ + color: #fff; + text-align: center; + font-family: Georgia, "Times New Roman", Times, serif; + font-size: 32px; + line-height: 120%; + text-shadow: -1px -1px 2px rgba(0,0,0,0.5); +} +.rooterPageFoot{ + border-top: 1px solid rgba(255,255,255,0.8); + margin-top: 20px; + padding: 10px 10px; + max-width: 950px; + margin: auto; + font-size: 16px; +} +.rooterFootMenu{ + float: left; + margin-bottom: 10px; +} +.rooterFootMenu A{ + text-decoration: none; +} +.rooterFootMenu A:hover{ + color: #000; +} +.rooterFootMenu UL{ + padding: 0; + margin: 0; + overflow: hidden; + display: inline-block; +} +.rooterFootMenu LI{ + float: left; + padding: 0; + margin: 0; + list-style: none; +} +.rooterFootMenu LI A{ + padding: 0 10px; + color: #555; +} +.rooterFootMenu LI:first-child A{ + padding-left: 0; +} +.rooterFootCredits{ + float: right; + padding: 0; + margin: 0; + color: #999; + text-align: right; +} +.rooterFootCredits A{ + color: #777; +} +/* @end */ + + + + +/* @group Page: Home +--------------------------------------------------*/ + + +/* @group Logo +++++++++++++++++++ */ +.rooterHeadBox{ + font-size: 50px; + font-family: Georgia, "Times New Roman", Times, serif; + color: #fff; + line-height: 100%; + overflow: hidden; + width: 700px; + margin: auto; + padding-top: 10px; + opacity: 0; +} +.rooterLogo{ + background: url("../img/kangaroo_800.png") no-repeat; + background-size: 100%; + float: left; + height: 110px; + width: 250px; + opacity: 0.4; +} +.rooterTagline{ + margin-left: 100px; + padding-left: 10px; + text-shadow: 2px 2px 3px rgba(0,0,0,0.3); +} + +/* @end */ + +@media only screen and (max-width: 600px) { + .rooterHeadBox{ + text-align: center; + width: auto; + } + .rooterLogo{ + display: inline-block; + float: none; + } + .rooterTagline { + display: none; + } + .rooterFootCredits, + .rooterFootMenu{ + float: none; + text-align: center; + } +} + +#rooterItems{ + clear: both; + max-width: 600px ; + margin: auto; +} + +#rooterItemss{ + clear: both; + max-width: 350px ; + margin: auto; +} +.rooterItem{ + overflow: hidden; + border: 5px solid #00; + border-color: #00 #DDD #DDD #00; + padding: 20px 15px; + margin-bottom: 20px; + border-radius: 8px; + background-color: #AFAFAF; +} +.rooterItem:hover{ + background-color: #CFCFCF; + border-color: #AAA; +} +.rooterItemTitle{ + float: left; + font-size: 18px; + font-weight: bold; + padding-right: 10px; + color: #000; + line-height: 2em; +} +.rooterItemTitle .icon{ + color: #55F; + margin-right: 8px; + font-size: 2em; + vertical-align: middle; +} + +.rooterItemsp{ + overflow: hidden; + border: 5px solid #00; + border-color: #00 #DDD #DDD #00; + padding: 5px 15px; + margin-bottom: 5px; + border-radius: 8px; + background-color: #AFAFAF; +} +.rooterItemsp:hover{ + background-color: #CFCFCF; + border-color: #AAA; +} + +#rooterItems A{ + text-decoration: none; +} +.rooterItemDesc{ + font-size: 18px; + color: #777; + margin-left: 220px; + margin-top: 0.7em; +} +/* @end */ + + + +/* @group Page: Status +--------------------------------------------------*/ + +.modemStatusBlock{ + margin-bottom: 30px; +} +#rooterSplashStatus h3{ + clear:both; + font-size: 18px; + color: #55F; +} +#rooterSplashStatus h3 .icon{ + margin-right: 3px; +} +#rooterSplashStatus h3 .msCell{ + color: #666; +} +.modemStatusRow{ + clear:both; + padding-bottom: 20px; + overflow: hidden; +} +.modemStatusRow .msTitle{ + border-radius: 2px 2px 0 0; + padding: 5px 5px ; + background: #484848; + color: #fff; + background: rgb(99,99,99); + background: -moz-linear-gradient(top, rgba(99,99,99,1) 0%, rgba(72,72,72,1) 100%); + background: -webkit-linear-gradient(top, rgba(99,99,99,1) 0%,rgba(72,72,72,1) 100%); + background: linear-gradient(to bottom, rgba(99,99,99,1) 0%,rgba(72,72,72,1) 100%); + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#636363', endColorstr='#484848',GradientType=0 ); +} +.modemStatusRow .msCell{ + border-radius: 10px; + display: inline-block; + margin-top: 10px; + float:left; + border: 1px solid #ccc; + padding-bottom: 5px; + background: #fff; + +} +.modemStatusRow1 .msCell{ + width: 176px; + margin: 10px 5px 0 5px; + text-align: center; +} +.modemStatusRow1 SPAN B{ + font-weight: bold; + font-size: 35px; + line-height: 110%; + text-shadow: 1px 1px 1px rgba(0,0,0,0.4); +} +.modemStatusRow1 .msDesc{ + color: #000; + font-size: 12px; +} +.modemStatusRow2 .msCell{ + margin: 10px 5px; + text-align: center; +} +.modemStatusRow2 SPAN{ + display: inline-block; + padding: 5px 5px ; + font-size: 14px; +} +#counter_div{ + color: #000; + font-weight: normal; + font-size: 14px; +} +#counter_val{ + color: #F00; + font-size: 32px; + font-weight: bold; + text-shadow: 1px 1px 1px rgba(0,0,0,0.1); +} +#msCell_per{} +#msCell_csq{} +#msCell_rssi{} +#msCell_rscp{} +#msCell_ecio{} + +#rooterSplashStatus .level_0{ + color: #0F0; // green +} +#rooterSplashStatus .level_1{ + color: #0CB; // green blue +} +#rooterSplashStatus .level_2{ + color: #00F; // blue +} +#rooterSplashStatus .level_3{ + color: #F0F; // violet +} +#rooterSplashStatus .level_4{ + color: #F80; // orange +} +#rooterSplashStatus .level_5{ + color: #F00; // red +} +#rooterSplashStatus .level_6{ + color: #FF0; // yellow +} + +/* @end */ + + +/* Easy Color changer ------------- */ + +.rooterPageHead{ + /*background: #55F;*/ +} +.rooterItemTitle .icon, +#rooterSplashStatus h3{ + color: #55F; +} + + + diff --git a/rooter/0optionalapps/ext-speedtest/files/www/luci-static/speed/fonts/icomoon_splash.eot b/rooter/0optionalapps/ext-speedtest/files/www/luci-static/speed/fonts/icomoon_splash.eot new file mode 100644 index 0000000..29cd4d1 Binary files /dev/null and b/rooter/0optionalapps/ext-speedtest/files/www/luci-static/speed/fonts/icomoon_splash.eot differ diff --git a/rooter/0optionalapps/ext-speedtest/files/www/luci-static/speed/fonts/icomoon_splash.svg b/rooter/0optionalapps/ext-speedtest/files/www/luci-static/speed/fonts/icomoon_splash.svg new file mode 100644 index 0000000..dc2127b --- /dev/null +++ b/rooter/0optionalapps/ext-speedtest/files/www/luci-static/speed/fonts/icomoon_splash.svg @@ -0,0 +1,22 @@ + + + +Generated by IcoMoon + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/rooter/0optionalapps/ext-speedtest/files/www/luci-static/speed/fonts/icomoon_splash.ttf b/rooter/0optionalapps/ext-speedtest/files/www/luci-static/speed/fonts/icomoon_splash.ttf new file mode 100644 index 0000000..4e27645 Binary files /dev/null and b/rooter/0optionalapps/ext-speedtest/files/www/luci-static/speed/fonts/icomoon_splash.ttf differ diff --git a/rooter/0optionalapps/ext-speedtest/files/www/luci-static/speed/fonts/icomoon_splash.woff b/rooter/0optionalapps/ext-speedtest/files/www/luci-static/speed/fonts/icomoon_splash.woff new file mode 100644 index 0000000..63f5413 Binary files /dev/null and b/rooter/0optionalapps/ext-speedtest/files/www/luci-static/speed/fonts/icomoon_splash.woff differ diff --git a/rooter/0optionalapps/ext-speedtest/files/www/luci-static/speed/img/favicon.gif b/rooter/0optionalapps/ext-speedtest/files/www/luci-static/speed/img/favicon.gif new file mode 100644 index 0000000..bfbe292 Binary files /dev/null and b/rooter/0optionalapps/ext-speedtest/files/www/luci-static/speed/img/favicon.gif differ diff --git a/rooter/0optionalapps/ext-speedtest/files/www/luci-static/speed/img/kangaroo_800.png b/rooter/0optionalapps/ext-speedtest/files/www/luci-static/speed/img/kangaroo_800.png new file mode 100644 index 0000000..478fa6d Binary files /dev/null and b/rooter/0optionalapps/ext-speedtest/files/www/luci-static/speed/img/kangaroo_800.png differ diff --git a/rooter/0optionalapps/ext-texting/Makefile b/rooter/0optionalapps/ext-texting/Makefile new file mode 100644 index 0000000..313d024 --- /dev/null +++ b/rooter/0optionalapps/ext-texting/Makefile @@ -0,0 +1,33 @@ +#Owned by DairyMan@Whirlpool +# +#Copyright GNU act. +include $(TOPDIR)/rules.mk + +PKG_NAME:=ext-texting +PKG_VERSION:=1.000 +PKG_RELEASE:=1 + +PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool +include $(INCLUDE_DIR)/package.mk + +define Package/ext-texting + SECTION:=utils + CATEGORY:=ROOter + SUBMENU:=Optional Applications + TITLE:=support for Random Texting + PKGARCH:=all +endef + +define Package/ext-texting/description + Helper scripts to enable Random Texting +endef + + +define Build/Compile +endef + +define Package/ext-texting/install + $(CP) ./files/* $(1)/ +endef + +$(eval $(call BuildPackage,ext-texting)) diff --git a/rooter/0optionalapps/ext-texting/files/etc/config/texting b/rooter/0optionalapps/ext-texting/files/etc/config/texting new file mode 100644 index 0000000..f3dd29d --- /dev/null +++ b/rooter/0optionalapps/ext-texting/files/etc/config/texting @@ -0,0 +1,32 @@ + +config setting 'setting' + option start '32' + option end '68' + option times '20' + option enabled '0' + +config texting 'texting' + option startmin '0' + option endmin '0' + option starthour '8' + option endhour '17' + option numbers '15' + option messages '10' + option interval '1620' + +config numbers 'numbers' + list number '1112223333' + + +config messages 'messages' + list message 'Hey what’s going on?' + list message 'When are week meeting up?' + list message 'Who is attending the party?' + list message 'Not sure, what about you?' + list message 'Hey can you take the dogs out? I won’t be home for a while ' + list message 'Are you going to the party this weekend?' + list message 'Send me a text whenever your available.' + list message 'Your mom told me to get a hold of you' + list message 'Let’s leave early on the morning.' + list message 'Cool that sounds awesome. Let’s chat tmrw. ' + diff --git a/rooter/0optionalapps/ext-texting/files/etc/init.d/texting b/rooter/0optionalapps/ext-texting/files/etc/init.d/texting new file mode 100644 index 0000000..8b8687d --- /dev/null +++ b/rooter/0optionalapps/ext-texting/files/etc/init.d/texting @@ -0,0 +1,12 @@ +#!/bin/sh /etc/rc.common + +START=88 + +log() { + logger -t "TEXTING" "$@" +} + +start() +{ + /usr/lib/fullmenu/text-setup.sh +} diff --git a/rooter/0optionalapps/ext-texting/files/usr/lib/fullmenu/chksms.sh b/rooter/0optionalapps/ext-texting/files/usr/lib/fullmenu/chksms.sh new file mode 100644 index 0000000..20b3376 --- /dev/null +++ b/rooter/0optionalapps/ext-texting/files/usr/lib/fullmenu/chksms.sh @@ -0,0 +1,21 @@ +#!/bin/sh + +ROOTER=/usr/lib/rooter +ROOTER_LINK="/tmp/links" + +CURRMODEM=1 + +rm -f /tmp/texting +CPORT=$(uci -q get modem.modem$CURRMODEM.commport) +if [ -z $CPORT ]; then + return +fi +OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "smschk.gcom" "$CURRMODEM") +ERROR="ERROR" +if `echo ${OX} | grep "${ERROR}" 1>/dev/null 2>&1` +then + return +fi +echo "0" > /tmp/texting +uci set modem.general.smsnum='1' +uci commit modem \ No newline at end of file diff --git a/rooter/0optionalapps/ext-texting/files/usr/lib/fullmenu/dotext.sh b/rooter/0optionalapps/ext-texting/files/usr/lib/fullmenu/dotext.sh new file mode 100644 index 0000000..5767c1f --- /dev/null +++ b/rooter/0optionalapps/ext-texting/files/usr/lib/fullmenu/dotext.sh @@ -0,0 +1,123 @@ +#!/bin/sh +. /lib/functions.sh + +log() { + logger -t "TEXTING" "$@" +} + +handle_numbers() { + let "NUMBERS = $NUMBERS + 1" + if [ $NUMBERS -eq $nindex ]; then + numch=$1 + fi +} + +do_numbers() { + local config=$1 + config_list_foreach "$config" number handle_numbers +} + +handle_messages() { + let "NUMBERS = $NUMBERS + 1" + if [ $NUMBERS -eq $nindex ]; then + numch=$1 + fi +} + +do_messages() { + local config=$1 + config_list_foreach "$config" message handle_messages +} + +sendmsg() { + nnum=$(uci -q get texting.texting.numbers) + mnum=$(uci -q get texting.texting.messages) + delay=$(uci -q get texting.texting.interval) + NUMBERS=0 + RANDOM=$(date +%s%N | cut -b10-19) + RAN=$RANDOM + RAN1=${RAN:0:1} + if [ $RAN1 = "0" ]; then + RAN="1"$RAN + rlen=${#RAN} + if [ $rlen -gt 9 ]; then + RAN=${RAN:0:8} + fi + fi + nindex=$(( $RAN % $nnum + 1 )) + config_load texting + config_foreach do_numbers numbers + Phone=$numch + NUMBERS=0 + RANDOM=$(date +%s%N | cut -b10-19) + RAN=$RANDOM + RAN1=${RAN:0:1} + if [ $RAN1 = "0" ]; then + RAN="1"$RAN + rlen=${#RAN} + if [ $rlen -gt 9 ]; then + RAN=${RAN:0:8} + fi + fi + nindex=$(( $RAN % $mnum + 1 )) + config_foreach do_messages messages + Message=$numch + /usr/lib/fullmenu/chksms.sh + if [ -e /tmp/texting ]; then + /usr/lib/sms/smsout.sh "$Phone" "$Message" + fi +} + +checktime() { + shour=$(uci -q get texting.texting.starthour) + smin=$(uci -q get texting.texting.startmin) + ehour=$(uci -q get texting.texting.endhour) + emin=$(uci -q get texting.texting.endmin) + chour=$(date +%H) + cmin=$(date +%M) + if [ $shour -gt $chour ]; then + flag="0" + else + if [ $shour -eq $chour ]; then + if [ $smin -le $cmin ]; then + flag="1" + else + flag="0" + fi + else + flag="1" + fi + fi + + if [ $flag = "1" ]; then + if [ $ehour -lt $chour ]; then + flag="0" + else + if [ $ehour -eq $chour ]; then + if [ $emin -lt $cmin ]; then + flag="0" + else + flag="1" + fi + else + flag="1" + fi + fi + fi + + echo $flag +} + +while true +do + running=$(checktime) + if [ $running = "1" ]; then + EN=$(uci -q get texting.setting.enabled) + if [ $EN = "1" ]; then + sendmsg + sleep $delay + fi + else + sleep 900 + fi +done \ No newline at end of file diff --git a/rooter/0optionalapps/ext-texting/files/usr/lib/fullmenu/text-setup.sh b/rooter/0optionalapps/ext-texting/files/usr/lib/fullmenu/text-setup.sh new file mode 100644 index 0000000..5d57226 --- /dev/null +++ b/rooter/0optionalapps/ext-texting/files/usr/lib/fullmenu/text-setup.sh @@ -0,0 +1,63 @@ +#!/bin/sh +. /lib/functions.sh + +log() { + logger -t "TEXTING" "$@" +} + +sleep 3 + +handle_numbers() { + let "NUMBERS = $NUMBERS + 1" +} + +do_numbers() { + local config=$1 + config_list_foreach "$config" number handle_numbers +} + +handle_messages() { + let "NUMBERS = $NUMBERS + 1" +} + +do_messages() { + local config=$1 + config_list_foreach "$config" message handle_numbers +} + +SHOUR=$(uci -q get texting.setting.start) +HOUR=`expr $SHOUR / 4` +let "TH = $HOUR * 4" +let "TMP1 = $SHOUR - $TH" +let "MIN = $TMP1 * 15" +uci set texting.texting.starthour=$HOUR +uci set texting.texting.startmin=$MIN +EHOUR=$(uci -q get texting.setting.end) +HOUR=`expr $EHOUR / 4` +let "TH = $HOUR * 4" +let "TMP1 = $EHOUR - $TH" +let "MIN = $TMP1 * 15" +uci set texting.texting.endhour=$HOUR +uci set texting.texting.endmin=$MIN + +NUMBERS=0 +config_load texting +config_foreach do_numbers numbers +uci set texting.texting.numbers=$NUMBERS +NUMBERS=0 +config_foreach do_messages messages +uci set texting.texting.messages=$NUMBERS + +TIMES=$(uci -q get texting.setting.times) +let "TH = $EHOUR - $SHOUR" +let "TMIN = $TH * 15" +let "INTERVAL = $TMIN / $TIMES" +let "INTERVAL = $INTERVAL * 60" +uci set texting.texting.interval=$INTERVAL +uci commit texting + +result=`ps | grep -i "dotext.sh" | grep -v "grep" | wc -l` +if [ $result -lt 1 ]; then + /usr/lib/fullmenu/dotext.sh & +fi + diff --git a/rooter/0optionalapps/ext-texting/files/usr/lib/lua/luci/controller/texting.lua b/rooter/0optionalapps/ext-texting/files/usr/lib/lua/luci/controller/texting.lua new file mode 100644 index 0000000..a729365 --- /dev/null +++ b/rooter/0optionalapps/ext-texting/files/usr/lib/lua/luci/controller/texting.lua @@ -0,0 +1,32 @@ +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 + end + + entry({"admin", "services", "chksms"}, call("action_chksms")) +end + +function action_chksms() + local rv = {} + os.execute("/usr/lib/fullmenu/chksms.sh") + file = io.open("/tmp/texting", "r") + if file ~= nil then + rv["sms"] = "1" + file:close() + else + rv["sms"] = "0" + end + + luci.http.prepare_content("application/json") + luci.http.write_json(rv) +end \ No newline at end of file diff --git a/rooter/0optionalapps/ext-texting/files/usr/lib/lua/luci/model/cbi/fullmenu/texting.lua b/rooter/0optionalapps/ext-texting/files/usr/lib/lua/luci/model/cbi/fullmenu/texting.lua new file mode 100644 index 0000000..d689c0b --- /dev/null +++ b/rooter/0optionalapps/ext-texting/files/usr/lib/lua/luci/model/cbi/fullmenu/texting.lua @@ -0,0 +1,254 @@ +local utl = require "luci.util" + +m = Map("texting", translate("Random Texting"), translate("Send random message to number at random times")) + +m.on_after_save = function(self) + luci.sys.call("/usr/lib/fullmenu/text-setup.sh &") +end + +s = m:section(TypedSection, "setting", "Global Settings") +s.anonymous = true +s.addremove = false + +s:option(Flag, "enabled", translate("Enabled : ")) + +sdhour = s:option(ListValue, "start", translate("Starting Time :")) +sdhour.rmempty = true +sdhour:value("0", "12:00 AM") +sdhour:value("1", "12:15 AM") +sdhour:value("2", "12:30 AM") +sdhour:value("3", "12:45 AM") +sdhour:value("4", "01:00 AM") +sdhour:value("5", "01:15 AM") +sdhour:value("6", "01:30 AM") +sdhour:value("7", "01:45 AM") +sdhour:value("8", "02:00 AM") +sdhour:value("9", "02:15 AM") +sdhour:value("10", "02:30 AM") +sdhour:value("11", "02:45 AM") +sdhour:value("12", "03:00 AM") +sdhour:value("13", "03:15 AM") +sdhour:value("14", "03:30 AM") +sdhour:value("15", "03:45 AM") +sdhour:value("16", "04:00 AM") +sdhour:value("17", "04:15 AM") +sdhour:value("18", "04:30 AM") +sdhour:value("19", "04:45 AM") +sdhour:value("20", "05:00 AM") +sdhour:value("21", "05:15 AM") +sdhour:value("22", "05:30 AM") +sdhour:value("23", "05:45 AM") +sdhour:value("24", "06:00 AM") +sdhour:value("25", "06:15 AM") +sdhour:value("26", "06:30 AM") +sdhour:value("27", "06:45 AM") +sdhour:value("28", "07:00 AM") +sdhour:value("29", "07:15 AM") +sdhour:value("30", "07:30 AM") +sdhour:value("31", "07:45 AM") +sdhour:value("32", "08:00 AM") +sdhour:value("33", "08:15 AM") +sdhour:value("34", "08:30 AM") +sdhour:value("35", "08:45 AM") +sdhour:value("36", "09:00 AM") +sdhour:value("37", "09:15 AM") +sdhour:value("38", "09:30 AM") +sdhour:value("39", "09:45 AM") +sdhour:value("40", "10:00 AM") +sdhour:value("41", "10:15 AM") +sdhour:value("42", "10:30 AM") +sdhour:value("43", "10:45 AM") +sdhour:value("44", "11:00 AM") +sdhour:value("45", "11:15 AM") +sdhour:value("46", "11:30 AM") +sdhour:value("47", "11:45 AM") +sdhour:value("48", "12:00 PM") +sdhour:value("49", "12:15 PM") +sdhour:value("50", "12:30 PM") +sdhour:value("51", "12:45 PM") +sdhour:value("52", "01:00 PM") +sdhour:value("53", "01:15 PM") +sdhour:value("54", "01:30 PM") +sdhour:value("55", "01:45 PM") +sdhour:value("56", "02:00 PM") +sdhour:value("57", "02:15 PM") +sdhour:value("58", "02:30 PM") +sdhour:value("59", "02:45 PM") +sdhour:value("60", "03:00 PM") +sdhour:value("61", "03:15 PM") +sdhour:value("62", "03:30 PM") +sdhour:value("63", "03:45 PM") +sdhour:value("64", "04:00 PM") +sdhour:value("65", "04:15 PM") +sdhour:value("66", "04:30 PM") +sdhour:value("67", "04:45 PM") +sdhour:value("68", "05:00 PM") +sdhour:value("69", "05:15 PM") +sdhour:value("70", "05:30 PM") +sdhour:value("71", "05:45 PM") +sdhour:value("72", "06:00 PM") +sdhour:value("73", "06:15 PM") +sdhour:value("74", "06:30 PM") +sdhour:value("75", "06:45 PM") +sdhour:value("76", "07:00 PM") +sdhour:value("77", "07:15 PM") +sdhour:value("78", "07:30 PM") +sdhour:value("79", "07:45 PM") +sdhour:value("80", "08:00 PM") +sdhour:value("81", "08:15 PM") +sdhour:value("82", "08:30 PM") +sdhour:value("83", "08:45 PM") +sdhour:value("84", "09:00 PM") +sdhour:value("85", "09:15 PM") +sdhour:value("86", "09:30 PM") +sdhour:value("87", "09:45 PM") +sdhour:value("88", "10:00 PM") +sdhour:value("89", "10:15 PM") +sdhour:value("90", "10:30 PM") +sdhour:value("91", "10:45 PM") +sdhour:value("92", "11:00 PM") +sdhour:value("93", "11:15 PM") +sdhour:value("94", "11:30 PM") +sdhour:value("95", "11:45 PM") +sdhour.default = "32" + +sdhour = s:option(ListValue, "end", translate("Ending Time :")) +sdhour.rmempty = true +sdhour:value("0", "12:00 AM") +sdhour:value("1", "12:15 AM") +sdhour:value("2", "12:30 AM") +sdhour:value("3", "12:45 AM") +sdhour:value("4", "01:00 AM") +sdhour:value("5", "01:15 AM") +sdhour:value("6", "01:30 AM") +sdhour:value("7", "01:45 AM") +sdhour:value("8", "02:00 AM") +sdhour:value("9", "02:15 AM") +sdhour:value("10", "02:30 AM") +sdhour:value("11", "02:45 AM") +sdhour:value("12", "03:00 AM") +sdhour:value("13", "03:15 AM") +sdhour:value("14", "03:30 AM") +sdhour:value("15", "03:45 AM") +sdhour:value("16", "04:00 AM") +sdhour:value("17", "04:15 AM") +sdhour:value("18", "04:30 AM") +sdhour:value("19", "04:45 AM") +sdhour:value("20", "05:00 AM") +sdhour:value("21", "05:15 AM") +sdhour:value("22", "05:30 AM") +sdhour:value("23", "05:45 AM") +sdhour:value("24", "06:00 AM") +sdhour:value("25", "06:15 AM") +sdhour:value("26", "06:30 AM") +sdhour:value("27", "06:45 AM") +sdhour:value("28", "07:00 AM") +sdhour:value("29", "07:15 AM") +sdhour:value("30", "07:30 AM") +sdhour:value("31", "07:45 AM") +sdhour:value("32", "08:00 AM") +sdhour:value("33", "08:15 AM") +sdhour:value("34", "08:30 AM") +sdhour:value("35", "08:45 AM") +sdhour:value("36", "09:00 AM") +sdhour:value("37", "09:15 AM") +sdhour:value("38", "09:30 AM") +sdhour:value("39", "09:45 AM") +sdhour:value("40", "10:00 AM") +sdhour:value("41", "10:15 AM") +sdhour:value("42", "10:30 AM") +sdhour:value("43", "10:45 AM") +sdhour:value("44", "11:00 AM") +sdhour:value("45", "11:15 AM") +sdhour:value("46", "11:30 AM") +sdhour:value("47", "11:45 AM") +sdhour:value("48", "12:00 PM") +sdhour:value("49", "12:15 PM") +sdhour:value("50", "12:30 PM") +sdhour:value("51", "12:45 PM") +sdhour:value("52", "01:00 PM") +sdhour:value("53", "01:15 PM") +sdhour:value("54", "01:30 PM") +sdhour:value("55", "01:45 PM") +sdhour:value("56", "02:00 PM") +sdhour:value("57", "02:15 PM") +sdhour:value("58", "02:30 PM") +sdhour:value("59", "02:45 PM") +sdhour:value("60", "03:00 PM") +sdhour:value("61", "03:15 PM") +sdhour:value("62", "03:30 PM") +sdhour:value("63", "03:45 PM") +sdhour:value("64", "04:00 PM") +sdhour:value("65", "04:15 PM") +sdhour:value("66", "04:30 PM") +sdhour:value("67", "04:45 PM") +sdhour:value("68", "05:00 PM") +sdhour:value("69", "05:15 PM") +sdhour:value("70", "05:30 PM") +sdhour:value("71", "05:45 PM") +sdhour:value("72", "06:00 PM") +sdhour:value("73", "06:15 PM") +sdhour:value("74", "06:30 PM") +sdhour:value("75", "06:45 PM") +sdhour:value("76", "07:00 PM") +sdhour:value("77", "07:15 PM") +sdhour:value("78", "07:30 PM") +sdhour:value("79", "07:45 PM") +sdhour:value("80", "08:00 PM") +sdhour:value("81", "08:15 PM") +sdhour:value("82", "08:30 PM") +sdhour:value("83", "08:45 PM") +sdhour:value("84", "09:00 PM") +sdhour:value("85", "09:15 PM") +sdhour:value("86", "09:30 PM") +sdhour:value("87", "09:45 PM") +sdhour:value("88", "10:00 PM") +sdhour:value("89", "10:15 PM") +sdhour:value("90", "10:30 PM") +sdhour:value("91", "10:45 PM") +sdhour:value("92", "11:00 PM") +sdhour:value("93", "11:15 PM") +sdhour:value("94", "11:30 PM") +sdhour:value("95", "11:45 PM") +sdhour.default = "68" + +sdhour = s:option(ListValue, "times", translate("Times per Day :")) +sdhour.rmempty = true +sdhour:value("2", "2") +sdhour:value("4", "4") +sdhour:value("6", "6") +sdhour:value("8", "8") +sdhour:value("10", "10") +sdhour:value("12", "12") +sdhour:value("14", "14") +sdhour:value("16", "16") +sdhour:value("18", "18") +sdhour:value("20", "20") +sdhour:value("22", "22") +sdhour:value("24", "24") +sdhour:value("26", "26") +sdhour:value("28", "28") +sdhour:value("30", "30") +sdhour:value("32", "32") +sdhour:value("34", "34") +sdhour:value("36", "36") +sdhour:value("38", "38") +sdhour:value("40", "40") +sdhour.default = "10" + + +s = m:section(TypedSection, "numbers", "Phone Numbers") +s.anonymous = true +s.addremove = false + +o = s:option(DynamicList, "number", translate("List of Phone Numbers : ")) + +s = m:section(TypedSection, "messages", "Messages") +s.anonymous = true +s.addremove = false + +o = s:option(DynamicList, "message", translate("List of Messages : ")) + +m:section(SimpleSection).template = "fullmenu/textarea" + +return m \ No newline at end of file diff --git a/rooter/0optionalapps/ext-texting/files/usr/lib/lua/luci/view/fullmenu/textarea.htm b/rooter/0optionalapps/ext-texting/files/usr/lib/lua/luci/view/fullmenu/textarea.htm new file mode 100644 index 0000000..fd7c69f --- /dev/null +++ b/rooter/0optionalapps/ext-texting/files/usr/lib/lua/luci/view/fullmenu/textarea.htm @@ -0,0 +1,103 @@ +<% + load_icon = resource .. "/icons/loading.gif" +%> + + + + +
                + <%:Manual Texting%> + + + + + + + + + +
                Phone Number :
                Message :
                 
                + + + + + + + + + +
                diff --git a/rooter/0optionalapps/ext-throttle/Makefile b/rooter/0optionalapps/ext-throttle/Makefile new file mode 100644 index 0000000..cf731cc --- /dev/null +++ b/rooter/0optionalapps/ext-throttle/Makefile @@ -0,0 +1,36 @@ +#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)) diff --git a/rooter/0optionalapps/ext-throttle/files/etc/config/sqm b/rooter/0optionalapps/ext-throttle/files/etc/config/sqm new file mode 100644 index 0000000..67f58de --- /dev/null +++ b/rooter/0optionalapps/ext-throttle/files/etc/config/sqm @@ -0,0 +1,34 @@ + +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' + diff --git a/rooter/0optionalapps/ext-throttle/files/etc/hotplug.d/iface/11-sqm b/rooter/0optionalapps/ext-throttle/files/etc/hotplug.d/iface/11-sqm new file mode 100644 index 0000000..75ff4ea --- /dev/null +++ b/rooter/0optionalapps/ext-throttle/files/etc/hotplug.d/iface/11-sqm @@ -0,0 +1,27 @@ +#!/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 + diff --git a/rooter/0optionalapps/ext-throttle/files/etc/init.d/sqm b/rooter/0optionalapps/ext-throttle/files/etc/init.d/sqm new file mode 100644 index 0000000..3badb62 --- /dev/null +++ b/rooter/0optionalapps/ext-throttle/files/etc/init.d/sqm @@ -0,0 +1,31 @@ +#!/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 "$@" +} diff --git a/rooter/0optionalapps/ext-throttle/files/etc/sqm/sqm.conf b/rooter/0optionalapps/ext-throttle/files/etc/sqm/sqm.conf new file mode 100644 index 0000000..b9a98b4 --- /dev/null +++ b/rooter/0optionalapps/ext-throttle/files/etc/sqm/sqm.conf @@ -0,0 +1,5 @@ +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 diff --git a/rooter/0optionalapps/ext-throttle/files/etc/uci-defaults/50-luci-sqm b/rooter/0optionalapps/ext-throttle/files/etc/uci-defaults/50-luci-sqm new file mode 100644 index 0000000..b3aa47c --- /dev/null +++ b/rooter/0optionalapps/ext-throttle/files/etc/uci-defaults/50-luci-sqm @@ -0,0 +1,12 @@ +#!/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 diff --git a/rooter/0optionalapps/ext-throttle/files/usr/lib/sqm/defaults.sh b/rooter/0optionalapps/ext-throttle/files/usr/lib/sqm/defaults.sh new file mode 100644 index 0000000..009cfc6 --- /dev/null +++ b/rooter/0optionalapps/ext-throttle/files/usr/lib/sqm/defaults.sh @@ -0,0 +1,109 @@ +# 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" diff --git a/rooter/0optionalapps/ext-throttle/files/usr/lib/sqm/functions.sh b/rooter/0optionalapps/ext-throttle/files/usr/lib/sqm/functions.sh new file mode 100644 index 0000000..c61edfa --- /dev/null +++ b/rooter/0optionalapps/ext-throttle/files/usr/lib/sqm/functions.sh @@ -0,0 +1,923 @@ +################################################################################ +# (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 +} diff --git a/rooter/0optionalapps/ext-throttle/files/usr/lib/sqm/layer_cake.qos b/rooter/0optionalapps/ext-throttle/files/usr/lib/sqm/layer_cake.qos new file mode 100644 index 0000000..27d8163 --- /dev/null +++ b/rooter/0optionalapps/ext-throttle/files/usr/lib/sqm/layer_cake.qos @@ -0,0 +1,52 @@ +# 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 +} diff --git a/rooter/0optionalapps/ext-throttle/files/usr/lib/sqm/layer_cake.qos.help b/rooter/0optionalapps/ext-throttle/files/usr/lib/sqm/layer_cake.qos.help new file mode 100644 index 0000000..1cab3ed --- /dev/null +++ b/rooter/0optionalapps/ext-throttle/files/usr/lib/sqm/layer_cake.qos.help @@ -0,0 +1,4 @@ +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 diff --git a/rooter/0optionalapps/ext-throttle/files/usr/lib/sqm/piece_of_cake.qos b/rooter/0optionalapps/ext-throttle/files/usr/lib/sqm/piece_of_cake.qos new file mode 100644 index 0000000..ac65eda --- /dev/null +++ b/rooter/0optionalapps/ext-throttle/files/usr/lib/sqm/piece_of_cake.qos @@ -0,0 +1,52 @@ +# 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 +} diff --git a/rooter/0optionalapps/ext-throttle/files/usr/lib/sqm/piece_of_cake.qos.help b/rooter/0optionalapps/ext-throttle/files/usr/lib/sqm/piece_of_cake.qos.help new file mode 100644 index 0000000..b95e9be --- /dev/null +++ b/rooter/0optionalapps/ext-throttle/files/usr/lib/sqm/piece_of_cake.qos.help @@ -0,0 +1,4 @@ +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 diff --git a/rooter/0optionalapps/ext-throttle/files/usr/lib/sqm/run.sh b/rooter/0optionalapps/ext-throttle/files/usr/lib/sqm/run.sh new file mode 100644 index 0000000..6f55ca7 --- /dev/null +++ b/rooter/0optionalapps/ext-throttle/files/usr/lib/sqm/run.sh @@ -0,0 +1,130 @@ +#!/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 diff --git a/rooter/0optionalapps/ext-throttle/files/usr/lib/sqm/simple.qos b/rooter/0optionalapps/ext-throttle/files/usr/lib/sqm/simple.qos new file mode 100644 index 0000000..55f3cdf --- /dev/null +++ b/rooter/0optionalapps/ext-throttle/files/usr/lib/sqm/simple.qos @@ -0,0 +1,234 @@ +################################################################################ +# 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 +} diff --git a/rooter/0optionalapps/ext-throttle/files/usr/lib/sqm/simple.qos.help b/rooter/0optionalapps/ext-throttle/files/usr/lib/sqm/simple.qos.help new file mode 100644 index 0000000..b3c0096 --- /dev/null +++ b/rooter/0optionalapps/ext-throttle/files/usr/lib/sqm/simple.qos.help @@ -0,0 +1 @@ +BW-limited three-tier prioritisation scheme with your qdisc on each queue. (default) diff --git a/rooter/0optionalapps/ext-throttle/files/usr/lib/sqm/simplest.qos b/rooter/0optionalapps/ext-throttle/files/usr/lib/sqm/simplest.qos new file mode 100644 index 0000000..80fe208 --- /dev/null +++ b/rooter/0optionalapps/ext-throttle/files/usr/lib/sqm/simplest.qos @@ -0,0 +1,104 @@ +################################################################################ +# 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 +} + +################################################################################ diff --git a/rooter/0optionalapps/ext-throttle/files/usr/lib/sqm/simplest.qos.help b/rooter/0optionalapps/ext-throttle/files/usr/lib/sqm/simplest.qos.help new file mode 100644 index 0000000..c359256 --- /dev/null +++ b/rooter/0optionalapps/ext-throttle/files/usr/lib/sqm/simplest.qos.help @@ -0,0 +1 @@ +Simplest possible configuration: HTB rate limiter with your qdisc attached. diff --git a/rooter/0optionalapps/ext-throttle/files/usr/lib/sqm/simplest_tbf.qos b/rooter/0optionalapps/ext-throttle/files/usr/lib/sqm/simplest_tbf.qos new file mode 100644 index 0000000..3f7a1c3 --- /dev/null +++ b/rooter/0optionalapps/ext-throttle/files/usr/lib/sqm/simplest_tbf.qos @@ -0,0 +1,85 @@ +################################################################################ +# 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 +} + +################################################################################ diff --git a/rooter/0optionalapps/ext-throttle/files/usr/lib/sqm/simplest_tbf.qos.help b/rooter/0optionalapps/ext-throttle/files/usr/lib/sqm/simplest_tbf.qos.help new file mode 100644 index 0000000..3f93f89 --- /dev/null +++ b/rooter/0optionalapps/ext-throttle/files/usr/lib/sqm/simplest_tbf.qos.help @@ -0,0 +1,2 @@ +Simplest possible configuration (TBF): TBF rate limiter with your qdisc attached. +TBF may give better performance than HTB on some architectures. diff --git a/rooter/0optionalapps/ext-throttle/files/usr/lib/sqm/start-sqm b/rooter/0optionalapps/ext-throttle/files/usr/lib/sqm/start-sqm new file mode 100644 index 0000000..cd76e01 --- /dev/null +++ b/rooter/0optionalapps/ext-throttle/files/usr/lib/sqm/start-sqm @@ -0,0 +1,66 @@ +#!/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 + + +[ -n "$IFACE" ] || exit 1 + +. /etc/sqm/sqm.conf +. ${SQM_LIB_DIR}/functions.sh +. ${SQM_LIB_DIR}/defaults.sh +STATE_FILE="${SQM_STATE_DIR}/${IFACE}.state" + +check_state_dir + +# log file for the most recent sqm instance start +if [ "$SQM_DEBUG" -eq "1" ] ; then + SQM_DEBUG_LOG="${SQM_START_LOG}" + OUTPUT_TARGET="${SQM_DEBUG_LOG}" + echo "start-sqm: Log for interface ${IFACE}: $(date)" > "${OUTPUT_TARGET}" +fi + +if [ -z "${SCRIPT}" ] ; then + sqm_error "SCRIPT value is not defined in /etc/sqm/${IFACE}.iface.conf" + sqm_error "Please check your configuration and try again." + exit 1 +fi + +if [ -f "${STATE_FILE}" ]; then + sqm_error "SQM already activated on ${IFACE}." + exit 1 +fi + +# in case of spurious hotplug events, try double check whether the interface is really up +if [ ! -d /sys/class/net/${IFACE} ] ; then + sqm_error "${IFACE} does currently not exist, not even trying to start SQM on nothing." + exit 1 +fi + +if [ "${ENABLED:-1}" -ne "1" ]; then + sqm_log "SQM config disabled on ${IFACE}." + exit 0 +fi + +if [ ! -f "${SQM_LIB_DIR}/$SCRIPT" ]; then + sqm_error "SQM script ${SCRIPT} not found!" + exit 1 +fi + +. "${SQM_LIB_DIR}/$SCRIPT" + +sqm_trace; sqm_trace "$(date): Starting." # Add some space and a date stamp to verbose log output and log files to separate runs +sqm_log "Starting SQM script: ${SCRIPT} on ${IFACE}, in: ${DOWNLINK} Kbps, out: ${UPLINK} Kbps" + +if fn_exists sqm_start ; then + sqm_debug "Using script specific sqm_start function overriding the generic sqm_start_default." + sqm_start && write_state_file ${STATE_FILE} && sqm_log "${SCRIPT} was started on ${IFACE} successfully" +else + sqm_debug "Using generic sqm_start_default function." + sqm_start_default && write_state_file ${STATE_FILE} && sqm_log "${SCRIPT} was started on ${IFACE} successfully" +fi + +exit 0 diff --git a/rooter/0optionalapps/ext-throttle/files/usr/lib/sqm/stop-sqm b/rooter/0optionalapps/ext-throttle/files/usr/lib/sqm/stop-sqm new file mode 100644 index 0000000..9a9cbeb --- /dev/null +++ b/rooter/0optionalapps/ext-throttle/files/usr/lib/sqm/stop-sqm @@ -0,0 +1,54 @@ +#!/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 + +# allow passing in the IFACE as first command line argument + +[ -n "$IFACE" ] || exit 1 + +. /etc/sqm/sqm.conf +. ${SQM_LIB_DIR}/functions.sh +. ${SQM_LIB_DIR}/defaults.sh + +check_state_dir +# log file for the most recent sqm instance stop +if [ "$SQM_DEBUG" -eq "1" ] ; then + SQM_DEBUG_LOG="${SQM_STOP_LOG}" + OUTPUT_TARGET="${SQM_DEBUG_LOG}" + echo "stop-sqm: Log for interface ${IFACE}: $(date)" > "${OUTPUT_TARGET}" +fi + +if [ ! -f "${SQM_STATE_DIR}/${IFACE}.state" ] ; then + sqm_error "State file does not exist; SQM was not running on interface ${IFACE}" + exit 1 +fi +STATE_FILE="${SQM_STATE_DIR}/${IFACE}.state" + +if [ -z "${SCRIPT}" ] ; then + sqm_error "SCRIPT value is not defined in /etc/sqm/${IFACE}.iface.conf" + sqm_error "Please check your configuration and try again." + exit 1 +fi + +sqm_trace; sqm_trace "$(date): Stopping." # Add some space and a date stamp to verbose log output and log files to separate runs +sqm_log "Stopping SQM on ${IFACE}" + +# make sure to only delete the ifb associated with the current interface +CUR_IFB=$( get_ifb_associated_with_if ${IFACE} ) +[ -z "$CUR_IFB" ] && CUR_IFB=$( ifb_name ${IFACE} ) + +if [ ! -f "${SQM_LIB_DIR}/$SCRIPT" ]; then + sqm_error "SQM script ${SCRIPT} not found!" + exit 1 +fi + +. "${SQM_LIB_DIR}/$SCRIPT" + +sqm_stop +rm -f "${STATE_FILE}" + +exit 0 diff --git a/rooter/0optionalapps/ext-throttle/files/usr/lib/sqm/update-available-qdiscs b/rooter/0optionalapps/ext-throttle/files/usr/lib/sqm/update-available-qdiscs new file mode 100644 index 0000000..c966a19 --- /dev/null +++ b/rooter/0optionalapps/ext-throttle/files/usr/lib/sqm/update-available-qdiscs @@ -0,0 +1,14 @@ +#!/bin/sh + +. /etc/sqm/sqm.conf +. ${SQM_LIB_DIR}/functions.sh +. ${SQM_LIB_DIR}/defaults.sh + +[ -d "${SQM_QDISC_STATE_DIR}" ] || mkdir -p "${SQM_QDISC_STATE_DIR}" + +SQM_VERBOSITY_MIN=5 # Silence errors while checking + +for qdisc in $SQM_CHECK_QDISCS; do + [ -f ${SQM_QDISC_STATE_DIR}/$qdisc ] && continue + verify_qdisc $qdisc && touch ${SQM_QDISC_STATE_DIR}/$qdisc +done diff --git a/rooter/0optionalapps/ext-throttle/files/usr/lib/throttle/throttle.sh b/rooter/0optionalapps/ext-throttle/files/usr/lib/throttle/throttle.sh new file mode 100644 index 0000000..6178cdb --- /dev/null +++ b/rooter/0optionalapps/ext-throttle/files/usr/lib/throttle/throttle.sh @@ -0,0 +1,47 @@ +#!/bin/sh +. /lib/functions.sh + +stop_interface() { + INTER=$1 + DEVICE=$(uci -q get sqm.$INTER.interface) + uci set sqm.$INTER.enabled='0' + uci commit sqm + if [ $DEVICE != "0" ]; then + /usr/lib/sqm/run.sh stop ${DEVICE} + fi +} + +start_interface() { + INTER=$1 + sdown=$2 + sup=$3 + uci set sqm.$INTER.enabled='1' + uci set sqm.$INTER.download=$sdown + uci set sqm.$INTER.upload=$sup + uci commit sqm + DEVICE=$(uci -q get sqm.$INTER.interface) + if [ $DEVICE != "0" ]; then + /usr/lib/sqm/run.sh stop ${DEVICE} + /usr/lib/sqm/run.sh start ${DEVICE} + fi +} + +cmd=$1 +if [ $cmd = 'start' ]; then + mult=$4 + if [ -z $mult ]; then + down=$2"000" + up=$3"000" + else + down=$2 + up=$3 + fi + /etc/init.d/sqm enabled + start_interface wan $down $up + start_interface wan1 $down $up + start_interface wan2 $down $up +else + stop_interface wan + stop_interface wan1 + stop_interface wan2 +fi \ No newline at end of file diff --git a/rooter/0optionalapps/ext-wireguard/Makefile b/rooter/0optionalapps/ext-wireguard/Makefile new file mode 100644 index 0000000..e46e0df --- /dev/null +++ b/rooter/0optionalapps/ext-wireguard/Makefile @@ -0,0 +1,35 @@ +#Owned by DairyMan@Whirlpool +# +#Copyright GNU act. +include $(TOPDIR)/rules.mk + +PKG_NAME:=ext-wireguard +PKG_VERSION:=4.500 +PKG_RELEASE:=1 + +PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool +include $(INCLUDE_DIR)/package.mk + +define Package/ext-wireguard + SECTION:=utils + CATEGORY:=ROOter + SUBMENU:=Optional Applications + DEPENDS:=+wireguard-tools +kmod-wireguard \ + +luci-proto-wireguard +udp-tunnel +eoip + TITLE:=Install scripts for Wireguard + PKGARCH:=all +endef + +define Package/ext-wireguard/description + Install scripts for Wireguard +endef + + +define Build/Compile +endef + +define Package/ext-wireguard/install + $(CP) ./files/* $(1)/ +endef + +$(eval $(call BuildPackage,ext-wireguard)) diff --git a/rooter/0optionalapps/ext-wireguard/files/etc/config/wireguard b/rooter/0optionalapps/ext-wireguard/files/etc/config/wireguard new file mode 100644 index 0000000..77908d4 --- /dev/null +++ b/rooter/0optionalapps/ext-wireguard/files/etc/config/wireguard @@ -0,0 +1,5 @@ + +config settings 'settings' + option enabled '0' + option client '0' + option server '0' diff --git a/rooter/0optionalapps/ext-wireguard/files/etc/config/wireguard_recipes b/rooter/0optionalapps/ext-wireguard/files/etc/config/wireguard_recipes new file mode 100644 index 0000000..52a6b2b --- /dev/null +++ b/rooter/0optionalapps/ext-wireguard/files/etc/config/wireguard_recipes @@ -0,0 +1,36 @@ +config wireguard_recipe b_client + option _description "Wireguard Client" + option _role "client" + option client "1" + option port "51280" + option auto '0' + option addresses '' + option dns '' + option privatekey '' + option name '' + option keepalive '25' + option publickey '' + option presharedkey '' + option ips '' + option ra_ips '1' + option endpoint_host '' + option sport '51280' + option active '0' + option udptunnel '0' + option mtu '1280' + +config wireguard_recipe b_server + option _description "Wireguard Server" + option _role "server" + option client "0" + option port "51280" + option auto '0' + option addresses '' + option publickey '' + option privatekey '' + option usepre '0' + option presharedkey '' + option active '0' + option udptunnel '0' + option udpport '54321' + option mtu '1280' \ No newline at end of file diff --git a/rooter/0optionalapps/ext-wireguard/files/etc/init.d/wireguard b/rooter/0optionalapps/ext-wireguard/files/etc/init.d/wireguard new file mode 100644 index 0000000..4e49b81 --- /dev/null +++ b/rooter/0optionalapps/ext-wireguard/files/etc/init.d/wireguard @@ -0,0 +1,87 @@ +#!/bin/sh /etc/rc.common +. /lib/functions.sh +# Copyright (C) 2006 OpenWrt.org + +START=99 + +log() { + logger -t "WireGuard Init.d : " "$@" +} + +chk_zone() { + local config=$1 + + config_get src $config src + config_get dest $config dest + if [ $src = "lan" -a $dest = "wg" ]; then + uci set firewall."$config".dest="wan" + uci commit firewall + fi +} + +check_config () { + log "Check Client Interfaces" + uci delete network.wg0 + uci delete network.wg1 + uci commit network + uci set network.wg0=interface + uci set network.wg0.proto="wireguard" + uci set network.wg0.auto="0" + uci set network.wg0.private_key="" + uci set network.wg0.listen_port="" + uci add_list network.wg0.addresses="" + uci set network.wg1=interface + uci set network.wg1.proto="wireguard" + uci set network.wg1.auto="0" + uci set network.wg1.private_key="" + uci set network.wg1.listen_port="" + uci add_list network.wg1.addresses="" + uci commit network + + uci delete firewall.wgzone + uci delete firewall.wgwforward + uci delete firewall.wwgforward + uci delete firewall.lwgforward + uci delete firewall.wglforward + uci commit firewall + uci set firewall.wgzone=zone + uci set firewall.wgzone.name="wg" + uci set firewall.wgzone.forward="ACCEPT" + uci set firewall.wgzone.output="ACCEPT" + uci set firewall.wgzone.network="wg0 wg1" + uci set firewall.wgzone.input="ACCEPT" + uci set firewall.wgzone.masq="1" + uci set firewall.wgzone.mtu_fix="1" + uci commit firewall + + config_load firewall + config_foreach chk_zone forwarding + + /etc/init.d/firewall restart +} + +chk_start() { + local config=$1 + + config_get auto $config auto + uci set wireguard."$config".active="0" + uci commit wireguard + if [ $auto = '1' ]; then + /usr/lib/wireguard/startvpn.sh $config + else + /usr/lib/wireguard/stopvpn.sh $config + fi +} + +start() { + uci set wireguard.settings.client="0" + uci set wireguard.settings.server="0" + uci commit wireguard + if [ ! -e /etc/openvpn ]; then + mkdir /etc/openvpn + fi + check_config + + config_load wireguard + config_foreach chk_start wireguard +} \ No newline at end of file diff --git a/rooter/0optionalapps/ext-wireguard/files/usr/lib/lua/luci/controller/wireguard.lua b/rooter/0optionalapps/ext-wireguard/files/usr/lib/lua/luci/controller/wireguard.lua new file mode 100644 index 0000000..48ea3c3 --- /dev/null +++ b/rooter/0optionalapps/ext-wireguard/files/usr/lib/lua/luci/controller/wireguard.lua @@ -0,0 +1,111 @@ +-- Copyright 2016-2017 Dan Luedtke +-- Licensed to the public under the Apache License 2.0. + +module("luci.controller.wireguard", package.seeall) + +I18N = require "luci.i18n" +translate = I18N.translate + +function index() + 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 + entry({"admin", "vpn", "wireguard"}, cbi("wireguard"), _("Wireguard"), 63) + entry( {"admin", "vpn", "wireguard", "client"}, cbi("wireguard-client"), nil ).leaf = true + entry( {"admin", "vpn", "wireguard", "server"}, cbi("wireguard-server"), nil ).leaf = true + end + + entry( {"admin", "vpn", "wireguard", "wupload"}, call("conf_upload")) + entry( {"admin", "vpn", "generateconf"}, call("conf_gen")) + entry( {"admin", "vpn", "textconf"}, call("text_gen")) + entry( {"admin", "vpn", "wirestatus"}, call("wirestatus")) +end + +function conf_upload() + local fs = require("nixio.fs") + local http = require("luci.http") + local util = require("luci.util") + local uci = require("luci.model.uci").cursor() + local upload = http.formvalue("ovpn_file") + local name = http.formvalue("instance_name2") + local file = "/etc/openvpn/" ..name.. ".conf" + + if name and upload then + local fp + + http.setfilehandler( + function(meta, chunk, eof) + local data = util.trim(chunk:gsub("\r\n", "\n")) .. "\n" + data = util.trim(data:gsub("[\128-\255]", "")) + + if not fp and meta and meta.name == "ovpn_file" then + fp = io.open(file, "w") + end + if fp and data then + fp:write(data) + end + if fp and eof then + fp:close() + end + end + ) + + if fs.access(file) then + os.execute("/usr/lib/wireguard/conf.sh " .. name .. " " .. file) + end + end + http.redirect(luci.dispatcher.build_url('admin/vpn/wireguard')) +end + +function conf_gen() + os.execute("/usr/lib/wireguard/create.sh") +end + +function text_gen() + local set = luci.http.formvalue("set") + os.execute("/usr/lib/wireguard/text.sh " .. "\"" .. set .. "\"") +end + +function wirestatus() + local data = { } + local last_device = "" + + local wg_dump = io.popen("wg show all dump") + if wg_dump then + local line + for line in wg_dump:lines() do + local line = string.split(line, "\t") + if not (last_device == line[1]) then + last_device = line[1] + data[line[1]] = { + name = line[1], + public_key = line[3], + listen_port = line[4], + fwmark = line[5], + peers = { } + } + else + local peer = { + public_key = line[2], + endpoint = line[4], + allowed_ips = { }, + latest_handshake = line[6], + transfer_rx = line[7], + transfer_tx = line[8], + persistent_keepalive = line[9] + } + if not (line[4] == '(none)') then + for ipkey, ipvalue in pairs(string.split(line[5], ",")) do + if #ipvalue > 0 then + table.insert(peer['allowed_ips'], ipvalue) + end + end + end + table.insert(data[line[1]].peers, peer) + end + end + end + + luci.http.prepare_content("application/json") + luci.http.write_json(data) +end \ No newline at end of file diff --git a/rooter/0optionalapps/ext-wireguard/files/usr/lib/lua/luci/model/cbi/wireguard-client.lua b/rooter/0optionalapps/ext-wireguard/files/usr/lib/lua/luci/model/cbi/wireguard-client.lua new file mode 100644 index 0000000..ec041aa --- /dev/null +++ b/rooter/0optionalapps/ext-wireguard/files/usr/lib/lua/luci/model/cbi/wireguard-client.lua @@ -0,0 +1,99 @@ +require("luci.ip") +require("luci.model.uci") + +--luci.sys.call("/usr/lib/wireguard/keygen.sh " .. arg[1]) + +local m = Map("wireguard", translate("Wireguard Client"), translate("Set up a Wireguard Client")) + +e = m:section(NamedSection, "settings", "") + +m.on_init = function(self) + --luci.sys.call("/usr/lib/wireguard/keygen.sh " .. arg[1]) +end + +btn = e:option(Button, "_btn", translate(" ")) +btn.inputtitle = translate("Back to Main Page") +btn.inputstyle = "apply" +btn.redirect = luci.dispatcher.build_url( + "admin", "vpn", "wireguard" +) +function btn.write(self, section, value) + luci.http.redirect( self.redirect ) +end + + +local s = m:section( NamedSection, arg[1], "wireguard", translate("Client") ) + +ip = s:option(Value, "addresses", translate("IP Addresses :"), translate("Comma separated list of IP Addresses that server will accept from this client")); +ip.rmempty = true; +ip.optional=false; +ip.default="10.14.0.2/24"; + +port = s:option(Value, "port", translate("Listen Port :"), translate("Client Listen Port")); +port.rmempty = true; +port.optional=false; +port.default="51820"; + +ul = s:option(ListValue, "udptunnel", translate("Enable UDP over TCP :")); +ul:value("0", translate("No")) +ul:value("1", translate("Yes")) +ul.default=0 + +dns = s:option(Value, "dns", translate("DNS Servers :"), translate("Comma separated list of DNS Servers.")); +dns.rmempty = true; +dns.optional=false; + +mtu = s:option(Value, "mtu", translate("MTU :"), translate("Maximum MTU")); +mtu.rmempty = true; +mtu.optional=false; +mtu.datatype = 'range(1280,1420)'; +mtu.default="1280"; + +pka = s:option(Value, "persistent_keepalive", translate("Persistent Keep Alive :"), translate("Seconds between keep alive messages")); +pka.rmempty = true; +pka.optional=false; +pka.datatype = 'range(1,100)'; +pka.default="25"; + +pkey = s:option(Value, "privatekey", translate("Private Key :"), translate("Private Key supplied by the Server")); +pkey.rmempty = true; +pkey.optional=false; + +bl = s:option(ListValue, "auto", translate("Start on Boot :")); +bl:value("0", translate("No")) +bl:value("1", translate("Yes")) +bl.default="0" + +xbl = s:option(ListValue, "forward", translate("All Traffic Through Tunnel :")); +xbl:value("0", translate("No")) +xbl:value("1", translate("Yes")) +xbl.default="1" + +s = m:section( NamedSection, arg[1], "wireguard", translate("Server") ) + +name = s:option( Value, "name", translate("Server Name :"), translate("Optional Server name")) + +pukey = s:option(Value, "publickey", translate("Public Key :"), translate("Public Key of the Server")); +pukey.rmempty = true; +pukey.optional=false; + +prkey = s:option(Value, "presharedkey", translate("Presharedkey :"), translate("PreShared Key from the Server")); +prkey.rmempty = true; +prkey.optional=false; + +host = s:option(Value, "endpoint_host", translate("Server Address :"), translate("URL or IP Address of Server")); +host.rmempty = true; +host.optional=false; +host.default=""; + +sport = s:option(Value, "sport", translate("Listen Port :"), translate("Server Listen Port")); +sport.rmempty = true; +sport.optional=false; +sport.default="51820"; + +sip = s:option(Value, "ips", translate("Allowed IP Addresses :"), translate("Comma separated list of IP Addresses that server will accept")); +sip.rmempty = true; +sip.optional=false; +sip.default="10.14.0.0/24"; + +return m \ No newline at end of file diff --git a/rooter/0optionalapps/ext-wireguard/files/usr/lib/lua/luci/model/cbi/wireguard-server.lua b/rooter/0optionalapps/ext-wireguard/files/usr/lib/lua/luci/model/cbi/wireguard-server.lua new file mode 100644 index 0000000..5fb15ee --- /dev/null +++ b/rooter/0optionalapps/ext-wireguard/files/usr/lib/lua/luci/model/cbi/wireguard-server.lua @@ -0,0 +1,130 @@ +require("luci.ip") +require("luci.model.uci") + +--luci.sys.call("/usr/lib/wireguard/keygen.sh " .. arg[1]) + +local m = Map("wireguard", translate("Wireguard Server"), translate("Set up a Wireguard Server")) + +e = m:section(NamedSection, "settings", "") + +m.on_init = function(self) + luci.sys.call("/usr/lib/wireguard/keygen.sh " .. arg[1]) +end + +m.on_after_save = function(self) + luci.sys.call("/usr/lib/wireguard/keygen.sh " .. arg[1] .. "&") +end + +btn = e:option(Button, "_btn", translate(" ")) +btn.inputtitle = translate("Back to Main Page") +btn.inputstyle = "apply" +btn.redirect = luci.dispatcher.build_url( + "admin", "vpn", "wireguard" +) +function btn.write(self, section, value) + luci.http.redirect( self.redirect ) +end + + +local s = m:section( NamedSection, arg[1], "wireguard", translate("Server") ) + +ip = s:option(Value, "addresses", translate("Internal IP Address :")); +ip.rmempty = true; +ip.optional=false; +ip.default="10.14.0.1/32"; +ip.datatype = "ipaddr" + +host = s:option(Value, "endpoint_host", translate("Server Address :"), translate("URL or IP Address of Server")); +host.rmempty = true; +host.optional=false; +host.default="example.wireguard.org"; + +port = s:option(Value, "port", translate("Port :"), translate("Server Listen Port. Default is 51280")); +port.rmempty = true; +port.optional=false; +port.default="51280"; + +ul = s:option(ListValue, "udptunnel", "Enable UDP over TCP :"); +ul:value("0", translate("No")) +ul:value("1", translate("Yes")) +ul.default=0 + +uport = s:option(Value, "udpport", translate("UDP over TCP Port :"), translate("Server Local TCP Port. Default is 54321")); +uport.rmempty = true; +uport.optional=false; +uport.default="54321"; +uport:depends("udptunnel", "1") + +pkey = s:option(DummyValue, "privatekey", translate("Private Key :")); +pkey.optional=false; + +pukey = s:option(DummyValue, "publickey", translate("Public Key :"), translate("Server Public key sent to Clients")); +pukey.optional=false; + +pl = s:option(ListValue, "usepre", "Use PreSharedKey :"); +pl:value("0", translate("No")) +pl:value("1", translate("Yes")) +pl.default=0 + +prkey = s:option(DummyValue, "presharedkey", translate("PreShared Key :"), translate("PreShared Key sent to Client")); +prkey.optional=false; +prkey:depends("usepre", "1") + +bl = s:option(ListValue, "auto", translate("Start on Boot :")); +bl:value("0", translate("No")) +bl:value("1", translate("Yes")) +bl.default="0" + +xbl = s:option(ListValue, "forward", translate("All Traffic Through Tunnel :")); +xbl:value("0", translate("No")) +xbl:value("1", translate("Yes")) +xbl.default="1" + + +b3 = s:option(DummyValue, "blank", " "); + +sx = s:option(Value, "_dmy1", translate(" ")) +sx.template = "wireguard/conf" + +ss = m:section(TypedSection, "custom" .. arg[1], translate("Clients"), translate("Clients of this server")) +ss.anonymous = true +ss.addremove = true + +name = ss:option(Value, "name", translate("Client Name")) +name.optional=false; + +cport = ss:option(Value, "endpoint_port", translate("Listen Port :"), translate("Port sent to Client. Default is 51280")); +cport.rmempty = true; +cport.optional=false; +cport.default=""; + +aip = ss:option(Value, "address", translate("Assigned IP Address :"), translate("IP Address assigned to Client")); +aip.rmempty = true; +aip.optional=false; +aip.default="10.14.0.2/32"; + +dns = ss:option(Value, "dns", translate("DNS Servers :"), translate("Comma separated list of DNS Servers sent to Client")); +dns.rmempty = true; +dns.optional=false; +dns.default=""; + +mtu = ss:option(Value, "mtu", translate("MTU :"), translate("Maximum MTU")); +mtu.rmempty = true; +mtu.optional=false; +mtu.datatype = 'range(1280,1420)'; +mtu.default="1280"; + +aip = ss:option(Value, "allowed_ips", translate("Allowed IP Address :"), translate("Comma separated list of IP Addresses allowed from Client")); +aip.rmempty = true; +aip.optional=false; +aip.default="0.0.0.0/0,::/0"; + +pukey = ss:option(DummyValue, "publickey", translate("Public Key :"), translate("Client Public Key")); +pukey.optional=false; + +pikey = ss:option(DummyValue, "privatekey", translate("Private Key :"), translate("Private Key sent to Client")); +pikey.optional=false; + +b3 = ss:option(DummyValue, "blank", " "); + +return m \ No newline at end of file diff --git a/rooter/0optionalapps/ext-wireguard/files/usr/lib/lua/luci/model/cbi/wireguard.lua b/rooter/0optionalapps/ext-wireguard/files/usr/lib/lua/luci/model/cbi/wireguard.lua new file mode 100644 index 0000000..0aab305 --- /dev/null +++ b/rooter/0optionalapps/ext-wireguard/files/usr/lib/lua/luci/model/cbi/wireguard.lua @@ -0,0 +1,182 @@ +local fs = require "nixio.fs" +local sys = require "luci.sys" +local uci = require "luci.model.uci".cursor() +local testfullps = sys.exec("ps --help 2>&1 | grep BusyBox") --check which ps do we have +local psstring = (string.len(testfullps)>0) and "ps w" or "ps axfw" --set command we use to get pid + +local m = Map("wireguard", translate("Wireguard"), translate("Set up a Wireguard VPN Tunnel on your Router")) + +local s = m:section( TypedSection, "wireguard", translate("Instances"), translate("Below is a list of configured Wireguard Instances and their current state") ) +s.template = "cbi/tblsection" +s.template_addremove = "wireguard/cbi-select-input-add" +s.addremove = true +s.add_select_options = { } + +local cfg = s:option(DummyValue, "config") +function cfg.cfgvalue(self, section) + local file_cfg = self.map:get(section, "client") + if file_cfg == "1" then + s.extedit = luci.dispatcher.build_url("admin", "vpn", "wireguard", "client", "%s") + else + s.extedit = luci.dispatcher.build_url("admin", "vpn", "wireguard", "server", "%s") + end +end + +uci:load("wireguard_recipes") +uci:foreach( "wireguard_recipes", "wireguard_recipe", + function(section) + s.add_select_options[section['.name']] = + section['_description'] or section['.name'] + end +) + +function s.parse(self, section) + local recipe = luci.http.formvalue( + luci.cbi.CREATE_PREFIX .. self.config .. "." .. + self.sectiontype .. ".select" + ) + + if recipe and not s.add_select_options[recipe] then + self.invalid_cts = true + else + TypedSection.parse( self, section ) + end +end + +function s.create(self, name) + local recipe = luci.http.formvalue( + luci.cbi.CREATE_PREFIX .. self.config .. "." .. + self.sectiontype .. ".select" + ) + local name = luci.http.formvalue( + luci.cbi.CREATE_PREFIX .. self.config .. "." .. + self.sectiontype .. ".text" + ) + if #name > 3 and not name:match("[^a-zA-Z0-9_]") then + local s = uci:section("wireguard", "wireguard", name) + if s then + local options = uci:get_all("wireguard_recipes", recipe) + for k, v in pairs(options) do + if k ~= "_role" and k ~= "_description" then + if type(v) == "boolean" then + v = v and "1" or "0" + end + uci:set("wireguard", name, k, v) + end + end + uci:save("wireguard") + uci:commit("wireguard") + if extedit then + luci.http.redirect( self.extedit:format(name) ) + end + end + elseif #name > 0 then + self.invalid_cts = true + end + return 0 +end + +function s.remove(self, name) + local cfg_file = "/etc/openvpn/" ..name.. ".conf" + local auth_file = "/etc/openvpn/" ..name.. ".auth" + if fs.access(cfg_file) then + fs.unlink(cfg_file) + end + if fs.access(auth_file) then + fs.unlink(auth_file) + end + uci:delete("wireguard", name) + uci:save("wireguard") + uci:commit("wireguard") +end + +local port = s:option( DummyValue, "client", translate("Type") ) +function port.cfgvalue(self, section) + local val = AbstractValue.cfgvalue(self, section) + if val == nil then + val = 0 + end + if val == "1" then + return "Client" + else + return "Server" + end +end + +local addr = s:option( DummyValue, "addresses", translate("IP Addresses") ) +function addr.cfgvalue(self, section) + local val = AbstractValue.cfgvalue(self, section) + return val or "----" +end + +local auto = s:option( DummyValue, "udptunnel", translate("UDP over TCP") ) +function auto.cfgvalue(self, section) + local val = AbstractValue.cfgvalue(self, section) + if val == nil then + val = 0 + end + if val == "1" then + return "Yes" + else + return "No" + end +end + +local auto = s:option( DummyValue, "auto", translate("Start on Boot") ) +function auto.cfgvalue(self, section) + local val = AbstractValue.cfgvalue(self, section) + if val == nil then + val = 0 + end + if val == "1" then + return "Yes" + else + return "No" + end +end + +local active = s:option( DummyValue, "active", translate("Started") ) +function active.cfgvalue(self, section) + local val = AbstractValue.cfgvalue(self, section) + if val == nil then + val = 0 + end + if val == "1" then + return "Yes" + else + return "No" + end +end + +local updown = s:option( Button, "_updown", translate("Start/Stop") ) +updown._state = false +updown.redirect = luci.dispatcher.build_url( + "admin", "vpn", "wireguard" +) +function updown.cbid(self, section) + local file_cfg = self.map:get(section, "active") + if file_cfg == "1" then + pid = 1 + else + pid = nil + end + self._state = pid ~= nil + self.option = self._state and "stop" or "start" + return AbstractValue.cbid(self, section) +end +function updown.cfgvalue(self, section) + self.title = self._state and "stop" or "start" + self.inputstyle = self._state and "reset" or "reload" +end +function updown.write(self, section, value) + if self.option == "stop" then + sys.call("/usr/lib/wireguard/stopvpn.sh %s" % section) + else + sys.call("/usr/lib/wireguard/startvpn.sh %s" % section) + end + luci.http.redirect( self.redirect ) +end + +m:section(SimpleSection).template = "wireguard/wireguard" + +return m \ No newline at end of file diff --git a/rooter/0optionalapps/ext-wireguard/files/usr/lib/lua/luci/view/wireguard/cbi-select-input-add.htm b/rooter/0optionalapps/ext-wireguard/files/usr/lib/lua/luci/view/wireguard/cbi-select-input-add.htm new file mode 100644 index 0000000..c6cb8ac --- /dev/null +++ b/rooter/0optionalapps/ext-wireguard/files/usr/lib/lua/luci/view/wireguard/cbi-select-input-add.htm @@ -0,0 +1,111 @@ + + + +<%+wireguard/ovpn_css%> + +
                +
                +

                <%:Template based configuration%>

                +
                +
                + +
                +
                + +
                +
                +
                +
                +
                +

                <%:Conf configuration file upload%>

                +
                +
                + +
                +
                + +
                +
                + +
                +
                +
                +
                + +
                +
                diff --git a/rooter/0optionalapps/ext-wireguard/files/usr/lib/lua/luci/view/wireguard/conf.htm b/rooter/0optionalapps/ext-wireguard/files/usr/lib/lua/luci/view/wireguard/conf.htm new file mode 100644 index 0000000..e75e88f --- /dev/null +++ b/rooter/0optionalapps/ext-wireguard/files/usr/lib/lua/luci/view/wireguard/conf.htm @@ -0,0 +1,27 @@ + + + +
                + + + + + + + +
                   
                +
                diff --git a/rooter/0optionalapps/ext-wireguard/files/usr/lib/lua/luci/view/wireguard/ovpn_css.htm b/rooter/0optionalapps/ext-wireguard/files/usr/lib/lua/luci/view/wireguard/ovpn_css.htm new file mode 100644 index 0000000..55c0a54 --- /dev/null +++ b/rooter/0optionalapps/ext-wireguard/files/usr/lib/lua/luci/view/wireguard/ovpn_css.htm @@ -0,0 +1,38 @@ + diff --git a/rooter/0optionalapps/ext-wireguard/files/usr/lib/lua/luci/view/wireguard/pageswitch.htm b/rooter/0optionalapps/ext-wireguard/files/usr/lib/lua/luci/view/wireguard/pageswitch.htm new file mode 100644 index 0000000..47056fa --- /dev/null +++ b/rooter/0optionalapps/ext-wireguard/files/usr/lib/lua/luci/view/wireguard/pageswitch.htm @@ -0,0 +1,30 @@ +<%# + Copyright 2008 Steven Barth + Copyright 2008 Jo-Philipp Wich + Licensed to the public under the Apache License 2.0. +-%> + +<%+openvpn/ovpn_css%> + +
                +

                + <%:Overview%> » + <%=luci.i18n.translatef("Instance \"%s\"", self.instance)%> +

                + <% if self.mode == "basic" then %> + "><%:Switch to advanced configuration%> »

                +


                + <% elseif self.mode == "advanced" then %> + <%:Switch to basic configuration%> »

                +


                + <%:Configuration category%>: + <% for i, c in ipairs(self.categories) do %> + <% if c == self.category then %> + <%=translate(c)%> + <% else %> + "><%=translate(c)%> + <% end %> + <% if next(self.categories, i) then %>|<% end %> + <% end %> + <% end %> +
                diff --git a/rooter/0optionalapps/ext-wireguard/files/usr/lib/lua/luci/view/wireguard/text_conf.htm b/rooter/0optionalapps/ext-wireguard/files/usr/lib/lua/luci/view/wireguard/text_conf.htm new file mode 100644 index 0000000..2a1a4b5 --- /dev/null +++ b/rooter/0optionalapps/ext-wireguard/files/usr/lib/lua/luci/view/wireguard/text_conf.htm @@ -0,0 +1,61 @@ +<% + +%> + + + +
                + <%:Paste Configuration File Here%> + + + + +
                + +
                + + + + + + + + + + +
                <%:Instance Name : %>
                <%:Start on Boot : %>
                + +  
                +
                diff --git a/rooter/0optionalapps/ext-wireguard/files/usr/lib/lua/luci/view/wireguard/wireguard.htm b/rooter/0optionalapps/ext-wireguard/files/usr/lib/lua/luci/view/wireguard/wireguard.htm new file mode 100644 index 0000000..d207f05 --- /dev/null +++ b/rooter/0optionalapps/ext-wireguard/files/usr/lib/lua/luci/view/wireguard/wireguard.htm @@ -0,0 +1,153 @@ +<%# + Copyright 2016-2017 Dan Luedtke + Licensed to the public under the Apache License 2.0. +-%> + +<% + +-%> + + + +

                <%:WireGuard Status%>

                + +
                + + <%:Interface%> WG0 + +
                + + + + + + + + + + + + + + + +
                  +
                <%:Configuration%>
                +
                   +
                + <%:Collecting data...%> +
                +
                  +
                <%:Peer%>
                +
                   +
                + <%:Collecting data...%> +
                +
                +
                + +
                + diff --git a/rooter/0optionalapps/ext-wireguard/files/usr/lib/wireguard/conf.sh b/rooter/0optionalapps/ext-wireguard/files/usr/lib/wireguard/conf.sh new file mode 100644 index 0000000..436e1f5 --- /dev/null +++ b/rooter/0optionalapps/ext-wireguard/files/usr/lib/wireguard/conf.sh @@ -0,0 +1,118 @@ +#!/bin/sh + +name=$1 +file=$2 +auto=$3 +if [ -z $auto ]; then + auto="0" +fi + +extract() { + line=$1 + PD=$(echo "$line" | grep "#") + if [ ! -z "$PD" ]; then + return + fi + PRK=$(echo "$line" | grep "PrivateKey" | tr " " ",") + if [ ! -z "$PRK" ]; then + PrivateKey=$(echo $PRK | cut -d, -f3) + fi + PRK=$(echo "$line" | grep "PublicKey" | tr " " ",") + if [ ! -z "$PRK" ]; then + PublicKey=$(echo $PRK | cut -d, -f3) + fi + PRK=$(echo "$line" | grep "PresharedKey" | tr " " ",") + if [ ! -z "$PRK" ]; then + PreSharedKey=$(echo $PRK | cut -d, -f3) + fi + PRK=$(echo "$line" | grep "Address" | tr " " "#") + if [ ! -z "$PRK" ]; then + if [ -z $Address ]; then + Address=$(echo $PRK | cut -d# -f3) + else + Address=$Address","$(echo $PRK | cut -d# -f3) + fi + fi + PRK=$(echo "$line" | grep "dns" | tr " " "#") + if [ ! -z "$PRK" ]; then + dns=$(echo $PRK | cut -d# -f3) + fi + PRK=$(echo "$line" | grep "DNS" | tr " " "#") + if [ ! -z "$PRK" ]; then + dns=$(echo $PRK | cut -d# -f3) + fi + PRK=$(echo "$line" | grep "ListenPort" | tr " " ",") + if [ ! -z "$PRK" ]; then + listenport=$(echo $PRK | cut -d, -f3) + fi + PRK=$(echo "$line" | grep "AllowedIPs" | tr " " "#") + if [ ! -z "$PRK" ]; then + if [ -z $allowedips ]; then + allowedips=$(echo $PRK | cut -d# -f3) + else + allowedips=$allowedips","$(echo $PRK | cut -d# -f3) + fi + fi + PRK=$(echo "$line" | grep "Endpoint" | tr " " ",") + if [ ! -z "$PRK" ]; then + endpoint=$(echo $PRK | cut -d, -f3) + fi + MTU=$(echo "$line" | grep "MTU" | tr " " ",") + if [ ! -z "$MTU" ]; then + mtu=$(echo $MTU | cut -d, -f3) + fi +} + +listenport="51280" +dns="" +sed -i -e "s!PrivateKey= !PrivateKey=!g" $file +sed -i -e "s!PrivateKey=!PrivateKey = !g" $file +sed -i -e "s!PublicKey= !PublicKey=!g" $file +sed -i -e "s!PublicKey=!PublicKey = !g" $file +sed -i -e "s!PresharedKey= !PresharedKey=!g" $file +sed -i -e "s!PresharedKey=!PresharedKey = !g" $file +sed -i -e "s!Address= !Address=!g" $file +sed -i -e "s!Address=!Address = !g" $file +sed -i -e "s!dns= !dns=!g" $file +sed -i -e "s!dns=!dns = !g" $file +sed -i -e "s!DNS= !DNS=!g" $file +sed -i -e "s!DNS=!DNS = !g" $file +sed -i -e "s!ListenPort= !ListenPort=!g" $file +sed -i -e "s!ListenPort=!ListenPort = !g" $file +sed -i -e "s!AllowedIPs= !AllowedIPs=!g" $file +sed -i -e "s!AllowedIPs=!AllowedIPs = !g" $file +sed -i -e "s!Endpoint= !Endpoint=!g" $file +sed -i -e "s!Endpoint=!Endpoint = !g" $file +sed -i -e "s!MTU= !MTU=!g" $file +sed -i -e "s!MTU=!MTU = !g" $file + +while IFS= read -r linex +do + extract "$linex" +done < $file +extract "$linex" +PRK=$(echo "$endpoint" | tr ":" ",") +endpoint=$(echo $PRK | cut -d, -f1) +sport=$(echo $PRK | cut -d, -f2) + +uci delete wireguard.$name +uci set wireguard.$name=wireguard +uci set wireguard.$name.auto=$auto +uci set wireguard.$name.client="1" +uci set wireguard.$name.active="0" +uci set wireguard.$name.privatekey="$PrivateKey" +uci set wireguard.$name.presharedkey="$PreSharedKey" +uci set wireguard.$name.port="$listenport" +uci set wireguard.$name.addresses="$Address" +uci set wireguard.$name.dns="$dns" +uci set wireguard.$name.publickey="$PublicKey" +uci set wireguard.$name.endpoint_host="$endpoint" +uci set wireguard.$name.ips="$allowedips" +uci set wireguard.$name.name="$name" +uci set wireguard.$name.sport="$sport" +uci set wireguard.$name.mtu="$mtu" +uci set wireguard.$name.persistent_keepalive='25' +uci commit wireguard + +rm -f $file + \ No newline at end of file diff --git a/rooter/0optionalapps/ext-wireguard/files/usr/lib/wireguard/create.sh b/rooter/0optionalapps/ext-wireguard/files/usr/lib/wireguard/create.sh new file mode 100644 index 0000000..9d41829 --- /dev/null +++ b/rooter/0optionalapps/ext-wireguard/files/usr/lib/wireguard/create.sh @@ -0,0 +1,76 @@ +#!/bin/sh +. /lib/functions.sh + +log() { + logger -t "Wireguard Conf" "$@" +} + +WG=$(cat /tmp/wginst) + +do_create() { + local config=$1 + + config_get name $config name + if [ -z $name ]; then + name=$config + fi + + echo "----Start Conf File for "$name" ----" >> ${PKI_DIR}/package/wg.conf + echo "[Interface]" >> ${PKI_DIR}/package/wg.conf + config_get privatekey $config privatekey + echo "PrivateKey = "$privatekey >> ${PKI_DIR}/package/wg.conf + config_get address $config address + echo "Address = "$address >> ${PKI_DIR}/package/wg.conf + config_get endpoint_port $config endpoint_port + if [ ! -z $endpoint_port ]; then + echo "ListenPort = "$endpoint_port >> ${PKI_DIR}/package/wg.conf + fi + config_get dns $config dns + if [ ! -z $dns ]; then + echo "DNS = "$dns >> ${PKI_DIR}/package/wg.conf + fi + config_get mtu $config mtu + if [ ! -z $mtu ]; then + echo "MTU = "$mtu >> ${PKI_DIR}/package/wg.conf + fi + echo " " >> ${PKI_DIR}/package/wg.conf + echo "[Peer]" >> ${PKI_DIR}/package/wg.conf + PUB=$(uci get wireguard."$WG".publickey) + echo "PublicKey = "$PUB >> ${PKI_DIR}/package/wg.conf + USE=$(uci get wireguard."$WG".usepre) + if [ $USE = "1" ]; then + PRE=$(uci get wireguard."$WG".presharedkey) + echo "PresharedKey = "$PRE >> ${PKI_DIR}/package/wg.conf + fi + HOST=$(uci get wireguard."$WG".endpoint_host) + PORT=$(uci get wireguard."$WG".port) + if [ ! -z $PORT ]; then + HOST=$HOST":"$PORT + fi + echo "Endpoint = "$HOST >> ${PKI_DIR}/package/wg.conf + config_get allowed_ips $config allowed_ips + echo "AllowedIPs = "$allowed_ips >> ${PKI_DIR}/package/wg.conf + echo "----EndConf File for "$name" ----" >> ${PKI_DIR}/package/wg.conf + echo " " >> ${PKI_DIR}/package/wg.conf +} + +#PKI_DIR="/tmp/wireguard" +PKI_DIR="/www" +#rm -rfv "$PKI_DIR" +#mkdir -p ${PKI_DIR} +#chmod -R 0777 ${PKI_DIR} +cd ${PKI_DIR} +mkdir -p package +cd .. +chmod -R 0777 ${PKI_DIR}/package +#rm -rfv "/www/package" +#ln -s ${PKI_DIR}/package /www/package + + +rm -f ${PKI_DIR}/package/wg.conf +config_load wireguard +config_foreach do_create custom$WG + +cd ${PKI_DIR}/package + +tar -czf wgconf.tar.gz wg.conf diff --git a/rooter/0optionalapps/ext-wireguard/files/usr/lib/wireguard/keygen.sh b/rooter/0optionalapps/ext-wireguard/files/usr/lib/wireguard/keygen.sh new file mode 100644 index 0000000..3b30f61 --- /dev/null +++ b/rooter/0optionalapps/ext-wireguard/files/usr/lib/wireguard/keygen.sh @@ -0,0 +1,63 @@ +#!/bin/sh +. /lib/functions.sh + +log() { + logger -t "Wireguard KeyGen" "$@" +} + +WG=$1 +echo "$WG" > /tmp/wginst + +sleep 5 + +EXST=$(uci get wireguard."$WG") +if [ -z $EXST ]; then + uci set wireguard."$WG"="wireguard" + uci commit wireguard +fi + +PRIV=$(uci get wireguard."$WG".privatekey) +if [ -z $PRIV ]; then + umask u=rw,g=,o= + wg genkey | tee /tmp/wgserver.key | wg pubkey > /tmp/wgclient.pub + wg genpsk > /tmp/wg.psk + + WG_KEY="$(cat /tmp/wgserver.key)" # private key + WG_PSK="$(cat /tmp/wg.psk)" # shared key + WG_PUB="$(cat /tmp/wgclient.pub)" # public key to be used on other end + rm -f /tmp/wgserver.key + rm -f /tmp/wg.psk + rm -f /tmp/wgclient.pub + uci set wireguard."$WG".privatekey=$WG_KEY + uci set wireguard."$WG".publickey=$WG_PUB + uci set wireguard."$WG".presharedkey=$WG_PSK + uci commit wireguard +fi + +do_custom() { + local config=$1 + + config_get privatekey $config privatekey + if [ -z "$privatekey" ]; then + umask u=rw,g=,o= + wg genkey | tee /tmp/wgserver.key | wg pubkey > /tmp/wgclient.pub + wg genpsk > /tmp/wg.psk + + WG_KEY="$(cat /tmp/wgserver.key)" # private key + WG_PSK="$(cat /tmp/wg.psk)" # shared key + WG_PUB="$(cat /tmp/wgclient.pub)" # public key to be used on other end + rm -f /tmp/wgserver.key + rm -f /tmp/wg.psk + rm -f /tmp/wgclient.pub + log "$WG_KEY" + uci set wireguard."$config".privatekey=$WG_KEY + uci set wireguard."$config".publickey=$WG_PUB + uci set wireguard."$config".presharedkey=$WG_PSK + uci set wireguard."$config".persistent_keepalive='25' + uci set wireguard."$config".route_allowed_ips='1' + fi +} + +config_load wireguard +config_foreach do_custom custom$WG +uci commit wireguard \ No newline at end of file diff --git a/rooter/0optionalapps/ext-wireguard/files/usr/lib/wireguard/startvpn.sh b/rooter/0optionalapps/ext-wireguard/files/usr/lib/wireguard/startvpn.sh new file mode 100644 index 0000000..352032d --- /dev/null +++ b/rooter/0optionalapps/ext-wireguard/files/usr/lib/wireguard/startvpn.sh @@ -0,0 +1,318 @@ +#!/bin/sh +. /lib/functions.sh + +log() { + logger -t "Wireguard Start" "$@" +} + +WG=$1 + +chk_zone() { + local config=$1 + + config_get src $config src + config_get dest $config dest + if [ $src = "lan" -a $dest = "wan" ]; then + uci set firewall."$config".dest="wg" + uci commit firewall + fi +} + +do_dns() { + cdns=$1 + ldns=$(uci -q get network.wg0.dns) + ex=$(echo "$ldns" | grep "$cdns") + if [ -z $ex ]; then + log "Add DNS $cdns to WG0" + uci add_list network.wg0.dns="$cdns" + uci commit network + /etc/init.d/network reload + fi +} + +do_port() { + PORT=$1 + udp=$2 + # look for rule for this port + INB="inbound"$PORT$udp + RULE=$(uci -q get firewall.$INB) + if [ -z $RULE ]; then + uci set firewall.$INB=rule + uci set firewall.$INB.name=$INB + uci set firewall.$INB.target=ACCEPT + uci set firewall.$INB.src=* + uci set firewall.$INB.proto=$udp + uci set firewall.$INB.dest_port=$PORT + uci commit firewall + /etc/init.d/firewall reload + fi +} + +do_delete() { + local config=$1 + + uci delete network.$1 +} + +create_speer() { + local config=$1 + + uci set network.$config="wireguard_wg1" + + config_get persistent_keepalive $config persistent_keepalive + uci set network.$config.persistent_keepalive="$persistent_keepalive" + config_get route_allowed_ips $config route_allowed_ips + uci set network.$config.route_allowed_ips="$route_allowed_ips" + config_get publickey $config publickey + uci set network.$config.public_key="$publickey" + usepre=$(uci -q get wireguard.$WG.usepre) + log "$usepre" + if [ $usepre = "1" ]; then + presharedkey=$(uci -q get wireguard.$WG.presharedkey) + log "$presharedkey" + uci set network.$config.preshared_key="$presharedkey" + fi + config_get allowed_ips $config allowed_ips + allowed_ips=$allowed_ips"," + ips=$(echo $allowed_ips | cut -d, -f1) + i=1 + while [ ! -z $ips ] + do + uci add_list network.$config.allowed_ips="$ips" + i=$((i+1)) + ips=$(echo $allowed_ips | cut -d, -f$i) + done + +} + +create_cpeer() { + local config=$1 + + uci set network.$config="wireguard_wg0" + + publickey=$(uci -q get wireguard."$config".publickey) + uci set network.$config.public_key="$publickey" + presharedkey=$(uci -q get wireguard."$WG".presharedkey) + if [ ! -z $presharedkey ]; then + uci set network.$config.preshared_key="$presharedkey" + fi + persistent_keepalive=$(uci -q get wireguard."$config".persistent_keepalive) + if [ -z $persistent_keepalive ]; then + persistent_keepalive=25 + fi + uci set network.$config.persistent_keepalive="$persistent_keepalive" + route_allowed_ips=1 + uci set network.$config.route_allowed_ips="$route_allowed_ips" + + if [ $UDP = 1 ]; then + endpoint_host="127.0.0.1" + uci set network.$config.endpoint_host="$endpoint_host" + sport=$(uci -q get wireguard."$config".port) + if [ -z $sport ]; then + sport="54321" + fi + uci set network.$config.endpoint_port="$sport" + else + endpoint_host=$(uci -q get wireguard."$config".endpoint_host) + uci set network.$config.endpoint_host="$endpoint_host" + sport=$(uci -q get wireguard."$config".sport) + if [ -z $sport ]; then + sport="51280" + fi + uci set network.$config.endpoint_port="$sport" + fi + + ips=$(uci -q get wireguard."$config".ips)"," + cips=$(echo $ips | cut -d, -f1) + i=1 + while [ ! -z $cips ] + do + uci add_list network.$config.allowed_ips="$cips" + i=$((i+1)) + cips=$(echo $ips | cut -d, -f$i) + done +} + +handle_server() { + config_foreach do_delete wireguard_wg1 + + uci delete network.wg1 + uci set network.wg1="interface" + uci set network.wg1.proto="wireguard" + + auto=$(uci -q get wireguard."$WG".auto) + if [ -z $auto ]; then + auto="0" + fi + uci set network.wg1.auto="$auto" + + port=$(uci -q get wireguard."$WG".port) + if [ -z $port ]; then + port="51280" + fi + uci set network.wg1.listen_port="$port" + do_port $port udp + + privatekey=$(uci -q get wireguard."$WG".privatekey) + uci set network.wg1.private_key="$privatekey" + + ips=$(uci -q get wireguard."$WG".addresses)"," + cips=$(echo $ips | cut -d, -f1) + i=1 + while [ ! -z $cips ] + do + uci add_list network.wg1.addresses="$cips" + i=$((i+1)) + cips=$(echo $ips | cut -d, -f"$i") + if [ -z $cips ]; then + break + fi + done + + config_load wireguard + config_foreach create_speer custom$WG + + uci commit network +} + +handle_client() { + config_foreach do_delete wireguard_wg0 + + uci delete network.wg0 + uci set network.wg0="interface" + uci set network.wg0.proto="wireguard" + + auto=$(uci -q get wireguard."$WG".auto) + if [ -z $auto ]; then + auto="0" + fi + uci set network.wg0.auto="$auto" + mtu=$(uci -q get wireguard."$WG".mtu) + if [ ! -z $mtu ]; then + uci set network.wg0.mtu="$mtu" + fi + dns=$(uci -q get wireguard."$WG".dns) + if [ ! -z $dns ]; then + do_dns $dns + fi + port=$(uci -q get wireguard."$WG".port) + if [ -z $port ]; then + port="51280" + fi + uci set network.wg0.listen_port="$port" + do_port $port udp + + privatekey=$(uci -q get wireguard."$WG".privatekey) + uci set network.wg0.private_key="$privatekey" + + ips=$(uci -q get wireguard."$WG".addresses)"," + cips=$(echo $ips | cut -d, -f1) + i=1 + while [ ! -z "$cips" ] + do + uci add_list network.wg0.addresses="$cips" + i=$((i+1)) + cips=$(echo "$ips" | cut -d, -f"$i") + if [ -z "$cips" ]; then + break + fi + done + uci add_list network.wg0.addresses="::/0" + + create_cpeer $WG + + uci commit network +} + +udp_server() { + local config=$1 + udpport=$(uci -q get wireguard."$WG".udpport) + if [ -z $udpport ]; then + udpport="54321" + fi + port=$(uci -q get wireguard."$WG".port) + if [ -z $port ]; then + port="54321" + fi + do_port $udpport tcp + udptunnel -s -v "0.0.0.0:"$udpport "127.0.0.1:"$port & + #log "udptunnel -s -v 0.0.0.0:$udpport 127.0.0.1:$port" +} + +udp_client() { + local config=$1 + port=$(uci -q get wireguard."$WG".port) + if [ -z $port ]; then + port="54321" + fi + endpoint_host=$(uci -q get wireguard.$WG.endpoint_host) + sport=$(uci -q get wireguard.$WG.sport) + if [ -z $sport ]; then + sport="51280" + fi + + udptunnel "127.0.0.1:"$port $endpoint_host":"$sport & + #log "udptunnel 127.0.0.1:$port $endpoint_host:$sport" +} + +forward=$(uci -q get wireguard."$WG".forward) +if [ "$forward" != "0" ]; then + config_load firewall + config_foreach chk_zone forwarding +else + uci set firewall.wgwforward=forwarding + uci set firewall.wgwforward.dest="wan" + uci set firewall.wgwforward.src="wg" + + uci set firewall.wwgforward=forwarding + uci set firewall.wwgforward.dest="wg" + uci set firewall.wwgforward.src="wan" + + uci set firewall.lwgforward=forwarding + uci set firewall.lwgforward.dest="wg" + uci set firewall.lwgforward.src="lan" + + uci set firewall.wglforward=forwarding + uci set firewall.wglforward.dest="lan" + uci set firewall.wglforward.src="wg" + uci commit firewall +fi +etc/init.d/firewall restart + +config_load network +SERVE=$(uci -q get wireguard."$WG".client) +if [ $SERVE = "0" ]; then + running=$(uci -q get wireguard.settings.server) + if [ $running = 1 ]; then + exit 0 + fi + UDP=$(uci -q get wireguard."$WG".udptunnel) + if [ $UDP = 1 ]; then + udp_server $WG + fi + handle_server + uci commit network + ifup wg1 + sleep 2 + uci set wireguard.settings.server="1" +else + running=$(uci -q get wireguard.settings.client) + log "Client running $running" + if [ $running = 1 ]; then + exit 0 + fi + UDP=$(uci -q get wireguard."$WG".udptunnel) + if [ $UDP = 1 ]; then + udp_client $WG + fi + handle_client + uci commit network + log "Start Interface" + ifup wg0 + sleep 2 + uci set wireguard.settings.client="1" +fi + +uci set wireguard."$WG".active="1" +uci commit wireguard + diff --git a/rooter/0optionalapps/ext-wireguard/files/usr/lib/wireguard/stopvpn.sh b/rooter/0optionalapps/ext-wireguard/files/usr/lib/wireguard/stopvpn.sh new file mode 100644 index 0000000..91e80dc --- /dev/null +++ b/rooter/0optionalapps/ext-wireguard/files/usr/lib/wireguard/stopvpn.sh @@ -0,0 +1,67 @@ +#!/bin/sh +. /lib/functions.sh + +log() { + logger -t "Wireguard Stop" "$@" +} + +chk_zone() { + local config=$1 + + config_get src $config src + config_get dest $config dest + if [ $src = "lan" -a $dest = "wg" ]; then + uci set firewall."$config".dest="wan" + uci commit firewall + fi +} + +WG=$1 + +forward=$(uci -q get wireguard."$WG".forward) +if [ "$forward" != "0" ]; then + config_load firewall + config_foreach chk_zone forwarding +else + uci delete firewall.wgwforward + uci delete firewall.wwgforward + uci delete firewall.lwgforward + uci delete firewall.wglforward + uci commit firewall +fi +/etc/init.d/firewall restart + +SERVE=$(uci get wireguard."$WG".client) +if [ $SERVE = "0" ]; then + ifdown wg1 + uci set wireguard.settings.server="0" + uci delete network.wg1 + uci set network.wg1=interface + uci set network.wg1.proto="wireguard" + uci set network.wg1.auto="0" + uci set network.wg1.private_key="" + uci set network.wg1.listen_port="" + uci add_list network.wg1.addresses="" + uci commit network +else + ifdown wg0 + uci set wireguard.settings.client="0" + uci delete network.wg0 + uci set network.wg0=interface + uci set network.wg0.proto="wireguard" + uci set network.wg0.auto="0" + uci set network.wg0.private_key="" + uci set network.wg0.listen_port="" + uci add_list network.wg0.addresses="" + uci commit network +fi +UDP=$(uci get wireguard."$WG".udptunnel) +if [ $UDP = 1 ]; then + PID=$(ps |grep "udptunnel" | grep -v grep |head -n 1 | awk '{print $1}') + kill -9 $PID +fi + +uci set wireguard."$WG".active="0" +uci commit wireguard + +/etc/init.d/wireguard stop \ No newline at end of file diff --git a/rooter/0optionalapps/ext-wireguard/files/usr/lib/wireguard/text.sh b/rooter/0optionalapps/ext-wireguard/files/usr/lib/wireguard/text.sh new file mode 100644 index 0000000..2f5a622 --- /dev/null +++ b/rooter/0optionalapps/ext-wireguard/files/usr/lib/wireguard/text.sh @@ -0,0 +1,19 @@ +#!/bin/sh +. /lib/functions.sh + +log() { + logger -t "Wireguard TextConf" "$@" +} + +conf1=$1 +conf=$(echo $conf1) +conf=$(echo "$conf" | tr "?" "~") + +boot=$(echo "$conf" | cut -d~ -f1) +iname=$(echo "$conf" | cut -d~ -f2) +conf=$(echo "$conf1" | tr "?" "~") +confile=$(echo "$conf" | cut -d~ -f3) + +echo "$confile" > /tmp/confile + +/usr/lib/wireguard/conf.sh $iname /tmp/confile $boot \ No newline at end of file diff --git a/rooter/0optionalapps/ext-wireguard/files/www/luci-static/resources/icons/wireguard.png b/rooter/0optionalapps/ext-wireguard/files/www/luci-static/resources/icons/wireguard.png new file mode 100644 index 0000000..34f85d8 Binary files /dev/null and b/rooter/0optionalapps/ext-wireguard/files/www/luci-static/resources/icons/wireguard.png differ diff --git a/rooter/0optionalapps/ext-wireguard/files/www/luci-static/resources/icons/wireguard_disabled.png b/rooter/0optionalapps/ext-wireguard/files/www/luci-static/resources/icons/wireguard_disabled.png new file mode 100644 index 0000000..ccfb7ae Binary files /dev/null and b/rooter/0optionalapps/ext-wireguard/files/www/luci-static/resources/icons/wireguard_disabled.png differ diff --git a/rooter/0optionalapps/ext-zerotier/Makefile b/rooter/0optionalapps/ext-zerotier/Makefile new file mode 100644 index 0000000..b7cfa94 --- /dev/null +++ b/rooter/0optionalapps/ext-zerotier/Makefile @@ -0,0 +1,34 @@ +#Owned by DairyMan@Whirlpool +# +#Copyright GNU act. +include $(TOPDIR)/rules.mk + +PKG_NAME:=ext-zerotier +PKG_VERSION:=4.500 +PKG_RELEASE:=1 + +PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool +include $(INCLUDE_DIR)/package.mk + +define Package/ext-zerotier + SECTION:=utils + CATEGORY:=ROOter + SUBMENU:=Optional Applications + DEPENDS:=+zerotier + TITLE:=Install scripts for Zerotier + PKGARCH:=all +endef + +define Package/ext-zerotier/description + Install scripts for Zerotier +endef + + +define Build/Compile +endef + +define Package/ext-zerotier/install + $(CP) ./files/* $(1)/ +endef + +$(eval $(call BuildPackage,ext-zerotier)) diff --git a/rooter/0optionalapps/ext-zerotier/files/etc/init.d/zerofire b/rooter/0optionalapps/ext-zerotier/files/etc/init.d/zerofire new file mode 100644 index 0000000..05b8693 --- /dev/null +++ b/rooter/0optionalapps/ext-zerotier/files/etc/init.d/zerofire @@ -0,0 +1,37 @@ +#!/bin/sh /etc/rc.common +. /lib/functions.sh +# Copyright (C) 2006 OpenWrt.org + +START=91 + +log() { + logger -t "ZeroTier Init.d : " "$@" +} + +check_config () { + WW=$(uci get firewall.zerozone) + if [ -z $WW ]; then + uci set firewall.zerozone=zone + uci set firewall.zerozone.name="zerotier" + uci set firewall.zerozone.forward="REJECT" + uci set firewall.zerozone.output="ACCEPT" + uci set firewall.zerozone.input="ACCEPT" + uci set firewall.zerozone.device="zt+" + uci set firewall.zerozone.masq="1" + uci set firewall.zerozone.mtu_fix="1" + + uci set firewall.zlzforward=forwarding + uci set firewall.zlzforward.dest="zerotier" + uci set firewall.zlzforward.src="lan" + + uci set firewall.zzlforward=forwarding + uci set firewall.zzlforward.dest="lan" + uci set firewall.zzlforward.src="zerotier" + uci commit firewall + /etc/init.d/firewall restart + fi +} + +start() { + check_config +} \ No newline at end of file diff --git a/rooter/0optionalapps/ext-zerotier/files/etc/uci-defaults/64-zerotier b/rooter/0optionalapps/ext-zerotier/files/etc/uci-defaults/64-zerotier new file mode 100644 index 0000000..eee1ac9 --- /dev/null +++ b/rooter/0optionalapps/ext-zerotier/files/etc/uci-defaults/64-zerotier @@ -0,0 +1,7 @@ +#!/bin/sh /etc/rc.common + +id=$(uci -q get custom.zerotier.networkid) +uci delete zerotier.zerotier.join +uci add_list zerotier.zerotier.join=$id +uci commit zerotier +/etc/init.d/zerotier restart diff --git a/rooter/0optionalapps/ext-zerotier/files/usr/lib/lua/luci/controller/zerotier.lua b/rooter/0optionalapps/ext-zerotier/files/usr/lib/lua/luci/controller/zerotier.lua new file mode 100644 index 0000000..74c997b --- /dev/null +++ b/rooter/0optionalapps/ext-zerotier/files/usr/lib/lua/luci/controller/zerotier.lua @@ -0,0 +1,62 @@ +module("luci.controller.zerotier", package.seeall) + +I18N = require "luci.i18n" +translate = I18N.translate + +function index() + local fs = require "nixio.fs" + 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 fs.stat("/etc/config/zerotier") then + local page + if (multilock == "1" and rootlock == "1") then + page = entry({"admin", "adminmenu", "zerotier"}, template("zerotier/zerotier"), translate("Zerotier"), 7) + page.dependent = true + else + page = entry({"admin", "adminmenu", "zerotier"}, template("zerotier/zerotier"), translate("---Router ID"), 7) + page.dependent = true + end + end + end + end + + entry({"admin", "services", "getid"}, call("action_getid")) + entry({"admin", "services", "sendid"}, call("action_sendid")) + entry({"admin", "services", "get_ids"}, call("action_get_ids")) +end + +function action_getid() + local rv = {} + id = luci.model.uci.cursor():get("zerotier", "zerotier", "join") + rv["netid"] = id + secret = luci.model.uci.cursor():get("zerotier", "zerotier", "secret") + if secret == nil then + secret = "xxxxxxxxxx" + end + rv["routerid"] = string.sub(secret,1,10) + rv["password"] = luci.model.uci.cursor():get("custom", "zerotier", "password") + luci.http.prepare_content("application/json") + luci.http.write_json(rv) +end + +function action_sendid() + local set = luci.http.formvalue("set") + os.execute("/usr/lib/zerotier/netid.sh 1 " .. set) +end + +function action_get_ids() + local rv = {} + id = luci.model.uci.cursor():get("zerotier", "zerotier", "join") + rv["netid"] = id + secret = luci.model.uci.cursor():get("zerotier", "zerotier", "secret") + if secret ~= nil then + rv["routerid"] = string.sub(secret,1,10) + else + rv["routerid"] = "xxxxxxxxxx" + end + luci.http.prepare_content("application/json") + luci.http.write_json(rv) +end \ No newline at end of file diff --git a/rooter/0optionalapps/ext-zerotier/files/usr/lib/lua/luci/view/admin_status/index/zero.htm b/rooter/0optionalapps/ext-zerotier/files/usr/lib/lua/luci/view/admin_status/index/zero.htm new file mode 100644 index 0000000..47fd4b2 --- /dev/null +++ b/rooter/0optionalapps/ext-zerotier/files/usr/lib/lua/luci/view/admin_status/index/zero.htm @@ -0,0 +1 @@ +<%+zerotier/zerotier1%> \ No newline at end of file diff --git a/rooter/0optionalapps/ext-zerotier/files/usr/lib/lua/luci/view/zerotier/zerotier.htm b/rooter/0optionalapps/ext-zerotier/files/usr/lib/lua/luci/view/zerotier/zerotier.htm new file mode 100644 index 0000000..2e7e15b --- /dev/null +++ b/rooter/0optionalapps/ext-zerotier/files/usr/lib/lua/luci/view/zerotier/zerotier.htm @@ -0,0 +1,182 @@ +<%+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 + +-%> + + + +
                +
                +

                <%:Router ID (Zerotier)%>

                +
                + + + + +
                + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                + +
                +
                +<%+footer%> \ No newline at end of file diff --git a/rooter/0optionalapps/ext-zerotier/files/usr/lib/lua/luci/view/zerotier/zerotier1.htm b/rooter/0optionalapps/ext-zerotier/files/usr/lib/lua/luci/view/zerotier/zerotier1.htm new file mode 100644 index 0000000..dfb07b6 --- /dev/null +++ b/rooter/0optionalapps/ext-zerotier/files/usr/lib/lua/luci/view/zerotier/zerotier1.htm @@ -0,0 +1,22 @@ + + +
                + <%:Router Info%> + + + +
                <%:Network ID%><%:Loading%> Collecting data...
                <%:Router ID%>
                +
                + diff --git a/rooter/0optionalapps/ext-zerotier/files/usr/lib/zerotier/netid.sh b/rooter/0optionalapps/ext-zerotier/files/usr/lib/zerotier/netid.sh new file mode 100644 index 0000000..8993552 --- /dev/null +++ b/rooter/0optionalapps/ext-zerotier/files/usr/lib/zerotier/netid.sh @@ -0,0 +1,21 @@ +#!/bin/sh +. /lib/functions.sh + +log() { + logger -t "NetID" "$@" +} + +ID=$2 + +log "$ID" + +if [ $ID = "xxxxxxxxxxxxxxxx" ]; then + uci set zerotier.zerotier.enabled='0' +else + uci set zerotier.zerotier.enabled='1' +fi + +uci delete zerotier.zerotier.join +uci add_list zerotier.zerotier.join=$ID +uci commit zerotier +/etc/init.d/zerotier restart diff --git a/rooter/0optionalapps/extramenu/Makefile b/rooter/0optionalapps/extramenu/Makefile new file mode 100644 index 0000000..8896ae0 --- /dev/null +++ b/rooter/0optionalapps/extramenu/Makefile @@ -0,0 +1,33 @@ +#Owned by DairyMan@Whirlpool +# +#Copyright GNU act. +include $(TOPDIR)/rules.mk + +PKG_NAME:=extramenu +PKG_VERSION:=4.500 +PKG_RELEASE:=1 + +PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool +include $(INCLUDE_DIR)/package.mk + +define Package/extramenu + SECTION:=utils + CATEGORY:=ROOter + SUBMENU:=Optional Applications + TITLE:=Install scripts for Extra menus + PKGARCH:=all +endef + +define Package/extramenu/description + Install scripts for Extra menus +endef + + +define Build/Compile +endef + +define Package/extramenu/install + $(CP) ./files/* $(1)/ +endef + +$(eval $(call BuildPackage,extramenu)) diff --git a/rooter/0optionalapps/extramenu/files/etc/init.d/fullmenu b/rooter/0optionalapps/extramenu/files/etc/init.d/fullmenu new file mode 100644 index 0000000..d4b7188 --- /dev/null +++ b/rooter/0optionalapps/extramenu/files/etc/init.d/fullmenu @@ -0,0 +1,18 @@ +#!/bin/sh /etc/rc.common + +START=88 + +log() { + logger -t "FULL MENU" "$@" +} + +start() +{ + df=$(uci -q get custom.menu.default) + if [ -z $df ]; then + df=0 + fi + uci set custom.menu.full=$df + uci set custom.menu.enabled='1' + uci commit custom +} diff --git a/rooter/0optionalapps/extramenu/files/usr/lib/fullmenu/setmenu.sh b/rooter/0optionalapps/extramenu/files/usr/lib/fullmenu/setmenu.sh new file mode 100644 index 0000000..d5963e8 --- /dev/null +++ b/rooter/0optionalapps/extramenu/files/usr/lib/fullmenu/setmenu.sh @@ -0,0 +1,18 @@ +#!/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" +else + fv="0" +fi +uci set custom.menu.full=$fv +uci commit custom \ No newline at end of file diff --git a/rooter/0optionalapps/extramenu/files/usr/lib/lua/luci/controller/fullmenu.lua b/rooter/0optionalapps/extramenu/files/usr/lib/lua/luci/controller/fullmenu.lua new file mode 100644 index 0000000..67488c4 --- /dev/null +++ b/rooter/0optionalapps/extramenu/files/usr/lib/lua/luci/controller/fullmenu.lua @@ -0,0 +1,39 @@ +module("luci.controller.fullmenu", package.seeall) + +I18N = require "luci.i18n" +translate = I18N.translate + +function index() + local page + entry({"admin", "adminmenu"}, firstchild(), translate("Administration"), 24).dependent=false + local df = luci.model.uci.cursor():get("custom", "menu", "default") + if df == '0' then + 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 + page = entry({"admin", "adminmenu", "fullmenu"}, template("fullmenu/fullmenu"), translate("Unlock / Lock Menus"), 5) + page.dependent = true + end + end + + entry({"admin", "menu", "getmenu"}, call("action_getmenu")) + entry({"admin", "menu", "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 \ No newline at end of file diff --git a/rooter/0optionalapps/extramenu/files/usr/lib/lua/luci/view/fullmenu/fullmenu.htm b/rooter/0optionalapps/extramenu/files/usr/lib/lua/luci/view/fullmenu/fullmenu.htm new file mode 100644 index 0000000..9511a60 --- /dev/null +++ b/rooter/0optionalapps/extramenu/files/usr/lib/lua/luci/view/fullmenu/fullmenu.htm @@ -0,0 +1,181 @@ +<%+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 + +-%> + + + +
                +
                +

                <%:Unlock or Lock Administrative Menus%>

                +
                + + + + +
                + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                + +
                +
                +<%+footer%> \ No newline at end of file diff --git a/rooter/0optionalapps/libmicroxml/Makefile b/rooter/0optionalapps/libmicroxml/Makefile new file mode 100644 index 0000000..b9fa2f3 --- /dev/null +++ b/rooter/0optionalapps/libmicroxml/Makefile @@ -0,0 +1,54 @@ +# +# Copyright (C) 2012-2014 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=libmicroxml +PKG_VERSION:=2015-03-18 +PKG_RELEASE=$(PKG_SOURCE_VERSION) + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL:=https://github.com/pivasoftware/microxml.git +PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION) +PKG_SOURCE_VERSION:=caa8d3e6887f5c70e54df555dd78e4e45cfa74cc +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz + +PKG_FIXUP:=autoreconf + +include $(INCLUDE_DIR)/package.mk + +define Package/libmicroxml + SECTION:=libs + CATEGORY:=Libraries + TITLE:=XML library + MAINTAINER:=Luka Perkov +endef + +define Package/libmicroxml/description + A micro sized XML library +endef + +CONFIGURE_ARGS += \ + --disable-threads \ + --enable-static \ + --enable-shared + +define Build/InstallDev + $(INSTALL_DIR) $(1)/usr/include + $(CP) $(PKG_BUILD_DIR)/microxml.h $(1)/usr/include + $(INSTALL_DIR) $(1)/usr/lib + $(CP) $(PKG_BUILD_DIR)/libmicroxml.so* $(1)/usr/lib + $(INSTALL_DIR) $(1)/usr/lib/pkgconfig + $(CP) $(PKG_BUILD_DIR)/microxml.pc $(1)/usr/lib/pkgconfig +endef + +define Package/libmicroxml/install + $(INSTALL_DIR) $(1)/usr/lib + $(CP) $(PKG_BUILD_DIR)/libmicroxml.so* $(1)/usr/lib +endef + +$(eval $(call BuildPackage,libmicroxml)) diff --git a/rooter/0optionalapps/luci-app-dnsmasq-ipset/Makefile b/rooter/0optionalapps/luci-app-dnsmasq-ipset/Makefile new file mode 100644 index 0000000..e6383bd --- /dev/null +++ b/rooter/0optionalapps/luci-app-dnsmasq-ipset/Makefile @@ -0,0 +1,34 @@ +#Owned by DairyMan@Whirlpool +# +#Copyright GNU act. +include $(TOPDIR)/rules.mk + +PKG_NAME:=luci-app-dnsmasq-ipset +PKG_VERSION:=1.000 +PKG_RELEASE:=1 + +PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool +include $(INCLUDE_DIR)/package.mk + +define Package/luci-app-dnsmasq-ipset + SECTION:=luci + CATEGORY:=LuCI + DEPENDS:=+dnsmasq-full + SUBMENU:=3. Applications + TITLE:=support for IP Set settings + PKGARCH:=all +endef + +define Package/luci-app-dnsmasq-ipset/description + Helper scripts for IP Set settings +endef + + +define Build/Compile +endef + +define Package/luci-app-dnsmasq-ipset/install + $(CP) ./files/* $(1)/ +endef + +$(eval $(call BuildPackage,luci-app-dnsmasq-ipset)) diff --git a/rooter/0optionalapps/luci-app-dnsmasq-ipset/files/etc/config/dnsmasq-ipset b/rooter/0optionalapps/luci-app-dnsmasq-ipset/files/etc/config/dnsmasq-ipset new file mode 100644 index 0000000..83ec840 --- /dev/null +++ b/rooter/0optionalapps/luci-app-dnsmasq-ipset/files/etc/config/dnsmasq-ipset @@ -0,0 +1,5 @@ +config ipsets + option ipset_name 'netflix' + option enabled '0' + list managed_domain 'netflix.com' + list managed_domain 'netflix.ca' \ No newline at end of file diff --git a/rooter/0optionalapps/luci-app-dnsmasq-ipset/files/etc/init.d/dnsmasq-ipset b/rooter/0optionalapps/luci-app-dnsmasq-ipset/files/etc/init.d/dnsmasq-ipset new file mode 100644 index 0000000..a993efd --- /dev/null +++ b/rooter/0optionalapps/luci-app-dnsmasq-ipset/files/etc/init.d/dnsmasq-ipset @@ -0,0 +1,49 @@ +#!/bin/sh /etc/rc.common +# Author Qier LU + +START=55 + +DNSMASQ="/etc/dnsmasq.conf" + +gen_config_file() { + local section="${1}" + config_get ipset_name "${section}" "ipset_name" + sname="#$ipset_name-1" + ename="#$ipset_name-2" + sed -i "/$sname/,/$ename/d" "$DNSMASQ" + config_get enabled "${section}" "enabled" + if [ -z $enabled ]; then + enabled=0 + fi + if [ ${enabled} -eq 0 ] + then + return + fi + + handle_domain() { + local domain="${1}" + ipline=$ipline"${domain}/" + } + + ipline="ipset=/" + echo "#$ipset_name-1" >> "$DNSMASQ" + config_list_foreach "${section}" "managed_domain" handle_domain + echo "$ipline${ipset_name}" >> "$DNSMASQ" + echo "#$ipset_name-2" >> "$DNSMASQ" + ipset -N -exist "$ipset_name" iphash + /etc/init.d/dnsmasq reload +} + +gen_config_files() { + config_load 'dnsmasq-ipset' + config_foreach gen_config_file 'ipsets' +} + +start() { + gen_config_files +} + +reload() { + sleep 5 + gen_config_files +} diff --git a/rooter/0optionalapps/luci-app-dnsmasq-ipset/files/usr/lib/lua/luci/controller/dnsmasq-ipset.lua b/rooter/0optionalapps/luci-app-dnsmasq-ipset/files/usr/lib/lua/luci/controller/dnsmasq-ipset.lua new file mode 100644 index 0000000..e1514b0 --- /dev/null +++ b/rooter/0optionalapps/luci-app-dnsmasq-ipset/files/usr/lib/lua/luci/controller/dnsmasq-ipset.lua @@ -0,0 +1,15 @@ + +-- Auther Qier LU + +module("luci.controller.dnsmasq-ipset", package.seeall) + +I18N = require "luci.i18n" +translate = I18N.translate + +function index() + if not nixio.fs.access("/etc/config/dnsmasq-ipset") then + return + end + + entry({"admin", "network", "dnsmasq-ipset"}, cbi("dnsmasq-ipset"), _(translate("DNSmasq IP-Set")), 60).dependent = true +end diff --git a/rooter/0optionalapps/luci-app-dnsmasq-ipset/files/usr/lib/lua/luci/model/cbi/dnsmasq-ipset.lua b/rooter/0optionalapps/luci-app-dnsmasq-ipset/files/usr/lib/lua/luci/model/cbi/dnsmasq-ipset.lua new file mode 100644 index 0000000..fe6fff5 --- /dev/null +++ b/rooter/0optionalapps/luci-app-dnsmasq-ipset/files/usr/lib/lua/luci/model/cbi/dnsmasq-ipset.lua @@ -0,0 +1,24 @@ +-- Auther Qier LU + +local m, s, o, p + +m = Map("dnsmasq-ipset", translate("DNSmasq IPSet"), translate("IPSet lists for DNSMasq-full")) + +m.on_after_save = function(self) + luci.sys.call("/etc/init.d/dnsmasq-ipset reload &") +end + +s = m:section(TypedSection, "ipsets", translate("IPSet Lists")) +s.anonymous = true +s.addremove = true + +o = s:option(Value, "ipset_name", translate("IPSet Name")) +o.placeholder = "target ipset" +o.default = "rooter" +o.rmempty = false + +o = s:option(Flag, "enabled", translate("Enabled")) + +o = s:option(DynamicList, "managed_domain", translate("Managed Domain List")) + +return m diff --git a/rooter/0optionalapps/luci-app-hotspot/Makefile b/rooter/0optionalapps/luci-app-hotspot/Makefile new file mode 100644 index 0000000..eedaaf3 --- /dev/null +++ b/rooter/0optionalapps/luci-app-hotspot/Makefile @@ -0,0 +1,34 @@ +#Owned by DairyMan@Whirlpool +# +#Copyright GNU act. +include $(TOPDIR)/rules.mk + +PKG_NAME:=luci-app-hotspot +PKG_VERSION:=1.000 +PKG_RELEASE:=1 + +PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool +include $(INCLUDE_DIR)/package.mk + +define Package/luci-app-hotspot + SECTION:=luci + CATEGORY:=LuCI + DEPENDS:=+iw +iwinfo + SUBMENU:=3. Applications + TITLE:=support for Wifi Hotspot Manager + PKGARCH:=all +endef + +define Package/luci-app-hotspot/description + Helper scripts to enable Wifi Hotspot Manager +endef + + +define Build/Compile +endef + +define Package/luci-app-hotspot/install + $(CP) ./files/* $(1)/ +endef + +$(eval $(call BuildPackage,luci-app-hotspot)) diff --git a/rooter/0optionalapps/luci-app-hotspot/files/etc/config/travelmate b/rooter/0optionalapps/luci-app-hotspot/files/etc/config/travelmate new file mode 100644 index 0000000..23b3751 --- /dev/null +++ b/rooter/0optionalapps/luci-app-hotspot/files/etc/config/travelmate @@ -0,0 +1,17 @@ + +config travelmate 'global' + option trm_debug '1' + option trm_maxwait '20' + option trm_maxretry '3' + option trm_iw '1' + option trm_auto '1' + option radio0 '2.4 Ghz' + option radio1 '5.8 Ghz' + option radcnt '2' + option reconn '1' + option connecting '0' + option ssid '5' + option trm_enabled '0' + option lost '0' + option delay '15' + diff --git a/rooter/0optionalapps/luci-app-hotspot/files/etc/hotplug.d/iface/99-travelmate-iface b/rooter/0optionalapps/luci-app-hotspot/files/etc/hotplug.d/iface/99-travelmate-iface new file mode 100644 index 0000000..1e1c211 --- /dev/null +++ b/rooter/0optionalapps/luci-app-hotspot/files/etc/hotplug.d/iface/99-travelmate-iface @@ -0,0 +1,46 @@ +#!/bin/sh + +if [ "$ACTION" = ifup -a "$INTERFACE" = "wwan" ]; then + exit 1 +fi + +if [ "$ACTION" = ifdown -a "$INTERFACE" = "wwan" ]; then + conn=$(uci -q get travelmate.global.connecting) + wif=$(uci -q get travelmate.global.freq) + if [ "$conn" != "1" ]; then + uci -q set wireless.wwan$wif.ssid="Hotspot Manager Interface" + uci -q set wireless.wwan$wif.encryption="none" + uci -q set wireless.wwan$wif.key= + uci -q set wireless.wwan$wif.disabled=1 + uci -q commit wireless + wifilog "HOTSPOT" "Lost Connection" + ubus call network reload + disa=$(uci -q get travelmate.global.ssid) + # check for disconnect or lost connection + if [ "$disa" != "7" ]; then + uci set travelmate.global.ssid="9" # lost connection + reconn=$(uci -q get travelmate.global.reconn) + if [ "$reconn" != "0" ]; then + lost=$(uci -q get travelmate.global.lost) + if [ $reconn -eq 99 ]; then + lost="1" + fi + if [ $lost -le $reconn ]; then + let lost=$lost+1 + uci set travelmate.global.lost=$lost + uci set travelmate.global.delay="30" + uci commit travelmate + /usr/lib/hotspot/travelmate.sh & + exit 0 + fi + fi + fi + uci set travelmate.global.trm_enabled="0" + uci commit travelmate + fi + + debug="$(uci -q get travelmate.global.trm_debug)" + if [ $debug = "1" ]; then + wifilog "HOTSPOT" "hotplug (iface): action='$ACTION' interface='$INTERFACE'" + fi +fi \ No newline at end of file diff --git a/rooter/0optionalapps/luci-app-hotspot/files/etc/init.d/travelmate b/rooter/0optionalapps/luci-app-hotspot/files/etc/init.d/travelmate new file mode 100644 index 0000000..7357870 --- /dev/null +++ b/rooter/0optionalapps/luci-app-hotspot/files/etc/init.d/travelmate @@ -0,0 +1,90 @@ +#!/bin/sh /etc/rc.common + +. /lib/functions.sh + +START=98 + +log() { + wifilog "Hotspot Initialize" "$@" +} + +do_zone() { + local config=$1 + local name + local network + + config_get name $1 name + config_get network $1 network + newnet="$network" + if [ $name = wan ]; then + WWAN=$(echo "$network" | grep "wwan2") + if [ -z "$WWAN" ]; then + newnet="$newnet wwan2 wwan5" + uci_set firewall "$config" network "$newnet" + uci_commit firewall + /etc/init.d/firewall restart + fi + fi +} + +do_radio() { + local config=$1 + local channel + local hwmode + + config_get channel $1 channel + config_get hwmode $1 hwmode + if [ $hwmode = "11g" ]; then + w2=$(uci -q get wireless.wwan2.device) + if [ -z $w2 ]; then + uci set wireless.wwan2=wifi-iface + uci set wireless.wwan2.device=$config + uci set wireless.wwan2.network="wwan2" + uci set wireless.wwan2.mode="sta" + uci set wireless.wwan2.ssid="Hotspot Manager Interface" + uci set wireless.wwan2.encryption="none" + uci set wireless.wwan2.disabled="1" + uci commit wireless + fi + else + w2=$(uci -q get wireless.wwan5.device) + if [ -z $w2 ]; then + uci set wireless.wwan5=wifi-iface + uci set wireless.wwan5.device=$config + uci set wireless.wwan5.network="wwan5" + uci set wireless.wwan5.mode="sta" + uci set wireless.wwan5.ssid="Hotspot Manager Interface" + uci set wireless.wwan5.encryption="none" + uci set wireless.wwan5.disabled="1" + uci commit wireless + fi + fi +} + +start() +{ +log "Hotspot Firewall" + + PRO=$(uci get network.wwan2.proto) + if [ -z $PRO ]; then + uci set network.wwan2=interface + uci set network.wwan2.proto=dhcp + uci set network.wwan26=interface + uci set network.wwan26.proto=dhcpv6 + uci set network.wwan5=interface + uci set network.wwan5.proto=dhcp + uci set network.wwan56=interface + uci set network.wwan56.proto=dhcpv6 + uci commit network + fi + config_load firewall + config_foreach do_zone zone + config_load wireless + config_foreach do_radio wifi-device + uci set travelmate.global.lost="0" + uci set travelmate.global.delay="30" + uci set travelmate.global.state='0' + uci commit travelmate +} + + diff --git a/rooter/0optionalapps/luci-app-hotspot/files/etc/init.d/zhot b/rooter/0optionalapps/luci-app-hotspot/files/etc/init.d/zhot new file mode 100644 index 0000000..f610bee --- /dev/null +++ b/rooter/0optionalapps/luci-app-hotspot/files/etc/init.d/zhot @@ -0,0 +1,17 @@ +#!/bin/sh /etc/rc.common + +. /lib/functions.sh + +START=99 + +log() { + wifilog "Z-Hotspot " "$@" +} + +start() +{ + uci set travelmate.global.lost="0" + uci set travelmate.global.delay="30" + uci commit travelmate + /usr/lib/hotspot/travelmate.sh & +} diff --git a/rooter/0optionalapps/luci-app-hotspot/files/lib/upgrade/keep.d/hotspot b/rooter/0optionalapps/luci-app-hotspot/files/lib/upgrade/keep.d/hotspot new file mode 100644 index 0000000..5ed46ef --- /dev/null +++ b/rooter/0optionalapps/luci-app-hotspot/files/lib/upgrade/keep.d/hotspot @@ -0,0 +1 @@ +/etc/hotspot diff --git a/rooter/0optionalapps/luci-app-hotspot/files/usr/bin/hkillall b/rooter/0optionalapps/luci-app-hotspot/files/usr/bin/hkillall new file mode 100644 index 0000000..3802082 --- /dev/null +++ b/rooter/0optionalapps/luci-app-hotspot/files/usr/bin/hkillall @@ -0,0 +1,9 @@ +#!/bin/sh +LOOKFOR=$1 +KILLLIST=$(ps | grep $LOOKFOR) +echo "$KILLLIST" | while read line; do + if `echo "$line" | grep "/$LOOKFOR" > /dev/null` ; then + PIDV=$(echo $line | grep -o "^[0-9]\{1,5\}" | grep -o "[0-9]\{1,5\}") + kill $PIDV + fi +done \ No newline at end of file diff --git a/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/hotspot/band.sh b/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/hotspot/band.sh new file mode 100644 index 0000000..a214c8a --- /dev/null +++ b/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/hotspot/band.sh @@ -0,0 +1,25 @@ +#!/bin/sh + +BAND=$1 +if [ $BAND = "1" ]; then + BAND=2 +else + BAND=5 +fi + +/usr/lib/hotspot/enable.sh 0 + +uci set travelmate.global.freq=$BAND +uci set travelmate.global.ssid="6" +uci commit travelmate + +result=`ps | grep -i "travelmate.sh" | grep -v "grep" | wc -l` +if [ $result -ge 1 ] +then + wifilog "Band Change" "Travelmate already running" +else + /usr/lib/hotspot/travelmate.sh & +fi +uci set travelmate.global.ssid="Hotspot Manager Interface" +uci commit travelmate +exit 0 \ No newline at end of file diff --git a/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/hotspot/copyhot.sh b/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/hotspot/copyhot.sh new file mode 100644 index 0000000..83d87ef --- /dev/null +++ b/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/hotspot/copyhot.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +if [ -f "/tmp/hot" ]; then + rm -f /etc/hotspot + while IFS='|' read -r ssid encrypt key flag + do + echo $ssid"|"$encrypt"|"$key >> /etc/hotspot + done <"/tmp/hot" +fi diff --git a/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/hotspot/dis_hot.sh b/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/hotspot/dis_hot.sh new file mode 100644 index 0000000..93e2f67 --- /dev/null +++ b/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/hotspot/dis_hot.sh @@ -0,0 +1,15 @@ +#!/bin/sh +. /lib/functions.sh + +wif=$(uci -q get travelmate.global.freq) +rm -f /tmp/hotman +uci set travelmate.global.ssid="7" +uci set travelmate.global.state='' +uci set travelmate.global.bssid="" +uci set travelmate.global.key='' +uci commit travelmate +uci -q set wireless.wwan$wif.disabled=1 +uci set wireless.wwan$wif.ssid="Hotspot Manager Interface" +uci -q commit wireless +/etc/init.d/network reload + diff --git a/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/hotspot/enable.sh b/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/hotspot/enable.sh new file mode 100644 index 0000000..e2b645f --- /dev/null +++ b/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/hotspot/enable.sh @@ -0,0 +1,42 @@ +#!/bin/sh +. /lib/functions.sh + +SET=$1 + +uci set travelmate.global.trm_enabled=$SET +uci commit travelmate + +wif=$(uci -q get travelmate.global.freq) + +if [ $SET = "1" ]; then + wifilog "Enable" "Connect Hotspot" + AU=$(uci get travelmate.global.trm_auto) + hkillall travelmate.sh + if [ $AU = "1" ]; then + uci set travelmate.global.ssid="8" + uci set travelmate.global.bssid="" + uci set travelmate.global.state='' + uci set travelmate.global.key='' + uci commit travelmate + uci -q set wireless.wwan$wif.encryption="none" + uci -q set wireless.wwan$wif.key= + uci set wireless.wwan$wif.ssid="Hotspot Manager Interface" + uci -q commit wireless + /usr/lib/hotspot/travelmate.sh & + fi +else + wifilog "Enable" "Disconnect Hotspot" + hkillall travelmate.sh + rm -f /tmp/hotman + uci set travelmate.global.ssid="7" + uci set travelmate.global.state="0" + uci set travelmate.global.key='' + uci set travelmate.global.bssid="" + uci set travelmate.global.trm_enabled="0" + uci commit travelmate + uci -q set wireless.wwan$wif.disabled=1 + uci set wireless.wwan$wif.ssid="Hotspot Manager Interface" + uci -q commit wireless + ubus call network.interface.wwan down + ubus call network reload +fi \ No newline at end of file diff --git a/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/hotspot/getssid.sh b/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/hotspot/getssid.sh new file mode 100644 index 0000000..c42fb01 --- /dev/null +++ b/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/hotspot/getssid.sh @@ -0,0 +1,15 @@ +#!/bin/sh + +wif=$(uci -q get travelmate.global.freq) +RADIO=$(uci get wireless.wwan$wif.device) +ap_list="$(ubus -S call network.wireless status | jsonfilter -e "@.$RADIO.interfaces[@.config.mode=\"ap\"].ifname")" +if [ -z $ap_list ]; then + wifi up + ap_list="$(ubus -S call network.wireless status | jsonfilter -e "@.$RADIO.interfaces[@.config.mode=\"ap\"].ifname")" +fi + +rm -f /tmp/ssidlist +for ap in ${ap_list} +do + iwinfo "${ap}" scan >> /tmp/ssidlist +done diff --git a/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/hotspot/inrange.sh b/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/hotspot/inrange.sh new file mode 100644 index 0000000..77df595 --- /dev/null +++ b/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/hotspot/inrange.sh @@ -0,0 +1,59 @@ +#!/bin/sh +. "/lib/functions.sh" + +log() { + wifilog "In Range" "$@" +} + +rm -f /tmp/hot1 +cnt=0 +trm_ifstatus="false" +while [ ${cnt} -lt 20 ] +do + trm_ifstatus="$(ubus -S call network.wireless status | jsonfilter -l1 -e '@.*.up')" + if [ "${trm_ifstatus}" = "true" ] + then + break + fi + cnt=$((cnt+1)) + sleep 1 +done + +wif=$(uci -q get travelmate.global.freq) +RADIO=$(uci get wireless.wwan$wif.device) +ap_list="$(ubus -S call network.wireless status | jsonfilter -e "@.$RADIO.interfaces[@.config.mode=\"ap\"].ifname")" + +trm_scanner="$(which iw)" +for ap in ${ap_list} +do + ssid_list="$(${trm_scanner} dev "${ap}" scan 2>/dev/null > /tmp/scan + cat /tmp/scan | awk '/SSID: /{if(!seen[$0]++){printf "\"";for(i=2; i<=NF; i++)if(i==2)printf $i;else printf " "$i;printf "\" "}}')" + + if [ -n "${ssid_list}" ] + then + if [ -f "/etc/hotspot" ]; then + while IFS='|' read -r ssid encrypt key + do + ssidq="\"$ssid\"" + if [ -n "$(printf "${ssid_list}" | grep -Fo "${ssidq}")" ] + then + echo $ssid"|"$encrypt"|"$key"|1" >> /tmp/hot1 + else + echo $ssid"|"$encrypt"|"$key"|0" >> /tmp/hot1 + fi + done <"/etc/hotspot" + fi + else + if [ -f "/etc/hotspot" ]; then + while IFS='|' read -r ssid encrypt key + do + echo $ssid"|"$encrypt"|"$key"|0" >> /tmp/hot1 + done <"/etc/hotspot" + fi + fi +done +if [ -f "/tmp/hot1" ]; then + mv -f /tmp/hot1 /tmp/hot +fi + + diff --git a/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/hotspot/manual.sh b/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/hotspot/manual.sh new file mode 100644 index 0000000..63323d4 --- /dev/null +++ b/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/hotspot/manual.sh @@ -0,0 +1,10 @@ +#!/bin/sh + +MAN="$1" + +hkillall travelmate.sh + +/usr/lib/hotspot/dis_hot.sh +echo "$MAN" > /tmp/hotman +/usr/lib/hotspot/travelmate.sh & + diff --git a/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/hotspot/mode.sh b/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/hotspot/mode.sh new file mode 100644 index 0000000..cbc9571 --- /dev/null +++ b/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/hotspot/mode.sh @@ -0,0 +1,19 @@ +#!/bin/sh + +SET=$1 + +rm -f /tmp/hotman +uci set travelmate.global.trm_auto=$SET +uci commit travelmate + +if [ $SET = "1" ]; then + result=`ps | grep -i "travelmate.sh" | grep -v "grep" | wc -l` + if [ $result -ge 1 ] + then + wifilog "HOTSPOT" "Travelmate already running" + else + /usr/lib/hotspot/travelmate.sh & + fi +else + hkillall travelmate.sh +fi \ No newline at end of file diff --git a/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/hotspot/reconn.sh b/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/hotspot/reconn.sh new file mode 100644 index 0000000..cef0a60 --- /dev/null +++ b/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/hotspot/reconn.sh @@ -0,0 +1,11 @@ +#!/bin/sh +. /lib/functions.sh + +log() { + logger -t "Reconnect" "$@" +} + +reconn=$1 +log "$reconn" +uci set travelmate.global.reconn=$reconn +uci commit travelmate \ No newline at end of file diff --git a/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/hotspot/travelmate.sh b/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/hotspot/travelmate.sh new file mode 100644 index 0000000..a31d4e0 --- /dev/null +++ b/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/hotspot/travelmate.sh @@ -0,0 +1,427 @@ +#!/bin/sh + +. /lib/functions.sh + +# travelmate, a wlan connection manager for travel router +# written by Dirk Brenken (dev@brenken.org) + +# This is free software, licensed under the GNU General Public License v3. +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# prepare environment +# +LC_ALL=C +PATH="/usr/sbin:/usr/bin:/sbin:/bin" +trm_ver="0.3.0" +trm_enabled=1 +trm_debug=0 +trm_maxwait=20 +trm_maxretry=1 +trm_iw=1 +trm_auto=$(uci -q get travelmate.global.trm_auto) + +check_wwan() { + uci set travelmate.global.ssid="0" + wif=$(uci -q get travelmate.global.freq) + if [ -z "$wif" ]; then + uci set travelmate.global.freq="2" + fi + uci commit travelmate + while [ ! -e /etc/config/wireless ] + do + sleep 1 + done + sleep 3 + f_check "ap" + cntx=0 + while [ "${trm_ifstatus}" != "true" ]; do + sleep 1 + f_check "ap" + let cntx=cntx+1 + if [ $cntx -ge 20 ]; then + break + fi + done + f_log "info" "AP Status ::: $trm_ifstatus" +} + +count_radio() { + local config=$1 + local channel + + config_get channel $1 channel + if [ $channel -gt 15 ]; then + uci set travelmate.global.radio5="5.8 Ghz" + else + uci set travelmate.global.radio2="2.4 Ghz" + fi + let radcnt=radcnt+1 +} + +check_radio() { + radcnt=0 + config_load wireless + config_foreach count_radio wifi-device + uci set travelmate.global.radcnt=$radcnt + uci commit travelmate +} + +f_envload() +{ + # source required system libraries + # + if [ -r "/lib/functions.sh" ] + then + . "/lib/functions.sh" + else + f_log "error" "required system library not found" + fi + + # load uci config and check 'enabled' option + # + option_cb() + { + local option="${1}" + local value="${2}" + eval "${option}=\"${value}\"" + } + config_load travelmate + + if [ ${trm_enabled} -ne 1 ] + then + f_log "info " "status ::: Hotspot Manager is currently disabled" + exit 0 + fi + + # check for preferred wireless tool + # + if [ ${trm_iw} -eq 1 ] + then + trm_scanner="$(which iw)" + else + trm_scanner="$(which iwinfo)" + fi + if [ -z "${trm_scanner}" ] + then + f_log "error" "status ::: no wireless tool for wlan scanning found, please install 'iw' or 'iwinfo'" + fi +} + +# function to bring down all STA interfaces +# +f_prepare() +{ + local config="${1}" + local mode="$(uci -q get wireless."${config}".mode)" + local network="$(uci -q get wireless."${config}".network)" + local disabled="$(uci -q get wireless."${config}".disabled)" + + if [ "${mode}" = "sta" ] && [ -n "${network}" ] + then + trm_stalist="${trm_stalist} ${config}_${network}" + if [ -z "${disabled}" ] || [ "${disabled}" = "0" ] + then + uci -q set wireless."${config}".disabled=1 + f_log "debug" "prepare ::: config: ${config}, interface: ${network}" + fi + fi +} + +f_check() +{ + local ifname cnt=0 mode="${1}" + trm_ifstatus="false" + + while [ ${cnt} -lt ${trm_maxwait} ] + do + wif=$(uci -q get travelmate.global.freq) + RADIO=$(uci get wireless.wwan$wif.device) + ifname="$(ubus -S call network.wireless status | jsonfilter -l 1 -e "@.$RADIO.interfaces[@.config.mode=\"${mode}\"].ifname")" + if [ -z $ifname ]; then + break + fi + if [ "${mode}" = "sta" ] + then + trm_ifstatus="$(ubus -S call network.interface dump | jsonfilter -e "@.interface[@.device=\"${ifname}\"].up")" + else + trm_ifstatus="$(ubus -S call network.wireless status | jsonfilter -l1 -e '@.*.up')" + fi + if [ "${trm_ifstatus}" = "true" ] + then + break + fi + cnt=$((cnt+1)) + sleep 1 + done + f_log "debug" "check ::: ${mode} name: ${ifname}, status: ${trm_ifstatus}, count: ${cnt}" +} + +# function to write to syslog +# +f_log() +{ + local class="${1}" + local log_msg="${2}" + + if [ -n "${log_msg}" ] && ([ "${class}" != "debug" ] || [ ${trm_debug} -eq 1 ]) + then + wifilog "HOTSPOT-[${trm_ver}] ${class}" "${log_msg}" + if [ "${class}" = "error" ] + then + wif=$(uci -q get travelmate.global.freq) + uci set travelmate.global.ssid="1" + uci commit travelmate + uci -q set wireless.wwan@wif.ssid="Hotspot Manager Interface" + uci -q set wireless.wwan$wif.encryption="none" + uci -q set wireless.wwan$wif.key= + uci -q commit wireless + #exit 255 + fi + fi +} + +ssid_list="" +ap_list="" +trm_stalist="" + +f_working_ap() { + f_check "ap" + wif=$(uci -q get travelmate.global.freq) + RADIO=$(uci get wireless.wwan$wif.device) + ap_list="$(ubus -S call network.wireless status | jsonfilter -e "@.$RADIO.interfaces[@.config.mode=\"ap\"].ifname")" + f_log "debug" "main ::: ap-list: ${ap_list}, sta-list: ${trm_stalist}" + if [ -z "${ap_list}" ] || [ -z "${trm_stalist}" ] + then + sleep 3 + f_check "ap" + ap_list="$(ubus -S call network.wireless status | jsonfilter -e "@.$RADIO.interfaces[@.config.mode=\"ap\"].ifname")" + f_log "debug" "main ::: ap-list: ${ap_list}, sta-list: ${trm_stalist}" + fi +} + +f_scan_ap() { + wif=$(uci -q get travelmate.global.freq) + radio=$(uci get wireless.wwan$wif.device) + # scan using AP radio + trm_iwinfo="$(command -v iwinfo)" + trm_maxscan="10" + scan_dev="$(ubus -S call network.wireless status 2>/dev/null | jsonfilter -q -l1 -e "@.${radio}.interfaces[0].ifname")" + ssid_list="$("${trm_iwinfo}" "${scan_dev:-${radio}}" scan 2>/dev/null | + awk 'BEGIN{FS="[[:space:]]"}/Address:/{var1=$NF}/ESSID:/{var2="";for(i=12;i<=NF;i++)if(var2==""){var2=$i}else{var2=var2" "$i}} + /Quality:/{split($NF,var0,"/")}/Encryption:/{if($NF=="none"){var3="+"}else{var3="-"}; + printf "%i %s %s %s\n",(var0[1]*100/var0[2]),var3,var1,var2}' | sort -rn | head -qn "${trm_maxscan}")" +} + +f_main() +{ + local config network ssid cnt=0 + wif=$(uci -q get travelmate.global.freq) + + trm_stalist="" + # check if wwan is connected + f_check "sta" + if [ "${trm_ifstatus}" == "true" ]; then + wifi down $(uci -q get wireless.wwan$wif.device) + f_check "sta" + f_log "info" "STA ${trm_ifstatus}" + while [ "${trm_ifstatus}" == "true" ]; do + sleep 1 + f_check "sta" + done + fi + if [ "${trm_ifstatus}" != "true" ] # not connected + then + uci set travelmate.global.state='1' + uci commit travelmate + f_check "ap" + f_log "info" "AP ${trm_ifstatus}" + if [ "${trm_ifstatus}" != "true" ]; then + wifi up $(uci -q get wireless.wwan$wif.device) + f_check "ap" + while [ "${trm_ifstatus}" != "true" ]; do + sleep 1 + f_check "ap" + done + fi + uci set travelmate.global.bssid="" + uci set travelmate.global.ssid="2" + uci commit travelmate + uci -q set wireless.wwan$wif.ssid="Hotspot Manager Interface" + uci -q set wireless.wwan$wif.encryption="none" + uci -q set wireless.wwan$wif.key= + uci -q commit wireless + ubus call network.interface.wwan$wif up + ubus call network reload + wifi up $(uci -q get wireless.wwan$wif.device) + sleep 5 + + # set disabled for wwan iface + config_load wireless + config_foreach f_prepare wifi-iface + if [ -n "$(uci -q changes wireless)" ] + then + uci -q commit wireless + ubus call network reload + fi + # check if AP working + f_working_ap + # AP or STA not working + if [ -z "${ap_list}" ] || [ -z "${trm_stalist}" ] + then + f_log "error" "main ::: no usable AP/STA configuration found" + + else + # single AP in list + for ap in ${ap_list} + do + #f_scan_ap + # repeat scan and connection + cnt=0 + delay=10 + reconn=$(uci -q get travelmate.global.reconn) + while [ ${cnt} -le $reconn ] + do + f_log "info" " Retry Count ${cnt}" + if [ $reconn -eq 99 ]; then + cnt=0 + fi + f_scan_ap + f_log "info" " SSID List ${ssid_list}" + # get list of Hotspots present + if [ -n "${ssid_list}" ]; then + if [ "$trm_auto" = "1" ]; then + FILE="/etc/hotspot" + else + FILE="/tmp/hotman" + fi + if [ -f "${FILE}" ]; then + # read list of selected Hotspots + while IFS='|' read -r ssid encrypt key + do + ssidq="\"$ssid\"" + # see if in scan list + if [ -n "$(printf "${ssid_list}" | grep -Fo "${ssidq}")" ]; then + # connect to Hotspot + uci set travelmate.global.bssid="$ssid" + uci set travelmate.global.ssid=">>> $ssid" + uci set travelmate.global.connecting="1" + uci commit travelmate + uci -q set wireless.wwan$wif.ssid="$ssid" + uci -q set wireless.wwan$wif.encryption=$encrypt + uci -q set wireless.wwan$wif.key=$key + uci -q set wireless.wwan$wif.disabled=0 + uci -q commit wireless + wifi up $(uci -q get wireless.wwan$wif.device) + ubus call network.interface.wwan$wif up + ubus call network reload + f_log "info " "main ::: wwan interface connected to uplink ${ssid}" + sleep 5 + # wait and check for good connection + f_check "ap" + f_log "info" "AP Status ::: $trm_ifstatus" + cntx=0 + while [ "${trm_ifstatus}" != "true" ]; do + sleep 1 + f_check "ap" + let cntx=cntx+1 + if [ $cntx -ge $delay ]; then + break + fi + f_log "info" "AP Status ::: $trm_ifstatus" + done + cntx=0 + #delay=$(uci -q get travelmate.global.delay) + f_check "sta" + f_log "info" "STA Status ${trm_ifstatus}" + while [ "${trm_ifstatus}" != "true" ]; do + sleep 1 + f_check "sta" + let cntx=cntx+1 + if [ $cntx -ge $delay ]; then + break + fi + f_log "info" "STA Status ${trm_ifstatus}" + done + + if [ "${trm_ifstatus}" = "true" ]; then + uci set travelmate.global.ssid="$ssid" + uci set travelmate.global.connecting="0" + uci set travelmate.global.lost="0" + uci set travelmate.global.state='2' + uci set travelmate.global.key=$key + uci set travelmate.global.trm_auto="1" + uci commit travelmate + # connection good + f_log "info" "Connected $ssid" + exit 0 + fi + # bad connection try next Hotspot in list + uci set travelmate.global.bssid="" + uci set travelmate.global.ssid="3" + uci commit travelmate + uci -q set wireless.wwan$wif.ssid="Hotspot Manager Interface" + uci -q set wireless.wwan$wif.encryption="none" + uci -q set wireless.wwan$wif.key= + uci -q set wireless.wwan$wif.disabled=1 + uci -q commit wireless + ubus call network.interface.wwan$wif down + ubus call network reload + f_log "info" "Try next in list" + fi + done <"${FILE}" + wifi up $(uci -q get wireless.wwan$wif.device) + f_check "ap" + while [ "${trm_ifstatus}" != "true" ]; do + f_check "ap" + sleep 1 + done + fi + fi + # No connection to any in list + cnt=$((cnt+1)) + if [ $reconn -gt 0 ]; then + f_log "info " "Sleep before retrying" + sleep 30 + fi + # repeat scan and connect + done + done + fi + # unable to connect + if [ "$trm_auto" = "1" ]; then + uci set travelmate.global.ssid="4" + else + uci set travelmate.global.ssid="5" + fi + reconn=$(uci -q get travelmate.global.reconn) + lost=$(uci -q get travelmate.global.lost) + if [ $reconn -eq 99 ]; then + lost="1" + fi + if [ $lost -gt $reconn ]; then + uci set travelmate.global.ssid="5" + fi + uci set travelmate.global.trm_enabled="0" + uci set travelmate.global.connecting="0" + uci set travelmate.global.lost="0" + uci set travelmate.global.state='0' + uci set travelmate.global.bssid="" + uci set travelmate.global.trm_auto="1" + uci commit travelmate + uci -q set wireless.wwan$wif.ssid="Hotspot Manager Interface" + uci -q set wireless.wwan$wif.encryption="none" + uci -q set wireless.wwan$wif.key= + uci -q commit wireless + f_log "info " "main ::: no wwan uplink found" + fi + # already connected + exit 0 +} + +check_wwan +check_radio +f_envload +f_main + +exit 0 \ No newline at end of file diff --git a/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/lua/luci/controller/hotspot.lua b/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/lua/luci/controller/hotspot.lua new file mode 100644 index 0000000..75ceb27 --- /dev/null +++ b/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/lua/luci/controller/hotspot.lua @@ -0,0 +1,307 @@ +module("luci.controller.hotspot", package.seeall) + +I18N = require "luci.i18n" +translate = I18N.translate + +function index() + local page + 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 + entry({"admin", "hotspot"}, firstchild(), translate("Wifi Hotspot"), 29).dependent=false + page = entry({"admin", "hotspot", "hotspot"}, template("hotspot/hotspot"), _(translate("Hotspot Manager")), 5) + page.dependent = true + end + + entry({"admin", "services", "check_spot"}, call("action_check_spot")) + entry({"admin", "services", "set_mode"}, call("action_set_mode")) + entry({"admin", "services", "set_enabled"}, call("action_set_enabled")) + entry({"admin", "services", "disconnect"}, call("action_disconnect")) + entry({"admin", "services", "refreshlist"}, call("action_refresh")) + entry({"admin", "services", "moveup"}, call("action_moveup")) + entry({"admin", "services", "movedown"}, call("action_movedown")) + entry({"admin", "services", "addtolist"}, call("action_addtolist")) + entry({"admin", "services", "dellist"}, call("action_dellist")) + entry({"admin", "services", "editlist"}, call("action_editlist")) + entry({"admin", "services", "mancon"}, call("action_mancon")) + entry({"admin", "services", "bandchange"}, call("action_bandchange")) + entry({"admin", "services", "reconn"}, call("action_reconn")) +end + +function readhot() + line = nil + file = io.open("/tmp/hot", "r") + if file ~= nil then + repeat + tmp = file:read("*line") + if tmp ~= nil then + if line == nil then + line = tmp + else + line = line .. "|" .. tmp + end + end + until tmp == nil + file:close() + end + return line +end + +function action_check_spot() + local rv = {} + local freq = {} + local set = luci.http.formvalue("set") + auto = luci.model.uci.cursor():get("travelmate", "global", "trm_auto") + rv["auto"] = auto + rv["enabled"] = luci.model.uci.cursor():get("travelmate", "global", "trm_enabled") + rv["reconn"] = luci.model.uci.cursor():get("travelmate", "global", "reconn") + if rv["reconn"] == nil then + rv["reconn"] = "0" + end + + rv["ssid"] = luci.model.uci.cursor():get("travelmate", "global", "ssid") + if rv["ssid"] == nil then + rv["ssid"] = "No Connection" + end + fre = luci.model.uci.cursor():get("travelmate", "global", "freq") + encr = luci.model.uci.cursor():get("wireless", "wwan" .. fre, "encryption") + if encr == "none" then + rv["encryp"] = translate("Open") + else + rv["encryp"] = translate("Encrypted") + end + rv["disable"] = luci.model.uci.cursor():get("wireless", "wwan" .. fre, "disabled") + + dual = luci.model.uci.cursor():get("travelmate", "global", "radcnt") + rv["dual"] = dual + nrad = tonumber(dual) + for k = 0, nrad do + freq[k] = luci.model.uci.cursor():get("travelmate", "global", "radio" .. tostring(k)) + end + rv['freq'] = freq + + device = luci.model.uci.cursor():get("wireless", "wwan" .. fre, "device") + device = string.sub(device, 6, 7) + if fre == "2" then + fre="0" + else + fre="1" + end + rv["band"] = fre + + luci.http.prepare_content("application/json") + luci.http.write_json(rv) +end + +function action_set_mode() + local set = luci.http.formvalue("set") + os.execute("/usr/lib/hotspot/enable.sh " .. set) +end + +function action_set_enabled() + local set = luci.http.formvalue("set") + os.execute("/usr/lib/hotspot/enable.sh " .. set) +end + +function action_disconnect() + os.execute("/usr/lib/hotspot/dis_hot.sh") +end + +function action_refresh() + local rv = {} + os.execute("/usr/lib/hotspot/inrange.sh") + hotline = readhot() + if hotline == nil then + rv["empty"] = "1" + else + rv["empty"] = "0" + rv["hotline"] = hotline + end + + luci.http.prepare_content("application/json") + luci.http.write_json(rv) +end + +function movelist(direc, set, key) + local temp = {} + local rv = {} + local index = 0 + file = io.open("/tmp/hot", "r") + if file ~= nil then + repeat + tmp = file:read("*line") + if tmp ~= nil then + temp[index] = tmp + index = index + 1 + end + until tmp == nil + file:close() + if direc == 0 then + line2 = temp[set-1] + temp[set-1] = temp[set] + temp[set] = line2 + elseif direc == 1 then + line2 = temp[set+1] + temp[set+1] = temp[set] + temp[set] = line2 + elseif direc == 2 then + if index > 0 then + for i=set, index-2 do + temp[i] = temp[i+1] + end + end + index = index - 1 + elseif direc == 3 then + s, e = temp[set]:find("|") + name = temp[set]:sub(1, s-1) + cs, ce = temp[set]:find("|", e+1) + enc = temp[set]:sub(e+1, cs-1) + bs, be = temp[set]:find("|", ce+1) + ko = temp[set]:sub(ce+1, bs-1) + fl = temp[set]:sub(be+1) + temp[set] = name .. "|" .. enc .. "|" .. key .. "|" .. fl + end + if index < 0 then + --os.execute("rm -f /tmp/hot1; rm -f /etc/hotspot") + else + file = io.open("/tmp/hot", "w") + for i=0, index-1 do + file:write(temp[i], "\n") + end + file:close() + os.execute("/usr/lib/hotspot/copyhot.sh") + end + end +end + +function action_moveup() + local set = tonumber(luci.http.formvalue("set")) + local rv = {} + movelist(0, set) + hotline = readhot() + if hotline == nil then + rv["empty"] = "1" + else + rv["empty"] = "0" + rv["hotline"] = hotline + end + + luci.http.prepare_content("application/json") + luci.http.write_json(rv) +end + +function action_movedown() + local set = tonumber(luci.http.formvalue("set")) + local rv = {} + movelist(1, set) + hotline = readhot() + if hotline == nil then + rv["empty"] = "1" + else + rv["empty"] = "0" + rv["hotline"] = hotline + end + + luci.http.prepare_content("application/json") + luci.http.write_json(rv) +end + +function action_dellist() + local set = tonumber(luci.http.formvalue("set")) + local rv = {} + movelist(2, set) + hotline = readhot() + if hotline == nil then + rv["empty"] = "1" + else + rv["empty"] = "0" + rv["hotline"] = hotline + end + + luci.http.prepare_content("application/json") + luci.http.write_json(rv) +end + +function action_addtolist() + local set = luci.http.formvalue("set") + local rv = {} + + s, e = set:find("|") + ssid = set:sub(1, e-1) + + file = io.open("/etc/hotspot", "r") + if file ~= nil then + i = 0 + repeat + line = file:read("*line") + if line == nil then + break + else + s, e = line:find(ssid) + if s ~= nil then + i = 1 + break + end + end + until 1==0 + if i == 0 then + file = io.open("/etc/hotspot", "a") + file:write(set) + file:write("\n") + file:close() + end + else + file = io.open("/etc/hotspot", "w") + file:write(set) + file:write("\n") + file:close() + end + os.execute("/usr/lib/hotspot/inrange.sh") + hotline = readhot() + if hotline == nil then + rv["empty"] = "1" + else + rv["empty"] = "0" + rv["hotline"] = hotline + end + + luci.http.prepare_content("application/json") + luci.http.write_json(rv) +end + +function action_editlist() + local set = luci.http.formvalue("set") + local rv = {} + s, e = set:find("|") + sel = set:sub(1, s-1) + idx = tonumber(sel) + key = set:sub(e+1) + movelist(3, idx, key) + hotline = readhot() + if hotline == nil then + rv["empty"] = "1" + else + rv["empty"] = "0" + rv["hotline"] = hotline + end + + luci.http.prepare_content("application/json") + luci.http.write_json(rv) +end + +function action_mancon() + local set = luci.http.formvalue("set") + local rv = {} + os.execute("/usr/lib/hotspot/manual.sh \"" .. set .. "\"") +end + +function action_bandchange() + local set = luci.http.formvalue("set") + local rv = {} + os.execute("/usr/lib/hotspot/band.sh \"" .. set .. "\"") +end + +function action_reconn() + local set = luci.http.formvalue("set") + os.execute("/usr/lib/hotspot/reconn.sh \"" .. set .. "\"") +end \ No newline at end of file diff --git a/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/lua/luci/controller/wifilog.lua b/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/lua/luci/controller/wifilog.lua new file mode 100644 index 0000000..b192569 --- /dev/null +++ b/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/lua/luci/controller/wifilog.lua @@ -0,0 +1,33 @@ +module("luci.controller.wifilog", package.seeall) + +I18N = require "luci.i18n" +translate = I18N.translate + +function index() + 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 + local page + page = entry({"admin", "hotspot", "wifilog"}, template("wifilog/wifilog"), _(translate("Hotspot Logging")), 61) + page.dependent = true + end + + entry({"admin", "status", "wifilog"}, call("action_wifilog")) +end + +function action_wifilog() + local file + local rv ={} + + file = io.open("/tmp/wifilog.log", "r") + if file ~= nil then + local tmp = file:read("*all") + rv["log"] = tmp + file:close() + else + rv["log"] = translate("No entries in log file") + end + + luci.http.prepare_content("application/json") + luci.http.write_json(rv) +end \ No newline at end of file diff --git a/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/lua/luci/view/hotspot/hotspot.htm b/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/lua/luci/view/hotspot/hotspot.htm new file mode 100644 index 0000000..fae6a6b --- /dev/null +++ b/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/lua/luci/view/hotspot/hotspot.htm @@ -0,0 +1,1139 @@ +<%- + +local sys = require "luci.sys" +local utl = require "luci.util" + +wifi = {} +scan = {} +numnet = 0 + +printf = function(s,...) + io.write(s:format(...)) + local ss = s:format(...) +end + +function trim(s) + return (s:gsub("^%s*(.-)%s*$", "%1")) +end + +function showicon() + return resource .. "/icons/encryption.png" +end + +function guess_wifi_signal(info) + local scale = scan[info]["quality"] + local icon + if scale < 15 then + icon = resource .. "/icons/signal-0.png" + elseif scale < 35 then + icon = resource .. "/icons/signal-0-25.png" + elseif scale < 55 then + icon = resource .. "/icons/signal-25-50.png" + elseif scale < 75 then + icon = resource .. "/icons/signal-50-75.png" + else + icon = resource .. "/icons/signal-75-100.png" + end + + return icon +end + +function scan_open(rrx, rry) + rony = 1 + if rry["encrypt"] == "Open" then + rony = 0 + end + ronx = 1 + if rrx["encrypt"] == "Open" then + ronx = 0 + end + if ronx < rony then + return true + end + if ronx > rony then + return false + end + ronx = rrx["quality"] + rony = rry["quality"] + if ronx > rony then + return true + end + return false +end + +function partition(arr, left, right) + local i = left + local j = right + local pivot = math.floor((left + right) / 2) + local tmp + while i <= j do + while scan_open(arr[i], arr[pivot]) do + i = i + 1 + end + while scan_open(arr[pivot], arr[j]) do + j = j - 1 + end + if i <= j then + tmp = arr[i] + arr[i] = arr[j] + arr[j] = tmp + i = i + 1 + j = j - 1 + end + end + return i, arr +end + +function quicksort(arr, left, right) + index, arr = partition(arr, left, right) + if left < (index - 1) then + quicksort(arr, left, index-1) + end + if index < right then + quicksort(arr, index, right) + end + return arr +end + +function build_scan(j, k) + scan[k]["channel"] = wifi[j]["channel"] + scan[k]["essid"] = wifi[j]["essid"] + scan[k]["signal"] = tonumber(wifi[j]["signal"]) + qc = tonumber(wifi[j]["quality"]) + qm = tonumber(wifi[j]["quality_max"]) + scan[k]["quality"] = math.floor((100 / qm) * qc) + scan[k]["ekey"] = wifi[j]["ekey"] + if wifi[j]["ekey"] == "none" then + scan[k]["encrypt"] = "Open" + scan[k]["encryption"] = wifi[j]["encryption"] + else + scan[k]["encrypt"] = wifi[j]["ekey"] + scan[k]["encryption"] = wifi[j]["encryption"] + end +end + +function get_networks() + luci.util.exec("/usr/lib/hotspot/getssid.sh") + file = io.open("/tmp/ssidlist", "r") + if file == nil then + numnet = 0 + return + end + i = 0 + cont = 2 + line = file:read("*line") + repeat + if line == nil then + cont = 0 + else + s, e = line:find("Cell ") + if s ~= nil then + cont = 1 + essid=nil + i = i + 1 + wifi[i] = {} + encryption = "none" + repeat + line = file:read("*line") + if line == nil then + cont = 0 + break + else + s, e = line:find("Cell ") + if s ~= nil then + break + else + s, e = line:find("ESSID:") + if s ~= nil then + ee = line:len() + essid = trim(line:sub(e+3, ee-1)) + end + s, e = line:find("Mode:") + if s ~= nil then + line1 = trim(line:sub(e+1)) + bs, be = line1:find(" ", 1) + mode = trim(line1:sub(1, bs)) + cs, ce = line1:find(" ") + line2 = trim(line1:sub(ce+1)) + s, e = line2:find("Channel:") + channel = trim(line2:sub(e+2)) + end + s, e = line:find("Signal:") + if s ~= nil then + line1 = trim(line:sub(e+1)) + bs, be = line1:find(" ", 1) + signal = trim(line1:sub(1, bs)) + cs, ce = line1:find(" ") + line2 = trim(line1:sub(ce+1)) + s, e = line2:find("Quality:") + cs, ce = line2:find("/", e) + quality = trim(line2:sub(e+1, ce-1)) + quality_max = trim(line2:sub(ce+1)) + end + s, e = line:find("Encryption:") + if s ~= nil then + cs, ce = line:find("WEP") + if cs == nil then + encrypt = trim(line:sub(e+2)) + s, e = encrypt:find("none") + if s ~= nil then + encryption = "none" + else + s, e = encrypt:find("mixed") + if s ~= nil then + encryption = "psk-mixed" + else + s, e = encrypt:find("WPA2") + if s ~= nil then + encryption = "psk2" + else + encryption = "psk" + end + end + end + else + cont = 2 + i = i - 1 + break + end + end + end + end + until 1==0 + else + line = file:read("*line") + end + end + if cont < 2 then + if i > 0 then + if essid ~= nil and mode == "Master" then + wifi[i]["essid"] = essid + wifi[i]["channel"] = channel + wifi[i]["signal"] = signal + wifi[i]["quality"] = quality + wifi[i]["quality_max"] = quality_max + wifi[i]["ekey"] = encrypt + wifi[i]["encryption"] = encryption + end + end + end + if cont == 0 then + break + end + cont = 2 + until 1==0 + file:close() + + k = 0 + if i > 0 then + for j=1, i do + if wifi[j]["essid"] ~= nil and tonumber(wifi[j]["quality"]) > 0 then + if k < 1 then + k = k+1 + scan[k] = {} + build_scan(j, k) + else + flag = 0 + for l=1, k do + if wifi[j]["essid"] == scan[l]["essid"] and wifi[j]["channel"] == scan[l]["channel"] and wifi[j]["ekey"] == scan[l]["ekey"] then + qc = tonumber(wifi[j]["quality"]) + qm = tonumber(wifi[j]["quality_max"]) + qual = math.floor((100 / qm) * qc) + if qual > scan[l]["quality"] then + build_scan(j, l) + end + flag = 1 + break + end + end + if flag == 0 then + k = k+1 + scan[k] = {} + build_scan(j, k) + end + end + end + end + scan = quicksort(scan, 1, k) + end + numnet = k +end + +-%> +<%+header%> + + + + +
                + +
                +

                <%:Wifi Hotspot Management%>

                +
                <%:Manage Your Wifi Hotspot Connections%>
                + + + +
                + + + + + + +
                  +  
                + + + + + +
                 
                + + + + + + + +
                <%:Reconnection Attempts on Dropped Connection%> + + +  
                + + + + + + + + + + + +
                 
                + + + + + + + +
                <%:Wifi Radio Frequency :%>
                + +  
                + + + + + +
                 
                + + + + + + + +
                <%:Current Wifi Hotspot : %>
                  + + + + + + + +
                  <%:Encryption : %>
                     
                    + + + + + +
                     
                    + + + + + + + + + +
                    <%:In Range%>
                    <%:Wifi Hotspot Networks%>
                     
                    + +
                      +
                    + +
                      +
                    •  
                    • +
                    • <%:No Wifi Hotspot Networks Selected%>
                    • +
                    •  
                    • +
                    + + + + + +
                     
                    + + + + + + + +
                    <%:Hotspot Name :%>
                       
                      + + + + + + + +
                      <%:Encrypted :%>
                         
                        + + + + + + + + +
                        <%:Key :%>
                           
                          + + + + + +
                           
                          + + + + + + + + + +
                           
                          + + + + + +
                           
                          + + <% get_networks() %> + + + + + +
                          <%:Available Networks : %><%=numnet%>
                          + <% if numnet > 0 then + for m=1, numnet do + data = scan[m]["essid"] .. "|" .. scan[m]["encryption"] + %> + + + + + + +
                          + +
                          + <%=scan[m]["quality"]%>% +
                          +
                          + <%=scan[m]["essid"]%>
                          + Channel: <%=scan[m]["channel"]%> | + Encryption: <%=scan[m]["encrypt"]%> +
                          + +
                          + <% end + end %> +
                          + +
                          +
                          + + + +
                          + + +<%+footer%> diff --git a/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/lua/luci/view/wifilog/wifilog.htm b/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/lua/luci/view/wifilog/wifilog.htm new file mode 100644 index 0000000..48bdb5f --- /dev/null +++ b/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/lua/luci/view/wifilog/wifilog.htm @@ -0,0 +1,32 @@ +<%+header%> + + + + +
                          +

                          <%:Hotspot Logging%>

                          +
                          +
                          + <%:Log%> + + + + +
                          + +
                          + +
                          + +
                          + +<%+footer%> \ No newline at end of file diff --git a/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/rooter/log/wifilogger.sh b/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/rooter/log/wifilogger.sh new file mode 100644 index 0000000..c9b7bc2 --- /dev/null +++ b/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/rooter/log/wifilogger.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +ROOTER=/usr/lib/rooter + +TEXT=$1 +DATE=$(date +%c) + +modlog="/tmp/wifilog.log" +tmplog="/tmp/twifilog" + +echo "$DATE : $TEXT" >> $modlog +lua $ROOTER/log/mrotate.lua $modlog $tmplog +mv $tmplog $modlog + diff --git a/rooter/0optionalapps/luci-app-hotspot/files/usr/sbin/wifilog b/rooter/0optionalapps/luci-app-hotspot/files/usr/sbin/wifilog new file mode 100644 index 0000000..962b1ce --- /dev/null +++ b/rooter/0optionalapps/luci-app-hotspot/files/usr/sbin/wifilog @@ -0,0 +1,7 @@ +#!/bin/sh + +name=$1 +text=$2 + +logger -t "$name" "$text" +/usr/lib/rooter/log/wifilogger.sh "$name $text" \ No newline at end of file diff --git a/rooter/0optionalapps/luci-app-hotspot/files/www/luci-static/resources/icons/encryption.png b/rooter/0optionalapps/luci-app-hotspot/files/www/luci-static/resources/icons/encryption.png new file mode 100644 index 0000000..b45e285 Binary files /dev/null and b/rooter/0optionalapps/luci-app-hotspot/files/www/luci-static/resources/icons/encryption.png differ diff --git a/rooter/0optionalapps/luci-app-iperf/Makefile b/rooter/0optionalapps/luci-app-iperf/Makefile new file mode 100644 index 0000000..264060e --- /dev/null +++ b/rooter/0optionalapps/luci-app-iperf/Makefile @@ -0,0 +1,34 @@ +#Owned by DairyMan@Whirlpool +# +#Copyright GNU act. +include $(TOPDIR)/rules.mk + +PKG_NAME:=luci-app-iperf +PKG_VERSION:=1.000 +PKG_RELEASE:=1 + +PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool +include $(INCLUDE_DIR)/package.mk + +define Package/luci-app-iperf + SECTION:=luci + CATEGORY:=LuCI + DEPENDS:=+iperf3-ssl + SUBMENU:=3. Applications + TITLE:=support for Iperf + PKGARCH:=all +endef + +define Package/luci-app-iperf/description + Helper scripts to enable Iperf +endef + + +define Build/Compile +endef + +define Package/luci-app-iperf/install + $(CP) ./files/* $(1)/ +endef + +$(eval $(call BuildPackage,luci-app-iperf)) diff --git a/rooter/0optionalapps/luci-app-iperf/files/etc/config/iperf b/rooter/0optionalapps/luci-app-iperf/files/etc/config/iperf new file mode 100644 index 0000000..911c3a1 --- /dev/null +++ b/rooter/0optionalapps/luci-app-iperf/files/etc/config/iperf @@ -0,0 +1,96 @@ +config server 'bouygues' + option host 'bouygues.iperf.fr' + option ipv4 '1' + option ipv6 '1' + option speed '10000' + option ports '5200,5201,5202,5203,5204,5205,5206,5207,5208,5209' + option tcp '1' + option udp '0' + option location 'Europe' + +config server 'online_ipv4' + option host 'ping.online.net' + option ipv4 '1' + option ipv6 '0' + option speed '10000' + option ports '5200,5201,5202,5203,5204,5205,5206,5207,5208,5209' + option tcp '1' + option udp '1' + option location 'Europe' + +config server 'online_ipv6' + option host 'ping.online.net' + option ipv4 '0' + option ipv6 '1' + option speed '10000' + option ports '5200,5201,5202,5203,5204,5205,5206,5207,5208,5209' + option tcp '1' + option udp '1' + option location 'Europe' + +config server 'serverius' + option host 'speedtest.serverius.net' + option ipv4 '1' + option ipv6 '1' + option speed '10000' + option ports '5002' + option tcp '1' + option udp '1' + option location 'Europe' + +config server 'eenet' + option host 'iperf.eenet.ee' + option ipv4 '1' + option ipv6 '0' + option ports '5201' + option tcp '1' + option udp '1' + option location 'Europe' + +config server 'volia' + option host 'iperf.volia.net' + option ipv4 '1' + option ipv6 '0' + option ports '5201' + option tcp '1' + option udp '1' + option location 'Europe' + +config server 'it_north' + option host 'iperf.it-north.net' + option ipv4 '1' + option ipv6 '0' + option speed '1000' + option ports '5200,5201,5202,5203,5204,5205,5206,5207,5208,5209' + option tcp '1' + option udp '1' + option location 'Asia' + +config server 'biznet' + option host 'iperf.biznetnetworkds.com' + option ipv4 '1' + option ipv6 '1' + option speed '1000' + option ports '5201,5202,5203' + option tcp '1' + option udp '0' + option location 'Asia' + +config server 'scottlinux' + option host 'iperf.scottlinux.com' + option ipv4 '1' + option ipv6 '1' + option speed '1000' + option ports '5201' + option tcp '1' + option udp '1' + option location 'America' + +config server 'he' + option host 'iperf.he.net' + option ipv4 '1' + option ipv6 '1' + option ports '5201' + option tcp '1' + option udp '1' + option location 'America' diff --git a/rooter/0optionalapps/luci-app-iperf/files/usr/lib/lua/luci/controller/iperf.lua b/rooter/0optionalapps/luci-app-iperf/files/usr/lib/lua/luci/controller/iperf.lua new file mode 100644 index 0000000..9d3e197 --- /dev/null +++ b/rooter/0optionalapps/luci-app-iperf/files/usr/lib/lua/luci/controller/iperf.lua @@ -0,0 +1,56 @@ +local uci = luci.model.uci.cursor() +local ut = require "luci.util" + +module("luci.controller.iperf", package.seeall) + +function index() + --entry({"admin", "openmptcprouter", "iperf"}, cbi("iperf"), _("iperf")) + entry({"admin", "services", "iperf"}, alias("admin", "services", "iperf", "test"), _("iPerf Speed Test"),72) + entry({"admin", "services", "iperf", "test"}, template("iperf/test"), nil,1) + entry({"admin", "services", "iperf", "run_test"}, post("run_test")).leaf = true +end + +function run_test(server,proto,mode,updown,omit,parallel,transmit,bitrate) + luci.http.prepare_content("text/plain") + local iperf + local addr = uci:get("iperf",server,"host") + local ports = uci:get("iperf",server,"ports") + local user = uci:get("iperf",server,"user") or "" + local password = uci:get("iperf",server,"password") or "" + local key = uci:get("iperf",server,"key") or "" + local options = "" + if user ~= "" and password ~= "" and key ~= "" then + luci.sys.call("echo " .. key .. " | base64 -d > /tmp/iperf.pem") + options = options .. " --username " .. user .. " --rsa-public-key-path /tmp/iperf.pem" + end + if mode == "udp" then + options = options .. " -u -b " .. bitrate + end + if updown ~= "upload" then + options = options .. " -R" + end + local ipv = "4" + if proto == "ipv6" then + local ipv = "6" + end + + local t={} + for pt in ports:gmatch("([^,%s]+)") do + table.insert(t,pt) + end + local port = t[ math.random( #t ) ] + if password ~= "" then + iperf = io.popen("omr-iperf -P %s -%s -O %s -t %s -J -Z %s" % {parallel,ipv,omit,transmit,options}) + else + iperf = io.popen("iperf3 -c %s -P %s -%s -p %s -O %s -t %s -J -Z %s" % {ut.shellquote(addr),parallel,ipv,port,omit,transmit,options}) + end + if iperf then + while true do + local ln = iperf:read("*l") + if not ln then break end + luci.http.write(ln) + luci.http.write("\n") + end + end + return +end \ No newline at end of file diff --git a/rooter/0optionalapps/luci-app-iperf/files/usr/lib/lua/luci/view/iperf/test.htm b/rooter/0optionalapps/luci-app-iperf/files/usr/lib/lua/luci/view/iperf/test.htm new file mode 100644 index 0000000..03d0150 --- /dev/null +++ b/rooter/0optionalapps/luci-app-iperf/files/usr/lib/lua/luci/view/iperf/test.htm @@ -0,0 +1,185 @@ +<%+header%> + +<% + local uci = require("luci.model.uci").cursor() +%> + + + + +<% if stderr and #stderr > 0 then %>
                          <%=pcdata(stderr)%>
                          <% end %> +
                          +
                          +

                          <%:iPerf Speed Test%>

                          +
                          <%:Test Internet speeds using iPerf.%>
                          +
                          + <%:Settings%> +
                          +
                          + +
                          + +
                          +
                          +
                          + +
                          + +
                          +
                          +
                          + +
                          + +
                          +
                          + <%:0 for unlimited.%> +
                          +
                          +
                          + +
                          + +
                          + +
                          +
                          +
                          + +
                          + +
                          +
                          +
                          + +
                          + +
                          +
                          + <%:Server VPS IP is bypassed, so this will test only default route speed.%> +
                          +
                          +
                          + + + +
                          +
                          +
                          + +
                          + + +
                          +<%+footer%> diff --git a/rooter/0optionalapps/luci-app-iperf/files/usr/share/luci/menu.d/luci-app-iperf.json b/rooter/0optionalapps/luci-app-iperf/files/usr/share/luci/menu.d/luci-app-iperf.json new file mode 100644 index 0000000..dd6151e --- /dev/null +++ b/rooter/0optionalapps/luci-app-iperf/files/usr/share/luci/menu.d/luci-app-iperf.json @@ -0,0 +1,13 @@ +{ + "admin/services/iperf": { + "title": "iPerf", + "order": 10, + "action": { + "type": "template", + "path": "iperf/test" + }, + "depends": { + "acl": [ "luci-app-iperf" ] + } + } +} diff --git a/rooter/0optionalapps/luci-app-iperf/files/usr/share/rpcd/acl.d/luci-app-iperf.json b/rooter/0optionalapps/luci-app-iperf/files/usr/share/rpcd/acl.d/luci-app-iperf.json new file mode 100644 index 0000000..c851828 --- /dev/null +++ b/rooter/0optionalapps/luci-app-iperf/files/usr/share/rpcd/acl.d/luci-app-iperf.json @@ -0,0 +1,11 @@ +{ + "luci-app-iperf": { + "description": "Grant UCI access for luci-app-iperf", + "read": { + "uci": [ "iperf" ] + }, + "write": { + "uci": [ "iperf" ] + } + } +} \ No newline at end of file diff --git a/rooter/0optionalapps/luci-app-rootervpn/Makefile b/rooter/0optionalapps/luci-app-rootervpn/Makefile new file mode 100644 index 0000000..46f6d81 --- /dev/null +++ b/rooter/0optionalapps/luci-app-rootervpn/Makefile @@ -0,0 +1,34 @@ +#Owned by DairyMan@Whirlpool +# +#Copyright GNU act. +include $(TOPDIR)/rules.mk + +PKG_NAME:=luci-app-rootervpn +PKG_VERSION:=1.000 +PKG_RELEASE:=1 + +PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool +include $(INCLUDE_DIR)/package.mk + +define Package/luci-app-rootervpn + SECTION:=luci + CATEGORY:=LuCI + DEPENDS:=+openvpn-easy-rsa +openvpn-openssl +eoip + SUBMENU:=3. Applications + TITLE:=support for modified OpenVPN + PKGARCH:=all +endef + +define Package/luci-app-rootervpn/description + Helper scripts to enable OpenVPN support +endef + + +define Build/Compile +endef + +define Package/luci-app-rootervpn/install + $(CP) ./files/* $(1)/ +endef + +$(eval $(call BuildPackage,luci-app-rootervpn)) diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/etc/config/openvpn_recipes b/rooter/0optionalapps/luci-app-rootervpn/files/etc/config/openvpn_recipes new file mode 100644 index 0000000..68b6274 --- /dev/null +++ b/rooter/0optionalapps/luci-app-rootervpn/files/etc/config/openvpn_recipes @@ -0,0 +1,293 @@ +# +# Routed point-to-point server +# +config openvpn_recipe b_server_tun_ptp + option _description "Basic point-to-point TUN VPN Server" + option _role "server" + option dev "tun-server" + option ifconfig "10.0.0.1 10.0.0.2" + option secret "shared-secret.key" + option keepalive "10 60" + option comp_lzo "yes" + option verb "3" + option mssfix "1420" + option topology "p2p" + +# +# Routed point-to-point client +# +config openvpn_recipe b_client_tun_ptp + option _description "Basic point-to-point TUN VPN Client" + option _role "client" + option client "1" + option dev "tun0" + list remote "vpnserver.example.org" + option ifconfig "10.0.0.2 10.0.0.1" + option secret "shared-secret.key" + option nobind "1" + option comp_lzo "yes" + option verb "3" + +# +# Routed multi-client server +# +config openvpn_recipe a_server_tun + option _description "Basic TUN VPN Server" + option _role "server" + option dev "tun-server" + option topology "subnet" + option port "1194" + option proto "udp" + option server "10.0.100.0 255.255.255.0" + option ca "/etc/openvpn/placeholder/placeholder.file" + option cert "/etc/openvpn/placeholder/placeholder.file" + option key "/etc/openvpn/placeholder/placeholder.file" + option dh "/etc/openvpn/placeholder/placeholder.file" + option keepalive "10 60" + option comp_lzo "yes" + option verb "3" + option mssfix "1420" + +# +# Routed client +# +config openvpn_recipe a_client_tun + option _description "Basic TUN VPN Client" + option _role "client" + option client "1" + option dev "tun0" + option proto "udp" + list remote "vpnserver.example.org" + option remote_cert_tls "server" + option comp_lzo "yes" + option nobind "1" + option persist_key "1" + option persist_tun "1" + option verb "3" + option reneg_sec "0" + option float "1" + option auth_user_pass "/etc/openvpn/placeholder/placeholder.file" + option ca "/etc/openvpn/placeholder/placeholder.file" + option cert "/etc/openvpn/placeholder/placeholder.file" + option key "/etc/openvpn/placeholder/placeholder.file" + +# +# Multi-client ethernet bridge server +# +config openvpn_recipe c_server_tap_bridge + option _description "Basic Server-Bridge TAP VPN Server" + option _role "server" + option dev "tap-server" + option port "1194" + option server_bridge "192.168.100.1 255.255.255.0 192.168.100.128 192.168.100.254" + option ca "/etc/openvpn/placeholder/placeholder.file" + option cert "/etc/openvpn/placeholder/placeholder.file" + option key "/etc/openvpn/placeholder/placeholder.file" + option dh "/etc/openvpn/placeholder/placeholder.file" + option keepalive "10 60" + option comp_lzo "yes" + option verb "3" + option mssfix "1420" + +# +# Ethernet bridge client +# +config openvpn_recipe c_client_tap_bridge + option _description "Basic Server-Bridge TAP VPN Client" + option _role "client" + option client "1" + option dev "tap0" + list remote "vpnserver.example.org" + option auth_user_pass "/etc/openvpn/placeholder/placeholder.file" + option ca "/etc/openvpn/placeholder/placeholder.file" + option cert "/etc/openvpn/placeholder/placeholder.file" + option key "/etc/openvpn/placeholder/placeholder.file" + option remote_cert_tls "server" + option comp_lzo "yes" + option nobind "1" + option persist_key "1" + option verb "3" + option reneg_sec "0" + option float "1" + +# +# OVPN Client +# +config openvpn_recipe d_ovpn_client + option _description "Client using OVPN File" + option _role "client" + option config "/etc/openvpn/placeholder/placeholder.file" + option auth_user_pass "/etc/openvpn/placeholder/placeholder.file" + +# +# NordVpn +# +config openvpn_recipe e_nordvpn_client_tun + option _description "Predefined Client for NordVPN" + option _role "client" + option config "/etc/openvpn/placeholder/placeholder.file" + option auth_user_pass "/etc/openvpn/placeholder/placeholder.file" + +# +# Private Internet Access Client +# +config openvpn_recipe e_pia_client_tun + option _description "Predefined Client for Private Internet Access" + option _role "client" + option client "1" + option dev "tun0" + option proto "udp" + list remote "us-example.privateinternetaccess.com" + option port "1198" + option resolv_retry "infinite" + option nobind "1" + option persist_key "1" + option persist_tun "1" + option cipher "aes-128-cbc" + option auth "sha1" + option tls_client "1" + option remote_cert_tls "server" + option auth_user_pass "/etc/openvpn/placeholder/placeholder.file" + option comp_lzo "yes" + option verb "1" + option reneg_sec "0" + option crl_verify "/etc/openvpn/pia/crl.rsa.2048.pem" + option ca "/etc/openvpn/pia/ca.rsa.2048.crt" + option disable_occ "1" + +# +# Windscribe +# +config openvpn_recipe e_windscribe_client_tun + option _description "Predefined Client for Windscribe" + option _role "client" + option client "1" + option dev "tun0" + option proto "udp" + list remote "example.windscribe.com" + option port "443" + option resolv_retry "infinite" + option nobind "1" + option persist_key "1" + option persist_tun "1" + option cipher "aes-256-cbc" + option auth "sha512" + option tls_client "1" + option remote_cert_tls "server" + option key_direction "1" + option auth_user_pass "/etc/openvpn/placeholder/placeholder.file" + option comp_lzo "yes" + option verb "2" + option reneg_sec "432000" + option tls_auth "/etc/openvpn/windscribe/ta.key" + option ca "/etc/openvpn/windscribe/ca.crt" + option redirect_gateway "def1" + +# +# ProtonVPN +# +config openvpn_recipe e_proton_client_tun + option _description "Predefined Client for ProtonVPN" + option _role "client" + option client "1" + option dev "tun0" + option proto "udp" + list remote "example.protonvpn.com" + option port "1194" + option resolv_retry "infinite" + option nobind "1" + option persist_key "1" + option persist_tun "1" + option cipher "aes-256-cbc" + option auth "sha512" + option tls_client "1" + option remote_cert_tls "server" + option key_direction "1" + option auth_user_pass "/etc/openvpn/placeholder/placeholder.file" + option comp_lzo "yes" + option verb "3" + option reneg_sec "0" + option tls_auth "/etc/openvpn/placeholder/placeholder.file" + option ca "/etc/openvpn/placeholder/placeholder.file" + option redirect_gateway "def1" + +# +# Mullvad +# +config openvpn_recipe e_mullvad_client_tun + option _description "Predefined Client for Mullvad" + option _role "client" + option client "1" + option dev "tun0" + option proto "udp" + list remote "example.mullvad.net" + option port "1194" + option resolv_retry "infinite" + option nobind "1" + option persist_key "1" + option persist_tun "1" + option cipher "aes-256-cbc" + option tls_client "1" + option remote_cert_tls "server" + option auth_user_pass "/etc/openvpn/placeholder/placeholder.file" + option comp_lzo "yes" + option verb "3" + option ca "/etc/openvpn/mullvad/mullvad_ca.crt" + option crl_verify "/etc/openvpn/mullvad/mullvad_crl.pem" + option redirect_gateway "def1" + +# +# AirVPN +# +config openvpn_recipe e_airvpn_client_tun + option _description "Predefined Client for AirVPN" + option _role "client" + option client "1" + option dev "tun0" + option proto "udp" + list remote "example.vpn.airdns.org" + option port "443" + option resolv_retry "infinite" + option nobind "1" + option persist_key "1" + option persist_tun "1" + option cipher "aes-256-cbc" + option route_delay "5" + option explicit_exit_notify "5" + option tls_client "1" + option remote_cert_tls "server" + option auth_user_pass "/etc/openvpn/placeholder/placeholder.file" + option comp_lzo "no" + option verb "3" + option key_direction "1" + option ca "/etc/openvpn/airvpn/ca.crt" + option cert "/etc/openvpn/airvpn/client.crt" + option key "/etc/openvpn/airvpn/client.key" + option tls_auth "/etc/openvpn/airvpn/ta.key" + +# +# Tunnelbear +# +config openvpn_recipe e_tunnelbear_client_tun + option _description "Predefined Client for Tunnelbear" + option _role "client" + option dev "tun0" + option proto "udp" + option port "443" + option client "1" + option nobind "1" + option persist_key "1" + option persist_tun "1" + option remote_cert_tls "server" + option reneg_sec "0" + option verb "1" + option comp_lzo "yes" + option auth_user_pass "/etc/openvpn/placeholder/placeholder.file" + option ca "/etc/openvpn/placeholder/placeholder.file" + option cert "/etc/openvpn/placeholder/placeholder.file" + option key "/etc/openvpn/placeholder/placeholder.file" + option remote "example.tunnelbear-ios.com" + option auth "SHA256" + option keysize "256" + option keep_alive "10 30" + option redirect_gateway "def1" diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/etc/init.d/openvpn b/rooter/0optionalapps/luci-app-rootervpn/files/etc/init.d/openvpn new file mode 100644 index 0000000..543cdf1 --- /dev/null +++ b/rooter/0optionalapps/luci-app-rootervpn/files/etc/init.d/openvpn @@ -0,0 +1,194 @@ +#!/bin/sh /etc/rc.common +# Copyright (C) 2008-2013 OpenWrt.org +# Copyright (C) 2008 Jo-Philipp Wich +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. + +START=90 +STOP=10 + +USE_PROCD=1 +PROG=/usr/sbin/openvpn + +LIST_SEP=" +" +log() { + logger -t "OpenVpn init.d" "$@" +} + +if [ -e /tmp/openvpnboot ]; then + if [ -z "$1" ]; then + return + fi +fi + +UCI_STARTED= +UCI_DISABLED= + +append_param() { + local s="$1" + local v="$2" + case "$v" in + *_*_*_*) v=${v%%_*}-${v#*_}; v=${v%%_*}-${v#*_}; v=${v%%_*}-${v#*_} ;; + *_*_*) v=${v%%_*}-${v#*_}; v=${v%%_*}-${v#*_} ;; + *_*) v=${v%%_*}-${v#*_} ;; + esac + echo -n "$v" >> "/var/etc/openvpn-$s.conf" + return 0 +} + +append_bools() { + local p; local v; local s="$1"; shift + for p in $*; do + config_get_bool v "$s" "$p" + [ "$v" = 1 ] && append_param "$s" "$p" && echo >> "/var/etc/openvpn-$s.conf" + done +} + +append_params() { + local p; local v; local s="$1"; shift + for p in $*; do + config_get v "$s" "$p" + IFS="$LIST_SEP" + for v in $v; do + [ -n "$v" ] && [ "$p" != "push" ] && append_param "$s" "$p" && echo " $v" >> "/var/etc/openvpn-$s.conf" + [ -n "$v" ] && [ "$p" == "push" ] && append_param "$s" "$p" && echo " \"$v\"" >> "/var/etc/openvpn-$s.conf" + done + unset IFS + done +} + +append_list() { + local p; local v; local s="$1"; shift + + list_cb_append() { + v="${v}:$1" + } + + for p in $*; do + unset v + config_list_foreach "$s" "$p" list_cb_append + [ -n "$v" ] && append_param "$s" "$p" && echo " ${v:1}" >> "/var/etc/openvpn-$s.conf" + done +} + +section_enabled() { + config_get_bool enable "$1" 'enable' 0 + config_get_bool enabled "$1" 'enabled' 0 + [ $enable -gt 0 ] || [ $enabled -gt 0 ] +} + +openvpn_add_instance() { + local name="$1" + local dir="$2" + local conf="$3" + + uci set openvpn.$1.laststart="$(date +%s)" + uci commit openvpn + + procd_open_instance "$name" + procd_set_param command "$PROG" \ + --syslog "openvpn($name)" \ + --status "/var/run/openvpn.$name.status" \ + --cd "$dir" \ + --config "$conf" + procd_set_param file "$dir/$conf" + procd_set_param term_timeout 15 + procd_set_param respawn + procd_append_param respawn 3600 + procd_append_param respawn 5 + procd_append_param respawn -1 + procd_close_instance +} + +start_instance() { + local s="$1" + + config_get config "$s" config + config="${config:+$(readlink -f "$config")}" + + log "start instance $s" + if [ ! -e /tmp/openvpnboot ]; then + config_get_bool bootstart "$s" 'bootstart' 0 + if [ $bootstart -eq 0 ]; then + append UCI_DISABLED "$config" "$LIST_SEP" + return 1 + fi + fi + + section_enabled "$s" || { + append UCI_DISABLED "$config" "$LIST_SEP" + return 1 + } + + [ ! -d "/var/run" ] && mkdir -p "/var/run" + + if [ ! -z "$config" ]; then + append UCI_STARTED "$config" "$LIST_SEP" + openvpn_add_instance "$s" "${config%/*}" "$config" + return + fi + + [ ! -d "/var/etc" ] && mkdir -p "/var/etc" + [ -f "/var/etc/openvpn-$s.conf" ] && rm "/var/etc/openvpn-$s.conf" + + append_bools "$s" $OPENVPN_BOOLS + append_params "$s" $OPENVPN_PARAMS + append_list "$s" $OPENVPN_LIST + + openvpn_add_instance "$s" "/var/etc" "openvpn-$s.conf" + sleep 5 +} + +start_service() { + local instance="$1" + local instance_found=0 + + /etc/init.d/rootervpn start + + config_cb() { + local type="$1" + local name="$2" + if [ "$type" = "openvpn" ]; then + if [ -n "$instance" -a "$instance" = "$name" ]; then + instance_found=1 + fi + fi + } + + . /usr/share/openvpn/openvpn.options + config_load 'openvpn' + + if [ -n "$instance" ]; then + [ "$instance_found" -gt 0 ] || return + start_instance "$instance" + else + config_foreach start_instance 'openvpn' $1 + + + local path name + for path in /etc/openvpn/*.conf; do + if [ -f "$path" ]; then + name="${path##*/}"; name="${name%.conf}" + + # don't start configs again that are already started by uci + if echo "$UCI_STARTED" | grep -qxF "$path"; then + continue + + # don't start configs which are set to disabled in uci + elif echo "$UCI_DISABLED" | grep -qxF "$path"; then + logger -t openvpn "$name.conf is disabled in /etc/config/openvpn" + continue + fi + + openvpn_add_instance "$name" "${path%/*}" "$path" + + fi + done + fi + echo "0" > /tmp/openvpnboot +} + +service_triggers() { + procd_add_reload_trigger openvpn +} diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/etc/init.d/rootervpn b/rooter/0optionalapps/luci-app-rootervpn/files/etc/init.d/rootervpn new file mode 100644 index 0000000..eb83a60 --- /dev/null +++ b/rooter/0optionalapps/luci-app-rootervpn/files/etc/init.d/rootervpn @@ -0,0 +1,183 @@ +#!/bin/sh /etc/rc.common +# Copyright (C) 2006 OpenWrt.org + +START=60 + +log() { + logger -t "OpenVPN : " "$@" +} + +check_config () { + log "Check Client Interfaces" + CHANGE="0" + WW=$(uci get network.VPN) + if [ -z $WW ]; then + uci set network.VPN=interface + uci set network.VPN.proto="none" + uci set network.VPN.ifname="tun0" + uci set network.VPN.auto="0" + CHANGE="1" + fi + WW=$(uci get network.VPNS) + if [ -z $WW ]; then + uci set network.VPNS=interface + uci set network.VPNS.proto="none" + uci set network.VPNS.ifname="tun-server" + uci set network.VPNS.auto="0" + CHANGE="1" + fi + WW=$(uci get network.TAP) + if [ -z $WW ]; then + uci set network.TAP=interface + uci set network.TAP.proto="none" + uci set network.TAP.ifname="tap0" + uci set network.TAP.auto="1" + LANIF=$(uci get network.lan.ifname) + TAP0=$(echo $LANIF | grep "tap0") + if [ -z "$TAP0" ]; then + uci set network.lan.ifname="$(uci get network.lan.ifname) tap0" + fi + CHANGE="1" + fi + WW=$(uci get network.TAPS) + if [ -z $WW ]; then + uci set network.TAPS=interface + uci set network.TAPS.proto="none" + uci set network.TAPS.ifname="tap-server" + uci set network.TAPS.auto="0" + LANIF=$(uci get network.lan.ifname) + TAP1=$(echo $LANIF | grep "tap-server") + if [ -z "$TAP1" ]; then + uci set network.lan.ifname="$(uci get network.lan.ifname) tap-server" + fi + CHANGE="1" + fi + if [ $CHANGE = "1" ]; then + uci commit network + /etc/init.d/network restart + fi + + CHANGE="0" + WW=$(uci get firewall.vpnzone) + if [ -z $WW ]; then + uci set firewall.vpnzone=zone + uci set firewall.vpnzone.name="VPN" + uci set firewall.vpnzone.forward="REJECT" + uci set firewall.vpnzone.output="ACCEPT" + uci set firewall.vpnzone.network="VPN" + uci set firewall.vpnzone.input="REJECT" + uci set firewall.vpnzone.masq="1" + uci set firewall.vpnzone.mtu_fix="1" + uci set firewall.vpnforward=forwarding + uci set firewall.vpnforward.dest="VPN" + uci set firewall.vpnforward.src="lan" + CHANGE="1" + fi + WW=$(uci get firewall.vpnzones) + if [ -z $WW ]; then + uci set firewall.vpnzones=zone + uci set firewall.vpnzones.name="VPNS" + uci set firewall.vpnzones.forward="REJECT" + uci set firewall.vpnzones.output="ACCEPT" + uci set firewall.vpnzones.network="VPNS" + uci set firewall.vpnzones.input="ACCEPT" + uci set firewall.vpnzones.masq="1" + uci set firewall.vpnzones.mtu_fix="1" + uci set firewall.vpnforwards=forwarding + uci set firewall.vpnforwards.dest="VPNS" + uci set firewall.vpnforwards.src="lan" + CHANGE="1" + fi + if [ $CHANGE = "1" ]; then + uci commit firewall + /etc/init.d/firewall restart + fi + WW=$(uci get openvpn.settings) + if [ -z $WW ]; then + uci set openvpn.settings=settings + uci set openvpn.settings.vpn2lan="0" + uci set openvpn.settings.vpns2lan="0" + uci set openvpn.settings.vpn2wan="0" + uci set openvpn.settings.country="CA" + uci set openvpn.settings.city="Abbotsford" + uci set openvpn.settings.organ="ROOter" + uci set openvpn.settings.days="3650" + uci set openvpn.settings.nclient='1' + uci commit openvpn + fi +} + +checkserver() { + log "Check Server Interfaces" + local s=$1 + if [ -z $s ]; then + return + fi + local SERVER="0" + local config=$(uci get openvpn.$s.config) + if [ ! -z $config ]; then + return + fi + local client=$(uci get openvpn.$s.client) + if [ -z $client ]; then + SERVER="1" + else + if [ $client = "0" ]; then + SERVER="1" + fi + fi + + if [ $SERVER = "1" ]; then + port=$(uci get openvpn.$s.port) + if [ -z $port ]; then + PORT="1194" + else + PORT=$port + fi + # look for rule for this port + INB="inbound"$PORT + RULE=$(uci get firewall.$INB) + if [ -z $RULE ]; then + uci set firewall.$INB=rule + uci set firewall.$INB.name=$INB + uci set firewall.$INB.target=ACCEPT + uci set firewall.$INB.src=* + uci set firewall.$INB.proto=udp + uci set firewall.$INB.dest_port=$PORT + uci commit firewall + /etc/init.d/firewall reload + fi + DEV=$(uci get openvpn.$s.dev) + if [ $DEV = "tun0" ]; then + uci set openvpn.$s.dev="tun1" + uci commit openvpn + else + + if [ $DEV = "tap0" ]; then + uci set openvpn.$s.dev="tap1" + uci commit openvpn + fi + fi + else + DEV=$(uci get openvpn.$s.dev) + if [ $DEV = "tun1" ]; then + uci set openvpn.$s.dev="tun0" + uci commit openvpn + else + if [ $DEV = "tap1" ]; then + uci set openvpn.$s.dev="tap0" + uci commit openvpn + fi + fi + fi +} + +start() { + check_config + checkserver + + if [ -d /etc/luci-uploads ]; then + rm -rfv /etc/luci-uploads + fi + ln -s /etc/openvpn /etc/luci-uploads +} \ No newline at end of file diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/airvpn/ca.crt b/rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/airvpn/ca.crt new file mode 100644 index 0000000..cc37250 --- /dev/null +++ b/rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/airvpn/ca.crt @@ -0,0 +1,36 @@ +-----BEGIN CERTIFICATE----- +MIIGVDCCBDygAwIBAgIJAIzYQ+/kXyADMA0GCSqGSIb3DQEBBQUAMHkxCzAJBgNV +BAYTAklUMQswCQYDVQQIEwJJVDEQMA4GA1UEBxMHUGVydWdpYTETMBEGA1UEChMK +YWlydnBuLm9yZzEWMBQGA1UEAxMNYWlydnBuLm9yZyBDQTEeMBwGCSqGSIb3DQEJ +ARYPaW5mb0BhaXJ2cG4ub3JnMB4XDTE0MDQxMTEwMTU0NVoXDTI0MDQwODEwMTU0 +NVoweTELMAkGA1UEBhMCSVQxCzAJBgNVBAgTAklUMRAwDgYDVQQHEwdQZXJ1Z2lh +MRMwEQYDVQQKEwphaXJ2cG4ub3JnMRYwFAYDVQQDEw1haXJ2cG4ub3JnIENBMR4w +HAYJKoZIhvcNAQkBFg9pbmZvQGFpcnZwbi5vcmcwggIiMA0GCSqGSIb3DQEBAQUA +A4ICDwAwggIKAoICAQDGG3ZrJbP61PNjGc4mjTx0TLkUjP7IXZ3wnpPjwF/lwK9n +HgRqoPL0KY/ABJuzMViD8ChtwthNfc7PuJ7vSPtN84lSJ4JGmTxvZkNeLQLZsu1F +f88OcSpjW5ErBM05iVBeF8/ljwaajgFfbgop9W/UK5yMji4qgq5KHxxXqsB8R4rC +eFpWHoNTwFjvXhtVyMgXiT9XAh/vBYim021m8onio4K48q7YRZ4qU8gvE79h5M0g +miIlt6v1vaZskw9cqIBbCYefGMsvBRk2x824ChPf6FazMwAnQHsuBHt6eXAARvfF +DBDanzPHlRSiCP6Je6Vod/MPyepiTZgjgk2VxYUc1ohNxEEGzPGTayeNzLJUldou +P4B+tjJ0Xly30+wvlahADlqjtz3CGQmKMj7btZjd+Uo61B7gau5YiXR/IO7ZpFAC +PCZJSbrwFs6rt9Kewqk8zslfVIro8oDndXRkVsa/c8Qmd6ZE7V+oMGl2OggdWOLl +mDEjkytzx+Bw2sSSalJRAQmOQO8V0anOI6jGYLuU2jnFDsnqSHuwIK11xb6iHmh7 +ONsRLUtQ+d64TzB00w2M0fCvGqUIp0N+lf7nsZKsEcU08OoHQYUuwX75ZEOYNSZJ +rqAXohcXdVUHqgRlJRErfSkjcGMM0yqjHkvopcnBIRXKMYTDVXvzRJboyJiVpQID +AQABo4HeMIHbMB0GA1UdDgQWBBTlFdcTqJ4x49Ew1/Ef9OJj0lDIiDCBqwYDVR0j +BIGjMIGggBTlFdcTqJ4x49Ew1/Ef9OJj0lDIiKF9pHsweTELMAkGA1UEBhMCSVQx +CzAJBgNVBAgTAklUMRAwDgYDVQQHEwdQZXJ1Z2lhMRMwEQYDVQQKEwphaXJ2cG4u +b3JnMRYwFAYDVQQDEw1haXJ2cG4ub3JnIENBMR4wHAYJKoZIhvcNAQkBFg9pbmZv +QGFpcnZwbi5vcmeCCQCM2EPv5F8gAzAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEB +BQUAA4ICAQCUVAQteCtgNQiZMXV0wCdqivlxlCCuj5sD+XvEuoDqb7dH70u1KQ90 +OAbkeotHlIbqJU10xWtvHEjnXg8QG5VOzaWnWWev+ivdPCkGWe8E7C8shsr4WMlA +EF8PPRtzOwCKayxjR713x+Tc2Sb6/rDsXcY5LV6RNmE9HWBM6IoHdqruR8PHkYge +2CPXMuLByEADri6xmvussAjCWEDplJNY7tQsUGT7vjrwrNSNBx/SvxkXnWBj0wYa +EwNu43jrjcRfM/3eGcKDX3cQqTfRQd3j3OA7zmJOXPeExRUIWZTNCvQItGy1TJdw +JTphflw15Bui4l2mYfDqK08zm4aJODrCjoQnVVzM5uOzSTOjmneI6AHj3MjjL3A/ +CFA5PCSquBhUycF4UEVf3aPGiV0vAthCBUqM4eKE+rbjWPSaxKghVdr/S82o7Wzz +9mGwnOZDqWk+8AWSsGBjamMk3mNMR45E9FRfPF/dyjOSbVyyTsd1VzlTFEJa0wjB +l3yq3r3iZAM3UtevocAyTEAu0vDYBbS6TgWmWEDOizybB0hNrTx5u/SEI0Kwcthc +rilYxD+n4kmV7TvIR0ZSaYpgYALWQV27zOqY51Ol4UT98WCOokge9HdoFcGJU2Uj +5VneGp14/Oklh7y6BxxxGC3zNGjKGNQYuHGTIgw1DoASmRUdkPkn/w== +-----END CERTIFICATE----- \ No newline at end of file diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/airvpn/client.crt b/rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/airvpn/client.crt new file mode 100644 index 0000000..7c8e434 --- /dev/null +++ b/rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/airvpn/client.crt @@ -0,0 +1,38 @@ +-----BEGIN CERTIFICATE----- +MIIGnTCCBIWgAwIBAgIDAUsLMA0GCSqGSIb3DQEBBQUAMHkxCzAJBgNVBAYTAklU +MQswCQYDVQQIEwJJVDEQMA4GA1UEBxMHUGVydWdpYTETMBEGA1UEChMKYWlydnBu +Lm9yZzEWMBQGA1UEAxMNYWlydnBuLm9yZyBDQTEeMBwGCSqGSIb3DQEJARYPaW5m +b0BhaXJ2cG4ub3JnMB4XDTE2MDcyNjAwMTgxN1oXDTI2MDcyNDAwMTgxN1oweDEL +MAkGA1UEBhMCSVQxCzAJBgNVBAgTAklUMRAwDgYDVQQHEwdQZXJ1Z2lhMRMwEQYD +VQQKEwphaXJ2cG4ub3JnMRUwEwYDVQQDEwxhaXJ2cG4yNjE5MTQxHjAcBgkqhkiG +9w0BCQEWD2luZm9AYWlydnBuLm9yZzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCC +AgoCggIBANGrd9SWDf82gqtFjhtUfT3m43nozx+6I3/DYJplEk3K3xY/DU+0j9/Z +mftg6R4FJx562KHySqZfpTvPT99KjQMsyMW5iwGXlkbW3FdYn1GUNWQTzi+upzEA +eZqtBbPY5XQqX2aW03OdNJ5ycP63NqIkF34g9EAEOVodqC41wDJ0Fy/iak8htHRa ++tReSt/QxYVHT/n/pLgsrSZ00iJiSNEMRIdc7lmthj69C5HFi0tenWFgXbvn2vkJ +/m9FZq7tita9kuMsCPWWYA6qFuBlDhm62e/op5Z9TFXnp07PU4Y5xsPPuLVA/prL +bjuXSwhrHpkTCxxrSB+iNzcxRwKmDovdwauJ+ntqccpMx3i+xC4qWhxaVrqjgtYf +LWJxbyNDPDEsPACZDSSDu7lDciy/EJMW9ndS6A834dU8omx8LGpp7ZveEvBPcFRC +0XxoNiVyfcZG7HR9JtwNizNvndkcKJFoiYUkuZYofqU11VyGMG7Uf7GuksQsSgk1 +v78UCSq6sgm2ltb6maX44qAQ4cxxWpxCe9tFCV2I97EszKMxVlsbg9hUGbmlFG0/ +JH+/DfF26N/IHWR8hzgbfolj7wWLm5G7Xp8ft0JNCMiIpfqKdWCMq5MmPJ0thNpL +V7XEQ7zd1LWyNYR61bkiMAtpszs67NurV2OKfqYeGk07nV4Fu2Z7AgMBAAGjggEt +MIIBKTAJBgNVHRMEAjAAMC0GCWCGSAGG+EIBDQQgFh5FYXN5LVJTQSBHZW5lcmF0 +ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFLFHNef5VZb2wM1uSQh7lh7aEWApMIGr +BgNVHSMEgaMwgaCAFJzkYNlvN+jPLlRVMsXY2QC+jXgDoX2kezB5MQswCQYDVQQG +EwJJVDELMAkGA1UECBMCSVQxEDAOBgNVBAcTB1BlcnVnaWExEzARBgNVBAoTCmFp +cnZwbi5vcmcxFjAUBgNVBAMTDWFpcnZwbi5vcmcgQ0ExHjAcBgkqhkiG9w0BCQEW +D2luZm9AYWlydnBuLm9yZ4IJAMJkKKJ2Uo1nMBMGA1UdJQQMMAoGCCsGAQUFBwMC +MAsGA1UdDwQEAwIHgDANBgkqhkiG9w0BAQUFAAOCAgEAJ2+ob0AbwJjOueMBjFmC +kLig/OpJr5Sx0RQ01x4759ULEs/NMzaNUr2lhsQAVkYN8EvPp4UM/iO46sATsigA +IgsBKoIZrJ5YzOQsczcE73AJSRBtHLQXesRXKreYVd02Kxez3zcO92xMURmo1YIM +gpEj332reruw6SCY5YQTN2Kso+Kx6nLaLiDMNVaeMlWlIZY0ZucQRVRsFhc2KLTN +OWUZOhHlNaeMltzqRzD5ncRB8e0disWdHpkjtSz18BvER7v4lZCjWZ8BDzg6YKf7 +hlphmxEB97t8b/3zBHjI72lgeKx/vo0M+mL5dzaujhQ0b2yqqsTsth3azULjXjUw +zb9g359T2QAJrGSuMsB0u+bzFE7R+8pYQwu6IYav4whElyp+HRAIE7AFqOh+BcWR +RAgN8weGnxN1H2AjtkCc9jDuvR9f5/eMePf2IxdbY/QQ5RS4s5mOQrC8XQj4YPUL +v3d6oci8Rud4R8vNYTBV92qhUoPkWnqxy5sIA9/JWLFPtnhJqmyTJJQnTVMHWp/6 +2lc9j/wvDQSSpu/za127+ULh27qh89IrqvtbE8C6G+cOIUs3/CcKiIcHtVsIcCWR +HN1jf5qZ8HtIB0K0EZ47kYWIfJbllnqshWGRRPAnzCpWafNIXWf/MjWUfyrfAkZ8 +qAZoGjCdOJq/IrQCq/95Cpw= +-----END CERTIFICATE----- \ No newline at end of file diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/airvpn/client.key b/rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/airvpn/client.key new file mode 100644 index 0000000..9f34129 --- /dev/null +++ b/rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/airvpn/client.key @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +MIIJRAIBADANBgkqhkiG9w0BAQEFAASCCS4wggkqAgEAAoICAQDRq3fUlg3/NoKr +RY4bVH095uN56M8fuiN/w2CaZRJNyt8WPw1PtI/f2Zn7YOkeBSceetih8kqmX6U7 +z0/fSo0DLMjFuYsBl5ZG1txXWJ9RlDVkE84vrqcxAHmarQWz2OV0Kl9mltNznTSe +cnD+tzaiJBd+IPRABDlaHaguNcAydBcv4mpPIbR0WvrUXkrf0MWFR0/5/6S4LK0m +dNIiYkjRDESHXO5ZrYY+vQuRxYtLXp1hYF2759r5Cf5vRWau7YrWvZLjLAj1lmAO +qhbgZQ4Zutnv6KeWfUxV56dOz1OGOcbDz7i1QP6ay247l0sIax6ZEwsca0gfojc3 +MUcCpg6L3cGrifp7anHKTMd4vsQuKlocWla6o4LWHy1icW8jQzwxLDwAmQ0kg7u5 +Q3IsvxCTFvZ3UugPN+HVPKJsfCxqae2b3hLwT3BUQtF8aDYlcn3GRux0fSbcDYsz +b53ZHCiRaImFJLmWKH6lNdVchjBu1H+xrpLELEoJNb+/FAkqurIJtpbW+pml+OKg +EOHMcVqcQnvbRQldiPexLMyjMVZbG4PYVBm5pRRtPyR/vw3xdujfyB1kfIc4G36J +Y+8Fi5uRu16fH7dCTQjIiKX6inVgjKuTJjydLYTaS1e1xEO83dS1sjWEetW5IjAL +abM7Ouzbq1djin6mHhpNO51eBbtmewIDAQABAoICAQCpSr2ylIYwrx7Kk5quToXh +WXAKmwPCJlVLb8GsaDdjQI7oM3jYBn60y8ocwp73ckmnvqD0AeJse4W6ySVAsb0x +9xMVMz8dxfu8rveyPwhEolqJt8Qfk/HDCxMk5NdZ46NBLIVjHB0XmLNHzDeYMu6V +9HZTjOAqYD6+mHuW9Cd/lWSzcSlNQ3WlDWDB4HCsTrFtb6sPvG6PluMnzeNth9Yr +lLAwa8S3+/gM6C9TQCG8dWS1n02PzyFrO7qItYy3aW1U/jR/4KpLQWPF82gNPwsn +k0ss/rlyNTFRm33nkFdsZXIr4KjPEO+CpQcYboxS+8r05f9uruDJSf0zP0KKzPGo +XiEhxGolfry0GR17AmJliWOmEbCrHkkOaMP8M2feV9C8vwQsEpNHsK2fyyyMUsok +eM4hNYpd/OsglhDrcBJy9h2Sg8y8II1xMDtnxpWAvhGky4UMUZY3oqNGHCRInexl +XHQkVmqa0hc0k+jD0EBxbGNLAd1tqV8pwlTxdPRdhREDLIUZi93Sn/AehCmwFngK +g+TQaLKUGxk86ccenr1+ElK8ulC0olGg4EFp6Y9O9KJsvy3E1PrpaUO2urP+SkUB +Qn0NJiw5TxJC9XeEpnPbk0aMU7bx3iuLdSMqBadrlM13mbALHdVnybC2KCoYTU3g +phLhUn+2+hmlh098M11nYQKCAQEA+ARSNiJ/t8YeDNotJ37JYaTVwMYa/ovU/DBI +LhEOASS4jXLTkJkbX/0V6cUsnlC27FjnRJ7l+QNCb23GgZnQTXY9nnUStyrCWvqC +fh00s0UntY079xT/d8X92yFKt9/NixdxF6WCbH1QDfF1HHDSMVdXdmWlqhgsFedD +yd7YWFacr2GddDfqQybkzFHxuSxizEH/uPmh/LlEtxSX1Kgg5veWsITPyxU0EdKX +Nlr3OmGYMc4eLKu0lsNEYhXkMPnIcu62eJYGCWJ2korruPDAS1i0KXSYlZ9VQU6r +9Fq/3iM3KY4MNYR9kOz4LLqSXFwEAyKfOGl0Y8o4+P7AGCnCHwKCAQEA2Gsp95OW +BXIC4JMn3mthg8DUyaPV7iG6oXBMBMPrzxcykb0Q+sFuMWaCaQoGdYQgMRrfb9uT +hu3BzOh5T5f8gq2MkbWDbifMjTvHG3nf/Z4zVgMgzjMZ+6Q7GRccxNLXSiyLecfO +oIklutGyE1zLnlrhxUPv0cOLpc1u1mpm2eDuIinCN/4A2BGe4L8NIRCN0KOclvEd +YWmipgoNxZ9wXuxwBO6I9rQa4ggmShJvgaAtoQ6QPY1hZqxedkXDrqPSCEGzCKeE +d8PhGutilMp0mkCpzHvS38e/01XjDBr8g5F3ORopbIpF2O/xMdzFoObPtC/awvlX +JQhsMEAMgfKoJQKCAQANPN3OeeTrQC3Wbca/Nus0xQGLuocyUvBZTZJsswhWU0lu +c1SLgUCOzQlgYt/Qy2oYD164sOqBcgUXwXo47KbLm6YKUSFgmW2qQXi5loF7mBNY +g2NR+tLv56d3DL3aNp3X8LZelrzxYXbmZ57il7sAWzMV5LME8ylXOfLKUZSmkmjm +i4VF8L4WO3s21KDcS1wynssxalGVFaZvRzAbb6Xh7hEi9tPIeSdAVEcx5YUQnqjq +7594rumCqoV53sVBP/PM/qTKpudHlPPTOor+YgtBekiTdd+3DLwWMkbHUhivmJ2X +IDfSm3HATIWqjYLGXzrvl+d7sVU/BkooMCC8qW3tAoIBAQDNG8OKgLWOM5/Gd7Ex +e1PQKtGAyWXXauAWYPerDIRQoQusVCPjg6+L4jt2kanNdouL/owE13XaSzuBmFJg +vQr0TscK0ZzeqZmTwTPTNo6zL1w4CH7u7j+R3vSjsuPxJmIkSlNl95g9Tb4UcOj0 +sN3KFxgifWCszUdsvGZvkCgqFqOafTk1F+Z04T5Sgr9OtwGw219tLtdJm3QrKRwk +UBeP30XLZscoCUnxLwga654CnGyiV8sciwHk7TgZn8T1nw1QBfRIH3vMhjix6qRj +n/0itGY5BqG0tPt4r82fi3QGvbbgx4q689F+6OkO+M3U0OvJOhF6+BU/Y9wlXo58 +Gh6BAoIBAQDxM76UGIx7ptYpbb2qmNj4MHJFzn2LiU+9GH1zRuOcphkafb/neZJw +poIYozm5MUPcuKcSMrvRNCDXL5HVkbtN0iPOvDA88Jp/rNEF0I9NPcGRAQJ6OvZS +QaMgnce4y0SNOq4o2bWNE2n6LRLBmvxacyFpggleOwjIHk+RUj6yWQcUjRid1U1s +LVg5clPNYxf5pm+4k0GS2nye4+wCKiu9/KUtCd73PPBvrW5xN9sKbrN+hy+m5KVC +Kx1/k/aB3j7WxVIJBKMxQqlM8k1frd0um6CaD18DvZHDAGMInEwTfkJJVLQDxN4/ +59PFiE0grG3JNZa3g34RjxOtsoNrz3bH +-----END PRIVATE KEY----- \ No newline at end of file diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/airvpn/ta.key b/rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/airvpn/ta.key new file mode 100644 index 0000000..7d53ac5 --- /dev/null +++ b/rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/airvpn/ta.key @@ -0,0 +1,18 @@ +-----BEGIN OpenVPN Static key V1----- +7bb7a23a0f5f28d01e792df68f1764ab +f2688719288808bf58e8a2d4f9354ecf +132625dfb895fc3f6330ae1e868e4dfa +c164c0931593d7f9a7da9595cf353433 +8896e1d0a987a0d19838944af8fea4e5 +215a3a0c76f4c67d5a4aee6a53be66a4 +c88b84f850030840fb30f8550ed8068f +35c1ef34ee8f40a0ea5862dfb6f8d3c5 +7ab5e27ac2799cf93e8765ff63cd8cd8 +6b391b813925cd373bb202796f64d16f +003d042ca828d1b07f18ba1d0cb0323d +df3ee9287e9e084e655699efb3cffa92 +3626946fa372e7beee245e7a95b4c1d8 +7d16cae685218d4b8afc019b22e41083 +476ee9883fe666d236301e55b2062551 +4d91c8a69467a758293994df1e6fa7ae +-----END OpenVPN Static key V1----- \ No newline at end of file diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/mullvad/mullvad_ca.crt b/rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/mullvad/mullvad_ca.crt new file mode 100644 index 0000000..b795d91 --- /dev/null +++ b/rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/mullvad/mullvad_ca.crt @@ -0,0 +1,109 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 3 (0x3) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=NA, ST=None, L=None, O=Mullvad, CN=Mullvad CA/emailAddress=info@mullvad.net + Validity + Not Before: Mar 24 16:19:48 2009 GMT + Not After : Mar 22 16:19:48 2019 GMT + Subject: C=NA, ST=None, L=None, O=Mullvad, CN=master.mullvad.net/emailAddress=info@mullvad.net + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:c5:00:39:5d:fe:9b:0c:b7:ff:76:a4:93:bf:26: + 1b:d6:c8:4a:e5:3c:ce:1c:2c:16:80:a2:61:a6:e9: + 63:4b:70:a1:80:6f:0e:0c:bb:a9:b6:d1:bd:f5:a0: + 78:82:09:4d:94:22:aa:77:7c:09:36:42:cd:a5:a6: + 90:73:27:42:00:31:e4:d4:8b:49:36:65:a3:25:82: + b8:26:d7:d1:f5:b5:a9:be:57:93:9d:7c:d6:1c:df: + 9a:87:81:53:0b:17:81:d1:0d:ca:dc:4d:19:13:fa: + 11:e6:da:68:eb:81:05:39:e3:1e:3a:3f:fc:e2:64: + 3c:98:3c:89:a9:42:b3:30:70:57:56:a1:f5:08:b2: + 75:12:a0:36:93:9d:69:e9:7e:11:71:d9:1c:e8:7d: + ec:03:21:11:7a:0a:7a:03:35:ba:b8:b2:0c:3a:6f: + 57:88:62:45:3d:0c:6c:18:ff:21:49:37:ae:40:78: + 6d:45:52:29:ac:21:ad:4a:01:61:67:0b:01:c4:ac: + b0:88:97:52:ff:cb:3a:21:f0:14:2b:c1:79:8d:79: + 35:14:fc:9c:3f:6c:c9:62:fc:8c:c7:a8:51:34:75: + 1c:23:d5:db:b9:44:08:1c:0c:17:2c:21:2a:b4:29: + db:15:59:e7:a9:1c:d6:19:19:ef:e4:6b:ea:78:6d: + 76:8d + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 75:8A:14:92:0D:F3:6E:B7:36:4F:8B:4F:15:6C:3F:18:15:90:64:DE + X509v3 Authority Key Identifier: + keyid:E1:63:B4:3E:55:A3:D2:37:5F:DE:3A:91:48:51:4B:20:1A:F2:9B:C5 + DirName:/C=NA/ST=None/L=None/O=Mullvad/CN=Mullvad CA/emailAddress=info@mullvad.net + serial:84:68:2E:A0:51:2A:BB:D4 + + X509v3 Basic Constraints: + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + a4:b4:62:3d:cb:7e:57:b3:bd:2a:41:e0:3b:94:d0:4c:08:69: + 8a:b1:73:15:13:20:c9:d7:b0:b6:5d:65:4a:4d:1d:27:cc:ca: + 11:0e:86:fa:65:61:26:39:c2:54:8e:da:eb:78:21:37:0e:c7: + a4:d2:17:8a:4b:ad:17:84:25:5e:24:0e:9a:81:ff:d1:1b:0e: + 32:9b:f4:81:e0:07:e9:8f:9d:c1:43:7f:40:30:01:07:7c:02: + c7:c4:9c:05:48:4c:bf:41:69:57:c1:d3:bb:a3:5a:01:17:96: + b0:c9:00:22:57:2f:84:da:45:33:6e:6c:2b:13:c5:af:75:a7: + b2:6b:71:6e:13:2c:97:0e:d9:93:da:6d:d9:34:c6:06:7d:0e: + e2:b8:d2:78:13:79:0f:ac:ac:a8:68:a9:72:73:7a:d8:ab:7b: + 0a:b0:54:b5:f3:ce:29:0d:47:82:0c:b4:d9:20:64:ff:ef:17: + 46:92:de:65:e8:67:ce:3a:92:de:e4:3e:99:73:9f:7a:7c:00: + 72:07:39:78:77:37:62:89:a2:db:24:fd:60:2a:e0:82:57:f6: + 55:94:f6:79:47:19:c9:13:3b:5d:b7:6b:66:14:d4:7d:3c:76: + 75:e9:a3:55:ba:b4:92:30:3b:ad:66:72:0c:39:4b:cc:95:a9: + bc:06:ef:2b +-----BEGIN CERTIFICATE----- +MIIEQjCCAyqgAwIBAgIBAzANBgkqhkiG9w0BAQUFADBzMQswCQYDVQQGEwJOQTEN +MAsGA1UECBMETm9uZTENMAsGA1UEBxMETm9uZTEQMA4GA1UEChMHTXVsbHZhZDET +MBEGA1UEAxMKTXVsbHZhZCBDQTEfMB0GCSqGSIb3DQEJARYQaW5mb0BtdWxsdmFk +Lm5ldDAeFw0wOTAzMjQxNjE5NDhaFw0xOTAzMjIxNjE5NDhaMHsxCzAJBgNVBAYT +Ak5BMQ0wCwYDVQQIEwROb25lMQ0wCwYDVQQHEwROb25lMRAwDgYDVQQKEwdNdWxs +dmFkMRswGQYDVQQDExJtYXN0ZXIubXVsbHZhZC5uZXQxHzAdBgkqhkiG9w0BCQEW +EGluZm9AbXVsbHZhZC5uZXQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB +AQDFADld/psMt/92pJO/JhvWyErlPM4cLBaAomGm6WNLcKGAbw4Mu6m20b31oHiC +CU2UIqp3fAk2Qs2lppBzJ0IAMeTUi0k2ZaMlgrgm19H1tam+V5OdfNYc35qHgVML +F4HRDcrcTRkT+hHm2mjrgQU54x46P/ziZDyYPImpQrMwcFdWofUIsnUSoDaTnWnp +fhFx2RzofewDIRF6CnoDNbq4sgw6b1eIYkU9DGwY/yFJN65AeG1FUimsIa1KAWFn +CwHErLCIl1L/yzoh8BQrwXmNeTUU/Jw/bMli/IzHqFE0dRwj1du5RAgcDBcsISq0 +KdsVWeepHNYZGe/ka+p4bXaNAgMBAAGjgdgwgdUwHQYDVR0OBBYEFHWKFJIN8263 +Nk+LTxVsPxgVkGTeMIGlBgNVHSMEgZ0wgZqAFOFjtD5Vo9I3X946kUhRSyAa8pvF +oXekdTBzMQswCQYDVQQGEwJOQTENMAsGA1UECBMETm9uZTENMAsGA1UEBxMETm9u +ZTEQMA4GA1UEChMHTXVsbHZhZDETMBEGA1UEAxMKTXVsbHZhZCBDQTEfMB0GCSqG +SIb3DQEJARYQaW5mb0BtdWxsdmFkLm5ldIIJAIRoLqBRKrvUMAwGA1UdEwQFMAMB +Af8wDQYJKoZIhvcNAQEFBQADggEBAKS0Yj3LflezvSpB4DuU0EwIaYqxcxUTIMnX +sLZdZUpNHSfMyhEOhvplYSY5wlSO2ut4ITcOx6TSF4pLrReEJV4kDpqB/9EbDjKb +9IHgB+mPncFDf0AwAQd8AsfEnAVITL9BaVfB07ujWgEXlrDJACJXL4TaRTNubCsT +xa91p7JrcW4TLJcO2ZPabdk0xgZ9DuK40ngTeQ+srKhoqXJzetirewqwVLXzzikN +R4IMtNkgZP/vF0aS3mXoZ846kt7kPplzn3p8AHIHOXh3N2KJotsk/WAq4IJX9lWU +9nlHGckTO123a2YU1H08dnXpo1W6tJIwO61mcgw5S8yVqbwG7ys= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEQjCCAyqgAwIBAgIJAIRoLqBRKrvUMA0GCSqGSIb3DQEBBQUAMHMxCzAJBgNV +BAYTAk5BMQ0wCwYDVQQIEwROb25lMQ0wCwYDVQQHEwROb25lMRAwDgYDVQQKEwdN +dWxsdmFkMRMwEQYDVQQDEwpNdWxsdmFkIENBMR8wHQYJKoZIhvcNAQkBFhBpbmZv +QG11bGx2YWQubmV0MB4XDTA5MDMyNDA2NDcyNVoXDTE5MDMyMjA2NDcyNVowczEL +MAkGA1UEBhMCTkExDTALBgNVBAgTBE5vbmUxDTALBgNVBAcTBE5vbmUxEDAOBgNV +BAoTB011bGx2YWQxEzARBgNVBAMTCk11bGx2YWQgQ0ExHzAdBgkqhkiG9w0BCQEW +EGluZm9AbXVsbHZhZC5uZXQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB +AQDNNzZOrq+gMaA6wfyWdNFmxlM2OB1czwFgtPiDd9f6F8m6CGYBQog3Q2Wx3yAv +hxt/uchFBCKtYz6Yh59BCxXKfNAQT2uaMC6KAvKFgz0wppi4S8YbWg2KDelNO/Zv +Rb1QT4CBWMbtYzCQZvlJpHr2ZwuXG2OiT477oMyX5Hmf+iT0drmqi+wylRr7CRBs +LBu+fxLZ2LFD5g6MATuL3ql5JLIoVjlSqIgbld74pD4WUnM61HRwFsKoCEjq409Y +QNP1xO7BeaJu3uQvg/HJhXnGZxTatXhqvdCuAPQRppQ4UnkUzxdSTrfgM3hqMony +vX1vy0dX1S8iTQCIeyzAYNObAgMBAAGjgdgwgdUwHQYDVR0OBBYEFOFjtD5Vo9I3 +X946kUhRSyAa8pvFMIGlBgNVHSMEgZ0wgZqAFOFjtD5Vo9I3X946kUhRSyAa8pvF +oXekdTBzMQswCQYDVQQGEwJOQTENMAsGA1UECBMETm9uZTENMAsGA1UEBxMETm9u +ZTEQMA4GA1UEChMHTXVsbHZhZDETMBEGA1UEAxMKTXVsbHZhZCBDQTEfMB0GCSqG +SIb3DQEJARYQaW5mb0BtdWxsdmFkLm5ldIIJAIRoLqBRKrvUMAwGA1UdEwQFMAMB +Af8wDQYJKoZIhvcNAQEFBQADggEBAMjMAFPDeFOrQsvMXD/x+CuARwegS2PDZuB5 +f1Svw3YDF6cB1jlc0F12nh9SZxaYRwKIlpYoolLCOLoUCLwQJ0gsokxLV7G4gVb8 +dzETnNq4HG/QOPwPisjoOCaEmcd0tx1EkyNY0KLqFZTS0VdmDHCn89dDFA/6yuYI +5u04uJs7c/K4qaW7X6ajOOdneqjbtPeVOvx9DWXHxA0xz4Y+/w4laX/OTRD7jySq +K9fLfRliE5zsxzpUr5EWxAnqiABoWL71SiItk5fG8k3MJJ9SVr+YnTHmE7S4KNqu +4wTksvkb0Tmjae1lRSlMd6u2AulAxVcVKAod2QVffhj+hdkYM94= +-----END CERTIFICATE----- diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/mullvad/mullvad_crl.pem b/rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/mullvad/mullvad_crl.pem new file mode 100644 index 0000000..10e26dd --- /dev/null +++ b/rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/mullvad/mullvad_crl.pem @@ -0,0 +1,36 @@ +-----BEGIN X509 CRL----- +MIIGMTCCBRkwDQYJKoZIhvcNAQELBQAwezELMAkGA1UEBhMCTkExDTALBgNVBAgT +BE5vbmUxDTALBgNVBAcTBE5vbmUxEDAOBgNVBAoTB011bGx2YWQxGzAZBgNVBAMT +Em1hc3Rlci5tdWxsdmFkLm5ldDEfMB0GCSqGSIb3DQEJARYQaW5mb0BtdWxsdmFk +Lm5ldBcNMTcwNjIyMTQzMzEyWhcNMjcwNjIwMTQzMzEyWjCCBGswEgIBARcNMTcw +NjIyMTQzMzExWjASAgEDFw0xNzA2MjIxNDMzMTFaMBICASkXDTE3MDYyMjE0MzMx +MVowEwICDasXDTE3MDYyMjE0MzMxMVowEwICDawXDTE3MDYyMjE0MzMxMVowEwIC +Da0XDTE3MDYyMjE0MzMxMVowEwICDx4XDTE3MDYyMjE0MzMxMVowEwICGxsXDTE3 +MDYyMjE0MzMxMVowEwICPf4XDTE3MDYyMjE0MzMxMVowEwICSrUXDTE3MDYyMjE0 +MzMxMVowFAIDAbbXFw0xNzA2MjIxNDMzMTFaMBQCAwaeUBcNMTcwNjIyMTQzMzEx +WjAUAgMGnlUXDTE3MDYyMjE0MzMxMVowFAIDCheTFw0xNzA2MjIxNDMzMTFaMBQC +AwpvDBcNMTcwNjIyMTQzMzExWjAUAgML2jcXDTE3MDYyMjE0MzMxMVowFAIDDCfI +Fw0xNzA2MjIxNDMzMTFaMBQCAwwrKhcNMTcwNjIyMTQzMzExWjAUAgMMNWEXDTE3 +MDYyMjE0MzMxMVowFAIDDDViFw0xNzA2MjIxNDMzMTFaMBQCAwyXhRcNMTcwNjIy +MTQzMzExWjAUAgMM99UXDTE3MDYyMjE0MzMxMVowFAIDDPfWFw0xNzA2MjIxNDMz +MTFaMBQCAwz31xcNMTcwNjIyMTQzMzExWjAUAgMM9+MXDTE3MDYyMjE0MzMxMVow +FAIDDPfkFw0xNzA2MjIxNDMzMTFaMBQCAwz35RcNMTcwNjIyMTQzMzExWjAUAgMN +FHEXDTE3MDYyMjE0MzMxMVowFAIDDRSLFw0xNzA2MjIxNDMzMTFaMBQCAw1FfBcN +MTcwNjIyMTQzMzExWjAUAgMNUWcXDTE3MDYyMjE0MzMxMVowFAIDDVFoFw0xNzA2 +MjIxNDMzMTFaMBQCAw1RbBcNMTcwNjIyMTQzMzExWjAUAgMN2AoXDTE3MDYyMjE0 +MzMxMVowFAIDDdgLFw0xNzA2MjIxNDMzMTFaMBQCAw6G3xcNMTcwNjIyMTQzMzEx +WjAUAgMOkpwXDTE3MDYyMjE0MzMxMVowFAIDDpKdFw0xNzA2MjIxNDMzMTFaMBQC +Aw7DWhcNMTcwNjIyMTQzMzExWjAUAgMPFEEXDTE3MDYyMjE0MzMxMVowFAIDDyaP +Fw0xNzA2MjIxNDMzMTFaMBQCAw9D1xcNMTcwNjIyMTQzMzExWjAUAgMPzJQXDTE3 +MDYyMjE0MzMxMVowFAIDE3pTFw0xNzA2MjIxNDMzMTFaMBQCAxN6VBcNMTcwNjIy +MTQzMzExWjAUAgMTjroXDTE3MDYyMjE0MzMxMVowFAIDFIUDFw0xNzA2MjIxNDMz +MTFaMBQCAx7XBxcNMTcwNjIyMTQzMzExWjAUAgMgFScXDTE3MDYyMjE0MzMxMVow +FAIDImufFw0xNzA2MjIxNDMzMTFaMBQCAyPpNRcNMTcwNjIyMTQzMzExWjAUAgMk +eEgXDTE3MDYyMjE0MzMxMVowDQYJKoZIhvcNAQELBQADggEBAEdGuk5OitTepMQL +O2ugSjKl9le9ttuwiNkXCowYZwMpvOvk98RuhcgqwetDtxdMIi7koMIlbILfbIwA +VYvaV7HzpOzkL9D4RpE8GN3r1xjc+pjz5RN08Q+l/pRI9VeS2Bz6sstujqDMu0kT +LEzxtyiWGgdyYL0ykirahStLxmjc0JLLSsZXHuVJGmdJsphoEw/zgTRR02N7Q0gP +AmL6+i4mXY8OMaUMFWwKikliT+VAT23H1VPPUpS/5n3p+j15Hn5bI+rHyLmO2Ca7 +0UlcBbTVhoNMO25/6js5icRktebiaI0hq3Zofd5U80tGJnH+udIUEAq6CD/wUNqq +VcdW4oc= +-----END X509 CRL----- diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/pia/ca.rsa.2048.crt b/rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/pia/ca.rsa.2048.crt new file mode 100644 index 0000000..6deea60 --- /dev/null +++ b/rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/pia/ca.rsa.2048.crt @@ -0,0 +1,33 @@ +-----BEGIN CERTIFICATE----- +MIIFqzCCBJOgAwIBAgIJAKZ7D5Yv87qDMA0GCSqGSIb3DQEBDQUAMIHoMQswCQYD +VQQGEwJVUzELMAkGA1UECBMCQ0ExEzARBgNVBAcTCkxvc0FuZ2VsZXMxIDAeBgNV +BAoTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMSAwHgYDVQQLExdQcml2YXRlIElu +dGVybmV0IEFjY2VzczEgMB4GA1UEAxMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3Mx +IDAeBgNVBCkTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMS8wLQYJKoZIhvcNAQkB +FiBzZWN1cmVAcHJpdmF0ZWludGVybmV0YWNjZXNzLmNvbTAeFw0xNDA0MTcxNzM1 +MThaFw0zNDA0MTIxNzM1MThaMIHoMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0Ex +EzARBgNVBAcTCkxvc0FuZ2VsZXMxIDAeBgNVBAoTF1ByaXZhdGUgSW50ZXJuZXQg +QWNjZXNzMSAwHgYDVQQLExdQcml2YXRlIEludGVybmV0IEFjY2VzczEgMB4GA1UE +AxMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3MxIDAeBgNVBCkTF1ByaXZhdGUgSW50 +ZXJuZXQgQWNjZXNzMS8wLQYJKoZIhvcNAQkBFiBzZWN1cmVAcHJpdmF0ZWludGVy +bmV0YWNjZXNzLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPXD +L1L9tX6DGf36liA7UBTy5I869z0UVo3lImfOs/GSiFKPtInlesP65577nd7UNzzX +lH/P/CnFPdBWlLp5ze3HRBCc/Avgr5CdMRkEsySL5GHBZsx6w2cayQ2EcRhVTwWp +cdldeNO+pPr9rIgPrtXqT4SWViTQRBeGM8CDxAyTopTsobjSiYZCF9Ta1gunl0G/ +8Vfp+SXfYCC+ZzWvP+L1pFhPRqzQQ8k+wMZIovObK1s+nlwPaLyayzw9a8sUnvWB +/5rGPdIYnQWPgoNlLN9HpSmsAcw2z8DXI9pIxbr74cb3/HSfuYGOLkRqrOk6h4RC +OfuWoTrZup1uEOn+fw8CAwEAAaOCAVQwggFQMB0GA1UdDgQWBBQv63nQ/pJAt5tL +y8VJcbHe22ZOsjCCAR8GA1UdIwSCARYwggESgBQv63nQ/pJAt5tLy8VJcbHe22ZO +sqGB7qSB6zCB6DELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRMwEQYDVQQHEwpM +b3NBbmdlbGVzMSAwHgYDVQQKExdQcml2YXRlIEludGVybmV0IEFjY2VzczEgMB4G +A1UECxMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3MxIDAeBgNVBAMTF1ByaXZhdGUg +SW50ZXJuZXQgQWNjZXNzMSAwHgYDVQQpExdQcml2YXRlIEludGVybmV0IEFjY2Vz +czEvMC0GCSqGSIb3DQEJARYgc2VjdXJlQHByaXZhdGVpbnRlcm5ldGFjY2Vzcy5j +b22CCQCmew+WL/O6gzAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBDQUAA4IBAQAn +a5PgrtxfwTumD4+3/SYvwoD66cB8IcK//h1mCzAduU8KgUXocLx7QgJWo9lnZ8xU +ryXvWab2usg4fqk7FPi00bED4f4qVQFVfGfPZIH9QQ7/48bPM9RyfzImZWUCenK3 +7pdw4Bvgoys2rHLHbGen7f28knT2j/cbMxd78tQc20TIObGjo8+ISTRclSTRBtyC +GohseKYpTS9himFERpUgNtefvYHbn70mIOzfOJFTVqfrptf9jXa9N8Mpy3ayfodz +1wiqdteqFXkTYoSDctgKMiZ6GdocK9nMroQipIQtpnwd4yBDWIyC6Bvlkrq5TQUt +YDQ8z9v+DMO6iwyIDRiU +-----END CERTIFICATE----- diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/pia/crl.rsa.2048.pem b/rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/pia/crl.rsa.2048.pem new file mode 100644 index 0000000..a58ef56 --- /dev/null +++ b/rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/pia/crl.rsa.2048.pem @@ -0,0 +1,15 @@ +-----BEGIN X509 CRL----- +MIICWDCCAUAwDQYJKoZIhvcNAQENBQAwgegxCzAJBgNVBAYTAlVTMQswCQYDVQQI +EwJDQTETMBEGA1UEBxMKTG9zQW5nZWxlczEgMB4GA1UEChMXUHJpdmF0ZSBJbnRl +cm5ldCBBY2Nlc3MxIDAeBgNVBAsTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMSAw +HgYDVQQDExdQcml2YXRlIEludGVybmV0IEFjY2VzczEgMB4GA1UEKRMXUHJpdmF0 +ZSBJbnRlcm5ldCBBY2Nlc3MxLzAtBgkqhkiG9w0BCQEWIHNlY3VyZUBwcml2YXRl +aW50ZXJuZXRhY2Nlc3MuY29tFw0xNjA3MDgxOTAwNDZaFw0zNjA3MDMxOTAwNDZa +MCYwEQIBARcMMTYwNzA4MTkwMDQ2MBECAQYXDDE2MDcwODE5MDA0NjANBgkqhkiG +9w0BAQ0FAAOCAQEAQZo9X97ci8EcPYu/uK2HB152OZbeZCINmYyluLDOdcSvg6B5 +jI+ffKN3laDvczsG6CxmY3jNyc79XVpEYUnq4rT3FfveW1+Ralf+Vf38HdpwB8EW +B4hZlQ205+21CALLvZvR8HcPxC9KEnev1mU46wkTiov0EKc+EdRxkj5yMgv0V2Re +ze7AP+NQ9ykvDScH4eYCsmufNpIjBLhpLE2cuZZXBLcPhuRzVoU3l7A9lvzG9mjA +5YijHJGHNjlWFqyrn1CfYS6koa4TGEPngBoAziWRbDGdhEgJABHrpoaFYaL61zqy +MR6jC0K2ps9qyZAN74LEBedEfK7tBOzWMwr58A== +-----END X509 CRL----- diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/placeholder/placeholder.file b/rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/placeholder/placeholder.file new file mode 100644 index 0000000..e88efe6 --- /dev/null +++ b/rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/placeholder/placeholder.file @@ -0,0 +1,2 @@ +placeholder file +placeholder \ No newline at end of file diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/windscribe/ca.crt b/rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/windscribe/ca.crt new file mode 100644 index 0000000..7edc133 --- /dev/null +++ b/rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/windscribe/ca.crt @@ -0,0 +1,34 @@ +-----BEGIN CERTIFICATE----- +MIIF3DCCA8SgAwIBAgIJAMsOivWTmu9fMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNV +BAYTAkNBMQswCQYDVQQIDAJPTjEQMA4GA1UEBwwHVG9yb250bzEbMBkGA1UECgwS +V2luZHNjcmliZSBMaW1pdGVkMRMwEQYDVQQLDApPcGVyYXRpb25zMRswGQYDVQQD +DBJXaW5kc2NyaWJlIE5vZGUgQ0EwHhcNMTYwMzA5MDMyNjIwWhcNNDAxMDI5MDMy +NjIwWjB7MQswCQYDVQQGEwJDQTELMAkGA1UECAwCT04xEDAOBgNVBAcMB1Rvcm9u +dG8xGzAZBgNVBAoMEldpbmRzY3JpYmUgTGltaXRlZDETMBEGA1UECwwKT3BlcmF0 +aW9uczEbMBkGA1UEAwwSV2luZHNjcmliZSBOb2RlIENBMIICIjANBgkqhkiG9w0B +AQEFAAOCAg8AMIICCgKCAgEAruBtLR1Vufd71LeQEqChgHS4AQJ0fSRner0gmZPE +r2TL5uWboOEWXFFoEUTthF+P/N8yy3xRZ8HhG/zKlmJ1xw+7KZRbTADD6shJPj3/ +uvTIO80sU+9LmsyKSWuPhQ1NkgNA7rrMTfz9eHJ2MVDs4XCpYWyX9iuAQrHSY6aP +q+4TpCbUgprkM3Gwjh9RSt9IoDoc4CF2bWSaVepUcL9yz/SXLPzFx2OT9rFrDhL3 +ryHRzJQ/tA+VD8A7lo8bhOcDqiXgEFmVOZNMLw+r167Qq1Ck7X86yr2mnW/6HK2g +JOvY0/SPKukfGJAiYZKdG+fe4ekyYcAVhDfPJg7rF9wUqPwUzejJyAs1K18JwX94 +Y8fnD6vQobjpC3qfHtwQP7Uj2AcI6QC8ytWDegV6UIkHXAMXBQSX5suSQoE11deG +32cy7nyp5vhgy31rTyNoopqlcCAhPm6k0jVVQbvXhLcpTSL8iCCoMdrP28i/xsfv +ktBAkl5giHMdK6hxqWgPI+Bx9uPIhRp3fJ2z8AgFm8g1ARB2ZzQ+OZZ2RUIkJuUK +hi2kUhgKSAQ+eF89aoqDjp/J1miZqGRzt4DovSZfQOeL01RkKHEibAPYCfgHG2ZS +woLoeaxE2vNZiX4dpXiOQYTOIXOwEPZzPvfTQf9T4Kxvx3jzQnt3PzjlMCqKk3Ai +pm8CAwEAAaNjMGEwHQYDVR0OBBYEFEH2v9F2z938Ebngsj9RkVSSgs45MB8GA1Ud +IwQYMBaAFEH2v9F2z938Ebngsj9RkVSSgs45MA8GA1UdEwEB/wQFMAMBAf8wDgYD +VR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQAgI6NgYkVo5rB6yKStgHjj +ZsINsgEvoMuHwkM0YaV22XtKNiHdsiOmY/PGCRemFobTEHk5XHcvcOTWv/D1qVf8 +fI21WAoNQVH7h8KEsr4uMGKCB6Lu8l6xALXRMjo1xb6JKBWXwIAzUu691rUD2exT +1E+A5t+xw+gzqV8rWTMIoUaH7O1EKjN6ryGW71Khiik8/ETrP3YT32ZbS2P902iM +Kw9rpmuS0wWhnO5k/iO/6YNA1ZMV5JG5oZvZQYEDk7enLD9HvqazofMuy/Sz/n62 +ZCDdQsnabzxl04wwv5Y3JZbV/6bOM520GgdJEoDxviY05ax2Mz05otyBzrAVjFw9 +RZt/Ls8ATifu9BusZ2ootvscdIuE3x+ZCl5lvANcFEnvgGw0qpCeASLpsfxwq1dR +gIn7BOiTauFv4eoeFAQvCD+l+EKGWKu3M2y19DgYX94N2+Xs2bwChroaO5e4iFem +MLMuWKZvYgnqS9OAtRSYWbNX/wliiPz7u13yj+qSWgMfu8WPYNQlMZJXuGWUvKLE +XCUExlu7/o8D4HpsVs30E0pUdaqN0vExB1KegxPWWrmLcYnPG3knXpkC3ZBZ5P/e +l/2eyhZRy9ydiITF8gM3L08E8aeqvzZMw2FDSmousydIzlXgeS5VuEf+lUFA2h8o +ZYGQgrLt+ot8MbLhJlkp4Q== +-----END CERTIFICATE----- \ No newline at end of file diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/windscribe/ta.key b/rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/windscribe/ta.key new file mode 100644 index 0000000..dd556ac --- /dev/null +++ b/rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/windscribe/ta.key @@ -0,0 +1,18 @@ +-----BEGIN OpenVPN Static key V1----- +5801926a57ac2ce27e3dfd1dd6ef8204 +2d82bd4f3f0021296f57734f6f1ea714 +a6623845541c4b0c3dea0a050fe6746c +b66dfab14cda27e5ae09d7c155aa554f +399fa4a863f0e8c1af787e5c602a801d +3a2ec41e395a978d56729457fe6102d7 +d9e9119aa83643210b33c678f9d4109e +3154ac9c759e490cb309b319cf708cae +83ddadc3060a7a26564d1a24411cd552 +fe6620ea16b755697a4fc5e6e9d0cfc0 +c5c4a1874685429046a424c026db672e +4c2c492898052ba59128d46200b40f88 +0027a8b6610a4d559bdc9346d33a0a6b +08e75c7fd43192b162bfd0aef0c716b3 +1584827693f676f9a5047123466f0654 +eade34972586b31c6ce7e395f4b478cb +-----END OpenVPN Static key V1----- \ No newline at end of file diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/lib/upgrade/keep.d/rootervpn b/rooter/0optionalapps/luci-app-rootervpn/files/lib/upgrade/keep.d/rootervpn new file mode 100644 index 0000000..30f20da --- /dev/null +++ b/rooter/0optionalapps/luci-app-rootervpn/files/lib/upgrade/keep.d/rootervpn @@ -0,0 +1 @@ +/etc/openvpn/* diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/usr/bin/ovpn-userpass b/rooter/0optionalapps/luci-app-rootervpn/files/usr/bin/ovpn-userpass new file mode 100644 index 0000000..615c85c --- /dev/null +++ b/rooter/0optionalapps/luci-app-rootervpn/files/usr/bin/ovpn-userpass @@ -0,0 +1,16 @@ +#!/bin/sh + +log() { + logger -t "UserPass : " "$@" +} + +conf="/etc/openvpn/ovpnauth.conf" + +userpass=`cat $1` +username=`echo $userpass | awk '{print $1}'` +password=`echo $userpass | awk '{print $2}'` + +log "$username $password" + + +exit 0 \ No newline at end of file diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/usr/bin/rkillall b/rooter/0optionalapps/luci-app-rootervpn/files/usr/bin/rkillall new file mode 100644 index 0000000..3802082 --- /dev/null +++ b/rooter/0optionalapps/luci-app-rootervpn/files/usr/bin/rkillall @@ -0,0 +1,9 @@ +#!/bin/sh +LOOKFOR=$1 +KILLLIST=$(ps | grep $LOOKFOR) +echo "$KILLLIST" | while read line; do + if `echo "$line" | grep "/$LOOKFOR" > /dev/null` ; then + PIDV=$(echo $line | grep -o "^[0-9]\{1,5\}" | grep -o "[0-9]\{1,5\}") + kill $PIDV + fi +done \ No newline at end of file diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/easyrsa/dns.sh b/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/easyrsa/dns.sh new file mode 100644 index 0000000..b461228 --- /dev/null +++ b/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/easyrsa/dns.sh @@ -0,0 +1,67 @@ +#!/bin/sh + +log() { + logger -t "Firewall Settings : " "$@" +} + +sleep 5 +LANOPENDNS=$(uci get openvpn.settings.lanopendns) +if [ -z $LANOPENDNS ]; then + LANOPENDNS="0" +fi +LANGOOGLE=$(uci get openvpn.settings.langoogle) +if [ -z $LANGOOGLE ]; then + LANGOOGLE="0" +fi +WANOPENDNS=$(uci get openvpn.settings.wanopendns) +if [ -z $WANOPENDNS ]; then + WANOPENDNS="0" +fi +WANGOOGLE=$(uci get openvpn.settings.wangoogle) +if [ -z $WANGOOGLE ]; then + WANGOOGLE="0" +fi + +if [ $LANOPENDNS = "1" -a $LANGOOGLE = "0" ]; then + uci del dhcp.lan.dhcp_option + uci add_list dhcp.lan.dhcp_option='6,208.67.222.222,208.67.220.220' +fi +if [ $LANOPENDNS = "0" -a $LANGOOGLE = "1" ]; then + uci del dhcp.lan.dhcp_option + uci add_list dhcp.lan.dhcp_option='6,8.8.8.8,8.8.4.4' +fi +if [ $LANOPENDNS = "1" -a $LANGOOGLE = "1" ]; then + uci del dhcp.lan.dhcp_option + uci add_list dhcp.lan.dhcp_option='6,8.8.8.8,8.8.4.4' + uci add_list dhcp.lan.dhcp_option='6,208.67.222.222,208.67.220.220' +fi +if [ $LANOPENDNS = "0" -a $LANGOOGLE = "0" ]; then + uci del dhcp.lan.dhcp_option +fi + +if [ $WANOPENDNS = "1" -a $WANGOOGLE = "0" ]; then + uci set network.wan.peerdns='0' + uci del network.wan.dns + uci add_list network.wan.dns='208.67.222.222' + uci add_list network.wan.dns='208.67.220.220' +fi +if [ $WANOPENDNS = "0" -a $WANGOOGLE = "1" ]; then + uci set network.wan.peerdns='0' + uci del network.wan.dns + uci add_list network.wan.dns='8.8.8.8' + uci add_list network.wan.dns='8.8.4.4' +fi +if [ $WANOPENDNS = "1" -a $WANGOOGLE = "1" ]; then + uci set network.wan.peerdns='0' + uci del network.wan.dns + uci add_list network.wan.dns='8.8.8.8' + uci add_list network.wan.dns='8.8.4.4' + uci add_list network.wan.dns='208.67.222.222' + uci add_list network.wan.dns='208.67.220.220' +fi +if [ $WANOPENDNS = "0" -a $WANGOOGLE = "0" ]; then + uci set network.wan.peerdns='1' + uci del network.wan.dns +fi +uci commit +/etc/init.d/network restart \ No newline at end of file diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/easyrsa/firewall.sh b/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/easyrsa/firewall.sh new file mode 100644 index 0000000..3ae0752 --- /dev/null +++ b/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/easyrsa/firewall.sh @@ -0,0 +1,73 @@ +#!/bin/sh + +log() { + logger -t "Firewall Settings : " "$@" +} + +sleep 5 +VPN2LAN=$(uci get openvpn.settings.vpn2lan) +if [ -z $VPN2LAN ]; then + VPN2LAN="0" +fi +VPNS2LAN=$(uci get openvpn.settings.vpns2lan) +if [ -z $VPNS2LAN ]; then + VPNS2LAN="0" +fi +VPN2WAN=$(uci get openvpn.settings.vpn2wan) +if [ -z $VPN2WAN ]; then + VPN2WAN="0" +fi + +CHANGE="0" +if [ $VPN2LAN = "1" ]; then + WW=$(uci get firewall.vpnforward1) + if [ -z $WW ]; then + uci set firewall.vpnforward1=forwarding + uci set firewall.vpnforward1.dest="lan" + uci set firewall.vpnforward1.src="VPN" + CHANGE="1" + fi +else + WW=$(uci get firewall.vpnforward1) + if [ ! -z $WW ]; then + uci delete firewall.vpnforward1 + CHANGE="1" + fi +fi + +if [ $VPNS2LAN = "1" ]; then + WW=$(uci get firewall.vpnforwards1) + if [ -z $WW ]; then + uci set firewall.vpnforwards1=forwarding + uci set firewall.vpnforwards1.dest="lan" + uci set firewall.vpnforwards1.src="VPNS" + CHANGE="1" + fi +else + WW=$(uci get firewall.vpnforwards1) + if [ ! -z $WW ]; then + uci delete firewall.vpnforwards1 + CHANGE="1" + fi +fi + +if [ $VPN2WAN = "1" ]; then + WW=$(uci get firewall.vpnforward2) + if [ -z $WW ]; then + uci set firewall.vpnforward2=forwarding + uci set firewall.vpnforward2.dest="wan" + uci set firewall.vpnforward2.src="VPNS" + CHANGE="1" + fi +else + WW=$(uci get firewall.vpnforward2) + if [ ! -z $WW ]; then + uci delete firewall.vpnforward2 + CHANGE="1" + fi +fi + +if [ $CHANGE = "1" ]; then + uci commit firewall + /etc/init.d/firewall restart +fi \ No newline at end of file diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/easyrsa/generate.sh b/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/easyrsa/generate.sh new file mode 100644 index 0000000..17e1704 --- /dev/null +++ b/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/easyrsa/generate.sh @@ -0,0 +1,131 @@ +#!/bin/sh + + rm -f /tmp/easyrsa +### Step 1: Create the PKI directory tree + PKI_DIR="/tmp/openvpn" + +# if [ -d "$PKI_DIR" ]; then + rm -rfv "$PKI_DIR" +# fi + mkdir -p ${PKI_DIR} + chmod -R 0777 ${PKI_DIR} + mkdir -p ${PKI_DIR}/client + chmod -R 0777 ${PKI_DIR}/client + mkdir -p ${PKI_DIR}/server + chmod -R 0777 ${PKI_DIR}/server + mkdir -p ${PKI_DIR}/package + chmod -R 0777 ${PKI_DIR}/package + if [ -d "/www/package" ]; then + rm -rfv "/www/package" + fi + ln -s ${PKI_DIR}/package /www/package + cd ${PKI_DIR} + + touch index.txt + echo 1000 > serial + mkdir newcerts + + +### Step 2: Start with a clean configuration, and establish the basic variables + cp /etc/ssl/openssl.cnf ${PKI_DIR} + PKI_CNF=${PKI_DIR}/openssl.cnf + + CNT=$(uci get openvpn.settings.country) + CTY=$(uci get openvpn.settings.city) + ORG=$(uci get openvpn.settings.organ) + DAYS=$(uci get openvpn.settings.days) + CNAME=$(uci get openvpn.settings.comm) + EMAIL=$(uci get openvpn.settings.email) + UNIT=$(uci get openvpn.settings.unit) + UNSTRUC=$(uci get openvpn.settings.unstruc) + NCLIENT=$(uci get openvpn.settings.nclient) + if [ -z $NCLIENT ]; then + NCLIENT=1 + fi + + sed -i "/^dir/ s:=.*:= ${PKI_DIR}/:" ${PKI_CNF} + sed -i '/.*Name/ s:= match:= optional:' ${PKI_CNF} + + sed -i "/organizationName_default/ s:= .*:= $ORG:" ${PKI_CNF} + sed -i "/stateOrProvinceName_default/ s:= .*:= $CTY:" ${PKI_CNF} + sed -i "/countryName_default/ s:= .*:= $CNT:" ${PKI_CNF} + if [ ! -z $CNAME ]; then + sed -i -e "s/commonName = Common Name (e.g. server FQDN or YOUR name)/commonName = $CNAME/g" ${PKI_CNF} + fi + if [ ! -z $EMAIL ]; then + sed -i -e "s/emailAddress = Email Address/emailAddress = $EMAIL/g" ${PKI_CNF} + fi + if [ ! -z $UNIT ]; then + sed -i -e "s/organizationalUnitName = Organizational Unit Name (eg, section)/organizationalUnitName = $UNIT/g" ${PKI_CNF} + fi + if [ ! -z $UNSTRUC ]; then + sed -i -e "s/unstructuredName = An optional company name/unstructuredName = $UNSTRUC/g" ${PKI_CNF} + fi + + sed -i "/default_days/ s:=.*:= $DAYS:" ${PKI_CNF} + sed -i "/default_bits/ s:=.*:= 2048:" ${PKI_CNF} + + +cat >> ${PKI_CNF} <<"EOF" +############################################################################### +### Check via: openssl x509 -text -noout -in *.crt | grep 509 -A 1 +[ my-server ] +# X509v3 Key Usage: Digital Signature, Key Encipherment +# X509v3 Extended Key Usage: TLS Web Server Authentication + keyUsage = digitalSignature, keyEncipherment + extendedKeyUsage = serverAuth + +[ my-client ] +# X509v3 Key Usage: Digital Signature +# X509v3 Extended Key Usage: TLS Web Client Authentication + keyUsage = digitalSignature + extendedKeyUsage = clientAuth + +EOF + + echo "1" > /tmp/easyrsa + +### Step 3a: Create the CA, Server, and Client certificates (*without* using easy-rsa): +# pkitool --initca ## equivalent to the 'build-ca' script + openssl req -batch -nodes -new -keyout "ca.key" -out "ca.crt" -x509 -days $DAYS -config ${PKI_CNF} 2> /dev/null ## x509 (self-signed) for the CA + + echo "2" > /tmp/easyrsa +# pkitool --server my-server ## equivalent to the 'build-key-server' script + openssl req -batch -nodes -new -keyout "$ORG-server.key" -out "$ORG-server.csr" -subj "/CN=$ORG-server" -config ${PKI_CNF} 2> /dev/null + openssl ca -batch -keyfile "ca.key" -cert "ca.crt" -in "$ORG-server.csr" -out "$ORG-server.crt" -config ${PKI_CNF} -extensions my-server 2> /dev/null + + echo "3" > /tmp/easyrsa +# pkitool my-client ## equivalent to the 'build-key' script + COUNTER=$NCLIENT + while [ $COUNTER -gt 0 ]; do + openssl req -batch -nodes -new -keyout "$ORG-client$COUNTER.key" -out "$ORG-client$COUNTER.csr" -subj "/CN=$ORG-client$COUNTER" -config ${PKI_CNF} 2> /dev/null + openssl ca -batch -keyfile "ca.key" -cert "ca.crt" -in "$ORG-client$COUNTER.csr" -out "$ORG-client$COUNTER.crt" -config ${PKI_CNF} -extensions my-client 2> /dev/null + let COUNTER=COUNTER-1 + done + + chmod 0600 "ca.key" + chmod 0600 "$ORG-server.key" + COUNTER=$NCLIENT + while [ $COUNTER -gt 0 ]; do + chmod 0600 "$ORG-client$COUNTER.key" + cp "$ORG-client$COUNTER.crt" ${PKI_DIR}/client + cp "$ORG-client$COUNTER.key" ${PKI_DIR}/client + let COUNTER=COUNTER-1 + done + + cp "ca.crt" ${PKI_DIR}/client + cp "ca.crt" ${PKI_DIR}/server + cp "$ORG-server.key" ${PKI_DIR}/server + cp "$ORG-server.crt" ${PKI_DIR}/server + + echo "4" > /tmp/easyrsa +### Step 4: Create the Diffie-Hellman parameters + openssl dhparam -out dh2048.pem 2048 2> /dev/null + cp "dh2048.pem" ${PKI_DIR}/server + + echo "5" > /tmp/easyrsa + + + tar -czf ${PKI_DIR}/package/certificates.tar.gz ./client ./server + sleep 7 + echo "6" > /tmp/easyrsa \ No newline at end of file diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/easyrsa/stop.sh b/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/easyrsa/stop.sh new file mode 100644 index 0000000..e9088c9 --- /dev/null +++ b/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/easyrsa/stop.sh @@ -0,0 +1,11 @@ +#!/bin/sh + +result=`ps | grep -i "generate.sh" | grep -v "grep" | wc -l` +if [ $result -ge 1 ]; then + rkillall generate.sh + rm -f /tmp/easyrsa + PKI_DIR="/etc/openvpn/ssl" + if [ -d "$PKI_DIR" ]; then + rm -rfv "$PKI_DIR" + fi +fi \ No newline at end of file diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/easyrsa/vpn.sh b/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/easyrsa/vpn.sh new file mode 100644 index 0000000..e99b9b9 --- /dev/null +++ b/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/easyrsa/vpn.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +log() { + logger -t "OpenVpn Vpn" "$@" +} + +/etc/init.d/openvpn stop $1 +sleep 5 + diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/easyrsa/vpng.sh b/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/easyrsa/vpng.sh new file mode 100644 index 0000000..8b34078 --- /dev/null +++ b/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/easyrsa/vpng.sh @@ -0,0 +1,128 @@ +#!/bin/sh +. /lib/functions.sh + +convert() { + secs=$1 + csec=$(printf "%02d:%02d:%02d" $(($secs/3600)) $(($secs%3600/60)) $(($secs%60))) +} + +clist() { + SDIR="/tmp/run" + + STAT=$SDIR"/openvpn."$1".status" + + COUNT=0 + RT=0 + TT="Virtual Address Common Name Real Address" + while read -r line; do + name="$line" + RTT=$(echo "$name" | grep "Virtual Address") + if [ ! -z "$RTT" ]; then + RT=1 + fi + RTT=$(echo "$name" | grep "GLOBAL STATS") + if [ ! -z "$RTT" ]; then + RT=0 + fi + if [ $RT = 1 ]; then + if [ $COUNT -gt 0 ]; then + vip=$(echo "$name" | cut -d, -f1) + com=$(echo "$name" | cut -d, -f2) + rel=$(echo "$name" | cut -d, -f3) + TT="$TT $vip $com $rel" + fi + let COUNT=COUNT+1 + fi + done < "$STAT" + if [ $COUNT -le 1 ]; then + TT="No clients" + COUNT=0 + else + let COUNT=COUNT-1 + fi +} + +rm -f /tmp/vpn + +vpn_instance() { + local s="$1" + echo "$s " >> /tmp/vpn + config_get config "$s" config + if [ -z $config ]; then + config_get_bool client "$s" client 0 + else + client=1 + fi + echo "$client" >> /tmp/vpn + config_get_bool enabled "$s" 'enabled' 0 + echo "$enabled" >> /tmp/vpn + + result=`ps | grep -i "/usr/sbin/openvpn --syslog openvpn($s)" | grep -v "grep" | wc -l` + if [ $result -ge 1 ] + then + echo "1" >> /tmp/vpn + else + echo "0" >> /tmp/vpn + fi + + if [ -z $config ]; then + config_get port "$s" port + if [ -z $port ]; then + echo "1194" >> /tmp/vpn + else + echo "$port" >> /tmp/vpn + fi + config_get proto "$s" proto + if [ -z $proto ]; then + echo "udp" >> /tmp/vpn + else + echo "$proto" >> /tmp/vpn + fi + else + prott=$(cat "$config" | grep -i "proto " | tr " " ",") + prot=$(echo "$prott" | cut -d, -f2) + remtt=$(cat "$config" | grep -i -m 1 "remote " | tr " " ",") + remt=$(echo "$remtt" | cut -d, -f3) + echo "$remt" >> /tmp/vpn + echo "$prot" >> /tmp/vpn + fi + if [ $client = "0" ]; then + echo "---" >> /tmp/vpn + if [ $result -ge 1 ]; then + clist $s + echo "$COUNT" >> /tmp/vpn + echo "$TT" >> /tmp/vpn + else + echo "0" >> /tmp/vpn + echo "Not running" >> /tmp/vpn + fi + else + if [ -z $config ]; then + config_get remote "$s" remote + echo "$remote" >> /tmp/vpn + else + remtt=$(cat "$config" | grep -i -m 1 "remote " | tr " " ",") + remt=$(echo "$remtt" | cut -d, -f2) + echo "$remt" >> /tmp/vpn + fi + echo "---" >> /tmp/vpn + echo "not server" >> /tmp/vpn + fi + if [ $result -ge 1 ] + then + config_get laststart "$s" laststart + CURRTIME=$(date +%s) + let upt=CURRTIME-laststart + convert $upt + upt=$csec + else + upt="---" + fi + echo "$upt" >> /tmp/vpn +} + +config_load 'openvpn' +config_foreach vpn_instance 'openvpn' + +exit 0 + diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/controller/openvpn.lua b/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/controller/openvpn.lua new file mode 100644 index 0000000..80dbf89 --- /dev/null +++ b/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/controller/openvpn.lua @@ -0,0 +1,135 @@ +-- Copyright 2008 Steven Barth +-- Copyright 2008 Jo-Philipp Wich +-- Licensed to the public under the Apache License 2.0. + +module("luci.controller.openvpn", package.seeall) + +I18N = require "luci.i18n" +translate = I18N.translate + +function index() + 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 + entry({"admin", "vpn"}, firstchild(), translate("VPN"), 30).dependent=false + entry( {"admin", "vpn", "openvpn"}, cbi("openvpn"), _(translate("OpenVPN")), 1 ) + entry( {"admin", "vpn", "openvpn-server"}, cbi("openvpn-server"), _(translate("--OpenVPN Extras")), 2 ) + + entry( {"admin", "vpn", "openvpn", "basic"}, cbi("openvpn-basic"), nil ).leaf = true + entry( {"admin", "vpn", "openvpn", "advanced"}, cbi("openvpn-advanced"), nil ).leaf = true + entry( {"admin", "vpn", "openvpn", "file"}, form("openvpn-file"), nil ).leaf = true + entry( {"admin", "vpn", "openvpn", "upload"}, call("ovpn_upload")) + end + + entry({"admin", "vpn", "vpnstatus"}, call("action_vpnstatus")) + entry({"admin", "vpn", "rsastatus"}, call("action_status")) + entry({"admin", "vpn", "rsagenerate"}, call("action_generate")) + entry({"admin", "vpn", "rsastop"}, call("action_stop")) +end + +function ovpn_upload() + local fs = require("nixio.fs") + local http = require("luci.http") + local util = require("luci.util") + local uci = require("luci.model.uci").cursor() + local upload = http.formvalue("ovpn_file") + local name = http.formvalue("instance_name2") + local file = "/etc/openvpn/" ..name.. ".ovpn" + + if name and upload then + local fp + + http.setfilehandler( + function(meta, chunk, eof) + local data = util.trim(chunk:gsub("\r\n", "\n")) .. "\n" + data = util.trim(data:gsub("[\128-\255]", "")) + + if not fp and meta and meta.name == "ovpn_file" then + fp = io.open(file, "w") + end + if fp and data then + fp:write(data) + end + if fp and eof then + fp:close() + end + end + ) + + if fs.access(file) then + if not uci:get_first("openvpn", name) then + uci:set("openvpn", name, "openvpn") + uci:set("openvpn", name, "config", file) + uci:save("openvpn") + uci:commit("openvpn") + end + end + end + http.redirect(luci.dispatcher.build_url('admin/vpn/openvpn')) +end + +function action_status() + local rv = {} + + file = io.open("/tmp/easyrsa", "r") + if file ~= nil then + rv["status"] = file:read("*line") + file:close() + else + rv["status"] = "0" + end + + luci.http.prepare_content("application/json") + luci.http.write_json(rv) +end + +function action_generate() + os.execute("/usr/lib/easyrsa/generate.sh &") +end + +function action_stop() + os.execute("/usr/lib/easyrsa/stop.sh") +end + +function action_vpnstatus() + local rv ={} + + os.execute("/usr/lib/easyrsa/vpng.sh") + local file = io.open("/tmp/vpn", "r") + if file ~= nil then + i = 0 + name = file:read("*line") + while name ~= nil do + vpntype = file:read("*line") + enabled = file:read("*line") + started = file:read("*line") + port = file:read("*line") + proto = file:read("*line") + remote = file:read("*line") + clients = file:read("*line") + tooltip = file:read("*line") + laststart = file:read("*line") + rv[#rv+1] = { + name = name, + vpntype = vpntype, + enabled = enabled, + started = started, + port = port, + proto = proto, + remote = remote, + clients = clients, + tooltip = tooltip, + laststart = laststart + } + name = file:read("*line") + end + file:close() + else + rv[#rv+1] = { + enabled = "-1", + } + end + + luci.http.prepare_content("application/json") + luci.http.write_json(rv) +end \ No newline at end of file diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/model/cbi/openvpn-advanced.lua b/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/model/cbi/openvpn-advanced.lua new file mode 100644 index 0000000..a79288d --- /dev/null +++ b/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/model/cbi/openvpn-advanced.lua @@ -0,0 +1,902 @@ +-- Copyright 2008 Steven Barth +-- Licensed to the public under the Apache License 2.0. + +local fs = require("nixio.fs") + +local knownParams = { + -- + --Widget + -- Name + -- Default(s) + -- Description + -- Option(s) + + { "Service", { + -- initialisation and daemon options + { ListValue, + "verb", + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }, + translate("Set output verbosity") }, + { Flag, + "mlock", + 0, + translate("Disable Paging") }, + { Flag, + "disable_occ", + 0, + translate("Disable options consistency check") }, + -- { Value, + -- "user", + -- "root", + -- translate("Set UID to user") }, + -- { Value, + -- "group", + -- "root", + -- translate("Set GID to group") }, + { Value, + "cd", + "/etc/openvpn", + translate("Change to directory before initialization") }, + { Value, + "chroot", + "/var/run", + translate("Chroot to directory after initialization") }, + -- { Value, + -- "daemon", + -- "Instance-Name", + -- translate("Daemonize after initialization") }, + -- { Value, + -- "syslog", + -- "Instance-Name", + -- translate("Output to syslog and do not daemonize") }, + { Flag, + "passtos", + 0, + translate("TOS passthrough (applies to IPv4 only)") }, + -- { Value, + -- "inetd", + -- "nowait Instance-Name", + -- translate("Run as an inetd or xinetd server") }, + { Value, + "log", + "/var/log/openvpn.log", + translate("Write log to file") }, + { Value, + "log_append", + "/var/log/openvpn.log", + translate("Append log to file") }, + { Flag, + "suppress_timestamps", + 0, + translate("Don't log timestamps") }, + -- { Value, + -- "writepid", + -- "/var/run/openvpn.pid", + -- translate("Write process ID to file") }, + { Value, + "nice", + 0, + translate("Change process priority") }, + { Flag, + "fast_io", + 0, + translate("Optimize TUN/TAP/UDP writes") }, + { Value, + "echo", + "some params echoed to log", + translate("Echo parameters to log") }, + { ListValue, + "remap_usr1", + { "SIGHUP", "SIGTERM" }, + translate("Remap SIGUSR1 signals") }, + { Value, + "status", + "/var/run/openvpn.status 5", + translate("Write status to file every n seconds") }, + { Value, + "status_version", + { 1, 2 }, + translate("Status file format version") }, -- status + { Value, + "mute", + 5, + translate("Limit repeated log messages") }, + { Value, + "up", + "/usr/bin/ovpn-up", + translate("Shell cmd to execute after tun device open") }, + { Value, + "up_delay", + 5, + translate("Delay tun/tap open and up script execution") }, + { Value, + "down", + "/usr/bin/ovpn-down", + translate("Shell cmd to run after tun device close") }, + { Flag, + "down_pre", + 0, + translate("Call down cmd/script before TUN/TAP close") }, + { Flag, + "up_restart", + 0, + translate("Run up/down scripts for all restarts") }, + { Value, + "route_up", + "/usr/bin/ovpn-routeup", + translate("Execute shell cmd after routes are added") }, + { Value, + "ipchange", + "/usr/bin/ovpn-ipchange", + translate("Execute shell command on remote ip change"), + { mode="p2p" } }, + { DynamicList, + "setenv", + { "VAR1 value1", "VAR2 value2" }, + translate("Pass environment variables to script") }, + { Value, + "tls_verify", + "/usr/bin/ovpn-tlsverify", + translate("Shell command to verify X509 name") }, + { Value, + "client_connect", + "/usr/bin/ovpn-clientconnect", + translate("Run script cmd on client connection") }, + { Value, + "client_disconnect", + "/usr/bin/ovpn-clientdisconnect", + translate("Run script cmd on client disconnection") }, + { Value, + "learn_address", + "/usr/bin/ovpn-learnaddress", + translate("Executed in server mode whenever an IPv4 address/route or MAC address is added to OpenVPN's internal routing table") }, + { Value, + "auth_user_pass_verify", + "/usr/bin/ovpn-userpass via-env", + translate("Executed in server mode on new client connections, when the client is still untrusted") }, + { ListValue, + "script_security", + { 0, 1, 2, 3 }, + translate("Policy level over usage of external programs and scripts") }, + { ListValue, + "compress", + { "lzo", "lz4" }, + translate("Enable a compression algorithm") }, + } }, + + { "Networking", { + -- socket config + { ListValue, + "mode", + { "p2p", "server" }, + translate("Major mode") }, + { Value, + "local", + "0.0.0.0", + translate("Local host name or ip address") }, + { Value, + "port", + 1194, + translate("TCP/UDP port # for both local and remote") }, + { Value, + "lport", + 1194, + translate("TCP/UDP port # for local (default=1194)") }, + { Value, + "rport", + 1194, + translate("TCP/UDP port # for remote (default=1194)") }, + { Flag, + "float", + 0, + translate("Allow remote to change its IP or port") }, + { Flag, + "nobind", + 0, + translate("Do not bind to local address and port") }, + { Value, + "dev", + "tun0", + translate("tun/tap device") }, + { ListValue, + "dev_type", + { "tun", "tap" }, + translate("Type of used device") }, + { Value, + "dev_node", + "/dev/net/tun", + translate("Use tun/tap device node") }, + { Value, + "ifconfig", + "10.200.200.3 10.200.200.1", + translate("Set tun/tap adapter parameters") }, + { Flag, + "ifconfig_noexec", + 0, + translate("Don't actually execute ifconfig") }, + { Flag, + "ifconfig_nowarn", + 0, + translate("Don't warn on ifconfig inconsistencies") }, + { DynamicList, + "route", + "10.123.0.0 255.255.0.0", + translate("Add route after establishing connection") }, + { Value, + "route_gateway", + "10.234.1.1", + translate("Specify a default gateway for routes") }, + { Value, + "route_delay", + 0, + translate("Delay n seconds after connection") }, + { Flag, + "route_noexec", + 0, + translate("Don't add routes automatically") }, + { Flag, + "route_nopull", + 0, + translate("Don't pull routes automatically") }, + { Flag, + "allow_recursive_routing", + 0, + translate("Don't drop incoming tun packets with same destination as host") }, + { ListValue, + "mtu_disc", + { "yes", "maybe", "no" }, + translate("Enable Path MTU discovery") }, + { Flag, + "mtu_test", + 0, + translate("Empirically measure MTU") }, + { ListValue, + "comp_lzo", + { "yes", "no", "adaptive" }, + translate("Use fast LZO compression") }, + { Flag, + "comp_noadapt", + 0, + translate("Don't use adaptive lzo compression"), + { comp_lzo=1 } }, + { Value, + "link_mtu", + 1500, + translate("Set TCP/UDP MTU") }, + { Value, + "tun_mtu", + 1500, + translate("Set tun/tap device MTU") }, + { Value, + "tun_mtu_extra", + 1500, + translate("Set tun/tap device overhead") }, + { Value, + "fragment", + 1500, + translate("Enable internal datagram fragmentation"), + { proto="udp" } }, + { Value, + "mssfix", + 1500, + translate("Set upper bound on TCP MSS"), + { proto="udp" } }, + { Value, + "sndbuf", + 65536, + translate("Set the TCP/UDP send buffer size") }, + { Value, + "rcvbuf", + 65536, + translate("Set the TCP/UDP receive buffer size") }, + { Value, + "txqueuelen", + 100, + translate("Set tun/tap TX queue length") }, + { Value, + "shaper", + 10240, + translate("Shaping for peer bandwidth") }, + { Value, + "inactive", + 240, + translate("tun/tap inactivity timeout") }, + { Value, + "keepalive", + "10 60", + translate("Helper directive to simplify the expression of --ping and --ping-restart in server mode configurations") }, + { Value, + "ping", + 30, + translate("Ping remote every n seconds over TCP/UDP port") }, + { Value, + "ping_exit", + 120, + translate("Remote ping timeout") }, + { Value, + "ping_restart", + 60, + translate("Restart after remote ping timeout") }, + { Flag, + "ping_timer_rem", + 0, + translate("Only process ping timeouts if routes exist") }, + { Flag, + "persist_tun", + 0, + translate("Keep tun/tap device open on restart") }, + { Flag, + "persist_key", + 0, + translate("Don't re-read key on restart") }, + { Flag, + "persist_local_ip", + 0, + translate("Keep local IP address on restart") }, + { Flag, + "persist_remote_ip", + 0, + translate("Keep remote IP address on restart") }, + -- management channel + { Value, + "management", + "127.0.0.1 31194 /etc/openvpn/mngmt-pwds", + translate("Enable management interface on IP port") }, + -- management + { Flag, + "management_query_passwords", + 0, + translate("Query management channel for private key") }, + -- management + { Flag, + "management_hold", + 0, + translate("Start OpenVPN in a hibernating state") }, + -- management + { Value, + "management_log_cache", + 100, + translate("Number of lines for log file history") }, + { ListValue, + "topology", + { "net30", "p2p", "subnet" }, + translate("'net30', 'p2p', or 'subnet'"), + {dev_type="tun" } }, + } }, + + { "VPN", { + { Value, + "server", + "10.200.200.0 255.255.255.0", + translate("Configure server mode"), + { client="0" }, { client="" } }, + { Value, + "server_bridge", + "10.200.200.1 255.255.255.0 10.200.200.200 10.200.200.250", + translate("Configure server bridge"), + { client="0" }, { client="" } }, + { DynamicList, + "push", + { "redirect-gateway", "comp-lzo" }, + translate("Push options to peer"), + { client="0" }, { client="" } }, + { Flag, + "push_reset", + 0, + translate("Don't inherit global push options"), + { client="0" }, { client="" } }, + { Flag, + "disable", + 0, + translate("Client is disabled"), + { client="0" }, { client="" } }, + { Value, + "ifconfig_pool", + "10.200.200.100 10.200.200.150 255.255.255.0", + translate("Set aside a pool of subnets"), + { client="0" }, { client="" } }, + { Value, + "ifconfig_pool_persist", + "/etc/openvpn/ipp.txt 600", + translate("Persist/unpersist ifconfig-pool"), + { client="0" }, { client="" } }, + { Value, + "ifconfig_push", + "10.200.200.1 255.255.255.255", + translate("Push an ifconfig option to remote"), + { client="0" }, { client="" } }, + { Value, + "iroute", + "10.200.200.0 255.255.255.0", + translate("Route subnet to client"), + { client="0" }, { client="" } }, + { Flag, + "client_to_client", + 0, + translate("Allow client-to-client traffic"), + { client="0" }, { client="" } }, + { Flag, + "duplicate_cn", + 0, + translate("Allow multiple clients with same certificate"), + { client="0" }, { client="" } }, + { Value, + "client_config_dir", + "/etc/openvpn/ccd", + translate("Directory for custom client config files"), + { client="0" }, { client="" } }, + { Flag, + "ccd_exclusive", + 0, + translate("Refuse connection if no custom client config"), + { client="0" }, { client="" } }, + { Value, + "tmp_dir", + "/var/run/openvpn", + translate("Temporary directory for client-connect return file"), + { client="0" }, { client="" } }, + { Value, + "hash_size", + "256 256", + translate("Set size of real and virtual address hash tables"), + { client="0" }, { client="" } }, + { Value, + "bcast_buffers", + 256, + translate("Number of allocated broadcast buffers"), + { client="0" }, { client="" } }, + { Value, + "tcp_queue_limit", + 64, + translate("Maximum number of queued TCP output packets"), + { client="0" }, { client="" } }, + { Value, + "max_clients", + 10, + translate("Allowed maximum of connected clients"), + { client="0" }, { client="" } }, + { Value, + "max_routes_per_client", + 256, + translate("Allowed maximum of internal"), + { client="0" }, { client="" } }, + { Value, + "connect_freq", + "3 10", + translate("Allowed maximum of new connections"), + { client="0" }, { client="" } }, + { Flag, + "username_as_common_name", + 0, + translate("Use username as common name"), + { client="0" }, { client="" } }, + { Flag, + "client", + 0, + translate("Configure client mode") }, + { Flag, + "pull", + 0, + translate("Accept options pushed from server"), + { client="1" } }, + { FileUpload, + "auth_user_pass", + "/etc/openvpn/userpass.txt", + translate("Authenticate using username/password"), + { client="1" } }, + { ListValue, + "auth_retry", + { "none", "nointeract", "interact" }, + translate("Handling of authentication failures"), + { client="1" } }, + { Value, + "explicit_exit_notify", + 1, + translate("Send notification to peer on disconnect"), + { client="1" } }, + { DynamicList, + "remote", + "1.2.3.4", + translate("Remote host name or ip address") }, + { Flag, + "remote_random", + 0, + translate("Randomly choose remote server"), + { client="1" } }, + { ListValue, + "proto", + { "udp", "tcp-client", "tcp-server" }, + translate("Use protocol"), + { client="1" } }, + { Value, + "connect_retry", + 5, + translate("Connection retry interval"), + { proto="tcp-client" }, { client="1" } }, + { Value, + "http_proxy", + "192.168.1.100 8080", + translate("Connect to remote host through an HTTP proxy"), + { client="1" } }, + { Flag, + "http_proxy_retry", + 0, + translate("Retry indefinitely on HTTP proxy errors"), + { client="1" } }, + { Value, + "http_proxy_timeout", + 5, + translate("Proxy timeout in seconds"), + { client="1" } }, + { DynamicList, + "http_proxy_option", + { "VERSION 1.0", "AGENT OpenVPN/2.0.9" }, + translate("Set extended HTTP proxy options"), + { client="1" } }, + { Value, + "socks_proxy", + "192.168.1.200 1080", + translate("Connect through Socks5 proxy"), + { client="1" } }, + -- client && socks_proxy + { Value, + "socks_proxy_retry", + 5, + translate("Retry indefinitely on Socks proxy errors"), + { client="1" } }, + { Value, + "resolv_retry", + "infinite", + translate("If hostname resolve fails, retry"), + { client="1" } }, + { ListValue, + "redirect_gateway", + { "", "local", "def1", "local def1" }, + translate("Automatically redirect default route"), + { client="1" } }, + { Value, + "verify_client_cert", + { "none", "optional", "require" }, + translate("Specify whether the client is required to supply a valid certificate") }, + } }, + + { "Cryptography", { + { FileUpload, + "secret", + "/etc/openvpn/secret.key", + translate("Enable Static Key encryption mode (non-TLS)") }, + -- parse + { Value, + "auth", + "SHA1", + translate("HMAC authentication for packets") }, + -- parse + { Value, + "cipher", + { + "AES-128-CBC", + "AES-128-CFB", + "AES-128-CFB1", + "AES-128-CFB8", + "AES-128-GCM", + "AES-128-OFB", + "AES-192-CBC", + "AES-192-CFB", + "AES-192-CFB1", + "AES-192-CFB8", + "AES-192-GCM", + "AES-192-OFB", + "AES-256-CBC", + "AES-256-CFB", + "AES-256-CFB1", + "AES-256-CFB8", + "AES-256-GCM", + "AES-256-OFB", + "BF-CBC", + "BF-CFB", + "BF-OFB", + "CAST5-CBC", + "CAST5-CFB", + "CAST5-OFB", + "DES-CBC", + "DES-CFB", + "DES-CFB1", + "DES-CFB8", + "DES-EDE-CBC", + "DES-EDE-CFB", + "DES-EDE-OFB", + "DES-EDE3-CBC", + "DES-EDE3-CFB", + "DES-EDE3-CFB1", + "DES-EDE3-CFB8", + "DES-EDE3-OFB", + "DES-OFB", + "DESX-CBC", + "RC2-40-CBC", + "RC2-64-CBC", + "RC2-CBC", + "RC2-CFB", + "RC2-OFB" + }, + translate("Encryption cipher for packets") }, + -- parse + { Value, + "keysize", + 1024, + translate("Size of cipher key") }, + -- parse + { Value, + "engine", + "dynamic", + translate("Enable OpenSSL hardware crypto engines") }, + { Value, + "replay_window", + "64 15", + translate("Replay protection sliding window size") }, + { Flag, + "mute_replay_warnings", + 0, + translate("Silence the output of replay warnings") }, + { Value, + "replay_persist", + "/var/run/openvpn-replay-state", + translate("Persist replay-protection state") }, + { Flag, + "tls_server", + 0, + translate("Enable TLS and assume server role"), + { tls_client="" }, { tls_client="0" } }, + { Flag, + "tls_client", + 0, + translate("Enable TLS and assume client role"), + { tls_server="" }, { tls_server="0" } }, + { FileUpload, + "ca", + "/etc/easy-rsa/keys/ca.crt", + translate("Certificate authority") }, + { FileUpload, + "dh", + "/etc/easy-rsa/keys/dh1024.pem", + translate("Diffie Hellman parameters") }, + { FileUpload, + "cert", + "/etc/easy-rsa/keys/some-client.crt", + translate("Local certificate") }, + { FileUpload, + "key", + "/etc/easy-rsa/keys/some-client.key", + translate("Local private key") }, + { FileUpload, + "pkcs12", + "/etc/easy-rsa/keys/some-client.pk12", + translate("PKCS#12 file containing keys") }, + { ListValue, + "key_method", + { 1, 2 }, + translate("Enable TLS and assume client role") }, + { DynamicList, + "tls_cipher", + { + "DHE-RSA-AES256-SHA", + "DHE-DSS-AES256-SHA", + "AES256-SHA", + "EDH-RSA-DES-CBC3-SHA", + "EDH-DSS-DES-CBC3-SHA", + "DES-CBC3-SHA", + "DHE-RSA-AES128-SHA", + "DHE-DSS-AES128-SHA", + "AES128-SHA", + "RC4-SHA", + "RC4-MD5", + "EDH-RSA-DES-CBC-SHA", + "EDH-DSS-DES-CBC-SHA", + "DES-CBC-SHA", + "EXP-EDH-RSA-DES-CBC-SHA", + "EXP-EDH-DSS-DES-CBC-SHA", + "EXP-DES-CBC-SHA", + "EXP-RC2-CBC-MD5", + "EXP-RC4-MD5" + }, + translate("TLS cipher") }, + { DynamicList, + "tls_ciphersuites", + { + "TLS_AES_256_GCM_SHA384", + "TLS_AES_128_GCM_SHA256", + "TLS_CHACHA20_POLY1305_SHA256" + }, + translate("TLS 1.3 or newer cipher") }, + { Value, + "tls_timeout", + 2, + translate("Retransmit timeout on TLS control channel") }, + { Value, + "reneg_bytes", + 1024, + translate("Renegotiate data chan. key after bytes") }, + { Value, + "reneg_pkts", + 100, + translate("Renegotiate data chan. key after packets") }, + { Value, + "reneg_sec", + 3600, + translate("Renegotiate data chan. key after seconds") }, + { Value, + "hand_window", + 60, + translate("Timeframe for key exchange") }, + { Value, + "tran_window", + 3600, + translate("Key transition window") }, + { Flag, + "single_session", + 0, + translate("Allow only one session") }, + { Flag, + "tls_exit", + 0, + translate("Exit on TLS negotiation failure") }, + { Value, + "tls_auth", + "/etc/openvpn/tlsauth.key", + translate("Additional authentication over TLS") }, + { Value, + "tls_crypt", + "/etc/openvpn/tlscrypt.key", + translate("Encrypt and authenticate all control channel packets with the key") }, + -- { Value, + -- "askpass", + -- "[file]", + -- translate("Get PEM password from controlling tty before we daemonize") }, + { Flag, + "auth_nocache", + 0, + translate("Don't cache --askpass or --auth-user-pass passwords") }, + { Value, + "tls_remote", + "remote_x509_name", + translate("Only accept connections from given X509 name") }, + { ListValue, + "ns_cert_type", + { "client", "server" }, + translate("Require explicit designation on certificate") }, + { ListValue, + "remote_cert_tls", + { "client", "server" }, + translate("Require explicit key usage on certificate") }, + { Value, + "crl_verify", + "/etc/easy-rsa/keys/crl.pem", + translate("Check peer certificate against a CRL") }, + { Value, + "tls_version_min", + "1.0", + translate("The lowest supported TLS version") }, + { Value, + "tls_version_max", + "1.2", + translate("The highest supported TLS version") }, + { ListValue, + "key_direction", + { 0, 1 }, + translate("The key direction for 'tls-auth' and 'secret' options") }, + { Flag, + "ncp_disable", + 0, + translate("This completely disables cipher negotiation") }, + { Value, + "ncp_ciphers", + "AES-256-GCM:AES-128-GCM", + translate("Restrict the allowed ciphers to be negotiated") }, + } } +} + + +local cts = { } +local params = { } + +local m = Map("openvpn") +m.redirect = luci.dispatcher.build_url("admin", "vpn", "openvpn") +m.apply_on_parse = true + +local p = m:section( SimpleSection ) +p.template = "openvpn/pageswitch" +p.mode = "advanced" +p.instance = arg[1] +p.category = arg[2] or "Service" + +for _, c in ipairs(knownParams) do + cts[#cts+1] = c[1] + if c[1] == p.category then params = c[2] end +end + +p.categories = cts + + +local s = m:section( + NamedSection, arg[1], "openvpn", + translate("%s" % arg[2]) +) + +s.title = translate("%s" % arg[2]) +s.addremove = false +s.anonymous = true + + +for _, option in ipairs(params) do + local o = s:option( + option[1], option[2], + option[2], option[4] + ) + + o.optional = true + + if option[1] == DummyValue then + o.value = option[3] + elseif option[1] == FileUpload then + + o.initial_directory = "/etc/openvpn" + + function o.cfgvalue(self, section) + local cfg_val = AbstractValue.cfgvalue(self, section) + + if cfg_val then + return cfg_val + end + end + + function o.formvalue(self, section) + local sel_val = AbstractValue.formvalue(self, section) + local txt_val = luci.http.formvalue("cbid."..self.map.config.."."..section.."."..self.option..".textbox") + + if sel_val and sel_val ~= "" then + return sel_val + end + + if txt_val and txt_val ~= "" then + return txt_val + end + end + + function o.remove(self, section) + local cfg_val = AbstractValue.cfgvalue(self, section) + local txt_val = luci.http.formvalue("cbid."..self.map.config.."."..section.."."..self.option..".textbox") + + if cfg_val and fs.access(cfg_val) and txt_val == "" then + fs.unlink(cfg_val) + end + return AbstractValue.remove(self, section) + end + elseif option[1] == Flag then + o.default = nil + else + if option[1] == DynamicList then + function o.cfgvalue(...) + local val = AbstractValue.cfgvalue(...) + return ( val and type(val) ~= "table" ) and { val } or val + end + end + + if type(option[3]) == "table" then + if o.optional then o:value("", "-- remove --") end + for _, v in ipairs(option[3]) do + v = tostring(v) + o:value(v) + end + o.default = tostring(option[3][1]) + else + o.default = tostring(option[3]) + end + end + + for i=5,#option do + if type(option[i]) == "table" then + o:depends(option[i]) + end + end +end + +return m diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/model/cbi/openvpn-basic.lua b/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/model/cbi/openvpn-basic.lua new file mode 100644 index 0000000..dbab780 --- /dev/null +++ b/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/model/cbi/openvpn-basic.lua @@ -0,0 +1,196 @@ +-- Copyright 2008 Steven Barth +-- Licensed to the public under the Apache License 2.0. + +local fs = require("nixio.fs") + +local basicParams = { + -- + -- Widget, Name, Default(s), Description + -- + { ListValue, + "verb", + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }, + translate("Set output verbosity") }, + { Value, + "nice", + 0, + translate("Change process priority") }, + { Value, + "port", + 1194, + translate("TCP/UDP port # for both local and remote") }, + { ListValue, + "dev_type", + { "tun", "tap" }, + translate("Type of used device") }, + { Value, + "ifconfig", + "10.200.200.3 10.200.200.1", + translate("Set tun/tap adapter parameters") }, + { Value, + "server", + "10.200.200.0 255.255.255.0", + translate("Configure server mode") }, + { Value, + "server_bridge", + "192.168.1.1 255.255.255.0 192.168.1.128 192.168.1.254", + translate("Configure server bridge") }, + { Flag, + "nobind", + 0, + translate("Do not bind to local address and port") }, + { ListValue, + "comp_lzo", + {"yes","no","adaptive"}, + translate("Use fast LZO compression") }, + { Value, + "keepalive", + "10 60", + translate("Helper directive to simplify the expression of --ping and --ping-restart in server mode configurations") }, + { Flag, + "client", + 0, + translate("Configure client mode") }, + { Flag, + "client_to_client", + 0, + translate("Allow client-to-client traffic") }, + { DynamicList, + "remote", + "vpnserver.example.org", + translate("Remote host name or ip address") }, + { FileUpload, + "secret", + "/etc/openvpn/secret.key", + translate("Enable Static Key encryption mode (non-TLS)") }, + { ListValue, + "key_direction", + { 0, 1 }, + translate("The key direction for 'tls-auth' and 'secret' options") }, + { FileUpload, + "pkcs12", + "/etc/easy-rsa/keys/some-client.pk12", + translate("PKCS#12 file containing keys") }, + { FileUpload, + "ca", + "/etc/easy-rsa/keys/ca.crt", + translate("Certificate authority") }, + { FileUpload, + "dh", + "/etc/easy-rsa/keys/dh1024.pem", + translate("Diffie Hellman parameters") }, + { FileUpload, + "cert", + "/etc/easy-rsa/keys/some-client.crt", + translate("Local certificate") }, + { FileUpload, + "key", + "/etc/easy-rsa/keys/some-client.key", + translate("Local private key") }, + { FileUpload, + "auth_user_pass", + "/etc/easy-rsa/keys/some-client.pass", + translate("Password file") }, +} + +local has_ipv6 = fs.access("/proc/net/ipv6_route") +if has_ipv6 then + table.insert( basicParams, { ListValue, + "proto", + { "udp", "tcp-client", "tcp-server", "udp4", "tcp4-client", "tcp4-server","udp6", "tcp6-client", "tcp6-server" }, + translate("Use protocol") + }) +else + table.insert( basicParams, { ListValue, + "proto", + { "udp", "tcp-client", "tcp-server" }, + translate("Use protocol") + }) +end + +local m = Map("openvpn") +m.redirect = luci.dispatcher.build_url("admin", "vpn", "openvpn") +m.apply_on_parse = true + +local p = m:section( SimpleSection ) +p.template = "openvpn/pageswitch" +p.mode = "basic" +p.instance = arg[1] + + +local s = m:section( NamedSection, arg[1], "openvpn" ) + +for _, option in ipairs(basicParams) do + local o = s:option( + option[1], option[2], + option[2], option[4] + ) + + o.optional = true + + if option[1] == DummyValue then + o.value = option[3] + elseif option[1] == FileUpload then + + o.initial_directory = "/etc/openvpn" + + function o.cfgvalue(self, section) + local cfg_val = AbstractValue.cfgvalue(self, section) + + if cfg_val then + return cfg_val + end + end + + function o.formvalue(self, section) + local sel_val = AbstractValue.formvalue(self, section) + local txt_val = luci.http.formvalue("cbid."..self.map.config.."."..section.."."..self.option..".textbox") + + if sel_val and sel_val ~= "" then + return sel_val + end + + if txt_val and txt_val ~= "" then + return txt_val + end + end + + function o.remove(self, section) + local cfg_val = AbstractValue.cfgvalue(self, section) + local txt_val = luci.http.formvalue("cbid."..self.map.config.."."..section.."."..self.option..".textbox") + + if cfg_val and fs.access(cfg_val) and txt_val == "" then + fs.unlink(cfg_val) + end + return AbstractValue.remove(self, section) + end + elseif option[1] == Flag then + o.default = nil + else + if option[1] == DynamicList then + function o.cfgvalue(...) + local val = AbstractValue.cfgvalue(...) + return ( val and type(val) ~= "table" ) and { val } or val + end + end + + if type(option[3]) == "table" then + if o.optional then o:value("", "-- remove --") end + for _, v in ipairs(option[3]) do + v = tostring(v) + o:value(v) + end + o.default = tostring(option[3][1]) + else + o.default = tostring(option[3]) + end + end + + for i=5,#option do + if type(option[i]) == "table" then + o:depends(option[i]) + end + end +end + +return m diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/model/cbi/openvpn-file.lua b/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/model/cbi/openvpn-file.lua new file mode 100644 index 0000000..9d50601 --- /dev/null +++ b/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/model/cbi/openvpn-file.lua @@ -0,0 +1,82 @@ +-- Licensed to the public under the Apache License 2.0. + +local ip = require("luci.ip") +local fs = require("nixio.fs") +local util = require("luci.util") +local uci = require("luci.model.uci").cursor() +local cfg_file = uci:get("openvpn", arg[1], "config") +local auth_file = cfg_file:match("(.+)%..+").. ".auth" + +local m = Map("openvpn") + +local p = m:section( SimpleSection ) +p.template = "openvpn/pageswitch" +p.mode = "file" +p.instance = arg[1] + +if not cfg_file or not fs.access(cfg_file) then + local f = SimpleForm("error", nil, translatef("The OVPN config file (%s) could not be found, please check your configuration.", cfg_file or "n/a")) + f:append(Template("openvpn/ovpn_css")) + f.reset = false + f.submit = false + return m, f +end + +if fs.stat(cfg_file).size >= 102400 then + f = SimpleForm("error", nil, + translatef("The size of the OVPN config file (%s) is too large for online editing in LuCI (≥ 100 KB). ", cfg_file) + .. translate("Please edit this file directly in a terminal session.")) + f:append(Template("openvpn/ovpn_css")) + f.reset = false + f.submit = false + return m, f +end + +f = SimpleForm("cfg", nil) +f:append(Template("openvpn/ovpn_css")) +f.submit = translate("Save") +f.reset = false + +s = f:section(SimpleSection, nil, translatef("Section to modify the OVPN config file (%s)", cfg_file)) +file = s:option(TextValue, "data1") +file.datatype = "string" +file.rows = 20 + +function file.cfgvalue() + return fs.readfile(cfg_file) or "" +end + +function file.write(self, section, data1) + return fs.writefile(cfg_file, "\n" .. util.trim(data1:gsub("\r\n", "\n")) .. "\n") +end + +function file.remove(self, section, value) + return fs.writefile(cfg_file, "") +end + +function s.handle(self, state, data1) + return true +end + +s = f:section(SimpleSection, nil, translatef("Section to add an optional 'auth-user-pass' file with your credentials (%s)", auth_file)) +file = s:option(TextValue, "data2") +file.datatype = "string" +file.rows = 5 + +function file.cfgvalue() + return fs.readfile(auth_file) or "" +end + +function file.write(self, section, data2) + return fs.writefile(auth_file, util.trim(data2:gsub("\r\n", "\n")) .. "\n") +end + +function file.remove(self, section, value) + return fs.writefile(auth_file, "") +end + +function s.handle(self, state, data2) + return true +end + +return m, f diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/model/cbi/openvpn-server.lua b/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/model/cbi/openvpn-server.lua new file mode 100644 index 0000000..88c8888 --- /dev/null +++ b/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/model/cbi/openvpn-server.lua @@ -0,0 +1,86 @@ +-- Copyright 2008 Steven Barth +-- Licensed to the public under the Apache License 2.0. + +local fs = require "nixio.fs" +local sys = require "luci.sys" +local uci = require "luci.model.uci".cursor() + +local m = Map("openvpn", translate("OpenVPN Extras"), translate("Extra Settings for an OpenVPN Client or Server")) + +m.on_after_save = function(self) + luci.sys.call("/usr/lib/easyrsa/firewall.sh &") + luci.sys.call("/usr/lib/easyrsa/dns.sh &") +end + +gw = m:section(TypedSection, "settings", translate("Advanced Extras")) +gw.anonymous = true +gw:tab("default", translate("Custom Firewall Settings")) +gw:tab("dns", translate("Custom DNS Settings")) +gw:tab("key", translate("Key and Certificate Generation")) + +this_tab = "default" + +gw:taboption(this_tab, Flag, "vpn2lan", translate("Forward Client VPN to LAN"), translate("(Client) Allow clients behind the VPN server to connect to computers within your LAN") ) +gw:taboption(this_tab, Flag, "vpns2lan", translate("Forward Server VPN to LAN"), translate("(Server) Allow clients behind the VPN server to connect to computers within your LAN") ) +gw:taboption(this_tab, Flag, "vpn2wan", translate("Forward Server VPN to WAN"), translate("(Server) Allow clients to connect to the internet (WAN) through the tunnel") ) + +this_tab = "dns" + +gw:taboption(this_tab, Flag, "lanopendns", translate("LAN DNS using OpenDNS"), translate("Fixed DNS on LAN interface using OpenDNS") ) +gw:taboption(this_tab, Flag, "langoogle", translate("LAN DNS using Google"), translate("Fixed DNS on LAN interface using Google") ) +gw:taboption(this_tab, Flag, "wanopendns", translate("WAN DNS using OpenDNS"), translate("Fixed DNS on WAN interface using OpenDNS") ) +gw:taboption(this_tab, Flag, "wangoogle", translate("WAN DNS using Google"), translate("Fixed DNS on WAN interface using Google") ) + +this_tab = "key" + +country = gw:taboption(this_tab, Value, "country", translate("Country Name :"), translate("2 letter country abbreviation")); +country.optional=false; +country.rmempty = true; +country.default="CA" +country.datatype = "rangelength(2, 2)" + +city = gw:taboption(this_tab, Value, "city", translate("City Name :")); +city.optional=false; +city.rmempty = true; +city.default="Abbotsford" +city.datatype = "minlength(2)" + +organ = gw:taboption(this_tab, Value, "organ", translate("Organization Name :"), translate("name will appear on certs and keys")); +organ.optional=false; +organ.rmempty = true; +organ.default="ROOter" +organ.datatype = "minlength(2)" + +comm = gw:taboption(this_tab, Value, "comm", translate("Common Name :"), translate("(Optional) Common Name of Organization")); +comm.optional=true; +comm.rmempty = true; + +unit = gw:taboption(this_tab, Value, "unit", translate("Section Name :"), translate("(Optional) Name of Section")); +unit.optional=true; +unit.rmempty = true; + +unstruc = gw:taboption(this_tab, Value, "unstruc", translate("Optional Organization Name :"), translate("(Optional) Another Name for Organization")); +unstruc.optional=true; +unstruc.rmempty = true; + +email = gw:taboption(this_tab, Value, "email", translate("Email Address :"), translate("(Optional) Email Address")); +unit.optional=true; +unit.rmempty = true; + +days = gw:taboption(this_tab, Value, "days", translate("Days to certify for :"), translate("number of days certs and keys are valid")); +days.optional=false; +days.rmempty = true; +days.default="3650" +days.datatype = "min(1)" + +clnt = gw:taboption(this_tab, Value, "nclient", translate("Number of Clients :"), translate("number of clients to generate certs and keys for")); +clnt.optional=false; +clnt.rmempty = true; +clnt.default="1" +clnt.datatype = "min(1)" + +sx = gw:taboption(this_tab, Value, "_dmy1", translate(" ")) +sx.template = "easyrsa/easyrsa" + + +return m diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/model/cbi/openvpn.lua b/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/model/cbi/openvpn.lua new file mode 100644 index 0000000..b79df8b --- /dev/null +++ b/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/model/cbi/openvpn.lua @@ -0,0 +1,179 @@ +-- Copyright 2008 Steven Barth +-- Licensed to the public under the Apache License 2.0. + +local fs = require "nixio.fs" +local sys = require "luci.sys" +local uci = require "luci.model.uci".cursor() +local testfullps = sys.exec("ps --help 2>&1 | grep BusyBox") --check which ps do we have +local psstring = (string.len(testfullps)>0) and "ps w" or "ps axfw" --set command we use to get pid + +local m = Map("openvpn", translate("OpenVPN")) +local s = m:section( TypedSection, "openvpn", translate("OpenVPN instances"), translate("Below is a list of configured OpenVPN instances and their current state") ) +s.template = "cbi/tblsection" +s.template_addremove = "openvpn/cbi-select-input-add" +s.addremove = true +s.add_select_options = { } + +local cfg = s:option(DummyValue, "config") +function cfg.cfgvalue(self, section) + local file_cfg = self.map:get(section, "config") + if file_cfg then + s.extedit = luci.dispatcher.build_url("admin", "vpn", "openvpn", "file", "%s") + else + s.extedit = luci.dispatcher.build_url("admin", "vpn", "openvpn", "basic", "%s") + end +end + +uci:load("openvpn_recipes") +uci:foreach( "openvpn_recipes", "openvpn_recipe", + function(section) + s.add_select_options[section['.name']] = + section['_description'] or section['.name'] + end +) + +function s.getPID(section) -- Universal function which returns valid pid # or nil + local pid = sys.exec("%s | grep -w '[o]penvpn(%s)'" % { psstring, section }) + if pid and #pid > 0 then + return tonumber(pid:match("^%s*(%d+)")) + else + return nil + end +end + +function s.parse(self, section) + local recipe = luci.http.formvalue( + luci.cbi.CREATE_PREFIX .. self.config .. "." .. + self.sectiontype .. ".select" + ) + + if recipe and not s.add_select_options[recipe] then + self.invalid_cts = true + else + TypedSection.parse( self, section ) + end +end + +function s.create(self, name) + local recipe = luci.http.formvalue( + luci.cbi.CREATE_PREFIX .. self.config .. "." .. + self.sectiontype .. ".select" + ) + local name = luci.http.formvalue( + luci.cbi.CREATE_PREFIX .. self.config .. "." .. + self.sectiontype .. ".text" + ) + if #name > 3 and not name:match("[^a-zA-Z0-9_]") then + local s = uci:section("openvpn", "openvpn", name) + if s then + local options = uci:get_all("openvpn_recipes", recipe) + for k, v in pairs(options) do + if k ~= "_role" and k ~= "_description" then + if type(v) == "boolean" then + v = v and "1" or "0" + end + uci:set("openvpn", name, k, v) + end + end + uci:save("openvpn") + uci:commit("openvpn") + if extedit then + luci.http.redirect( self.extedit:format(name) ) + end + end + elseif #name > 0 then + self.invalid_cts = true + end + return 0 +end + +function s.remove(self, name) + local cfg_file = "/etc/openvpn/" ..name.. ".ovpn" + local auth_file = "/etc/openvpn/" ..name.. ".auth" + if fs.access(cfg_file) then + fs.unlink(cfg_file) + end + if fs.access(auth_file) then + fs.unlink(auth_file) + end + uci:delete("openvpn", name) + uci:save("openvpn") + uci:commit("openvpn") +end + +s:option( Flag, "enabled", translate("Enabled") ) +s:option( Flag, "bootstart", translate("Start on Bootup") ) + +local active = s:option( DummyValue, "_active", translate("Started") ) +function active.cfgvalue(self, section) + local pid = s.getPID(section) + if pid ~= nil then + return (sys.process.signal(pid, 0)) + and translatef("yes (%i)", pid) + or translate("no") + end + return translate("no") +end + +local updown = s:option( Button, "_updown", translate("Start/Stop") ) +updown._state = false +updown.redirect = luci.dispatcher.build_url( + "admin", "vpn", "openvpn" +) +function updown.cbid(self, section) + local pid = s.getPID(section) + self._state = pid ~= nil and sys.process.signal(pid, 0) + self.option = self._state and "stop" or "start" + return AbstractValue.cbid(self, section) +end +function updown.cfgvalue(self, section) + self.title = self._state and "stop" or "start" + self.inputstyle = self._state and "reset" or "reload" +end +function updown.write(self, section, value) + if self.option == "stop" then + --sys.call("/etc/init.d/openvpn stop %s" % section) + sys.call("/usr/lib/easyrsa/vpn.sh %s" % section) + else + sys.call("/etc/init.d/openvpn start %s" % section) + end + luci.http.redirect( self.redirect ) +end + +local port = s:option( DummyValue, "port", translate("Port") ) +function port.cfgvalue(self, section) + local val = AbstractValue.cfgvalue(self, section) + if not val then + local file_cfg = self.map:get(section, "config") + if file_cfg and fs.access(file_cfg) then + val = sys.exec("awk '{if(match(tolower($1),/^port$/)&&match($2,/[0-9]+/)){cnt++;printf $2;exit}}END{if(cnt==0)printf \"-\"}' " ..file_cfg) + if val == "-" then + val = sys.exec("awk '{if(match(tolower($1),/^remote$/)&&match($3,/[0-9]+/)){cnt++;printf $3;exit}}END{if(cnt==0)printf \"-\"}' " ..file_cfg) + end + end + end + return val or "-" +end + +local proto = s:option( DummyValue, "proto", translate("Protocol") ) +function proto.cfgvalue(self, section) + local val = AbstractValue.cfgvalue(self, section) + if not val then + local file_cfg = self.map:get(section, "config") + if file_cfg and fs.access(file_cfg) then + val = sys.exec("awk '{if(match(tolower($1),/^proto$/)&&match(tolower($2),/^udp[46]*$|^tcp[46]*-server$|^tcp[46]*-client$/)){cnt++;printf tolower($2);exit}}END{if(cnt==0)printf \"-\"}' " ..file_cfg) + if val == "-" then + val = sys.exec("awk '{if(match(tolower($1),/^remote$/)&&match(tolower($4),/^udp[46]*$|^tcp[46]*-server$|^tcp[46]*-client$/)){cnt++;printf $4;exit}}END{if(cnt==0)printf \"-\"}' " ..file_cfg) + end + end + end + return val or "-" +end + +function m.on_after_apply(self,map) + --sys.call('/etc/init.d/openvpn reload') +end + +m:section(SimpleSection).template = "openvpn/vpn1" + +return m diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/view/admin_status/index/vpn.htm b/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/view/admin_status/index/vpn.htm new file mode 100644 index 0000000..fab323d --- /dev/null +++ b/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/view/admin_status/index/vpn.htm @@ -0,0 +1 @@ +<%+openvpn/vpn1%> \ No newline at end of file diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/view/easyrsa/easyrsa.htm b/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/view/easyrsa/easyrsa.htm new file mode 100644 index 0000000..998a866 --- /dev/null +++ b/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/view/easyrsa/easyrsa.htm @@ -0,0 +1,172 @@ + + + +
                          + + + + + + + +
                             
                          +

                           

                          + + + + + + + +
                           <%:Key Generation will take 60 minutes or more so be patient.%>  
                          +

                           

                          +

                          <%:Status of Key Generation%>

                          +

                           

                          + + + + +
                          + +
                          + +

                           

                          + + + + + + + + +
                             
                          + +
                          diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/view/openvpn/cbi-select-input-add.htm b/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/view/openvpn/cbi-select-input-add.htm new file mode 100644 index 0000000..9ca1e87 --- /dev/null +++ b/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/view/openvpn/cbi-select-input-add.htm @@ -0,0 +1,111 @@ + + + +<%+openvpn/ovpn_css%> + +
                          +
                          +

                          <%:Template based configuration%>

                          +
                          +
                          + +
                          +
                          + +
                          +
                          +
                          +
                          +
                          +

                          <%:OVPN configuration file upload%>

                          +
                          +
                          + +
                          +
                          + +
                          +
                          + +
                          +
                          +
                          +
                          + +
                          +
                          diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/view/openvpn/ovpn_css.htm b/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/view/openvpn/ovpn_css.htm new file mode 100644 index 0000000..55c0a54 --- /dev/null +++ b/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/view/openvpn/ovpn_css.htm @@ -0,0 +1,38 @@ + diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/view/openvpn/pageswitch.htm b/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/view/openvpn/pageswitch.htm new file mode 100644 index 0000000..7d88b84 --- /dev/null +++ b/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/view/openvpn/pageswitch.htm @@ -0,0 +1,30 @@ +<%# + Copyright 2008 Steven Barth + Copyright 2008 Jo-Philipp Wich + Licensed to the public under the Apache License 2.0. +-%> + +<%+openvpn/ovpn_css%> + +
                          +

                          + <%:Overview%> » + <%=luci.i18n.translatef("Instance \"%s\"", self.instance)%> +

                          + <% if self.mode == "basic" then %> + "><%:Switch to advanced configuration%> »

                          +


                          + <% elseif self.mode == "advanced" then %> + <%:Switch to basic configuration%> »

                          +


                          + <%:Configuration category%>: + <% for i, c in ipairs(self.categories) do %> + <% if c == self.category then %> + <%=translate(c)%> + <% else %> + "><%=translate(c)%> + <% end %> + <% if next(self.categories, i) then %>|<% end %> + <% end %> + <% end %> +
                          diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/view/openvpn/vpn1.htm b/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/view/openvpn/vpn1.htm new file mode 100644 index 0000000..1c70818 --- /dev/null +++ b/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/view/openvpn/vpn1.htm @@ -0,0 +1,120 @@ + + +
                          +

                          <%:OpenVPN Status%>

                          + + + + + + + + + + + + + + +
                          <%:Name%><%:Type%><%:Status%><%:Uptime%><%:Remote IP%><%:Clients%><%:Port%>

                          <%:Collecting data...%>
                          +
                          \ No newline at end of file diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/www/luci-static/resources/icons/vpn-disabled.png b/rooter/0optionalapps/luci-app-rootervpn/files/www/luci-static/resources/icons/vpn-disabled.png new file mode 100644 index 0000000..ccb0f56 Binary files /dev/null and b/rooter/0optionalapps/luci-app-rootervpn/files/www/luci-static/resources/icons/vpn-disabled.png differ diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/www/luci-static/resources/icons/vpn-started.png b/rooter/0optionalapps/luci-app-rootervpn/files/www/luci-static/resources/icons/vpn-started.png new file mode 100644 index 0000000..3f58ff1 Binary files /dev/null and b/rooter/0optionalapps/luci-app-rootervpn/files/www/luci-static/resources/icons/vpn-started.png differ diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/www/luci-static/resources/icons/vpn-stopped.png b/rooter/0optionalapps/luci-app-rootervpn/files/www/luci-static/resources/icons/vpn-stopped.png new file mode 100644 index 0000000..83ad3a0 Binary files /dev/null and b/rooter/0optionalapps/luci-app-rootervpn/files/www/luci-static/resources/icons/vpn-stopped.png differ diff --git a/rooter/0optionalapps/pingtest/Makefile b/rooter/0optionalapps/pingtest/Makefile new file mode 100644 index 0000000..0393fd7 --- /dev/null +++ b/rooter/0optionalapps/pingtest/Makefile @@ -0,0 +1,36 @@ +#Owned by DairyMan@Whirlpool +# +#Copyright GNU act. +include $(TOPDIR)/rules.mk + +PKG_NAME:=pingtest +PKG_VERSION:=1.000 +PKG_RELEASE:=1 + +PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool +include $(INCLUDE_DIR)/package.mk + +define Package/pingtest + SECTION:=utils + CATEGORY:=ROOter + SUBMENU:=Optional Applications + DEPENDS:=+httping +curl + TITLE:=Added scripts for custom ping test + PKGARCH:=all +endef + +define Package/pingtest/description + Added scripts for custom ping test +endef + + +define Build/Compile +endef + +define Package/pingtest/install + $(CP) ./files/* $(1)/ + + +endef + +$(eval $(call BuildPackage,pingtest)) diff --git a/rooter/0optionalapps/pingtest/files/usr/lib/custom/johns_ping.sh b/rooter/0optionalapps/pingtest/files/usr/lib/custom/johns_ping.sh new file mode 100644 index 0000000..32af6cb --- /dev/null +++ b/rooter/0optionalapps/pingtest/files/usr/lib/custom/johns_ping.sh @@ -0,0 +1,99 @@ +#!/bin/sh + +. /lib/functions.sh + +ROOTER=/usr/lib/rooter +ROOTER_LINK="/tmp/links" + +log() { +logger -t "Custom Ping Test " "$@" +} + +tping() { + hp=$(httping $2 -c 3 -s $1) + pingg=$(echo $hp" " | grep -o "round-trip .\+ ms ") + if [ -z "$pingg" ]; then + tmp=0 + else + tmp=200 + fi +} + +uci set ping.ping.conn="4" +uci commit ping + +CURRMODEM=1 +CPORT=$(uci -q get modem.modem$CURRMODEM.commport) +DELAY=$(uci get ping.ping.delay) + +TYPE=$(uci get ping.ping.type) +if [ $TYPE = "1" ]; then +log "Curl" + RETURN_CODE_1=$(curl -m 10 -s -o /dev/null -w "%{http_code}" http://www.google.com/) + RETURN_CODE_2=$(curl --ipv6 -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) +else +log "Ping" + tping "http://www.google.com/"; RETURN_CODE_1=$tmp + tping "http://www.example.org/" "-6"; RETURN_CODE_2=$tmp + tping "https://github.com"; RETURN_CODE_3=$tmp +fi + +if [[ "$RETURN_CODE_1" != "200" && "$RETURN_CODE_2" != "200" && "$RETURN_CODE_3" != "200" ]]; then + log "Bad Ping Test" + if [ $TYPE = "1" ]; then + tping "http://www.google.com/"; RETURN_CODE_1=$tmp + tping "http://www.example.org/" "-6"; RETURN_CODE_2=$tmp + tping "https://github.com"; RETURN_CODE_3=$tmp + else + RETURN_CODE_1=$(curl -m 10 -s -o /dev/null -w "%{http_code}" http://www.google.com/) + RETURN_CODE_2=$(curl --ipv6 -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) + fi + if [[ "$RETURN_CODE_1" != "200" && "$RETURN_CODE_2" != "200" && "$RETURN_CODE_3" != "200" ]]; then + log "Second Bad Ping Test" + uci set ping.ping.conn="3" + uci commit ping + ATCMDD="AT+CFUN=1,1" + $ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD" + sleep $DELAY + tries=0 + while [ $tries -lt 9 ] + do + CONN=$(uci -q get modem.modem$CURRMODEM.connected) + if [ $CONN = "1" ]; then + uci set ping.ping.conn="4" + uci commit ping + if [ $TYPE = "1" ]; then + log "Curl" + RETURN_CODE_1=$(curl -m 10 -s -o /dev/null -w "%{http_code}" http://www.google.com/) + RETURN_CODE_2=$(curl --ipv6 -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) + else + log "Ping" + tping "http://www.google.com/"; RETURN_CODE_1=$tmp + tping "http://www.example.org/" "-6"; RETURN_CODE_2=$tmp + tping "https://github.com"; RETURN_CODE_3=$tmp + fi + if [[ "$RETURN_CODE_1" != "200" && "$RETURN_CODE_2" != "200" && "$RETURN_CODE_3" != "200" ]]; then + uci set ping.ping.conn="1" + uci commit ping + reboot -f + fi + log "Second Ping Test Good" + uci set ping.ping.conn="2" + uci commit ping + exit 0 + else + sleep 20 + tries=$((tries+1)) + fi + done + reboot -f + fi +else + log "Good Ping" + uci set ping.ping.conn="2" + uci commit ping +fi +exit 0 diff --git a/rooter/0optionalapps/pingtest/files/usr/lib/custom/test_ping.sh b/rooter/0optionalapps/pingtest/files/usr/lib/custom/test_ping.sh new file mode 100644 index 0000000..ab3c5a3 --- /dev/null +++ b/rooter/0optionalapps/pingtest/files/usr/lib/custom/test_ping.sh @@ -0,0 +1,35 @@ +#!/bin/sh + +. /lib/functions.sh + +ROOTER=/usr/lib/rooter +ROOTER_LINK="/tmp/links" + +log() { +logger -t "Custom Ping Test " "$@" +} + +sleep 20 +CURRMODEM=1 +uci set ping.ping.conn="1" +uci commit ping +while [ true ] +do + INTER=$(uci get ping.ping.interval) + ENB=$(uci get ping.ping.enable) + if [ $ENB = 0 ]; then + sleep $INTER + else + CONN=$(uci -q get modem.modem$CURRMODEM.connected) + if [ $CONN = "1" ]; then + result=`ps | grep -i "johns_ping.sh" | grep -v "grep" | wc -l` + if [ $result -lt 1 ]; then + /usr/lib/custom/johns_ping.sh & + fi + else + uci set ping.ping.conn="1" + uci commit ping + fi + sleep $INTER + fi +done \ No newline at end of file diff --git a/rooter/0optionalapps/pingtest/files/usr/lib/lua/luci/controller/ping.lua b/rooter/0optionalapps/pingtest/files/usr/lib/lua/luci/controller/ping.lua new file mode 100644 index 0000000..025d16b --- /dev/null +++ b/rooter/0optionalapps/pingtest/files/usr/lib/lua/luci/controller/ping.lua @@ -0,0 +1,16 @@ +-- Licensed to the public under the Apache License 2.0. + +module("luci.controller.ping", package.seeall) + +I18N = require "luci.i18n" +translate = I18N.translate + +function index() + local page + 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 + page = entry({"admin", "modem", "ping"}, cbi("ping"), _(translate("Custom Ping Test")), 45) + page.dependent = true + end +end diff --git a/rooter/0optionalapps/pingtest/files/usr/lib/lua/luci/model/cbi/ping.lua b/rooter/0optionalapps/pingtest/files/usr/lib/lua/luci/model/cbi/ping.lua new file mode 100644 index 0000000..bb52017 --- /dev/null +++ b/rooter/0optionalapps/pingtest/files/usr/lib/lua/luci/model/cbi/ping.lua @@ -0,0 +1,42 @@ +local utl = require "luci.util" + +local sys = require "luci.sys" +local zones = require "luci.sys.zoneinfo" +local fs = require "nixio.fs" +local conf = require "luci.config" + +m = Map("ping", translate("Custom Ping Test"), translate("Enable/Disable Custom Ping Test")) + +d = m:section(TypedSection, "ping", " ") +d.anonymous = true + +c1 = d:option(ListValue, "enable", translate("Ping Test Status : "), translate("Ping every 20 seconds and, if it fails, restart modem or reboot router")); +c1:value("0", translate("Disabled")) +c1:value("1", translate("Enabled")) +c1.default=0 + +interval = d:option(Value, "interval", translate("Test Interval :"), translate("Number of seconds between testing the connection. Range is 20 to 120 secs.")); +interval.rmempty = true; +interval.optional=false; +interval.datatype = 'range(20,120)'; +interval.default="20"; + +type = d:option(ListValue, "type", translate("Test Type :"), translate("Type of test - Page Retrieval or Ping")); +type:value("0", translate("Ping")) +type:value("1", translate("Page Retrieval")) +type.default=1 + +d1 = d:option(ListValue, "delay", translate("Reconnection Delay"),translate("Delay in seconds after restarting modem before checking for connection")); +d1:value("40", "40 seconds") +d1:value("45", "45 seconds") +d1:value("50", "50 seconds") +d1:value("55", "55 seconds") +d1:value("60", "60 seconds") +d1:value("70", "70 seconds") +d1:value("80", "80 seconds") +d1:value("90", "90 seconds") +d1:value("100", "100 seconds") +d1:value("120", "120 seconds") +d1.default=40 + +return m \ No newline at end of file diff --git a/rooter/0optionalapps/pingtest/files/usr/lib/lua/luci/view/admin_status/index/extping.htm b/rooter/0optionalapps/pingtest/files/usr/lib/lua/luci/view/admin_status/index/extping.htm new file mode 100644 index 0000000..ed0c240 --- /dev/null +++ b/rooter/0optionalapps/pingtest/files/usr/lib/lua/luci/view/admin_status/index/extping.htm @@ -0,0 +1 @@ +<%+pingtest/extping%> \ No newline at end of file diff --git a/rooter/0optionalapps/pingtest/files/usr/lib/lua/luci/view/pingtest/extping.htm b/rooter/0optionalapps/pingtest/files/usr/lib/lua/luci/view/pingtest/extping.htm new file mode 100644 index 0000000..daba06c --- /dev/null +++ b/rooter/0optionalapps/pingtest/files/usr/lib/lua/luci/view/pingtest/extping.htm @@ -0,0 +1,26 @@ + + +
                          + <%:Custom Ping Test Status%> + + +
                          <%:Ping Status%><%:Loading%> Collecting data...
                          +
                          + diff --git a/rooter/0optionalapps/qfirehose/Makefile b/rooter/0optionalapps/qfirehose/Makefile new file mode 100644 index 0000000..6ceb348 --- /dev/null +++ b/rooter/0optionalapps/qfirehose/Makefile @@ -0,0 +1,40 @@ +# +# Copyright (C) 2011-2014 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=qfirehose +PKG_RELEASE:=1 + +PKG_FLAGS:=nonshared + +include $(INCLUDE_DIR)/package.mk + +define Package/qfirehose + SECTION:=utils + CATEGORY:=ROOter + SUBMENU:=Optional Applications + TITLE:=Quectel FireHose + MAINTAINER:=Dairyman +endef + +define Package/qfirehose/description + Quectel FireHose +endef + +define Build/Compile + $(MAKE) -C $(PKG_BUILD_DIR) \ + CC="$(TARGET_CC)" \ + CFLAGS="$(TARGET_CFLAGS) -Wall" +endef + +define Package/qfirehose/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/qfirehose $(1)/usr/bin/QFirehose +endef + +$(eval $(call BuildPackage,qfirehose)) diff --git a/rooter/0optionalapps/qfirehose/src/Makefile b/rooter/0optionalapps/qfirehose/src/Makefile new file mode 100644 index 0000000..44864b7 --- /dev/null +++ b/rooter/0optionalapps/qfirehose/src/Makefile @@ -0,0 +1,7 @@ +all: qfirehose + +qfirehose: + $(CC) $(CFLAGS) -Wall firehose_protocol.c qfirehose.c sahara_protocol.c usb_linux.c stream_download_protocol.c md5.c usb2tcp.c -o $@ $^ + +clean: + rm -rf firehose obj libs diff --git a/rooter/0optionalapps/qfirehose/src/firehose_protocol.c b/rooter/0optionalapps/qfirehose/src/firehose_protocol.c new file mode 100644 index 0000000..25c6ea1 --- /dev/null +++ b/rooter/0optionalapps/qfirehose/src/firehose_protocol.c @@ -0,0 +1,1087 @@ +/****************************************************************************** + @file firehose_protocol.c + @brief firehose protocol. + + DESCRIPTION + QFirehoe Tool for USB and PCIE of Quectel wireless cellular modules. + + INITIALIZATION AND SEQUENCING REQUIREMENTS + None. + + --------------------------------------------------------------------------- + Copyright (c) 2016 - 2020 Quectel Wireless Solution, Co., Ltd. All Rights Reserved. + Quectel Wireless Solution Proprietary and Confidential. + --------------------------------------------------------------------------- +******************************************************************************/ +#include "usb_linux.h" +#include +#include +#include + +#define error_return() do {dbg_time("%s %s %d fail\n", __FILE__, __func__, __LINE__); return __LINE__; } while(0) +int recv_sc600y_configure_num = 1; +extern int g_is_sc600y_chip; + +extern unsigned q_erase_all_before_download; +extern int update_transfer_bytes(long long bytes_cur); +extern int show_progress(); + +struct fh_configure_cmd { + const char *type; + const char *MemoryName; + uint32_t Verbose; + uint32_t AlwaysValidate; + uint32_t MaxDigestTableSizeInBytes; + uint32_t MaxPayloadSizeToTargetInBytes; + uint32_t MaxPayloadSizeFromTargetInBytes ; //2048 + uint32_t MaxPayloadSizeToTargetInByteSupported; //16k + uint32_t ZlpAwareHost; + uint32_t SkipStorageInit; +}; + +struct fh_erase_cmd { + const char *type; + uint32_t PAGES_PER_BLOCK; + uint32_t SECTOR_SIZE_IN_BYTES; + char label[32]; + uint32_t last_sector; + uint32_t num_partition_sectors; + uint32_t physical_partition_number; + uint32_t start_sector; +}; + +struct fh_program_cmd { + const char *type; + char *filename; + uint32_t filesz; + uint32_t PAGES_PER_BLOCK; + uint32_t SECTOR_SIZE_IN_BYTES; + char label[32]; + uint32_t last_sector; + uint32_t num_partition_sectors; + uint32_t physical_partition_number; + uint32_t start_sector; +}; + +struct fh_response_cmd { + const char *type; + const char *value; + uint32_t rawmode; + uint32_t MaxPayloadSizeToTargetInBytes; +}; + +struct fh_log_cmd { + const char *type; +}; + +struct fh_patch_cmd { + const char *type; + char *filename; + uint32_t filesz; + uint32_t SECTOR_SIZE_IN_BYTES; + uint32_t num_partition_sectors; +}; + +struct fh_cmd_header { + const char *type; +}; + +struct fh_vendor_defines { + const char *type; // "vendor" + char buffer[256]; +}; + +struct fh_cmd { + union { + struct fh_cmd_header cmd; + struct fh_configure_cmd cfg; + struct fh_erase_cmd erase; + struct fh_program_cmd program; + struct fh_response_cmd response; + struct fh_log_cmd log; + struct fh_patch_cmd patch; + struct fh_vendor_defines vdef; + }; + int part_upgrade; + char xml_original_data[300]; +}; + +struct fh_data { + const char *firehose_dir; + const void *usb_handle; + unsigned MaxPayloadSizeToTargetInBytes; + unsigned fh_cmd_count; + unsigned ZlpAwareHost; + struct fh_cmd fh_cmd_table[128]; //AG525 have more than 64 partition + + unsigned xml_tx_size; + unsigned xml_rx_size; + char xml_tx_buf[1024]; + char xml_rx_buf[1024]; +}; + +static const char * fh_xml_get_value(const char *xml_line, const char *key) { + static char value[64]; + + char *pchar = strstr(xml_line, key); + char *pend; + + if (!pchar) { + dbg_time("%s: no key %s in %s\n", __func__, key, xml_line); + return NULL; + } + + pchar += strlen(key); + if (pchar[0] != '=' && pchar[1] != '"') { + dbg_time("%s: no start %s in %s\n", __func__, "=\"", xml_line); + return NULL; + } + + pchar += strlen("=\""); + pend = strstr(pchar, "\""); + if (!pend) { + dbg_time("%s: no end %s in %s\n", __func__, "\"", xml_line); + return NULL; + } + + strncpy(value, pchar, pend - pchar); + value[pend - pchar] = '\0'; + + //dbg_time("%s=%s\n", key, value); + + return value; +} + +static int fh_parse_xml_line(const char *xml_line, struct fh_cmd *fh_cmd) { + const char *pchar = NULL; + char *pret; + + memset(fh_cmd, 0, sizeof( struct fh_cmd)); + if (strstr(xml_line, "vendor=\"quectel\"")) { + fh_cmd->vdef.type = "vendor"; + snprintf(fh_cmd->vdef.buffer, sizeof(fh_cmd->vdef.buffer), "%.255s", xml_line); + return 0; + } + else if (!strncmp(xml_line, "erase.type = "erase"; + if ((pchar = fh_xml_get_value(xml_line, "PAGES_PER_BLOCK"))) + fh_cmd->erase.PAGES_PER_BLOCK = atoi(pchar); + if ((pchar = fh_xml_get_value(xml_line, "SECTOR_SIZE_IN_BYTES"))) + fh_cmd->erase.SECTOR_SIZE_IN_BYTES = atoi(pchar); + if (strstr(xml_line, "last_sector")) { + if ((pchar = fh_xml_get_value(xml_line, "last_sector"))) + fh_cmd->erase.last_sector = atoi(pchar); + if (strstr(xml_line, "label")) { + if ((pchar = fh_xml_get_value(xml_line, "label"))) + strcpy(fh_cmd->erase.label, pchar); + } + } + if ((pchar = fh_xml_get_value(xml_line, "num_partition_sectors"))) + fh_cmd->erase.num_partition_sectors = strtoul(pchar, &pret, 10); + if ((pchar = fh_xml_get_value(xml_line, "physical_partition_number"))) + fh_cmd->erase.physical_partition_number = atoi(pchar); + if ((pchar = fh_xml_get_value(xml_line, "start_sector"))) + fh_cmd->erase.start_sector = atoi(pchar); + return 0; + } + else if (!strncmp(xml_line, "program.type = "program"; + if ((pchar = fh_xml_get_value(xml_line, "filename"))) + { + fh_cmd->program.filename = strdup(pchar); + if(fh_cmd->program.filename[0] == '\0') + {//some fw version have blank program line, ignore it. + return -1; + } + } + if (!g_is_sc600y_chip) + { + if ((pchar = fh_xml_get_value(xml_line, "PAGES_PER_BLOCK"))) + fh_cmd->program.PAGES_PER_BLOCK = atoi(pchar); + if ((pchar = fh_xml_get_value(xml_line, "SECTOR_SIZE_IN_BYTES"))) + fh_cmd->program.SECTOR_SIZE_IN_BYTES = atoi(pchar); + if (strstr(xml_line, "last_sector")) { + if ((pchar = fh_xml_get_value(xml_line, "last_sector"))) + fh_cmd->program.last_sector = atoi(pchar); + if (strstr(xml_line, "label")) { + if ((pchar = fh_xml_get_value(xml_line, "label"))) + strcpy(fh_cmd->program.label, pchar); + } + } + if ((pchar = fh_xml_get_value(xml_line, "num_partition_sectors"))) + fh_cmd->program.num_partition_sectors = atoi(pchar); + if ((pchar = fh_xml_get_value(xml_line, "physical_partition_number"))) + fh_cmd->program.physical_partition_number = atoi(pchar); + if ((pchar = fh_xml_get_value(xml_line, "start_sector"))) + fh_cmd->program.start_sector = atoi(pchar); + } + else + { + if ((pchar = fh_xml_get_value(xml_line, "start_sector"))) + fh_cmd->program.start_sector = atoi(pchar); + if ((pchar = fh_xml_get_value(xml_line, "num_partition_sectors"))) + fh_cmd->program.num_partition_sectors = atoi(pchar); + if ((pchar = fh_xml_get_value(xml_line, "SECTOR_SIZE_IN_BYTES"))) + fh_cmd->program.SECTOR_SIZE_IN_BYTES = atoi(pchar); + strcpy(fh_cmd->xml_original_data, xml_line); + } + + return 0; + } + else if (!strncmp(xml_line, "patch.type = "patch"; + if ((pchar = fh_xml_get_value(xml_line, "filename"))) + { + fh_cmd->patch.filename = strdup(pchar); + if(fh_cmd->patch.filename[0] == '\0' || strncasecmp(fh_cmd->patch.filename, "DISK",4)) + {//some fw version have blank program line, ignore it. + return -1; + } + } + strcpy(fh_cmd->xml_original_data, xml_line); + + return 0; + } + else if (!strncmp(xml_line, "response.type = "response"; + pchar = fh_xml_get_value(xml_line, "value"); + if (pchar) { + if (!strcmp(pchar, "ACK")) + fh_cmd->response.value = "ACK"; + else if(!strcmp(pchar, "NAK")) + fh_cmd->response.value = "NAK"; + else + fh_cmd->response.value = "OTHER"; + } + if (strstr(xml_line, "rawmode")) { + pchar = fh_xml_get_value(xml_line, "rawmode"); + if (pchar) { + fh_cmd->response.rawmode = !strcmp(pchar, "true"); + } + } + else if (strstr(xml_line, "MaxPayloadSizeToTargetInBytes")) { + pchar = fh_xml_get_value(xml_line, "MaxPayloadSizeToTargetInBytes"); + if (pchar) { + fh_cmd->response.MaxPayloadSizeToTargetInBytes = atoi(pchar); + } + } + return 0; + } + else if (!strncmp(xml_line, "program.type = "log"; + return 0; + } + + error_return(); +} + +static int fh_parse_xml_file(struct fh_data *fh_data, const char *xml_file) { + FILE *fp = fopen(xml_file, "rb"); + + if (fp == NULL) { + dbg_time("%s fail to fopen(%s), errno: %d (%s)\n", __func__, xml_file, errno, strerror(errno)); + error_return(); + } + + while (fgets(fh_data->xml_tx_buf, fh_data->xml_tx_size, fp)) { + char *xml_line = strstr(fh_data->xml_tx_buf, "<"); + + if (xml_line && strstr(xml_line, "")) { + if (strstr(xml_line, "/>") < strstr(xml_line, "") && strstr(xml_line, " SAHARA_RESET"); + if (0 == sahara_tx_data (usb_handle, tx_buffer, sizeof(sahara_packet_reset))) { + dbg(LOG_ERROR, "Sending RESET packet failed"); + return 0; + } + + return 1; +#endif +} + +static int send_done_packet (void *usb_handle, void *tx_buffer) { + sahara_packet_done *sahara_done = (sahara_packet_done *)tx_buffer; + + sahara_done->header.command = le_uint32(SAHARA_DONE_ID); + sahara_done->header.length = le_uint32(sizeof(sahara_packet_done)); + // Send the image data + dbg(LOG_EVENT, "SENDING --> SAHARA_DONE"); + if (0 == sahara_tx_data (usb_handle, tx_buffer, sizeof(sahara_packet_done))) { + dbg(LOG_ERROR, "Sending DONE packet failed"); + return 0; + } + return 1; +} + +static int start_image_transfer(void *usb_handle, void *tx_buffer, const sahara_packet_read_data *sahara_read_data, FILE *file_handle) +{ + int retval = 0; + uint32_t bytes_read = 0, bytes_to_read_next; + uint32_t DataOffset = le_uint32(sahara_read_data->data_offset); + uint32_t DataLength = le_uint32(sahara_read_data->data_length); + + dbg(LOG_INFO, "0x%08x 0x%08x 0x%08x", le_uint32(sahara_read_data->image_id), DataOffset, DataLength); + + if (fseek(file_handle, (long)DataOffset, SEEK_SET)) { + dbg(LOG_INFO, "%d errno: %d (%s)", __LINE__, errno, strerror(errno)); + return 0; + } + + while (bytes_read < DataLength) { + bytes_to_read_next = MIN((uint32_t)DataLength - bytes_read, SAHARA_RAW_BUFFER_SIZE); + retval = fread(tx_buffer, 1, bytes_to_read_next, file_handle); + + if (retval < 0) { + dbg(LOG_ERROR, "file read failed: %s", strerror(errno)); + return 0; + } + + if ((uint32_t) retval != bytes_to_read_next) { + dbg(LOG_ERROR, "Read %d bytes, but was asked for 0x%08x bytes", retval, DataLength); + return 0; + } + + /*send the image data*/ + if (0 == sahara_tx_data (usb_handle, tx_buffer, bytes_to_read_next)) { + dbg(LOG_ERROR, "Tx Sahara Image Failed"); + return 0; + } + + bytes_read += bytes_to_read_next; + } + + return 1; +} + +static int sahara_start(void *usb_handle, void *tx_buffer, void *rx_buffer, FILE *file_handle) { + uint32_t image_id = 0; + sahara_packet_header* sahara_cmd = (sahara_packet_header *)rx_buffer; + sahara_packet_hello *sahara_hello = (sahara_packet_hello *)rx_buffer; + sahara_packet_read_data *sahara_read_data = (sahara_packet_read_data *)rx_buffer; + sahara_packet_done_resp *sahara_done_resp = (sahara_packet_done_resp *)rx_buffer; + sahara_packet_end_image_tx *sahara_end_image_tx = (sahara_packet_end_image_tx *)rx_buffer; + + sahara_packet_hello_resp *sahara_hello_resp = (sahara_packet_hello_resp *)tx_buffer; + + dbg(LOG_EVENT, "STATE <-- SAHARA_WAIT_HELLO"); + if (0 == sahara_rx_data(usb_handle, rx_buffer, 0)) { +#if 0 + unsigned char edl_cmd[] = {0x4b, 0x65, 0x01, 0x00, 0x54, 0x0f, 0x7e}; + sahara_tx_data(usb_handle, edl_cmd, sizeof(edl_cmd)); +#else + sahara_tx_data(usb_handle, tx_buffer, 1); +#endif + if (0 == sahara_rx_data(usb_handle, rx_buffer, 0)) + return 0; + } + + //Check if the received command is a hello command + if (le_uint32(sahara_cmd->command) != SAHARA_HELLO_ID) { + dbg(LOG_ERROR, "Received a different command: %x while waiting for hello packet", sahara_hello->header.command); + send_reset_command(usb_handle, rx_buffer); + return 0; + } + + // Recieved hello, send the hello response + //Create a Hello request + sahara_hello_resp->header.command = le_uint32(SAHARA_HELLO_RESP_ID); + sahara_hello_resp->header.length = le_uint32(sizeof(sahara_packet_hello_resp)); + sahara_hello_resp->version = sahara_hello->version; //SAHARA_VERSION; + sahara_hello_resp->version_supported = sahara_hello->version_supported; //SAHARA_VERSION_SUPPORTED; + sahara_hello_resp->status = le_uint32(SAHARA_STATUS_SUCCESS); + sahara_hello_resp->mode = sahara_hello->mode; + sahara_hello_resp->reserved0 = le_uint32(1); + sahara_hello_resp->reserved1 = le_uint32(2); + sahara_hello_resp->reserved2 = le_uint32(3); + sahara_hello_resp->reserved3 = le_uint32(4); + sahara_hello_resp->reserved4 = le_uint32(5); + sahara_hello_resp->reserved5 = le_uint32(6); + + switch (le_uint32(sahara_hello->mode)) { + case SAHARA_MODE_IMAGE_TX_PENDING: + dbg(LOG_EVENT, "RECEIVED <-- SAHARA_MODE_IMAGE_TX_PENDING"); + break; + case SAHARA_MODE_IMAGE_TX_COMPLETE: + dbg(LOG_EVENT, "RECEIVED <-- SAHARA_MODE_IMAGE_TX_COMPLETE"); + break; + case SAHARA_MODE_MEMORY_DEBUG: + dbg(LOG_EVENT, "RECEIVED <-- SAHARA_MODE_MEMORY_DEBUG"); + break; + case SAHARA_MODE_COMMAND: + dbg(LOG_EVENT, "RECEIVED <-- SAHARA_MODE_COMMAND"); + break; + default: + dbg(LOG_EVENT, "RECEIVED <-- SAHARA_MODE_0x%x", le_uint32(sahara_hello->mode)); + break; + } + + if (le_uint32(sahara_hello->mode) != SAHARA_MODE_IMAGE_TX_PENDING) { + dbg(LOG_ERROR, "ERROR NOT SAHARA_MODE_IMAGE_TX_PENDING"); + sahara_hello_resp->mode = SAHARA_MODE_IMAGE_TX_PENDING; + } + + /*Send the Hello Resonse Request*/ + dbg(LOG_EVENT, "SENDING --> SAHARA_HELLO_RESPONSE"); + if (0 == sahara_tx_data (usb_handle, tx_buffer, sizeof(sahara_packet_hello_resp))) { + dbg(LOG_ERROR, "Tx Sahara Data Failed "); + return 0; + } + + while (1) { + dbg(LOG_INFO, "STATE <-- SAHARA_WAIT_COMMAND"); + if (0 == sahara_rx_data(usb_handle, rx_buffer, 0)) + return 0; + + if (le_uint32(sahara_cmd->command) == SAHARA_READ_DATA_ID) { + start_image_transfer(usb_handle, tx_buffer, sahara_read_data, file_handle); + } + else if (le_uint32(sahara_cmd->command) == SAHARA_END_IMAGE_TX_ID) { + dbg(LOG_EVENT, "image_id = %d, status = %d", le_uint32(sahara_end_image_tx->image_id), le_uint32(sahara_end_image_tx->status)); + if (le_uint32(sahara_end_image_tx->status) == SAHARA_STATUS_SUCCESS) { + image_id = le_uint32(sahara_end_image_tx->image_id); + send_done_packet (usb_handle, tx_buffer); + break; + } else { + return 0; + } + } + else if (le_uint32(sahara_cmd->command) == SAHARA_HELLO_ID) { + continue; + } + else { + dbg(LOG_ERROR, "Received an unknown command: %d ", le_uint32(sahara_cmd->command)); + send_reset_command (usb_handle, tx_buffer); + return 0; + } + } + + dbg(LOG_EVENT, "STATE <-- SAHARA_WAIT_DONE_RESP"); + if (0 == sahara_rx_data(usb_handle, rx_buffer, 0)) + return 0; + + dbg(LOG_INFO, "image_tx_status = %d", le_uint32(sahara_done_resp->image_tx_status)); + + if (SAHARA_MODE_IMAGE_TX_PENDING == le_uint32(sahara_done_resp->image_tx_status)) { + if (image_id == 13) //prog_nand_firehose_9x07.mbn + return 1; + if (image_id == 7) //NPRG9x55.mbn + return 1; + if (image_id == 21) //sbl1.mbn, October 22 2020 2:12 PM, AG35CEVAR05A07T4G + return 1; + } + else if (SAHARA_MODE_IMAGE_TX_COMPLETE == le_uint32(sahara_done_resp->image_tx_status)) { + dbg(LOG_EVENT,"Successfully uploaded all images"); + return 1; + } + else { + dbg(LOG_ERROR, "Received unrecognized status %d at SAHARA_WAIT_DONE_RESP state", + le_uint32(sahara_done_resp->image_tx_status)); + return 0; + } + + return 0; +} + +int sahara_main(const char *firehose_dir, void *usb_handle, int edl_mode_05c69008) { + int retval = 0; + char* prog_nand_firehose_filename = NULL; + char full_path[512]; + FILE *file_handle; + void *tx_buffer; + void *rx_buffer; + + if (edl_mode_05c69008) { + if(qfile_find_xmlfile(firehose_dir, "prog", &prog_nand_firehose_filename) != 0 + && qfile_find_xmlfile(firehose_dir, "prog_firehose", &prog_nand_firehose_filename) != 0) { + dbg(LOG_ERROR, "retrieve prog nand firehose failed."); + return ENOENT; + } + dbg(LOG_INFO, "prog_nand_firehose_filename = %s", prog_nand_firehose_filename); + + if (!strncmp(prog_nand_firehose_filename, "prog_emmc_firehose_8953_ddr.mbn", strlen(prog_nand_firehose_filename))) + g_is_sc600y_chip = 1; + + snprintf(full_path, sizeof(full_path), "%.255s/%.240s", firehose_dir, prog_nand_firehose_filename); + } + else { + snprintf(full_path, sizeof(full_path), "%.255s/..", firehose_dir); + if(qfile_find_xmlfile(full_path, "NPRG9x", &prog_nand_firehose_filename) != 0 + && qfile_find_xmlfile(full_path, "NPRG9x", &prog_nand_firehose_filename) != 0) { + dbg(LOG_ERROR, "retrieve NPRG MBN failed."); + return ENOENT; + } + dbg(LOG_INFO, "prog_nand_firehose_filename = %s", prog_nand_firehose_filename); + + snprintf(full_path, sizeof(full_path), "%.255s/../%.240s", firehose_dir, prog_nand_firehose_filename); + } + + free(prog_nand_firehose_filename); + file_handle = fopen(full_path, "rb"); + if (file_handle == NULL) { + dbg(LOG_INFO, "%s %d %s errno: %d (%s)", __func__, __LINE__, full_path, errno, strerror(errno)); + return ENOENT; + } + + rx_buffer = malloc (SAHARA_RAW_BUFFER_SIZE); + tx_buffer = malloc (SAHARA_RAW_BUFFER_SIZE); + + if (NULL == rx_buffer || NULL == tx_buffer) { + dbg(LOG_ERROR, "Failed to allocate sahara buffers"); + return ENOMEM; + } + + retval = sahara_start(usb_handle, tx_buffer, rx_buffer, file_handle); + if (0 == retval) { + dbg(LOG_ERROR, "Sahara protocol error"); + } + else { + dbg(LOG_STATUS, "Sahara protocol completed"); + } + + free(rx_buffer); + free(tx_buffer); + fclose(file_handle); + + if (retval) + return 0; + + return __LINE__; +} diff --git a/rooter/0optionalapps/qfirehose/src/sahara_protocol.h b/rooter/0optionalapps/qfirehose/src/sahara_protocol.h new file mode 100644 index 0000000..bb88a2c --- /dev/null +++ b/rooter/0optionalapps/qfirehose/src/sahara_protocol.h @@ -0,0 +1,385 @@ +/*=========================================================================== + * FILE: + * sahara_packet.h + * + * DESCRIPTION: + * Sahara protocol states and structure declaration. + * + * Copyright (C) 2012 Qualcomm Technologies, Inc. All rights reserved. + * Qualcomm Technologies Proprietary/GTDR + * + * All data and information contained in or disclosed by this document is + * confidential and proprietary information of Qualcomm Technologies, Inc. and all + * rights therein are expressly reserved. By accepting this material the + * recipient agrees that this material and the information contained therein + * is held in confidence and in trust and will not be used, copied, reproduced + * in whole or in part, nor its contents revealed in any manner to others + * without the express written permission of Qualcomm Technologies, Inc. + * =========================================================================== + * + * sahara_packet.h : Sahara protocol states and structure declaration. + * ========================================================================================== + * $Header: //components/rel/boot.bf/3.1.4/boot_images/core/storage/tools/QSaharaServer/src/sahara_protocol.h#1 $ + * $DateTime: 2017/02/21 04:58:32 $ + * $Author: pwbldsvc $ + * + * Edit History: + * YYYY-MM-DD who why + * ----------------------------------------------------------------------------- + * 2010-09-28 ng Added command mode support + * 2010-10-18 ab Added memory debug mode support + * + * Copyright 2012 by Qualcomm Technologies, Inc. All Rights Reserved. + * + *========================================================================================== + */ + +#ifndef SAHARA_PROTOCOL_H +#define SAHARA_PROTOCOL_H + +/*=========================================================================== + * + * INCLUDE FILES + * + * ===========================================================================*/ + +/*=========================================================================== + * + * PUBLIC DATA DECLARATIONS + * + * ===========================================================================*/ +// Sahara Protocol Version +#define SAHARA_VERSION 2 +#define SAHARA_VERSION_SUPPORTED 4 + +/*Maximum 1 megabyte tx buffer size*/ + +#define SAHARA_RAW_BUFFER_SIZE (4*1024) + +// Sahara command IDs +typedef enum +{ + SAHARA_NO_CMD_ID = 0x00, + SAHARA_HELLO_ID = 0x01, // sent from target to host + SAHARA_HELLO_RESP_ID = 0x02, // sent from host to target + SAHARA_READ_DATA_ID = 0x03, // sent from target to host + SAHARA_END_IMAGE_TX_ID = 0x04, // sent from target to host + SAHARA_DONE_ID = 0x05, // sent from host to target + SAHARA_DONE_RESP_ID = 0x06, // sent from target to host + SAHARA_RESET_ID = 0x07, // sent from host to target + SAHARA_RESET_RESP_ID = 0x08, // sent from target to host + SAHARA_MEMORY_DEBUG_ID = 0x09, // sent from target to host + SAHARA_MEMORY_READ_ID = 0x0A, // sent from host to target + SAHARA_CMD_READY_ID = 0x0B, // sent from target to host + SAHARA_CMD_SWITCH_MODE_ID = 0x0C, // sent from host to target + SAHARA_CMD_EXEC_ID = 0x0D, // sent from host to target + SAHARA_CMD_EXEC_RESP_ID = 0x0E, // sent from target to host + SAHARA_CMD_EXEC_DATA_ID = 0x0F, // sent from host to target + SAHARA_64_BITS_MEMORY_DEBUG_ID = 0x10, // sent from target to host + SAHARA_64_BITS_MEMORY_READ_ID = 0x11, // sent from host to target + SAHARA_64_BITS_READ_DATA_ID = 0x12, + // place all new commands above this + SAHARA_LAST_CMD_ID, + SAHARA_MAX_CMD_ID = 0x7FFFFFFF // To ensure 32-bits wide +} boot_sahara_cmd_id; + +typedef enum { + SAHARA_IMAGE_TYPE_BINARY = 0, /* Binary format */ + SAHARA_IMAGE_TYPE_ELF, /* ELF format */ + SAHARA_IMAGE_UNKNOWN = 0x7FFFFFFF /* To ensure 32-bits wide */ +} boot_sahara_image; + +// Status codes for Sahara +typedef enum +{ + // Success + SAHARA_STATUS_SUCCESS = 0x00, + + // Invalid command received in current state + SAHARA_NAK_INVALID_CMD = 0x01, + + // Protocol mismatch between host and target + SAHARA_NAK_PROTOCOL_MISMATCH = 0x02, + + // Invalid target protocol version + SAHARA_NAK_INVALID_TARGET_PROTOCOL = 0x03, + + // Invalid host protocol version + SAHARA_NAK_INVALID_HOST_PROTOCOL = 0x04, + + // Invalid packet size received + SAHARA_NAK_INVALID_PACKET_SIZE = 0x05, + + // Unexpected image ID received + SAHARA_NAK_UNEXPECTED_IMAGE_ID = 0x06, + + // Invalid image header size received + SAHARA_NAK_INVALID_HEADER_SIZE = 0x07, + + // Invalid image data size received + SAHARA_NAK_INVALID_DATA_SIZE = 0x08, + + // Invalid image type received + SAHARA_NAK_INVALID_IMAGE_TYPE = 0x09, + + // Invalid tranmission length + SAHARA_NAK_INVALID_TX_LENGTH = 0x0A, + + // Invalid reception length + SAHARA_NAK_INVALID_RX_LENGTH = 0x0B, + + // General transmission or reception error + SAHARA_NAK_GENERAL_TX_RX_ERROR = 0x0C, + + // Error while transmitting READ_DATA packet + SAHARA_NAK_READ_DATA_ERROR = 0x0D, + + // Cannot receive specified number of program headers + SAHARA_NAK_UNSUPPORTED_NUM_PHDRS = 0x0E, + + // Invalid data length received for program headers + SAHARA_NAK_INVALID_PDHR_SIZE = 0x0F, + + // Multiple shared segments found in ELF image + SAHARA_NAK_MULTIPLE_SHARED_SEG = 0x10, + + // Uninitialized program header location + SAHARA_NAK_UNINIT_PHDR_LOC = 0x11, + + // Invalid destination address + SAHARA_NAK_INVALID_DEST_ADDR = 0x12, + + // Invalid data size receieved in image header + SAHARA_NAK_INVALID_IMG_HDR_DATA_SIZE = 0x13, + + // Invalid ELF header received + SAHARA_NAK_INVALID_ELF_HDR = 0x14, + + // Unknown host error received in HELLO_RESP + SAHARA_NAK_UNKNOWN_HOST_ERROR = 0x15, + + // Timeout while receiving data + SAHARA_NAK_TIMEOUT_RX = 0x16, + + // Timeout while transmitting data + SAHARA_NAK_TIMEOUT_TX = 0x17, + + // Invalid mode received from host + SAHARA_NAK_INVALID_HOST_MODE = 0x18, + + // Invalid memory read access + SAHARA_NAK_INVALID_MEMORY_READ = 0x19, + + // Host cannot handle read data size requested + SAHARA_NAK_INVALID_DATA_SIZE_REQUEST = 0x1A, + + // Memory debug not supported + SAHARA_NAK_MEMORY_DEBUG_NOT_SUPPORTED = 0x1B, + + // Invalid mode switch + SAHARA_NAK_INVALID_MODE_SWITCH = 0x1C, + + // Failed to execute command + SAHARA_NAK_CMD_EXEC_FAILURE = 0x1D, + + // Invalid parameter passed to command execution + SAHARA_NAK_EXEC_CMD_INVALID_PARAM = 0x1E, + + // Unsupported client command received + SAHARA_NAK_EXEC_CMD_UNSUPPORTED = 0x1F, + + // Invalid client command received for data response + SAHARA_NAK_EXEC_DATA_INVALID_CLIENT_CMD = 0x20, + + // Failed to authenticate hash table + SAHARA_NAK_HASH_TABLE_AUTH_FAILURE = 0x21, + + // Failed to verify hash for a given segment of ELF image + SAHARA_NAK_HASH_VERIFICATION_FAILURE = 0x22, + + // Failed to find hash table in ELF image + SAHARA_NAK_HASH_TABLE_NOT_FOUND = 0x23, + + // Place all new error codes above this + SAHARA_NAK_LAST_CODE, + + SAHARA_NAK_MAX_CODE = 0x7FFFFFFF // To ensure 32-bits wide +} boot_sahara_status; + +// Status of all image transfers +typedef enum +{ + SAHARA_MODE_IMAGE_TX_PENDING = 0x0, + SAHARA_MODE_IMAGE_TX_COMPLETE = 0x1, + SAHARA_MODE_MEMORY_DEBUG = 0x2, + SAHARA_MODE_COMMAND = 0x3, + + // place all new commands above this + SAHARA_MODE_LAST, + SAHARA_MODE_MAX = 0x7FFFFFFF +} boot_sahara_mode; + +// Executable commands when target is in command mode +typedef enum +{ + SAHARA_EXEC_CMD_NOP = 0x00, + SAHARA_EXEC_CMD_SERIAL_NUM_READ = 0x01, + SAHARA_EXEC_CMD_MSM_HW_ID_READ = 0x02, + SAHARA_EXEC_CMD_OEM_PK_HASH_READ = 0x03, + SAHARA_EXEC_CMD_SWITCH_DMSS = 0x04, + SAHARA_EXEC_CMD_SWITCH_STREAMING = 0x05, + SAHARA_EXEC_CMD_READ_DEBUG_DATA = 0x06, + + // place all new commands above this + SAHARA_EXEC_CMD_LAST, + SAHARA_EXEC_CMD_MAX = 0x7FFFFFFF +} boot_sahara_exec_cmd_id; + +/* Sahara Protocol states */ +typedef enum { + SAHARA_WAIT_HELLO, + SAHARA_WAIT_COMMAND, + SAHARA_WAIT_RESET_RESP, + SAHARA_WAIT_DONE_RESP, + SAHARA_WAIT_MEMORY_READ, + SAHARA_WAIT_CMD_EXEC_RESP, + SAHARA_WAIT_MEMORY_TABLE, + SAHARA_WAIT_MEMORY_REGION, +} boot_sahara_state; + +/* ============================================================================= */ +/* Sahara protocol packet defintions */ +/* ============================================================================= */ + +typedef struct +{ + uint32_t command; // command ID + uint32_t length; // packet length incl command and length +} sahara_packet_header; + +// HELLO command packet type - sent from target to host +// indicates start of protocol on target side +typedef struct +{ + sahara_packet_header header; + uint32_t version; // target protocol version number + uint32_t version_supported; // minimum protocol version number supported + // on target + uint32_t cmd_packet_length; // maximum packet size supported for command + // packets + uint32_t mode; // expected mode of target operation + uint32_t reserved0; // reserved field + uint32_t reserved1; // reserved field + uint32_t reserved2; // reserved field + uint32_t reserved3; // reserved field + uint32_t reserved4; // reserved field + uint32_t reserved5; // reserved field +} sahara_packet_hello; + +// HELLO_RESP command packet type - sent from host to target +// response to hello, protocol version running on host and status sent +typedef struct +{ + sahara_packet_header header; + uint32_t version; // host protocol version number + uint32_t version_supported; // minimum protocol version number supported + // on host + uint32_t status; // OK or error condition + uint32_t mode; // mode of operation for target to execute + uint32_t reserved0; // reserved field + uint32_t reserved1; // reserved field + uint32_t reserved2; // reserved field + uint32_t reserved3; // reserved field + uint32_t reserved4; // reserved field + uint32_t reserved5; // reserved field +} sahara_packet_hello_resp; + +// READ_DATA command packet type - sent from target to host +// sends data segment offset and length to be read from current host +// image file +typedef struct +{ + sahara_packet_header header; + uint32_t image_id; // ID of image to be transferred + uint32_t data_offset; // offset into image file to read data from + uint32_t data_length; // length of data segment to be retreived + // from image file +} sahara_packet_read_data; + +// READ_DATA_64 command packet type - sent from target to host +// sends data segment offset and length to be read from current host +// image file +/* +#ifdef WINDOWSPC +#define PACK( __Declaration__ ) __pragma( pack(push, 1) ) __Declaration__ __pragma( pack(pop) ) +PACK( +typedef struct // note for gcc use __attribute__((__packed__)) +{ + sahara_packet_header header; + uint32_t image_id; // ID of image to be transferred + uint64_t data_offset; // offset into image file to read data from + uint32_t data_length; // length of data segment to be retreived + // from image file +} sahara_packet_read_data_64bit; +); +#else +typedef __attribute__((__packed__)) struct +{ + sahara_packet_header header; + uint32_t image_id; // ID of image to be transferred + uint64_t data_offset; // offset into image file to read data from + uint32_t data_length; // length of data segment to be retreived + // from image file +} sahara_packet_read_data_64bit; +#endif +*/ +typedef struct +{ + sahara_packet_header header; + uint64_t image_id; // ID of image to be transferred + uint64_t data_offset; // offset into image file to read data from + uint64_t data_length; // length of data segment to be retreived + // from image file +} sahara_packet_read_data_64bit; + +// END_IMAGE_TX command packet type - sent from target to host +// indicates end of a single image transfer and status of transfer +typedef struct +{ + sahara_packet_header header; + uint32_t image_id; // ID of image to be transferred + uint32_t status; // OK or error condition +} sahara_packet_end_image_tx; + +// DONE packet type - sent from host to target +// indicates end of single image transfer +typedef struct +{ + sahara_packet_header header; +} sahara_packet_done; + +// DONE_RESP packet type - sent from target to host +// indicates end of all image transfers +typedef struct +{ + sahara_packet_header header; + uint32_t image_tx_status; // indicates if all images have been + // transferred; + // 0 = IMAGE_TX_PENDING + // 1 = IMAGE_TX_COMPLETE +} sahara_packet_done_resp; + +// RESET packet type - sent from host to target +// indicates to target to reset +typedef struct +{ + sahara_packet_header header; +} sahara_packet_reset; + +// RESET_RESP packet type - sent from target to host +// indicates to host that target has reset +typedef struct +{ + sahara_packet_header header; +} sahara_packet_reset_resp; +#endif /* SAHARA_PACKET_H */ diff --git a/rooter/0optionalapps/qfirehose/src/stream_download_protocol.c b/rooter/0optionalapps/qfirehose/src/stream_download_protocol.c new file mode 100644 index 0000000..1033565 --- /dev/null +++ b/rooter/0optionalapps/qfirehose/src/stream_download_protocol.c @@ -0,0 +1,766 @@ +/****************************************************************************** + @file stream_download_protocol.c + @brief stream protocol. + + DESCRIPTION + QFirehoe Tool for USB and PCIE of Quectel wireless cellular modules. + + INITIALIZATION AND SEQUENCING REQUIREMENTS + None. + + --------------------------------------------------------------------------- + Copyright (c) 2016 - 2020 Quectel Wireless Solution, Co., Ltd. All Rights Reserved. + Quectel Wireless Solution Proprietary and Confidential. + --------------------------------------------------------------------------- +******************************************************************************/ + +#include "usb_linux.h" +#include "hostdl_packet.h" + +#define true (1==1) +#define false (1!=1) + +#define MAX_SEND_BUFFER_SIZE 1280 +#define MAX_RECEIVE_BUFFER_SIZE 1280 +unsigned char g_Transmit_Buffer[MAX_SEND_BUFFER_SIZE]; +int g_Transmit_Length; + +unsigned char g_Receive_Buffer[MAX_RECEIVE_BUFFER_SIZE]; +int g_Receive_Bytes; + +static void *stream_usb_handle; + +static void dump_buffer(unsigned char * buff, int len) +{ + int i = 0; + + dbg_time("dump buffer: %d bytes\n", len); + for(i = 0; i < len; i++) + { + dbg_time("%02x ", buff[i]); + } + dbg_time("\nend\n"); + +} + +#define CRC_16_L_SEED 0xFFFF +#define CRC_TAB_SIZE 256 /* 2^CRC_TAB_BITS */ +#define CRC_16_L_POLYNOMIAL 0x8408 + +static const uint16_t crc_16_l_table[ CRC_TAB_SIZE ] = { + 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, + 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, + 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, + 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, + 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, + 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, + 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, + 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, + 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, + 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, + 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, + 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, + 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, + 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, + 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, + 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, + 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, + 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, + 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, + 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, + 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, + 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, + 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, + 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, + 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, + 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, + 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, + 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, + 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, + 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, + 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, + 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 +}; + +unsigned short crc_16_l_calc(unsigned char *buf_ptr, int len) { + int data, crc_16; + for (crc_16 = CRC_16_L_SEED; len >= 8; len -= 8, buf_ptr++) { + crc_16 = crc_16_l_table[(crc_16 ^ *buf_ptr) & 0x00ff] ^ (crc_16 >> 8); + } + if (len != 0) { + + data = ((int) (*buf_ptr)) << (16 - 8); + + while (len-- != 0) { + if (((crc_16 ^ data) & 0x01) != 0) { + + crc_16 >>= 1; + crc_16 ^= CRC_16_L_POLYNOMIAL; + + } else { + + crc_16 >>= 1; + + } + + data >>= 1; + } + } + return (~crc_16); +} + +void compute_reply_crc () +{ + unsigned short crc = crc_16_l_calc (g_Transmit_Buffer, g_Transmit_Length * 8); + g_Transmit_Buffer[g_Transmit_Length] = crc & 0xFF; + g_Transmit_Buffer[g_Transmit_Length + 1] = crc >> 8; + g_Transmit_Length += 2; +} + +static void compose_packet(unsigned char cmd, unsigned char *parameter, uint32_t parameter_len, unsigned char *data, uint32_t data_len) { + uint32_t i; + + g_Transmit_Buffer[0] = cmd; + if (parameter == NULL) parameter_len = 0; + if (data == NULL) data_len = 0; + for (i = 0; i < parameter_len; i++) { + g_Transmit_Buffer[1 + i] = parameter[i]; + } + for (i = 0; i < data_len; i++) { + g_Transmit_Buffer[1 + parameter_len + i] = data[i]; + } + g_Transmit_Length = 1 + parameter_len + data_len; + g_Transmit_Buffer[g_Transmit_Length] = 0; +} + +static unsigned char stream_tx_buf[1280]; +#define CHECK_FOR_DATA() do {} while(0) +#define TRANSMIT_BYTE(_byte) do { stream_tx_buf[j++] = _byte; } while(0) + +static int send_packet(int flag) { + int i; + int ch; + int j; + + j = 0; + + + CHECK_FOR_DATA (); + + /* Since we don't know how long it's been. */ + if (!!flag) { + TRANSMIT_BYTE (0x7E); + } + + for (i = 0; i < g_Transmit_Length; i++) + { + /* we only need to check once every 31 characters, since RX and TX + * run at about the same speed, and our RX FIFO is 64 characters + */ + if ((i & 31) == 31) + CHECK_FOR_DATA (); + + ch = g_Transmit_Buffer[i]; + + if (ch == 0x7E || ch == 0x7D) + { + TRANSMIT_BYTE (0x7D); + TRANSMIT_BYTE (0x20 ^ ch); /*lint !e734 */ + } + else + { + TRANSMIT_BYTE (ch); /*lint !e734 */ + } + } + + CHECK_FOR_DATA (); + TRANSMIT_BYTE (0x7E); + +#if 0 + /* Hack for USB protocol. If we have an exact multiple of the USB frame + * size, then the last frame will not be sent out. The USB standard says + * that a "short packet" needs to be sent to flush the data. Two flag + * characters can serve as the short packet. Doing it this way, we only + * perform this test once on every entire packet from the target, so the + * over head is not too much. + */ + if ((j%512) == 0) + { + TRANSMIT_BYTE (0x7E); + TRANSMIT_BYTE (0x7E); + } + #endif + + return (qusb_noblock_write(stream_usb_handle, stream_tx_buf, j, j, 3000, 1) == j) ? 0 : -1; +} + +static int remove_escape_hdlc_flag(unsigned char* buffer, int len) +{ + int i = 0; + int index = 0; + int escape = 0; + //dump_buffer(buffer, len); + if(len == 0) return 0; + //ignore the first HDLC FLAG bytes + while(buffer[i] == 0x7e) + { + i++; + } + //all bytes is HDLC FLAG + if(i == len) + return 0; + for(; i < len; i++) + { + if(buffer[i] == 0x7D) + { + escape = 1; + continue; + } + if(escape == 1) + { + escape = 0; + buffer[i] ^= 0x20; + } + buffer[index++] = buffer[i]; + } + buffer[index] = 0; + //dump_buffer(buffer, index); + return index; +} + +static int receive_packet(void) +{ + int bytesread = 0; + unsigned char *buff = g_Receive_Buffer; + int idx = 0; + do + { + bytesread = qusb_noblock_read(stream_usb_handle, &buff[idx], MAX_RECEIVE_BUFFER_SIZE, 0, 3000); + if(bytesread == 0) + { + //timeout may be error + dbg_time("%s timeout\n", __FUNCTION__); + return 0; + } + //dump_buffer(&buff[idx], bytesread); + idx += bytesread; + if(buff[idx - 1] == 0x7e) + { + //check the packet whether valid. + g_Receive_Bytes = remove_escape_hdlc_flag(buff, idx); + if(g_Receive_Bytes == 0) + { + continue; + }else{ + return 1; + } + } + }while(1); + + return 0; +} + +static int handle_hello(void) +{ + static const char host_header[] = "QCOM fast download protocol host"; + //static const char target_header[] = "QCOM fast download protocol targ"; + //char string1[64]; + //int size; + int err; + dbg_time("%s\n", __func__); + + memset(&g_Transmit_Buffer[0],0,sizeof(g_Transmit_Buffer)); + g_Transmit_Buffer[HELLO_CMD_OFFSET] = HELLO_REQ; + memcpy(&g_Transmit_Buffer[HELLO_MAGIC_NUM_OFFSET],host_header,32); + g_Transmit_Buffer[HELLO_MAX_VER_OFFSET] = STREAM_DLOAD_MAX_VER; + g_Transmit_Buffer[HELLO_MIN_VER_OFFSET] = STREAM_DLOAD_MIN_VER; + g_Transmit_Buffer[HELLO_MAX_DATA_SZ_1_OFFSET] = 0; + g_Transmit_Length = 36; + + compute_reply_crc(); + send_packet(1); + + int timeout = 5; + do{ + err = receive_packet(); + if(err == 1){ + switch(g_Receive_Buffer[0]) + { + case 0x02: + return 1; + case 0x0d: + continue; + default: + //dump_buffer(g_Receive_Buffer, 64); + return 0; + } + } + else if(err == -1){ + dbg_time("error = %d, strerr = %s\n", errno, strerror(errno)); + return 0; + } + timeout--; + }while(timeout); + + return 0; +} + +static int handle_security_mode(unsigned char trusted) { + dbg_time("%s trusted = %d\n", __func__, trusted); + compose_packet(0x17, &trusted, 1, NULL, 0); + compute_reply_crc(); + send_packet(1); + int timeout = 5; + do{ + if(receive_packet() == 1){ + switch(g_Receive_Buffer[0]) + { + case 0x18: + return 1; + default: + return 0; + } + }else + { + timeout--; + if(timeout==0) + { + dbg_time("%s timeout\n", __FUNCTION__); + return 0; + } + } + }while(1); + return 0; +} +/* +set download flag in module, quectel custom command, +if flag : reboot, module will enter DM +if not flag: reboot normal +*/ +static int handle_quectel_download_flag(unsigned char mode) { + //byte mode = 1; + compose_packet(0x60, &mode, 1, NULL, 0); + compute_reply_crc(); + send_packet(1); + int timeout = 5; + do{ + if(receive_packet() == 1) + { + switch(g_Receive_Buffer[0]) + { + case 0x61: + switch( g_Receive_Buffer[1] ) + { + case 0x00: + return 1; + default: + return 0; + } + break; + case 0x0E: + dbg_time("Invalid command"); + return 2; + default: + dump_buffer(g_Receive_Buffer, 64); + return 0; + } + } + else + { + timeout--; + if(timeout==0) + { + dbg_time("%s timeout\n", __FUNCTION__); + return 0; + } + } + }while(1); +} + +static const char *stream_firehose_dir; +static int stread_fread(const char *filename, void **pp_filebuf) { + int filesize = 0; + FILE *fp; + char fullpath[MAX_PATH*2]; + + snprintf(fullpath, sizeof(fullpath), "%.240s/../%.240s", stream_firehose_dir, filename); + fp = fopen(fullpath, "rb"); + if (fp == NULL) { + dbg_time("fail to fope %s, errno: %d (%s)\n", fullpath, errno, strerror(errno)); + return 0; + } + + fseek(fp, 0, SEEK_END); + filesize = ftell(fp); + + *pp_filebuf = malloc(filesize); + fseek(fp, 0, SEEK_SET); + filesize = fread(*pp_filebuf, 1, filesize, fp); + fclose(fp); + + dbg_time("%s filename=%s, filesize=%d\n", __func__, filename, filesize); + return filesize; +} + +static int handle_parti_tbl(unsigned char override) { + int timeout = 5; + int filesize; + void *filebuf; + const char *partition_path= "partition.mbn"; + dbg_time("%s override = %d\n", __func__, override); + + filesize = stread_fread(partition_path, &filebuf); + if (filesize <= 0) + return 0; + + compose_packet(0x19, &override, 1, filebuf, filesize); + compute_reply_crc(); + send_packet(1); + free(filebuf); + + do{ + if(receive_packet() == 1){ + dbg_time("handle_parti_tbl command = %02x, status = %02x\n", g_Receive_Buffer[0], g_Receive_Buffer[1]); + switch(g_Receive_Buffer[0]) + { + case 0x1a: + switch( g_Receive_Buffer[1] ){ + case 0x00: + return 1; + case 0x01: //0x1 this means that the original partition is different from the current partition,try to send partition + return 0; + case 0x02: //0x2 Partition table format not recognized, does not accept override + return 0; + case 0x03: //0x3 Erase operation failed + return 0; + break; + default: + return 0; + } + default: + return 0; + } + }else + { + timeout--; + if(timeout == 0) + { + dbg_time("%s timeout\n", __FUNCTION__); + return 0; + } + } + }while(1); +} + +static int handle_reset(void) { + dbg_time("%s\n", __func__); + compose_packet(0x0b, NULL, 0, NULL, 0); + compute_reply_crc(); + send_packet(1); +#if 1 + return 1; +#else + int timeout = 5; + do{ + if(receive_packet() == 1){ + switch(g_Receive_Buffer[0]) + { + case 0x0c: + return 1; + case 0x0d: + continue; + default: + dump_buffer(g_Receive_Buffer, 64); + return 0; + } + } + else + { + + timeout--; + if(timeout == 0) + { + dbg_time("%s timeout\n", __FUNCTION__); + return 0; + } + } + }while(1); +#endif +} + +/******pkt_open_multi_image*******/ + +static void pkt_open_multi_image (unsigned char mode, unsigned char *data, uint32_t size) { + compose_packet(0x1b, &mode, 1, data, size); + compute_reply_crc(); +} + +static int handle_openmulti(uint32_t size,unsigned char* data) +{ + int timeout = 5; + unsigned char mode=0x0e; + + pkt_open_multi_image(mode, data, size); + send_packet(1); + do { + if (receive_packet() == 1) { + switch (g_Receive_Buffer[0]) { + case 0x1c: + return 1; + case 0x0d: + continue; + default: + return 0; + } + }else + { + + timeout--; + if(timeout == 0) + { + dbg_time("%s timeout\n", __FUNCTION__); + return 0; + } + } + } while (1); + return 1; +} + +/******pkt_write_multi_image*******/ +static void pkt_write_multi_image(uint32_t addr, unsigned char*data, uint16_t size) { + unsigned char parameter[4] = {(unsigned char)(addr)&0xff, (unsigned char)(addr>>8)&0xff, (unsigned char)(addr>>16)&0xff, (unsigned char)(addr>>24)&0xff}; + compose_packet(0x07, parameter, 4, data, size); + compute_reply_crc(); +} + +static int handle_write(unsigned char *data, uint32_t size) +{ + //uint32_t total_size; + uint32_t addr = 0; + uint32_t writesize; + uint32_t buffer_size = 1024; + //int loop = 1; + int retry_cnt = 3; //if send failed,send again + int ret; + + //total_size = size; + while(size) + { + writesize = (size < buffer_size) ? size : buffer_size; + + pkt_write_multi_image(addr, data, writesize); +start_send_packet: + ret = send_packet(1); + if(0 != ret) + { + dbg_time("io read/write failed\n"); + return 0; + } + if(receive_packet() == 1){ + switch(g_Receive_Buffer[0]) + { + case 0x08: + size -= writesize; + addr += writesize; + //retry_cnt=5; + break; + default: + goto retry_send_packet; + return 0; + } + } + else + { + +retry_send_packet: + retry_cnt--; + if(retry_cnt > 0) + { + goto start_send_packet; + } + else + { + dbg_time( "value is [0x%02x]",g_Receive_Buffer[0]); + return 0; + } + } + + } + + return 1; +} +/******PARTITION*******/ +static int handle_close(void) { + int timeout = 5; + compose_packet(0x15, NULL, 0, NULL, 0); + compute_reply_crc(); + send_packet(1); + + do{ + if(receive_packet() == 1){ + switch(g_Receive_Buffer[0]) + { + case 0x16: + return 1; + default: + return 0; + } + }else + { + + timeout--; + if(timeout == 0) + { + dbg_time("%s timeout\n", __FUNCTION__); + return 0; + } + } + }while(1); + return 0; +} + +static int do_flash_mbn(const char *partion, const char *filepath) { + int result = false; + void *filebuf = NULL; + int filesize = 0; + + dbg_time("%s %s\n", __func__, partion); + + if (filepath) { + filesize = stread_fread(filepath, &filebuf); + if (filesize <= 0) + return 0; + } + else { + filesize = 4*1024; + filebuf = (unsigned char *)malloc(filesize); + memset(filebuf, 0x00, filesize); + } + + result = handle_openmulti(strlen(partion) + 1, (unsigned char *)partion); + if (result == false) { + dbg_time("%s open failed\n", partion); + goto __fail; + } + + dbg_time("sending '%s' (%dKB)\n", partion, (int)(filesize/1024)); + + result = handle_write(filebuf, filesize); + if (result == false) { + dbg_time("%s download failed\n", partion); + goto __fail; + } + + result = handle_close(); + if (result == false) { + dbg_time("%s close failed.\n", partion); + goto __fail; + } + + dbg_time("OKAY\n"); + +__fail: + free(filebuf); + + return result; +} + +int stream_download(const char *firehose_dir, void *usb_handle, unsigned qusb_zlp_mode) +{ + (void)qusb_zlp_mode; + stream_usb_handle = usb_handle; + stream_firehose_dir = firehose_dir; + + if (handle_hello() == false) { + dbg_time("Send hello command fail\n"); + return false; + } + + /* + hello packet will set dload flag in module, when upgrade interrup, restart module,module will enter dm(quectel sbl) + */ + if (handle_security_mode(1) == false) { + dbg_time("Send trust command fail\n"); + return false; + } + + if (handle_parti_tbl(0) == false) { + dbg_time("----------------------------------\n"); + dbg_time("Detect partition mismatch.\n"); + dbg_time("Download parition with override.\n"); + dbg_time("----------------------------------\n"); + + if(handle_parti_tbl(1) == false) { + dbg_time("override failed. \n"); + return false; + } + + /* + partition is not match, the download flag will be clear, so set it again, reset will clear it + */ + if(handle_quectel_download_flag(1) == false) { + dbg_time("Set Quectel download flag failed\n"); + } + else { + dbg_time("Set Quectel download flag successfully\n"); + } + } + +#if 1 + if (do_flash_mbn("0:SBL", "sbl1.mbn") == false) { + return false; + } +#endif + + if (handle_reset() == false) { + dbg_time("Send reset command failed\n"); + return false; + } + + dbg_time("%s successful\n", __func__); + + return true; +} + +//hunter.lv add +//retrieve module soft revision + +typedef struct +{ + unsigned char cmd_code; + unsigned char version; + unsigned char reserved[2]; + unsigned char msm[4]; + unsigned char mobile_modle_number[4]; + unsigned char mobile_software_revision[1]; +}__attribute__ ((packed))extended_build_id_response_t; + +int retrieve_soft_revision(void *usb_handle, uint8_t *mobile_software_revision, unsigned length) +{ +/* +80-v1294-1_yyd_serial_interface_control_document_(icd)_for_cdma_dual-mode_subscriber_station_data 3.4.122 Extended Build ID +*/ + uint8_t req1[] = {0x7E,0x7C, 0x93,0x49, 0x7E}; + int ret; + uint8_t *rx_buff = malloc(2048); + + memset(mobile_software_revision, 0x00, length); + + if (rx_buff == NULL) + return 0; + + ret = qusb_noblock_write(usb_handle, req1, sizeof(req1), sizeof(req1), 1000, 0); + if(ret > 0) { + ret = qusb_noblock_read(usb_handle, rx_buff , 2048, 1, 3000); + if (ret > 0) { + if (rx_buff[0] == 0x7C && rx_buff[ret - 1] == 0x7E) { + extended_build_id_response_t *rsp = (extended_build_id_response_t *)rx_buff; + (void)length; + memcpy(mobile_software_revision, rsp->mobile_software_revision, strlen((const char *)rsp->mobile_software_revision)); + } + } + } + + free(rx_buff); + return (mobile_software_revision[0] != '\0'); +} diff --git a/rooter/0optionalapps/qfirehose/src/usb2tcp.c b/rooter/0optionalapps/qfirehose/src/usb2tcp.c new file mode 100644 index 0000000..0d8e4d3 --- /dev/null +++ b/rooter/0optionalapps/qfirehose/src/usb2tcp.c @@ -0,0 +1,338 @@ +/****************************************************************************** + @file tty2tcp.c + @brief switch data between tcp socket and ttyUSB port. + + DESCRIPTION + QLog Tool for USB and PCIE of Quectel wireless cellular modules. + + INITIALIZATION AND SEQUENCING REQUIREMENTS + None. + + --------------------------------------------------------------------------- + Copyright (c) 2016 - 2020 Quectel Wireless Solution, Co., Ltd. All Rights Reserved. + Quectel Wireless Solution Proprietary and Confidential. + --------------------------------------------------------------------------- +******************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 20) +#include +#else +#include +#endif +//#include +#include "usb_linux.h" +#include //for __BYTE_ORDER +char *inet_ntoa(struct in_addr in); + +#define dprintf dbg_time + +#define MIN(a,b) ((a) < (b)? (a) : (b)) + +#define MAX_USBFS_BULK_IN_SIZE (4 * 1024) +#define MAX_USBFS_BULK_OUT_SIZE (16 * 1024) + +static uint32_t cpu_to_le32 (uint32_t v32) { + uint32_t tmp = v32; +#if __BYTE_ORDER == __LITTLE_ENDIAN +#else + unsigned char *s = (unsigned char *)(&v32); + unsigned char *d = (unsigned char *)(&tmp); + d[0] = s[3]; + d[1] = s[2]; + d[2] = s[1]; + d[3] = s[0]; +#endif + return tmp; +} +#define le32_to_cpu(_v32) cpu_to_le32(_v32) + +static int qusb_control[2]; + +static int noblock_full_read(int fd, void *pbuf, ssize_t size) { + ssize_t cur = 0; + + while (cur < size) { + ssize_t ret = read(fd, (char *)pbuf+cur, size-cur); + + if (ret > 0) + cur += ret; + else if (ret < 0 && errno == EAGAIN) { + struct pollfd pollfds[] = {{fd, POLLIN, 0}}; + poll(pollfds, 1, -1); + if (pollfds[0].revents & (POLLERR | POLLHUP | POLLNVAL)) + break; + } else { + dprintf("fd=%d read=%zd, errno: %d (%s)\n", fd, ret, errno, strerror(errno)); + break; + } + } + + if (cur != size) { + dprintf("%s fd=%d cur=%zd, size=%zd\n", __func__, fd, cur, size); + } + + return cur; +} + +static ssize_t noblock_full_write(int fd, const void *pbuf, ssize_t size) { + ssize_t cur = 0; + + while (cur < size) { + ssize_t ret = write(fd, (char *)pbuf+cur, size-cur); + if (ret > 0) + cur += ret; + else if (ret <= 0 && errno == EAGAIN) { + struct pollfd pollfds[] = {{fd, POLLOUT, 0}}; + poll(pollfds, 1, -1); + if (pollfds[0].revents & (POLLERR | POLLHUP | POLLNVAL)) + break; + } else { + dprintf("fd=%d write=%zd, errno: %d (%s)\n", fd, ret, errno, strerror(errno)); + break; + } + } + + if (cur != size) { + dprintf("%s fd=%d cur=%zd, size=%zd\n", __func__, fd, cur, size); + } + + return cur; +} + +static void* usb_bulk_read_thread(void* arg) { + const void *usb_handle = arg; + void *buf = malloc(MAX_USBFS_BULK_IN_SIZE); + int fd = qusb_control[1]; + + if (buf == NULL) + return NULL; + + while(usb_handle) { + int count = qusb_noblock_read(usb_handle, buf, MAX_USBFS_BULK_IN_SIZE, 1, 30000); + + if (count > 0) { + count = write(fd, buf, count); + count = read(fd, buf, 32); //wait usb2tcp_main read + if (count <= 0) { + dprintf("read=%d\n", count); + break; + } + } else if (count <= 0) { + break; + } + } + + close(fd); + free(buf); + return NULL; +} + +static int qusb_open(const void *usb_handle) { + int fd = -1; + pthread_t thread_id; + + pthread_attr_t usb_thread_attr; + pthread_attr_init(&usb_thread_attr); + pthread_attr_setdetachstate(&usb_thread_attr, PTHREAD_CREATE_DETACHED); + + socketpair(AF_LOCAL, SOCK_STREAM, 0, qusb_control); + pthread_create(&thread_id, &usb_thread_attr, usb_bulk_read_thread, (void*)usb_handle); + + fd = qusb_control[0]; + + return fd; +} + +static ssize_t qusb_read(int fd, void* pbuf, size_t size) { + return read(fd, pbuf, size); +} + +static int create_tcp_server(int socket_port) { + int sockfd = -1; + int reuse_addr = 1; + struct sockaddr_in sockaddr; + + dprintf("%s tcp_port=%d\n", __func__, socket_port); + /*Create server socket*/ + sockfd = socket(AF_INET, SOCK_STREAM, 0); + if (sockfd <= 0) + return sockfd; + + memset(&sockaddr, 0, sizeof(sockaddr)); + sockaddr.sin_family = AF_INET; + sockaddr.sin_addr.s_addr = htonl(INADDR_ANY); + sockaddr.sin_port = htons(socket_port); + + setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse_addr,sizeof(reuse_addr)); + if (bind(sockfd, (struct sockaddr *)&sockaddr, sizeof(sockaddr)) < 0) { + close(sockfd); + dprintf("%s bind %d errno: %d (%s)\n", __func__, socket_port, errno, strerror(errno)); + return -1; + } + + return sockfd; +} + +static int wait_client_connect(int server_fd) { + int client_fd = -1; + unsigned char addr[128]; + socklen_t alen = sizeof(addr); + + dprintf("%s\n", __func__); + listen(server_fd, 1); + client_fd = accept(server_fd, (struct sockaddr *)addr, &alen); + if (client_fd <= 0) + return client_fd; + + if (client_fd > 0) { + struct sockaddr_in *addr_in = (struct sockaddr_in *)addr; + dprintf("clientfd = %d %s:%d connect\n", client_fd, inet_ntoa(addr_in->sin_addr), addr_in->sin_port); + } + + return client_fd; +} + +int usb2tcp_main(const void *usb_handle, int tcp_port, unsigned qusb_zlp_mode) { + void *pbuf = malloc(MAX_USBFS_BULK_OUT_SIZE); + int server_fd = -1, client_fd = -1, usb_fd = -1, size = -1; + TLV_USB tlv_usb; + + if (pbuf == NULL) + return -1; + + server_fd = create_tcp_server(tcp_port); + dprintf("server_fd=%d\n", server_fd); + if (server_fd <= 0) { + dprintf("Fail create_tcp_server\n"); + goto _out; + } + + if (client_fd <= 0) { + client_fd = wait_client_connect(server_fd); + if (client_fd < 0) { + dprintf("Fail wait_client_connect\n"); + goto _out; + } + } + + usb_fd = qusb_open(usb_handle); + dprintf("usb_fd = %d\n", usb_fd); + + tlv_usb.tag = cpu_to_le32(Q_USB2TCP_VERSION); + tlv_usb.length = cpu_to_le32(12); + tlv_usb.idVendor = cpu_to_le32(0x05c6); + tlv_usb.idProduct = cpu_to_le32(0x9008); + tlv_usb.interfaceNum = cpu_to_le32(1); + if (write(client_fd, &tlv_usb, sizeof(tlv_usb)) == -1) {}; + + fcntl(usb_fd, F_SETFL, fcntl(usb_fd,F_GETFL) | O_NONBLOCK); + fcntl(client_fd, F_SETFL, fcntl(client_fd,F_GETFL) | O_NONBLOCK); + + while (usb_fd > 0 && client_fd > 0) { + struct pollfd pollfds[] = {{usb_fd, POLLIN, 0}, {client_fd, POLLIN, 0}}; + int ne, ret, nevents = sizeof(pollfds)/sizeof(pollfds[0]); + + do { + ret = poll(pollfds, nevents, -1); + } while (ret < 0 && errno == EINTR); + + + if (ret <= 0) { + dprintf("%s poll=%d, errno: %d (%s)\n", __func__, ret, errno, strerror(errno)); + goto _hangup; + } + + + if (pollfds[0].revents & (POLLERR | POLLHUP | POLLNVAL)) { + dprintf("%s poll usb_fd = %d, revents = %04x\n", __func__, usb_fd, pollfds[0].revents); + goto _hangup; + } + + + if (pollfds[1].revents & (POLLERR | POLLHUP | POLLNVAL)) { + dprintf("%s poll client_fd = %d, revents = %04x\n", __func__, client_fd, pollfds[1].revents); + goto _hangup; + } + + for (ne = 0; ne < nevents; ne++) { + int fd = pollfds[ne].fd; + TLV tlv = {Q_USB2TCP_VERSION, 0}; + + if ((pollfds[ne].revents & POLLIN) == 0) + continue; + + if (fd == usb_fd) { + size = qusb_read(usb_fd, pbuf, MAX_USBFS_BULK_IN_SIZE); + if (size <= 0) { + dprintf("usb_fd=%d read=%d, errno: %d (%s)\n", fd, size, errno, strerror(errno)); + goto _hangup;; + } + if (write(usb_fd, pbuf, 1) == -1) {}; //wakeup usb_bulk_read_thread + + tlv.tag = cpu_to_le32(Q_USB2TCP_VERSION); + tlv.length = cpu_to_le32(size); + if (sizeof(tlv) != noblock_full_write(client_fd, &tlv, sizeof(tlv))) { + goto _hangup; + break; + } + + if (size != noblock_full_write(client_fd, pbuf, size)) { + goto _hangup; + break; + } + } + else if (fd == client_fd) { + size = noblock_full_read(client_fd, &tlv, sizeof(tlv)); + if (size != sizeof(tlv)) { + dprintf("client_fd=%d read=%d, errno: %d (%s)\n", fd, size, errno, strerror(errno)); + goto _hangup; + } + + if (le32_to_cpu(tlv.tag) != Q_USB2TCP_VERSION) { + break; + } + + size = le32_to_cpu(tlv.length); + if (size != noblock_full_read(client_fd, pbuf, size)) { + goto _hangup; + break; + } + qusb_noblock_write(usb_handle, pbuf, size, size, 3000, qusb_zlp_mode); + } + } + } + +_hangup: + if (usb_fd > 0) { + close(usb_fd); + usb_fd = -1; + } + if (client_fd > 0) { + close(client_fd); + client_fd = -1; + } + +_out: + free(pbuf); + return 0; +} diff --git a/rooter/0optionalapps/qfirehose/src/usb_linux.c b/rooter/0optionalapps/qfirehose/src/usb_linux.c new file mode 100644 index 0000000..9aa2ed8 --- /dev/null +++ b/rooter/0optionalapps/qfirehose/src/usb_linux.c @@ -0,0 +1,1170 @@ +/****************************************************************************** + @file usb_linux.c + @brief read and write usb devices. + + DESCRIPTION + QFirehoe Tool for USB and PCIE of Quectel wireless cellular modules. + + INITIALIZATION AND SEQUENCING REQUIREMENTS + None. + + --------------------------------------------------------------------------- + Copyright (c) 2016 - 2020 Quectel Wireless Solution, Co., Ltd. All Rights Reserved. + Quectel Wireless Solution Proprietary and Confidential. + --------------------------------------------------------------------------- +******************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 20) +#include +#else +#include +#endif +#include +#include +#include +#include "usb_linux.h" + +int edl_pcie_mhifd = -1; +int switch_to_edl_mode(void *usb_handle); + +extern uint32_t inet_addr(const char *); + +#define MAX_USBFS_BULK_IN_SIZE (4 * 1024) +#define MAX_USBFS_BULK_OUT_SIZE (16 * 1024) +#define EC20_MAX_INF 4 +#define MKDEV(__ma, __mi) (((__ma & 0xfff) << 8) | (__mi & 0xff) | ((__mi & 0xfff00) << 12)) + +struct quectel_usb_device { + char devname[64]; + int desc; + int ttyfd; + int idVendor; + int idProduct; + uint8_t bNumInterfaces; + uint8_t intr_ep[EC20_MAX_INF]; + uint8_t bulk_ep_in[EC20_MAX_INF]; + uint8_t bulk_ep_out[EC20_MAX_INF]; + int wMaxPacketSize[EC20_MAX_INF]; + int control[EC20_MAX_INF][2]; +}; + +static struct quectel_usb_device quectel_9x07; +static int tcp_socket_fd = -1; +static int usb_dm_interface = 0; + +static int strStartsWith(const char *line, const char *prefix) +{ + for ( ; *line != '\0' && *prefix != '\0' ; line++, prefix++) { + if (*line != *prefix) { + return 0; + } + } + + return *prefix == '\0'; +} + +static int quectel_get_sysinfo_by_uevent(const char *uevent, MODULE_SYS_INFO *pSysInfo) { + FILE *fp; + char line[MAX_PATH]; + + memset(pSysInfo, 0x00, sizeof(MODULE_SYS_INFO)); + + fp = fopen(uevent, "r"); + if (fp == NULL) { + dbg_time("fail to fopen %s, errno: %d (%s)\n", uevent, errno, strerror(errno)); + return 0; + } + + //dbg_time("%s\n", uevent); + while (fgets(line, sizeof(line), fp)) { + if (line[strlen(line) - 1] == '\n' || line[strlen(line) - 1] == '\r') { + line[strlen(line) - 1] = '\0'; + } + + //dbg_time("%s\n", line); + if (strStartsWith(line, "MAJOR=")) { + pSysInfo->MAJOR = atoi(&line[strlen("MAJOR=")]); + } + else if (strStartsWith(line, "MINOR=")) { + pSysInfo->MINOR = atoi(&line[strlen("MINOR=")]); + } + else if (strStartsWith(line, "DEVNAME=")) { + if(pSysInfo) + strncpy(pSysInfo->DEVNAME, &line[strlen("DEVNAME=")], sizeof(pSysInfo->DEVNAME)); + } + else if (strStartsWith(line, "DEVTYPE=")) { + strncpy(pSysInfo->DEVTYPE, &line[strlen("DEVTYPE=")], sizeof(pSysInfo->DEVTYPE)); + } + else if (strStartsWith(line, "PRODUCT=")) { + strncpy(pSysInfo->PRODUCT, &line[strlen("PRODUCT=")], sizeof(pSysInfo->PRODUCT)); + } + } + + fclose(fp); + + return 1; +} + +// the return value is the number of quectel modules +int auto_find_quectel_modules(char *module_sys_path, unsigned size) +{ + const char *base = "/sys/bus/usb/devices"; + DIR *busdir = NULL; + struct dirent *de = NULL; + int count = 0; + + busdir = opendir(base); + if (busdir == NULL) + return -1; + + while ((de = readdir(busdir))) { + static char uevent[MAX_PATH]; + static MODULE_SYS_INFO sysinfo; + + if (!isdigit(de->d_name[0])) continue; + + snprintf(uevent, sizeof(uevent), "%.24s/%.16s/uevent", base, de->d_name); + if (!quectel_get_sysinfo_by_uevent(uevent, &sysinfo)) + continue; + + if (sysinfo.MAJOR != 189) + continue; + + //dbg_time("MAJOR=%d, MINOR=%d, DEVNAME=%s, DEVTYPE=%s, PRODUCT=%s\n", + // sysinfo.MAJOR, sysinfo.MINOR, sysinfo.DEVNAME, sysinfo.DEVTYPE, sysinfo.PRODUCT); + + if (sysinfo.DEVTYPE[0] == '\0' || strStartsWith(sysinfo.DEVTYPE, "usb_device") == 0) + continue; + + if (sysinfo.PRODUCT[0] == '\0') { + continue; + } + + if (!(strStartsWith(sysinfo.PRODUCT, "2c7c/") + || strStartsWith(sysinfo.PRODUCT, "5c6/9008") + || strStartsWith(sysinfo.PRODUCT, "5c6/901f") + || strStartsWith(sysinfo.PRODUCT, "5c6/9091") + || strStartsWith(sysinfo.PRODUCT, "3763/3c93/318"))) { + continue; + } + + if ((strStartsWith(sysinfo.PRODUCT, "2c7c/6") || strStartsWith(sysinfo.PRODUCT, "2c7c/8")) + && (sysinfo.PRODUCT[strlen("2c7c/6000")] == '/')) //skip ASR&HISI modules + continue; + + snprintf(module_sys_path, size, "%.24s/%s", base, de->d_name); + count++; + dbg_time("[%d] %s %s\n", count, module_sys_path, sysinfo.PRODUCT); + } + + closedir(busdir); + + return count; +} + +void quectel_get_ttyport_by_syspath(const char *module_sys_path, char *module_port_name, unsigned size) { + char infname[256]; + DIR *infdir = NULL; + struct dirent *de = NULL; + + module_port_name[0] = '\0'; + + sprintf(infname, "%s:1.%d", module_sys_path, usb_dm_interface); + infdir = opendir(infname); + if (infdir == NULL) + return; + + while ((de = readdir(infdir))) { + if (strStartsWith(de->d_name, "ttyUSB")) { + snprintf(module_port_name, size, "/dev/%s", de->d_name); + break; + } + else if (!strncmp(de->d_name, "tty", strlen("tty"))) { + sprintf(infname, "%s:1.%d/tty", module_sys_path, usb_dm_interface); + closedir(infdir); + infdir = opendir(infname); + if (infdir == NULL) + break; + } + } + + if (infdir) closedir(infdir); +} + +static void quectel_fixup_sysport(const char *module_port_name, char *sysport, unsigned size) { + char syspath[MAX_PATH+16]; + const char *sys_base = "/sys/class/tty"; + DIR *sys_dir = NULL; + struct dirent *dev = NULL; + + sysport[0] = '\0'; + sys_dir = opendir(sys_base); + if (!sys_dir) { + dbg_time("fail to opendir('%s'), errno: %d (%s)\n", sys_base, errno, strerror(errno)); + return; + } + + while (NULL != (dev = readdir(sys_dir))) + { + if (!strncasecmp("ttyUSB", dev->d_name, strlen("ttyUSB"))) { + MODULE_SYS_INFO sysinfo; + + snprintf(syspath, sizeof(syspath), "%.24s/%.16s/uevent", sys_base, dev->d_name); + if (quectel_get_sysinfo_by_uevent(syspath, &sysinfo)) { + struct stat buf; + dev_t devt; + + devt = makedev(sysinfo.MAJOR, sysinfo.MINOR); + if(!stat(module_port_name, &buf) && buf.st_rdev == devt) { + snprintf(sysport, size, "/sys/class/tty/%.16s", dev->d_name); + break; + } + } + } + } + closedir(sys_dir); +} + + +void quectel_get_syspath_name_by_ttyport(const char *module_port_name, char *module_sys_path, unsigned size) { + char syspath[MAX_PATH]; + char sysport[64]; + int count; + char *pchar = NULL; + char dm_tty[24]; + + snprintf(dm_tty, sizeof(dm_tty), ":1.%d/tty", usb_dm_interface); + module_sys_path[0] = '\0'; + + snprintf(sysport, sizeof(sysport), "/sys/class/tty/%.48s", &module_port_name[strlen("/dev/")]); + if(access(sysport, F_OK) && errno == ENOENT) { + quectel_fixup_sysport(module_port_name, sysport, sizeof(sysport));//query real name + } + if(access(sysport, F_OK) && errno == ENOENT) + return; + count = readlink(sysport, syspath, sizeof(syspath) - 1); + if (count < (int)strlen(dm_tty)) + return; + +//ttyUSB0 -> ../../devices/soc0/soc/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb1/1-1/1-1:1.0/ttyUSB0/tty/ttyUSB0 + pchar = strstr(syspath, dm_tty); + if (pchar == NULL) + return; + + *pchar = '\0'; + while (*pchar != '/') + pchar--; + + snprintf(module_sys_path, size, "/sys/bus/usb/devices/%.232s", pchar + 1); +} + +static void quectel_get_usb_device_info(const char *module_sys_path, struct quectel_usb_device *udev) { + static unsigned char devdesc[1024]; + size_t desclength, len; + char devname[MAX_PATH]; + int desc_fd; + __u8 bInterfaceNumber = 0; + int dev_mknod_and_delete_after_use = 0; + + MODULE_SYS_INFO sysinfo; + snprintf(devname, sizeof(devname), "%.248s/%s", module_sys_path, "uevent"); + if (!quectel_get_sysinfo_by_uevent(devname, &sysinfo)) + return; + + snprintf(devname, sizeof(devname), "/dev/%s", sysinfo.DEVNAME); + if (access(devname, R_OK) && errno_nodev()) { + //maybe Linux have create /sys/ device, but not ready to create /dev/ device. + usleep(100*1000); + } + + if (access(devname, R_OK) && errno_nodev()) + { + char *p = strstr(devname+strlen("/dev/"), "/"); + + while (p) { + p[0] = '_'; + p = strstr(p, "/"); + } + + if (mknod(devname, S_IFCHR|0666, MKDEV(sysinfo.MAJOR, sysinfo.MINOR))) { + devname[1] = 't'; + devname[2] = 'm'; + devname[3] = 'p'; + + if (mknod(devname, S_IFCHR|0666, MKDEV(sysinfo.MAJOR, sysinfo.MINOR))) { + dbg_time("Fail to mknod %s, errno : %d (%s)\n", devname, errno, strerror(errno)); + return; + } + } + + dev_mknod_and_delete_after_use = 1; + } + + desc_fd = open(devname, O_RDWR | O_NOCTTY); + + if (dev_mknod_and_delete_after_use) { + remove(devname); + } + + if (desc_fd <= 0) { + dbg_time("fail to open %s, errno: %d (%s)\n", devname, errno, strerror(errno)); + return; + } + + desclength = read(desc_fd, devdesc, sizeof(devdesc)); + len = 0; + while (len < desclength) { + struct usb_descriptor_header *h = (struct usb_descriptor_header *)(&devdesc[len]); + + if (h->bLength == sizeof(struct usb_device_descriptor) && h->bDescriptorType == USB_DT_DEVICE) { + struct usb_device_descriptor *device = (struct usb_device_descriptor *)h; + + udev->idVendor = device->idVendor; + udev->idProduct = device->idProduct; + dbg_time("P: %s idVendor=%04x idProduct=%04x\n", devname, device->idVendor, device->idProduct); + } + else if (h->bLength == sizeof(struct usb_config_descriptor) && h->bDescriptorType == USB_DT_CONFIG) { + struct usb_config_descriptor *config = (struct usb_config_descriptor *)h; + + dbg_time("C: %s bNumInterfaces: %d\n", devname, config->bNumInterfaces); + udev->bNumInterfaces = config->bNumInterfaces; + } + else if (h->bLength == sizeof(struct usb_interface_descriptor) && h->bDescriptorType == USB_DT_INTERFACE) { + struct usb_interface_descriptor *interface = (struct usb_interface_descriptor *)h; + + dbg_time("I: If#= %d Alt= %d #EPs= %d Cls=%02x Sub=%02x Prot=%02x\n", + interface->bInterfaceNumber, interface->bAlternateSetting, interface->bNumEndpoints, + interface->bInterfaceClass, interface->bInterfaceSubClass, interface->bInterfaceProtocol); + bInterfaceNumber = interface->bInterfaceNumber; + } + else if (h->bLength == USB_DT_ENDPOINT_SIZE && h->bDescriptorType == USB_DT_ENDPOINT) { + if (bInterfaceNumber < EC20_MAX_INF) { + struct usb_endpoint_descriptor *endpoint = (struct usb_endpoint_descriptor *)h; + + dbg_time("E: Ad=%02x Atr=%02x MxPS= %d Ivl=%dms\n", + endpoint->bEndpointAddress, endpoint->bmAttributes, endpoint->wMaxPacketSize, endpoint->bInterval); + + if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) { + if (endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) + udev->bulk_ep_in[bInterfaceNumber] = endpoint->bEndpointAddress; + else + udev->bulk_ep_out[bInterfaceNumber] = endpoint->bEndpointAddress; + udev->wMaxPacketSize[bInterfaceNumber] = endpoint->wMaxPacketSize; + } else if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT){ + udev->intr_ep[bInterfaceNumber] = endpoint->bEndpointAddress; + } + } + } else { + } + + len += h->bLength; + } + + if (len == desclength) { + strcpy(udev->devname, devname); + udev->desc = desc_fd; + } + + usb_dm_interface = 0; + if ((udev->bulk_ep_in[usb_dm_interface] == 0 && udev->bulk_ep_in[usb_dm_interface] == 0) + || (udev->idVendor == 0x2c7c && udev->idProduct == 0x0127)) + usb_dm_interface = 3; +} + +static int usbfs_bulk_write(struct quectel_usb_device *udev, const void *data, int len, int timeout_msec, int need_zlp) { + struct usbdevfs_urb bulk; + struct usbdevfs_urb *urb = &bulk; + int n = -1; + int bInterfaceNumber = usb_dm_interface; + + (void)timeout_msec; + //if (urb->type == 0) + { + memset(urb, 0, sizeof(struct usbdevfs_urb)); + urb->type = USBDEVFS_URB_TYPE_BULK; + urb->endpoint = udev->bulk_ep_out[bInterfaceNumber]; + } + + urb->status = -1; + urb->buffer = (void *)data; + urb->buffer_length = (len > MAX_USBFS_BULK_OUT_SIZE) ? MAX_USBFS_BULK_OUT_SIZE : len; + urb->usercontext = urb; + + if ((len <= MAX_USBFS_BULK_OUT_SIZE) && need_zlp && (len%udev->wMaxPacketSize[bInterfaceNumber]) == 0) { + //dbg_time("USBDEVFS_URB_ZERO_PACKET\n"); +#ifndef USBDEVFS_URB_ZERO_PACKET +#define USBDEVFS_URB_ZERO_PACKET 0x40 +#endif + urb->flags = USBDEVFS_URB_ZERO_PACKET; + } else { + urb->flags = 0; + } + + do { + n = ioctl(udev->desc, USBDEVFS_SUBMITURB, urb); + } while((n < 0) && (errno == EINTR)); + + if (n != 0) { + dbg_time("inf[%d] USBDEVFS_SUBMITURB %d/%d, errno = %d (%s)\n", bInterfaceNumber, n, urb->buffer_length, errno, strerror(errno)); + return -1; + } + + do { + urb = NULL; + n = ioctl(udev->desc, USBDEVFS_REAPURB, &urb); + } while((n < 0) && (errno == EINTR)); + + if (n != 0) { + dbg_time("inf[%d] ep_out %d/%d, errno = %d (%s)\n", bInterfaceNumber, n, urb->buffer_length, errno, strerror(errno)); + } + + //dbg_time("[ urb @%p status = %d, actual = %d ]\n", urb, urb->status, urb->actual_length); + + if (urb && urb->status == 0 && urb->actual_length) + return urb->actual_length; + + return -1; +} + +static int poll_wait(int poll_fd, short events, int timeout_msec) { + struct pollfd pollfds[] = {{poll_fd, events, 0}}; + int ret; + + do { + ret = poll(pollfds, 1, timeout_msec); + } while(ret == -1 && errno == EINTR); + + if (ret == 1 && (pollfds[0].revents & (events))) + return 0; + else if (ret == 0) {//timeout + dbg_time("poll_wait events=%s msec=%d timeout\n", + (events & POLLIN) ? "POLLIN" : "POLLOUT", timeout_msec); + return ETIMEDOUT; + } + + return EIO; +} + +static int usbfs_bulk_read(struct quectel_usb_device *udev, void *pbuf, int len, int timeout) { + struct usbdevfs_bulktransfer bulk; + int n = -1; + int bInterfaceNumber = usb_dm_interface; + + if (len < 512) { + dbg_time("%s len=%d is too short\n", __func__, len); + return 0; + } + + bulk.ep = udev->bulk_ep_in[bInterfaceNumber]; + bulk.len = (len > MAX_USBFS_BULK_IN_SIZE) ? MAX_USBFS_BULK_IN_SIZE : len; + bulk.data = (void *)pbuf; + bulk.timeout = timeout; + + n = ioctl(udev->desc, USBDEVFS_BULK, &bulk); + if( n <= 0 ) { + if (errno == ETIMEDOUT) { + dbg_time("inf[%d] ep_in %d/%d, errno = %d (%s), timeout=%d\n", bInterfaceNumber, n, bulk.len, errno, strerror(errno), timeout); + n = 0; + } + else + dbg_time("inf[%d] ep_in %d/%d, errno = %d (%s)\n", bInterfaceNumber, n, bulk.len, errno, strerror(errno)); + } + + return n ; +} + +static int qtcp_connect(const char *port_name, int *idVendor, int *idProduct, int *interfaceNum) { + int fd = -1; + char *tcp_host = strdup(port_name); + char *tcp_port = strchr(tcp_host, ':'); + struct sockaddr_in sockaddr; + TLV_USB tlv_usb; + + dbg_time("%s port_name = %s\n", __func__, port_name); + + if (tcp_port == NULL) + return -1; + + *tcp_port++ = '\0'; + if (atoi(tcp_port) < 1 || atoi(tcp_port) > 0xFFFF) + return -1; + + fd = socket(AF_INET, SOCK_STREAM, 0); + + if (fd <= 0) { + dbg_time("Device could not be socket: Linux System Errno: %s\n", strerror (errno)); + return -1; + } + + memset(&sockaddr, 0, sizeof(sockaddr)); + sockaddr.sin_family = AF_INET; + sockaddr.sin_addr.s_addr = inet_addr(tcp_host); + sockaddr.sin_port = htons(atoi(tcp_port)); + + free(tcp_host); + if (connect(fd, (struct sockaddr *) &sockaddr, sizeof(sockaddr)) < 0) { + close(fd); + dbg_time("Device could not be connect: Linux System Errno: %s\n", strerror (errno)); + return -1; + } + + //block read, untill usb2tcp tell me the usb device information + memset(&tlv_usb, 0x00, sizeof(tlv_usb)); + if (read(fd, &tlv_usb, sizeof(tlv_usb)) == -1) { }; + *idVendor = tlv_usb.idVendor; + *idProduct = tlv_usb.idProduct; + *interfaceNum = tlv_usb.interfaceNum; + + dbg_time("idVendor=%04x, idProduct=%04x, interfaceNum=%d\n", *idVendor, *idProduct, *interfaceNum); + + return fd; +} + +static int qtcp_read(int fd, void *pbuf, int size, int timeout_msec) { + static TLV tlv = {Q_USB2TCP_VERSION, 0}; + int cur = 0; + int len; + + if (tlv.length == 0) { + len = read(fd, &tlv, sizeof(tlv)); + if (len != sizeof(tlv)) { + dbg_time("%s read=%d, errno: %d (%s)\n", __func__, len, errno, strerror(errno)); + return 0; + } + + if (tlv.tag != Q_USB2TCP_VERSION) { + dbg_time("%s tlv->tag=0x%x\n", __func__, tlv.tag); + return 0; + } + } + + if (size > tlv.length) + size = tlv.length; + tlv.length -= size; + + while (cur < size) { + if (poll_wait(fd, POLLIN, timeout_msec)) + break; + + len = read(fd, (uint8_t *)pbuf+cur, size-cur); + if (len > 0) { + cur += len; + } + else { + dbg_time("%s read=%d, errno: %d (%s)\n", __func__, len, errno, strerror(errno)); + break; + } + } + + if (cur != size) { + dbg_time("%s cur=%d, size=%d\n", __func__, cur, size); + } + + return cur; +} + +static int qtcp_write(int fd, void*pbuf, int size, int timeout_msec) { + TLV tlv = {Q_USB2TCP_VERSION, size}; + int cur = 0; + int len; + + len = write(fd, &tlv, sizeof(tlv)); + if (len != sizeof(tlv)) { + dbg_time("%s write=%d, errno: %d (%s)\n", __func__, len, errno, strerror(errno)); + return 0; + } + + while (cur < size) { + if (poll_wait(fd, POLLOUT, timeout_msec)) + break; + + len = write(fd, (uint8_t *)pbuf+cur, size-cur); + if (len > 0) { + cur += len; + } + else { + dbg_time("%s write=%d, errno: %d (%s)\n", __func__, len, errno, strerror(errno)); + break; + } + } + + if (cur != size) { + dbg_time("%s cur=%d, size=%d\n", __func__, cur, size); + } + + return cur; +} + +struct usbfs_getdriver +{ + unsigned int interface; + char driver[255 + 1]; +}; + +struct usbfs_ioctl +{ + int ifno; /* interface 0..N ; negative numbers reserved */ + int ioctl_code; /* MUST encode size + direction of data so the + * macros in give correct values */ + void *data; /* param buffer (in, or out) */ +}; + +#define IOCTL_USBFS_DISCONNECT _IO('U', 22) +#define IOCTL_USBFS_CONNECT _IO('U', 23) + +int usbfs_is_kernel_driver_alive(int fd, int ifnum) +{ + struct usbfs_getdriver getdrv; + getdrv.interface = ifnum; + if (ioctl(fd, USBDEVFS_GETDRIVER, &getdrv) < 0) { + if (errno != ENODATA) + dbg_time("%s ioctl USBDEVFS_GETDRIVER failed, errno: %d (%s)\n", __func__, errno, strerror(errno)); + return 0; + } + dbg_time("%s find interface %d has match the driver %s\n", __func__, ifnum, getdrv.driver); + return 1; +} + +void usbfs_detach_kernel_driver(int fd, int ifnum) +{ + struct usbfs_ioctl operate; + operate.data = NULL; + operate.ifno = ifnum; + operate.ioctl_code = IOCTL_USBFS_DISCONNECT; + if (ioctl(fd, USBDEVFS_IOCTL, &operate) < 0) { + dbg_time("%s detach kernel driver failed\n", __func__); + } else { + dbg_time("%s detach kernel driver success\n", __func__); + } +} + +#define KVERSION(j,n,p) ((j)*1000000 + (n)*1000 + (p)) +static struct utsname utsname; /* for the kernel version */ +static int ql_get_kernel_version(void) +{ + int osmaj, osmin, ospatch; + int kernel_version; + + uname(&utsname); + osmaj = osmin = ospatch = 0; + sscanf(utsname.release, "%d.%d.%d", &osmaj, &osmin, &ospatch); + kernel_version = KVERSION(osmaj, osmin, ospatch); + + return kernel_version; +} + +static int detect_xhci_usb_zero_packet_bug_not_fix(const char *module_sys_path) { + char buf[256]; + int tmp; + char *driver; + + tmp = snprintf(buf, sizeof(buf), "/sys/bus/usb/devices/usb%c/../driver", module_sys_path[strlen("/sys/bus/usb/devices/")]); + driver = buf + (++tmp); + *driver = '\0'; + + tmp = readlink(buf, driver, sizeof(buf) - tmp); + dbg_time("tmp=%s, driver=%s\n", buf, driver); + if (tmp <= 0) + return 0; + + if (!strstr(driver, "xhci")) + return 0; + + tmp = ql_get_kernel_version(); + if (tmp >= KVERSION(4,3,0)) + return 0; + + dbg_time("WARNNING ON File:%s Function:%s Line:%d\n", __FILE__, __func__, __LINE__); + dbg_time("The module attach to XHCI controller, but your kernel verison less than V4.3.0\n"); + dbg_time("Please make sure your kernel had apply patch 'usb: xhci: Add support for URB_ZERO_PACKET to bulk/sg transfers'\n"); + dbg_time("https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/commit/drivers/usb/host/xhci-ring.c?id=4758dcd19a7d9ba9610b38fecb93f65f56f86346\n"); + sleep(2); //sleep 2 seconds, make sure FAE/customers can notice this warnning. + + return 1; +} + +void *qusb_noblock_open(const char *module_sys_path, int *idVendor, int *idProduct, int *interfaceNum) { + struct termios ios; + int retval; + int fd = -1; + struct quectel_usb_device *udev = &quectel_9x07; + + *idVendor = *idProduct = *interfaceNum = 0; + tcp_socket_fd = -1; + + if (module_sys_path && module_sys_path[0] == '/') { + char port_name[64]; + + memset(udev, 0, sizeof(struct quectel_usb_device)); + quectel_get_usb_device_info(module_sys_path, udev); + if (udev->desc <= 0) + return NULL; + quectel_get_ttyport_by_syspath(module_sys_path, port_name, sizeof(port_name)); + detect_xhci_usb_zero_packet_bug_not_fix(module_sys_path); + + *idVendor = udev->idVendor; + *idProduct = udev->idProduct; + *interfaceNum = udev->bNumInterfaces; + + if (port_name[0] == '\0' || (port_name[0] != '\0' && access(port_name, R_OK)) || (udev->idVendor == 0x05c6 && udev->idProduct == 0x9008)) { + int bInterfaceNumber = 0; + + if (usbfs_is_kernel_driver_alive(udev->desc, bInterfaceNumber)) { + usbfs_detach_kernel_driver(udev->desc, bInterfaceNumber); + } + retval = ioctl(udev->desc, USBDEVFS_CLAIMINTERFACE, &bInterfaceNumber); + if(retval != 0) { + dbg_time("Fail to claim interface %d, errno: %d (%s)\n", bInterfaceNumber, errno, strerror(errno)); + if (udev->idVendor == 0x05c6) { + int n; + struct { + char infname[255 * 2]; + char driver[255 * 2]; + } *pl; + const char *driver = NULL; + + pl = (typeof(pl)) malloc(sizeof(*pl)); + + snprintf(pl->infname, sizeof(pl->infname), "%.255s:1.%d/driver", module_sys_path, usb_dm_interface); + n = readlink(pl->infname, pl->driver, sizeof(pl->driver)); + if (n > 0) { + pl->driver[n] = '\0'; + while (pl->driver[n] != '/') + n--; + driver = (&pl->driver[n+1]); + } + + dbg_time("Error: when module in 'Emergency download mode', should not register any usb driver\n"); + if (driver) + dbg_time("Error: it register to usb driver ' %s ' now, should delete 05c6&9008 from the source file of this driver\n", driver); + if (driver && !strcmp(driver, "qcserial")) + dbg_time("Delete 05c6&9008 from 'drivers/usb/serial/qcserial.c' or disable qcserial from kernel config\n"); + qusb_noblock_close(udev); + free(pl); + } + return NULL; + } + + udev->ttyfd = -1; + return udev; + } + else if (!access(port_name, R_OK)) { + dbg_time("%s port_name = %s\n", __func__, port_name); + + fd = open (port_name, O_RDWR | O_SYNC); + + if (fd <= 0) { + dbg_time("Device %s could not be open: Linux System Errno: %s", port_name, strerror (errno)); + return NULL; + } + + retval = tcgetattr (fd, &ios); + if (-1 == retval) { + dbg_time("ermio settings could not be fetched Linux System Error:%s", strerror (errno)); + return NULL; + } + + cfmakeraw (&ios); + cfsetispeed(&ios, B115200); + cfsetospeed(&ios, B115200); + + retval = tcsetattr (fd, TCSANOW, &ios); + if (-1 == retval) { + dbg_time("Device could not be configured: Linux System Errno: %s", strerror (errno)); + } + udev->ttyfd = fd; + fcntl(fd, F_SETFL, fcntl(fd,F_GETFL) | O_NONBLOCK); + + return udev; + } + else { + dbg_time("fail to access %s errno: %d (%s)\n", port_name, errno, strerror(errno)); + } + } + else { + fd = qtcp_connect(module_sys_path, idVendor, idProduct, interfaceNum); + if (fd > 0) { + tcp_socket_fd = fd; + fcntl(fd, F_SETFL, fcntl(fd,F_GETFL) | O_NONBLOCK); + return &tcp_socket_fd; + } + } + + return NULL; +} + +int qusb_noblock_close(void *handle) { + struct quectel_usb_device *udev = &quectel_9x07; + + if (handle == &tcp_socket_fd) { + close(tcp_socket_fd); + tcp_socket_fd = -1; + } if (handle == udev && udev->ttyfd > 0) { + close(udev->ttyfd); + close(udev->desc); + } + else if (handle == udev && udev->desc > 0) { + int bInterfaceNumber = 0; + ioctl(udev->desc, USBDEVFS_RELEASEINTERFACE, &bInterfaceNumber); + close(udev->desc); + } + else if (handle == &edl_pcie_mhifd && edl_pcie_mhifd > 0) { + close(edl_pcie_mhifd); edl_pcie_mhifd = -1; + } + memset(udev, 0, sizeof(*udev)); + + return 0; +} + +int qusb_use_usbfs_interface(const void *handle) { + struct quectel_usb_device *udev = &quectel_9x07; + + return (handle == udev && udev->ttyfd <= 0 && udev->desc > 0); +} + +int qusb_noblock_read(const void *handle, void *pbuf, int max_size, int min_size, int timeout_msec) { + struct quectel_usb_device *udev = &quectel_9x07; + int cur = 0; + int poll_ret = 0; + + if (min_size == 0) + min_size = 1; + if (timeout_msec == 0) + timeout_msec = 3000; + +#if 0 //depend on your worst net speed + if (handle == &tcp_socket_fd) { + if (timeout_msec > 1000) //before sahala&firebose, we allow read timeout occurs + timeout_msec = 120*1000; + } +#endif + + while (cur < min_size) { + int len = 0; + + if (handle == &tcp_socket_fd) { + if ((poll_ret = poll_wait(tcp_socket_fd, POLLIN, timeout_msec))) + break; + len = qtcp_read(tcp_socket_fd, (uint8_t *)pbuf+cur, max_size-cur, timeout_msec); + } + else if (handle == udev && udev->ttyfd > 0) { + if ((poll_ret = poll_wait(udev->ttyfd, POLLIN, timeout_msec))) + break; + len = read(udev->ttyfd, (uint8_t *)pbuf+cur, max_size-cur); + } + else if (handle == udev && udev->desc > 0) { + len = usbfs_bulk_read(udev, (uint8_t *)pbuf+cur, max_size-cur, timeout_msec); + } + else if (handle == &edl_pcie_mhifd && edl_pcie_mhifd > 0) { + if ((poll_ret = poll_wait(edl_pcie_mhifd, POLLIN, timeout_msec))) + break; + len = read(edl_pcie_mhifd, (uint8_t *)pbuf+cur, max_size-cur); + } + else { + break; + } + + if (len > 0) { + cur += len; + } else { + dbg_time("%s read=%d, errno: %d (%s)\n", __func__, len, errno, strerror(errno)); + break; + } + } + + if (poll_ret == EIO) + return -1; + else if (poll_ret == ETIMEDOUT) + return cur; + + if (cur < min_size) { + dbg_time("%s cur=%d, min_size=%d\n", __func__, cur, min_size); + } + + return cur; +} + +int qusb_noblock_write(const void *handle, void *pbuf, int max_size, int min_size, int timeout_msec, int need_zlp) { + struct quectel_usb_device *udev = &quectel_9x07; + int cur = 0; + + if (min_size == 0) + min_size = 1; + if (timeout_msec == 0) + timeout_msec = 3000; + +#if 0 //depend on your worst net speed + if (handle == &tcp_socket_fd) { + timeout_msec = 120*1000; + } +#endif + + while (cur < min_size) { + int len = 0; + + if (handle == &tcp_socket_fd) { + if (poll_wait(tcp_socket_fd, POLLOUT, timeout_msec)) + break; + len = qtcp_write(tcp_socket_fd, (uint8_t *)pbuf+cur, max_size-cur, timeout_msec); + } + else if (handle == udev && udev->ttyfd > 0) { + if (poll_wait(udev->ttyfd, POLLOUT, timeout_msec)) + break; + len = write(udev->ttyfd, (uint8_t *)pbuf+cur, max_size-cur); + } else if (handle == udev && udev->desc > 0) { + len = usbfs_bulk_write(udev, (uint8_t *)pbuf+cur, max_size-cur, timeout_msec, need_zlp); + } + else if (handle == &edl_pcie_mhifd && edl_pcie_mhifd > 0) { + if (poll_wait(edl_pcie_mhifd, POLLOUT, timeout_msec)) + break; + len = write(edl_pcie_mhifd, (uint8_t *)pbuf+cur, max_size-cur); + } + else { + break; + } + + if (len > 0) { + cur += len; + } else { + dbg_time("%s write=%d, errno: %d (%s)\n", __func__, len, errno, strerror(errno)); + break; + } + } + + if (cur < min_size) { + dbg_time("%s cur=%d, min_size=%d\n", __func__, cur, min_size); + } + + return cur; +} + +int qfile_find_xmlfile(const char *dir, const char *prefix, char** xmlfile) { + DIR *pdir; + struct dirent* ent = NULL; + pdir = opendir(dir); + + dbg_time("dir=%s\n", dir); + if(pdir) + { + while((ent = readdir(pdir)) != NULL) + { + if(!strncmp(ent->d_name, prefix, strlen(prefix)) && strncmp(ent->d_name, "rawprogram0.xml.bak", 15)) + { + dbg_time("d_name=%s\n", ent->d_name); + *xmlfile = strdup(ent->d_name); + closedir(pdir); + return 0; + } + } + + } + + closedir(pdir); + return 1; +} + +const char * firehose_get_time(void) { + static char time_buf[50]; + struct timeval tv; + static int s_start_msec = -1; + int now_msec, cost_msec; + + gettimeofday (&tv, NULL); + now_msec = tv.tv_sec * 1000; + now_msec += (tv.tv_usec + 500) / 1000; + + if (s_start_msec == -1) { + s_start_msec = now_msec; + } + + cost_msec = now_msec - s_start_msec; + + sprintf(time_buf, "[%03d.%03d]", cost_msec/1000, cost_msec%1000); + return time_buf; +} + +// void dbg_time (const char *fmt, ...) { +// va_list args; +// va_start(args, fmt); +// static char line[2048]; +// snprintf(line, sizeof(line), "%s ", firehose_get_time()); +// vsnprintf(line + strlen(line), sizeof(line) - strlen(line), fmt, args); +// fprintf(stdout, "%s", line); +// fflush(stdout); +// } + +int qpcie_open(const char *firehose_dir) { + int bhifd, edlfd, diagfd; + long ret; + FILE *fp; + BHI_INFO_TYPE *bhi_info = malloc(sizeof(BHI_INFO_TYPE)); + char prog_firehose_sdx24[256+32]; + size_t filesize; + void *filebuf; + + snprintf(prog_firehose_sdx24, sizeof(prog_firehose_sdx24), "%.255s/prog_firehose_sdx24.mbn", firehose_dir); + if (access(prog_firehose_sdx24, R_OK)) + snprintf(prog_firehose_sdx24, sizeof(prog_firehose_sdx24), "%.255s/prog_firehose_sdx55.mbn", firehose_dir); + + fp = fopen(prog_firehose_sdx24, "rb"); + if (fp ==NULL) { + dbg_time("fail to fopen %s, errno: %d (%s)\n", prog_firehose_sdx24, errno, strerror(errno)); + error_return(); + } + + fseek(fp, 0, SEEK_END); + filesize = ftell(fp); + fseek(fp, 0, SEEK_SET); + + filebuf = malloc(sizeof(filesize)+filesize); + memcpy(filebuf, &filesize, sizeof(filesize)); + if (fread((uint8_t *)filebuf+sizeof(filesize), 1, filesize, fp) == (size_t)0) { }; + fclose(fp); + + diagfd = open("/dev/mhi_DIAG", O_RDWR | O_NOCTTY); + if (diagfd > 0) + { + int edl_retry = 30; //SDX55 require long time by now 20190412 + void *usb_handle = &edl_pcie_mhifd; + edl_pcie_mhifd = diagfd; + + while (access("/dev/mhi_DIAG", R_OK) == 0 && edl_retry-- > 0) { + dbg_time("switch_to_edl_mode\n"); + switch_to_edl_mode(usb_handle); + sleep(1); + } + + close(diagfd); + edl_pcie_mhifd = -1; + } + + bhifd = open("/dev/mhi_BHI", O_RDWR | O_NOCTTY); + if (bhifd <= 0) { + dbg_time("fail to open %s, errno: %d (%s)\n", "/dev/mhi_BHI", errno, strerror(errno)); + error_return(); + } + + ret = ioctl(bhifd, IOCTL_BHI_GETDEVINFO, bhi_info); + if (ret) { + dbg_time("fail to ioctl IOCTL_BHI_GETDEVINFO, errno: %d (%s)\n", errno, strerror(errno)); + error_return(); + } + + dbg_time("bhi_ee = %d\n", bhi_info->bhi_ee); + if (bhi_info->bhi_ee != MHI_EE_EDL) { + dbg_time("bhi_ee is not MHI_EE_EDL\n"); + close(bhifd); + free(filebuf); + error_return(); + } + free(bhi_info); + + ret = ioctl(bhifd, IOCTL_BHI_WRITEIMAGE, filebuf); + if (ret) { + dbg_time("fail to ioctl IOCTL_BHI_GETDEVINFO, errno: %d (%s)\n", errno, strerror(errno)); + error_return(); + } + + close(bhifd); + free(filebuf); + + sleep(1); + edlfd = open("/dev/mhi_EDL", O_RDWR | O_NOCTTY); + if (edlfd <= 0) { + dbg_time("fail to access %s, errno: %d (%s)\n", "/dev/mhi_EDL", errno, strerror(errno)); + error_return(); + } + + edl_pcie_mhifd = edlfd; + + return 0; +} + +int usbmon_fd = -1; +int usbmon_logfile_fd = -1; + +void *catch_log(void *arg) +{ + int nreads = 0; + char tbuff[256]; + size_t off = strlen("[999.999] "); + + tbuff[off - 1] = ' '; + while(1) { + nreads = read(usbmon_fd, tbuff + off, sizeof(tbuff) - off); + if (nreads == -1 && errno == EINTR) + continue; + if (nreads <= 0) + break; + + tbuff[off + nreads] = '\0'; + memcpy(tbuff, firehose_get_time(), off - 1); + + if (write(usbmon_logfile_fd, tbuff, strlen(tbuff)) == -1) { }; + } + + return NULL; +} + +int ql_capture_usbmon_log(const char* usbmon_logfile) +{ + const char *usbmon_path = "/sys/kernel/debug/usb/usbmon/0u"; + pthread_t pt; + pthread_attr_t attr; + + if (access("/sys/kernel/debug/usb", F_OK)) { + dbg_time("debugfs is not mount, please execute \"mount -t debugfs none_debugs /sys/kernel/debug\"\n"); + return -1; + } + if (access("/sys/kernel/debug/usb/usbmon", F_OK)) { + dbg_time("usbmon is not load, please execute \"modprobe usbmon\" or \"insmod usbmon.ko\"\n"); + return -1; + } + + usbmon_fd = open(usbmon_path, O_RDONLY); + if (usbmon_fd < 0) { + dbg_time("open %s error(%d) (%s)\n", usbmon_path, errno, strerror(errno)); + return -1; + } + + usbmon_logfile_fd = open(usbmon_logfile, O_WRONLY | O_CREAT | O_TRUNC, 0666); + if (usbmon_logfile_fd < 0) { + dbg_time("open %s error(%d) (%s)\n", usbmon_logfile, errno, strerror(errno)); + close(usbmon_fd); + return -1; + } + + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + pthread_create(&pt, &attr, catch_log, NULL); + + return 0; +} + +void ql_stop_usbmon_log() +{ + if (usbmon_logfile_fd > 0) + close(usbmon_logfile_fd); + if (usbmon_fd > 0) + close(usbmon_fd); +} diff --git a/rooter/0optionalapps/qfirehose/src/usb_linux.h b/rooter/0optionalapps/qfirehose/src/usb_linux.h new file mode 100644 index 0000000..2f625f7 --- /dev/null +++ b/rooter/0optionalapps/qfirehose/src/usb_linux.h @@ -0,0 +1,142 @@ +#ifndef __QFIREHOSE_USB_LINUX_H__ +#define __QFIREHOSE_USB_LINUX_H__ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_PATH 256 +#define MIN(a,b) ((a) < (b)? (a) : (b)) + +extern const char *g_part_upgrade; + +typedef struct module_sys_info { +/* +MAJOR=189 +MINOR=1 +DEVNAME=bus/usb/001/002 +DEVTYPE=usb_device +DRIVER=usb +PRODUCT=2c7c/415/318 +TYPE=239/2/1 +BUSNUM=001 +*/ + //char sys_path[MAX_PATH]; + int MAJOR; + int MINOR; + char DEVNAME[64]; + char DEVTYPE[64]; + char PRODUCT[64]; +}MODULE_SYS_INFO; + +void * qusb_noblock_open(const char *module_sys_path, int *idVendor, int *idProduct, int *interfaceNum); +int qusb_noblock_close(void *handle); +int qusb_noblock_write(const void *handle, void *pbuf, int max_size, int min_size, int timeout_msec, int need_zlp); +int qusb_noblock_read(const void *handle, void *pbuf, int max_size, int min_size, int timeout_msec); +int qfile_find_xmlfile(const char *dir, const char *prefix, char** xmlfile); +#define errno_nodev() (errno == ENOENT || errno == ENODEV) +// void dbg_time (const char *fmt, ...); +const char * firehose_get_time(void); +extern FILE *loghandler; +#ifdef FH_DEBUG +#define dbg_time(fmt, args...) \ + do \ + { \ + fprintf(stdout, "[%15s-%04d]%s: " fmt, __FILE__, __LINE__, firehose_get_time(), ##args); \ + fflush(stdout); \ + if (loghandler) \ + fprintf(loghandler, "[%15s-%04d]%s: " fmt, __FILE__, __LINE__, firehose_get_time(), ##args); \ + } while (0); +#else +#define dbg_time(fmt, args...) \ + do \ + { \ + fprintf(stdout, "%s: " fmt, firehose_get_time(), ##args); \ + fflush(stdout); \ + if (loghandler) \ + fprintf(loghandler, "%s: " fmt, firehose_get_time(), ##args); \ + } while (0); +#endif +double get_now(); +void get_duration(double start); +int update_transfer_bytes(long long bytes_cur); +void set_transfer_allbytes(long long bytes); +int auto_find_quectel_modules(char *module_sys_path, unsigned size); +void quectel_get_syspath_name_by_ttyport(const char *module_port_name, char *module_sys_path, unsigned size); +void quectel_get_ttyport_by_syspath(const char *module_sys_path, char *module_port_name, unsigned size); +#define error_return() do {dbg_time("%s %s %d fail\n", __FILE__, __func__, __LINE__); return __LINE__; } while(0) + +extern int edl_pcie_mhifd; + +#define IOCTL_BHI_GETDEVINFO 0x8BE0 + 1 +#define IOCTL_BHI_WRITEIMAGE 0x8BE0 + 2 + +typedef unsigned int ULONG; + +typedef struct _bhi_info_type +{ + ULONG bhi_ver_minor; + ULONG bhi_ver_major; + ULONG bhi_image_address_low; + ULONG bhi_image_address_high; + ULONG bhi_image_size; + ULONG bhi_rsvd1; + ULONG bhi_imgtxdb; + ULONG bhi_rsvd2; + ULONG bhi_msivec; + ULONG bhi_rsvd3; + ULONG bhi_ee; + ULONG bhi_status; + ULONG bhi_errorcode; + ULONG bhi_errdbg1; + ULONG bhi_errdbg2; + ULONG bhi_errdbg3; + ULONG bhi_sernum; + ULONG bhi_sblantirollbackver; + ULONG bhi_numsegs; + ULONG bhi_msmhwid[6]; + ULONG bhi_oempkhash[48]; + ULONG bhi_rsvd5; +}BHI_INFO_TYPE, *PBHI_INFO_TYPE; + +enum MHI_EE { + MHI_EE_PBL = 0x0, /* Primary Boot Loader */ + MHI_EE_SBL = 0x1, /* Secondary Boot Loader */ + MHI_EE_AMSS = 0x2, /* AMSS Firmware */ + MHI_EE_RDDM = 0x3, /* WIFI Ram Dump Debug Module */ + MHI_EE_WFW = 0x4, /* WIFI (WLAN) Firmware */ + MHI_EE_PT = 0x5, /* PassThrough, Non PCIe BOOT (PCIe is BIOS locked, not used for boot */ + MHI_EE_EDL = 0x6, /* PCIe enabled in PBL for emergency download (Non PCIe BOOT) */ + MHI_EE_FP = 0x7, /* FlashProg, Flash Programmer Environment */ + MHI_EE_BHIE = MHI_EE_FP, + MHI_EE_UEFI = 0x8, /* UEFI */ + + MHI_EE_DISABLE_TRANSITION = 0x9, + MHI_EE_MAX +}; +int qpcie_open(const char *firehose_dir); + +#define Q_USB2TCP_VERSION 0x12345678 +typedef struct { + int tag; + int length; + int value[]; +} TLV; + +typedef struct { + int tag; + int length; + int idVendor; + int idProduct; + int interfaceNum; +} TLV_USB; +#endif diff --git a/rooter/0optionalapps/qlog/Makefile b/rooter/0optionalapps/qlog/Makefile new file mode 100644 index 0000000..cef8271 --- /dev/null +++ b/rooter/0optionalapps/qlog/Makefile @@ -0,0 +1,41 @@ +# +# Copyright (C) 2011-2014 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=qlog +PKG_RELEASE:=1 + +PKG_FLAGS:=nonshared + +include $(INCLUDE_DIR)/package.mk + +define Package/qlog + SECTION:=utils + CATEGORY:=ROOter + SUBMENU:=Optional Applications + TITLE:=Quectel Qlog + MAINTAINER:=Dairyman +endef + +define Package/qlog/description + Quectel Qlog +endef + +define Build/Compile + $(MAKE) -C $(PKG_BUILD_DIR) \ + CC="$(TARGET_CC)" \ + CFLAGS="$(TARGET_CFLAGS) -Wall" +endef + +define Package/qlog/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/QLog $(1)/usr/bin/QLog + $(CP) ./files/* $(1)/ +endef + +$(eval $(call BuildPackage,qlog)) diff --git a/rooter/0optionalapps/qlog/files/usr/lib/conf/T1.LinuxData-OTA-DataService-AP_V01.cfg b/rooter/0optionalapps/qlog/files/usr/lib/conf/T1.LinuxData-OTA-DataService-AP_V01.cfg new file mode 100644 index 0000000..f662486 Binary files /dev/null and b/rooter/0optionalapps/qlog/files/usr/lib/conf/T1.LinuxData-OTA-DataService-AP_V01.cfg differ diff --git a/rooter/0optionalapps/qlog/files/usr/lib/conf/T2.RegServ-CotextAct_V01.cfg b/rooter/0optionalapps/qlog/files/usr/lib/conf/T2.RegServ-CotextAct_V01.cfg new file mode 100644 index 0000000..8645a8a Binary files /dev/null and b/rooter/0optionalapps/qlog/files/usr/lib/conf/T2.RegServ-CotextAct_V01.cfg differ diff --git a/rooter/0optionalapps/qlog/files/usr/lib/conf/T3.SimpleData-(TCPUDP)_V01.cfg b/rooter/0optionalapps/qlog/files/usr/lib/conf/T3.SimpleData-(TCPUDP)_V01.cfg new file mode 100644 index 0000000..6289c58 Binary files /dev/null and b/rooter/0optionalapps/qlog/files/usr/lib/conf/T3.SimpleData-(TCPUDP)_V01.cfg differ diff --git a/rooter/0optionalapps/qlog/files/usr/lib/conf/T4.Throughput_V01.cfg b/rooter/0optionalapps/qlog/files/usr/lib/conf/T4.Throughput_V01.cfg new file mode 100644 index 0000000..3eccce1 Binary files /dev/null and b/rooter/0optionalapps/qlog/files/usr/lib/conf/T4.Throughput_V01.cfg differ diff --git a/rooter/0optionalapps/qlog/files/usr/lib/conf/T5.COMMON-T1T4_V01.cfg b/rooter/0optionalapps/qlog/files/usr/lib/conf/T5.COMMON-T1T4_V01.cfg new file mode 100644 index 0000000..57d1346 Binary files /dev/null and b/rooter/0optionalapps/qlog/files/usr/lib/conf/T5.COMMON-T1T4_V01.cfg differ diff --git a/rooter/0optionalapps/qlog/files/usr/lib/conf/T6.FullMessage.SimpleLogPacket(AT)_V01.cfg b/rooter/0optionalapps/qlog/files/usr/lib/conf/T6.FullMessage.SimpleLogPacket(AT)_V01.cfg new file mode 100644 index 0000000..19499f0 Binary files /dev/null and b/rooter/0optionalapps/qlog/files/usr/lib/conf/T6.FullMessage.SimpleLogPacket(AT)_V01.cfg differ diff --git a/rooter/0optionalapps/qlog/files/usr/lib/conf/T7.V2X_ALL_V01.cfg b/rooter/0optionalapps/qlog/files/usr/lib/conf/T7.V2X_ALL_V01.cfg new file mode 100644 index 0000000..656cb83 Binary files /dev/null and b/rooter/0optionalapps/qlog/files/usr/lib/conf/T7.V2X_ALL_V01.cfg differ diff --git a/rooter/0optionalapps/qlog/files/usr/lib/conf/default.cfg b/rooter/0optionalapps/qlog/files/usr/lib/conf/default.cfg new file mode 100644 index 0000000..d3ffdb1 Binary files /dev/null and b/rooter/0optionalapps/qlog/files/usr/lib/conf/default.cfg differ diff --git a/rooter/0optionalapps/qlog/src/Makefile b/rooter/0optionalapps/qlog/src/Makefile new file mode 100644 index 0000000..b5b7daa --- /dev/null +++ b/rooter/0optionalapps/qlog/src/Makefile @@ -0,0 +1,8 @@ +SOURCES = main.c asr.c mdm.c tty2tcp.c sahara.c + +linux: clean + ${CC} $(SOURCES) $(CFLAGS) -Wall -o QLog -lpthread -ldl + +clean: + rm -rf QLog *.exe *.dSYM *.obj *.exp .*o *.lib *~ libs out + diff --git a/rooter/0optionalapps/qlog/src/asr.c b/rooter/0optionalapps/qlog/src/asr.c new file mode 100644 index 0000000..af54c56 --- /dev/null +++ b/rooter/0optionalapps/qlog/src/asr.c @@ -0,0 +1,87 @@ +#include "qlog.h" + +struct CSDLFileHeader +{ + uint32_t dwHeaderVersion;//0x0 + uint32_t dwDataFormat;//0x1 + uint32_t dwAPVersion; + uint32_t dwCPVersion; + uint32_t dwSequenceNum;//ļţ0ʼ + uint32_t dwTime;//Total seconds from 1970.1.1 0:0:0 + uint32_t dwCheckSum;//0x0 +}; + +int g_is_asr_chip = 0; + +ssize_t asr_send_cmd(int ttyfd, const unsigned char *buf, size_t size) { + ssize_t wc = 0; + + while (wc < size) { + uint32_t *cmd_data = (uint32_t *)(buf+wc); + unsigned cmd_len = qlog_le32(cmd_data[0]); + //unsigned i; + + if (cmd_len > (size - wc)) + break; + + //qlog_dbg("Send CMD to UE: "); + //for(i=0; i ../../devices/soc0/soc/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb1/1-1/1-1:1.0/ttyUSB0/tty/ttyUSB0 + pchar = strstr(syspath, ":1.0/tty"); //MDM + if (pchar == NULL) { + pchar = strstr(syspath, ":1.2/tty"); //ASR + g_is_asr_chip = (pchar != NULL); + } + if (pchar == NULL) { + qlog_dbg("%s is not a usb-to-serial device?\n", ttyport); + return; + } + + *pchar = '\0'; + while (*pchar != '/') + pchar--; + + strcpy(sysport, pchar + 1); + + snprintf(syspath, sizeof(syspath), "/sys/bus/usb/devices/%s/idVendor", sysport); + fd = open(syspath, O_RDONLY); + if (fd <= 0) { + qlog_dbg("Fail to open %s, errno: %d (%s)\n", syspath, errno, strerror(errno)); + return; + } + read(fd, idVendor, 4); + close(fd); + + snprintf(syspath, sizeof(syspath), "/sys/bus/usb/devices/%s/idProduct", sysport); + fd = open(syspath, O_RDONLY); + if (fd <= 0) { + qlog_dbg("Fail to open %s, errno: %d (%s)\n", syspath, errno, strerror(errno)); + return; + } + read(fd, idProduct, 4); + close(fd); + + snprintf(syspath, sizeof(syspath), "/sys/bus/usb/devices/%s/bNumInterfaces", sysport); + fd = open(syspath, O_RDONLY); + if (fd <= 0) { + qlog_dbg("Fail to open %s, errno: %d (%s)\n", syspath, errno, strerror(errno)); + return; + } + read(fd, bNumInterfaces, 4); + close(fd); + + qlog_dbg("%s idVendor=%s, idProduct=%s, bNumInterfaces=%d\n", __func__, idVendor, idProduct, atoi(bNumInterfaces)); +} + +static unsigned long get_now_msec() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + return tv.tv_sec*1000 + tv.tv_usec / 1000; +} + +static size_t ql_tty_read(int fd, void *buf, size_t size) +{ + size_t rc; + + rc = read(fd,buf,size); + + if (rc > 0) { + static size_t total_read = 0; + static unsigned long now_msec = 0; + unsigned long n = get_now_msec(); + + if (now_msec == 0) + now_msec = get_now_msec(); + total_read += rc; + + if ((total_read >= (4*1024*1024)) || (n >= (now_msec + 5000))) { + qlog_dbg("recv: %zdM %zdK %zdB in %ld msec\n", total_read/(1024*1024), + total_read/1024%1024,total_read%1024, n-now_msec); + now_msec = n; + total_read = 0; + } + } + + return rc; +} + +ssize_t qlog_poll_write(int fd, const void *buf, size_t size, unsigned timeout_msec) { + ssize_t wc = 0; + ssize_t nbytes; + + nbytes = write(fd, buf+wc, size-wc); + + if (nbytes <= 0) { + if (errno != EAGAIN) { + qlog_dbg("Fail to write fd = %d, errno : %d (%s)\n", fd, errno, strerror(errno)); + goto out; + } + else { + nbytes = 0; + } + } + + wc += nbytes; + + while (wc < size) { + int ret; + struct pollfd pollfds[] = {{fd, POLLOUT, 0}}; + + ret = poll(pollfds, 1, timeout_msec); + + if (ret <= 0) { + qlog_dbg("Fail to poll fd = %d, errno : %d (%s)\n", fd, errno, strerror(errno)); + break; + } + + if (pollfds[0].revents & (POLLERR | POLLHUP | POLLNVAL)) { + qlog_dbg("Fail to poll fd = %d, revents = %04x\n", fd, pollfds[0].revents); + break; + } + + if (pollfds[0].revents & (POLLOUT)) { + nbytes = write(fd, buf+wc, size-wc); + + if (nbytes <= 0) { + qlog_dbg("Fail to write fd = %d, errno : %d (%s)\n", fd, errno, strerror(errno)); + break; + } + wc += nbytes; + } + } + +out: + if (wc != size) { + qlog_dbg("%s fd=%d, size=%zd, timeout=%d, wc=%zd\n", __func__, fd, size, timeout_msec, wc); + } + + return (wc); +} + +static int qlog_logfile_create(const char *logfile_dir, const char *logfile_suffix, unsigned logfile_seq) { + int logfd; + time_t ltime; + char shortname[32]; + char filename[255+1]; + struct tm *currtime; + + //delete old logfile + if (s_logfile_num && s_logfile_List[logfile_seq%s_logfile_num][0]) { + sprintf(filename, "%s/%s.%s", logfile_dir, s_logfile_List[logfile_seq%s_logfile_num], logfile_suffix); + if (access(filename, R_OK) == 0) { + remove(filename); + } + } + + time(<ime); + currtime = localtime(<ime); + snprintf(shortname, sizeof(shortname), "%04d%02d%02d_%02d%02d%02d_%04d", + (currtime->tm_year+1900), (currtime->tm_mon+1), currtime->tm_mday, + currtime->tm_hour, currtime->tm_min, currtime->tm_sec, logfile_seq); + sprintf(filename, "%s/%s.%s", logfile_dir, shortname, logfile_suffix); + + logfd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0444); + if (logfd <= 0) { + qlog_dbg("Fail to create new logfile! errno : %d (%s)\n", errno, strerror(errno)); + } + + qlog_dbg("%s %s logfd=%d\n", __func__, filename, logfd); + + if (s_logfile_num) { + strcpy(s_logfile_List[logfile_seq%s_logfile_num], shortname); + } + + return logfd; +} + +static size_t qlog_logfile_save(int logfd, const void *buf, size_t size) { + return qlog_poll_write(logfd, buf, size, 1000); +} + +static int qlog_logfile_close(int logfd) { + return close(logfd); +} + +static void* qlog_logfile_init_filter_thread(void* arg) { + void **thread_args = (void **)arg; + qlog_ops_t *qlog_ops = (qlog_ops_t *)thread_args[0]; + int *ttyfd = (int *)thread_args[1]; + const char *filter_cfg = ( const char *)thread_args[2]; + + if (qlog_ops->init_filter) + qlog_ops->init_filter(*ttyfd, filter_cfg); + + return NULL; +} + +static int qlog_handle(int ttyfd, const char *logfile_dir, size_t logfile_size, unsigned logfile_num, const char *filter_cfg) { + ssize_t savelog_size = 0; + void *rbuf; + const size_t rbuf_size = (16*1024); + static int logfd = -1; + unsigned logfile_seq = 0; + const char *logfile_suffix = g_is_asr_chip ? "sdl" : "qmdl"; + static qlog_ops_t qlog_ops; + pthread_t thread_id; + pthread_attr_t thread_attr; + const void *thread_args[3]; + + if (logfile_dir[0] == '9' && atoi(logfile_dir) >= 9000) { + filter_cfg = logfile_dir; + qlog_ops = tty2tcp_qlog_ops; + } + else { + qlog_ops = g_is_asr_chip ? asr_qlog_ops : mdm_qlog_ops; + if (access(logfile_dir, F_OK) && errno == ENOENT) + mkdir(logfile_dir, 0755); + } + + if (!qlog_ops.logfile_create) + qlog_ops.logfile_create = qlog_logfile_create; + if (!qlog_ops.logfile_save) + qlog_ops.logfile_save = qlog_logfile_save; + if (!qlog_ops.logfile_close) + qlog_ops.logfile_close = qlog_logfile_close; + + rbuf = malloc(rbuf_size); + if (rbuf == NULL) { + qlog_dbg("Fail to malloc rbuf_size=%zd, errno: %d (%s)\n", rbuf_size, errno, strerror(errno)); + return -1; + } + + thread_args[0] = &qlog_ops; + thread_args[1] = &ttyfd; + thread_args[2] = filter_cfg; + pthread_attr_init(&thread_attr); + pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED); + pthread_create(&thread_id, &thread_attr, qlog_logfile_init_filter_thread, (void*)thread_args); + + while(1) { + ssize_t rc, wc; + int ret; + struct pollfd pollfds[] = {{ttyfd, POLLIN, 0}}; + + ret = poll(pollfds, 1, -1); + + if (ret <= 0) { + qlog_dbg("poll(ttyfd) =%d, errno: %d (%s)\n", ret, errno, strerror(errno)); + break; + } + + if (pollfds[0].revents & (POLLERR | POLLHUP | POLLNVAL)) { + qlog_dbg("ttyfd revents = %04x\n", pollfds[0].revents); + break; + } + + if (pollfds[0].revents & (POLLIN)) { + rc = ql_tty_read(ttyfd, rbuf, rbuf_size); + + if(rc > 0) { + if (logfd == -1) { + logfd = qlog_ops.logfile_create(logfile_dir, logfile_suffix, logfile_seq); + if (logfd <= 0) { + break; + } + if (qlog_ops.logfile_init) + qlog_ops.logfile_init(logfd, logfile_seq); + logfile_seq++; + } + + wc = qlog_ops.logfile_save(logfd, rbuf, rc); + + if (wc != rc) { + qlog_dbg("savelog fail %zd/%zd, break\n", wc, rc); + break; + } + + savelog_size += wc; + + if (savelog_size >= logfile_size) { + savelog_size = 0; + qlog_ops.logfile_close(logfd); + logfd = -1; + } + } + else + { + qlog_dbg("ttyfd recv %zd Bytes. break\n", rc); + break; + } + } + } + + if (logfd > 0) + qlog_ops.logfile_close(logfd); + free(rbuf); + + return 0; +} + +static void ql_sigaction(int signal_num) { + qlog_dbg("recv signal %d\n", signal_num); +} + +static void qlog_usage(const char *self, const char *dev) { + qlog_dbg("Usage: %s -p -s -f filter_cfg -n -b \n", self); + qlog_dbg("Default: %s -p %s -s %s -n %d -b %d to save log to local disk\n", + self, dev, ".", LOGFILE_NUM, LOGFILE_SIZE_DEFAULT/1024/1024); + qlog_dbg(" -p ttyport to catch log, default is '/dev/ttyUSB0'\n"); + qlog_dbg(" -s where to save log, default is '.' \n"); + qlog_dbg(" if set as '9000', QLog will run as TCP Server Mode, and let 'QPST/QWinLog/CATStudio' to connect!\n"); + qlog_dbg(" -f filter cfg for catch log, can be found in directory 'conf'. if not set this arg, will use default filter conf\n"); + qlog_dbg(" and UC200T&EC200T do not need filter cfg.\n"); + qlog_dbg(" -n max num of log file to save, range is '0~512'. default is 0. 0 means no limit.\n"); + qlog_dbg(" or QLog will auto delete oldtest log file if exceed max num\n"); + qlog_dbg(" -m max size of single log file, unit is MBytes, range is '2~512', default is 128\n"); + + qlog_dbg("\nFor example: %s -p /dev/ttyUSB0 -w .\n", self); +} + +int main(int argc, char **argv) +{ + int opt; + char ttyname[32] = "/dev/ttyUSB0"; + int ttyfd = -1; + const char *logfile_dir = "./"; + const char *filter_cfg = NULL; + size_t logfile_size = LOGFILE_SIZE_DEFAULT; + unsigned logfile_num = LOGFILE_NUM; + char idVendor[5] = "0000"; + char idProduct[5] = "0000"; + char bNumInterfaces[5] = "0"; + + qlog_dbg("QLog Version: Quectel_QLog_Linux&Android_V1.3\n"); //when release, rename to V1.X + + optind = 1; //call by popen(), optind mayby is not 1 + while ( -1 != (opt = getopt(argc, argv, "d:p:s:w:n:m:b:f:c:h"))) { + switch (opt) { + case 'p': + if (optarg[0] == 't') //ttyUSB0 + snprintf(ttyname, sizeof(ttyname), "/dev/%s", optarg); + else if (optarg[0] == 'U') //USB0 + snprintf(ttyname, sizeof(ttyname), "/dev/tty%s", optarg); + else if (optarg[0] == '/') + snprintf(ttyname, sizeof(ttyname), "%s", optarg); + else { + qlog_dbg("unknow dev %s\n", optarg); + } + break; + case 's': + logfile_dir = optarg; + break; + case 'n': + logfile_num = atoi(optarg); + if (logfile_num < 0) + logfile_num = 0; + else if (logfile_num > LOGFILE_NUM) + logfile_num = LOGFILE_NUM; + s_logfile_num = logfile_num; + break; + case 'm': + logfile_size = atoi(optarg)*1024*1024; + if (logfile_size < LOGFILE_SIZE_MIN) + logfile_size = LOGFILE_SIZE_MIN; + else if (logfile_size > LOGFILE_SIZE_MAX) + logfile_size = LOGFILE_SIZE_MAX; + break; + case 'f': + filter_cfg = optarg; + break; + case 'b': + case 'c': //unused + break; + default: + qlog_usage(argv[0], ttyname); + return 0; + break; + } + } + + signal(SIGTERM, ql_sigaction); + signal(SIGHUP, ql_sigaction); + signal(SIGINT, ql_sigaction); + + ttyfd = open (ttyname, O_RDWR | O_NDELAY | O_NOCTTY); + + if (ttyfd <= 0) { + qlog_dbg("Fail to open %s, errno : %d (%s)\n", ttyname, errno, strerror(errno)); + return -1; + } + + qlog_dbg("open %s ttyfd = %d\n", ttyname, ttyfd); + + if ( ttyfd > 0 ) { + struct termios ios; + + memset(&ios, 0, sizeof(ios)); + tcgetattr( ttyfd, &ios ); + cfmakeraw(&ios); + cfsetispeed(&ios, B115200); + cfsetospeed(&ios, B115200); + tcsetattr( ttyfd, TCSANOW, &ios ); + } + + if (strncmp(ttyname, "/dev/mhi", strlen("/dev/mhi"))) { + qlog_get_vidpid_by_ttyport(ttyname, idVendor, idProduct, bNumInterfaces); + } + else { + if (!strcmp(ttyname, "/dev/mhi_DIAG")) { + strcpy(idVendor, "2c7c"); + strcpy(bNumInterfaces, "5"); //log mode + } + else if (!strcmp(ttyname, "/dev/mhi_SAHARA")) { + strcpy(idVendor, "2c7c"); + strcpy(bNumInterfaces, "1"); //dump mode + } + } + + qlog_dbg("Press CTRL+C to stop catch log.\n"); + + if (g_is_asr_chip == 0 && atoi(bNumInterfaces) == 1) { + if (access(logfile_dir, F_OK) && errno == ENOENT) + mkdir(logfile_dir, 0755); + sahara_catch_dump(ttyfd, logfile_dir, 1); + } + else if (atoi(bNumInterfaces) > 1) { + qlog_handle(ttyfd, logfile_dir, logfile_size, logfile_num, filter_cfg); + } + else { + qlog_dbg("unknow state! quit!\n"); + } + + close(ttyfd); + + return 0; +} diff --git a/rooter/0optionalapps/qlog/src/mdm.c b/rooter/0optionalapps/qlog/src/mdm.c new file mode 100644 index 0000000..42d1adf --- /dev/null +++ b/rooter/0optionalapps/qlog/src/mdm.c @@ -0,0 +1,203 @@ +#include "qlog.h" + +static unsigned char qlog_mdm_default_cfg[] = { +0x1d,0x1c,0x3b,0x7e,0x00,0x78,0xf0,0x7e,0x4b,0x32,0x06,0x00,0xba,0x4d,0x7e,0x7c,0x93,0x49,0x7e,0x1c,0x95,0x2a,0x7e,0x0c,0x14,0x3a,0x7e,0x63,0xe5,0xa1,0x7e,0x4b, +0x0f,0x00,0x00,0xbb,0x60,0x7e,0x4b,0x09,0x00,0x00,0x62,0xb6,0x7e,0x4b,0x08,0x00,0x00,0xbe,0xec,0x7e,0x4b,0x08,0x01,0x00,0x66,0xf5,0x7e,0x4b,0x04,0x00,0x00,0x1d, +0x49,0x7e,0x4b,0x04,0x0f,0x00,0xd5,0xca,0x7e,0x4b,0x0f,0x18,0x00,0x01,0x9e,0xa9,0x7e,0x4b,0x0f,0x18,0x00,0x02,0x05,0x9b,0x7e,0x4b,0x0f,0x2c,0x00,0x28,0xea,0x7e, +0x4b,0x12,0x39,0x00,0xeb,0x7b,0x7e,0x4b,0x12,0x3c,0x00,0x53,0x05,0x7e,0x4b,0x12,0x37,0x00,0xfb,0xe1,0x7e,0x4b,0x12,0x3b,0x00,0x5b,0x48,0x7e,0x4b,0x12,0x35,0x00, +0x4b,0xd2,0x7e,0x4b,0x12,0x3a,0x00,0x83,0x51,0x7e,0x4b,0x12,0x00,0x08,0x19,0x96,0x7e,0x7d,0x5d,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x74,0x41,0x7e,0x7d,0x5d,0x04, +0x00,0x00,0x02,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1c,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x4c,0x06,0x7e,0x7d,0x5d,0x04,0x05,0x00,0x05,0x00,0x00,0x00,0x1f,0x00, +0x00,0x00,0xce,0xa7,0x7e,0x7d,0x5d,0x04,0x07,0x00,0x08,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0xd0,0x71,0x7e,0x7d,0x5d,0x04,0x0b,0x00,0x0c,0x00, +0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x7c,0x68,0x7e,0x7d,0x5d,0x04,0x0e,0x00,0x12,0x00,0x00,0x00,0xff,0x01,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00, +0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0xb5,0x3a,0x7e,0x7d,0x5d,0x04,0x14,0x00,0x15,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x2e,0xbb, +0x7e,0x7d,0x5d,0x04,0x19,0x00,0x19,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x88,0xd0,0x7e,0x7d,0x5d,0x04,0x20,0x00,0x20,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0xea,0xaa, +0x7e,0x7d,0x5d,0x04,0x27,0x00,0x28,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0xfe,0x01,0x00,0x00,0x89,0x11,0x7e,0x7d,0x5d,0x04,0x2a,0x00,0x2b,0x00,0x00,0x00,0x1e,0x00, +0x00,0x00,0x1e,0x00,0x00,0x00,0x01,0x1a,0x7e,0x7d,0x5d,0x04,0x33,0x00,0x33,0x00,0x00,0x00,0x1f,0x00,0x00,0x00,0xc2,0xc1,0x7e,0x7d,0x5d,0x04,0x36,0x00,0x36,0x00, +0x00,0x00,0x1e,0x00,0x00,0x00,0xa3,0xd6,0x7e,0x7d,0x5d,0x04,0x39,0x00,0x3a,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x65,0xdf,0x7e,0x7d,0x5d,0x04, +0x3f,0x00,0x41,0x00,0x00,0x00,0x1f,0x00,0x00,0x00,0xfe,0xff,0x1f,0x00,0x1f,0x00,0x00,0x00,0xc9,0x67,0x7e,0x7d,0x5d,0x04,0x44,0x00,0x45,0x00,0x00,0x00,0x1e,0x00, +0x00,0x00,0x1e,0x00,0x00,0x00,0x2e,0x6c,0x7e,0x7d,0x5d,0x04,0x48,0x00,0x4a,0x00,0x00,0x00,0x1f,0x00,0x00,0x00,0x1f,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x4f,0xf2, +0x7e,0x7d,0x5d,0x04,0x4c,0x00,0x4c,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0xf2,0x66,0x7e,0x7d,0x5d,0x04,0x4e,0x00,0x4e,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x11,0x0f, +0x7e,0x7d,0x5d,0x04,0x58,0x00,0x58,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x9a,0x49,0x7e,0x7d,0x5d,0x04,0x5a,0x00,0x5b,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00, +0x00,0x00,0x0e,0x43,0x7e,0x7d,0x5d,0x04,0x63,0x00,0x63,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0xd9,0x60,0x7e,0x7d,0x5d,0x04,0x70,0x00,0x70,0x00,0x00,0x00,0x1e,0x00, +0x00,0x00,0x4a,0x17,0x7e,0x7d,0x5d,0x04,0x75,0x00,0x75,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0xc8,0x6d,0x7e,0x7d,0x5d,0x04,0xea,0x03,0xea,0x03,0x00,0x00,0x1e,0x00, +0x00,0x00,0xa9,0x9e,0x7e,0x7d,0x5d,0x04,0xee,0x03,0xef,0x03,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x9b,0x20,0x7e,0x7d,0x5d,0x04,0xd0,0x07,0xd7,0x07, +0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00, +0x00,0x00,0xdc,0x10,0x7e,0x7d,0x5d,0x04,0xb8,0x0b,0xc5,0x0b,0x00,0x00,0x1f,0x00,0x00,0x00,0xfe,0xff,0x7f,0x00,0x7f,0x00,0x00,0x00,0x1f,0x00,0x00,0x00,0x1f,0x00, +0x00,0x00,0xff,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00, +0x00,0x00,0x1c,0x00,0x00,0x00,0xa9,0x36,0x7e,0x7d,0x5d,0x04,0xa0,0x0f,0xaa,0x0f,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00, +0x00,0x00,0xfe,0x01,0x00,0x00,0x1e,0x00,0x00,0x00,0xfe,0xff,0x01,0x00,0xfe,0xff,0x07,0x00,0xfe,0xff,0x01,0x00,0xfe,0x07,0x00,0x00,0x1e,0x00,0x00,0x00,0xc3,0xb9, +0x7e,0x7d,0x5d,0x04,0x05,0x12,0x05,0x12,0x00,0x00,0x1f,0x00,0x00,0x00,0xd2,0x41,0x7e,0x7d,0x5d,0x04,0x07,0x12,0x07,0x12,0x00,0x00,0x1f,0x00,0x00,0x00,0xf3,0x12, +0x7e,0x7d,0x5d,0x04,0x88,0x13,0xa8,0x13,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00, +0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00, +0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1f,0x00,0x00,0x00,0x1f,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00, +0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00, +0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0xf4,0x4c,0x7e,0x7d,0x5d,0x04,0x72,0x17,0x72,0x17,0x00,0x00,0x1e,0x00,0x00,0x00,0xcc,0x20, +0x7e,0x7d,0x5d,0x04,0x74,0x17,0x74,0x17,0x00,0x00,0x3f,0x00,0x00,0x00,0x47,0x46,0x7e,0x7d,0x5d,0x04,0x93,0x17,0x93,0x17,0x00,0x00,0x1e,0x00,0x00,0x00,0x8f,0xca, +0x7e,0x7d,0x5d,0x04,0x97,0x17,0x97,0x17,0x00,0x00,0x1e,0x00,0x00,0x00,0xcd,0x6c,0x7e,0x7d,0x5d,0x04,0xa4,0x17,0xb7,0x17,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00, +0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00, +0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00, +0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x8d,0xd1,0x7e,0x7d,0x5d,0x04,0xc0,0x17,0xc0,0x17,0x00,0x00,0x1e,0x00,0x00,0x00,0x96,0x89,0x7e,0x7d,0x5d,0x04, +0x34,0x21,0x34,0x21,0x00,0x00,0x1e,0x00,0x00,0x00,0x10,0xc3,0x7e,0x7d,0x5d,0x04,0x1c,0x25,0x25,0x25,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0xff,0x1f,0x00,0x7d,0x5e, +0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x7d,0x5e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0xfe,0x03,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x3e,0xd0,0x00,0x00, +0x90,0xed,0x7e,0x7d,0x5d,0x04,0x0b,0x28,0x0f,0x28,0x00,0x00,0x1c,0x00,0x00,0x00,0x1c,0x00,0x00,0x00,0x1c,0x00,0x00,0x00,0x1c,0x00,0x00,0x00,0x1c,0x00,0x00,0x00, +0x71,0x86,0x7e,0x7d,0x5d,0x04,0x6e,0x28,0x89,0x28,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00, +0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00, +0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00, +0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x52,0x90,0x7e,0x73, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xda,0x81,0x7e,0x73,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0xfe,0x0f,0x00,0x00,0xf0,0x07,0xc8,0x00,0x00,0x40, +0xc4,0x00,0x00,0x00,0x00,0xc0,0x49,0xf3,0xc7,0x5b,0x7c,0xf3,0x0b,0x01,0x00,0x00,0x00,0x20,0xec,0x00,0xcc,0x83,0x01,0x00,0x00,0x00,0x00,0x00,0x38,0x00,0x38,0x00, +0x38,0x00,0x38,0x00,0x00,0x01,0x01,0x00,0x40,0x08,0xf0,0x07,0x0c,0xf8,0x47,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x40,0x04,0x00,0xff,0xf7,0x7f,0xf0,0xfc,0xff,0xff,0xad,0xe0,0x7f,0x02,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78, +0xe0,0xff,0xff,0xff,0x48,0x1c,0x1e,0x00,0x03,0x10,0x18,0xff,0xff,0xff,0xff,0xbf,0x00,0x00,0x00,0x00,0x00,0x90,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x80,0x1b,0x80,0xff,0x5f,0x06,0x00,0x00,0x41,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0xc0,0x07,0x01,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x10,0x00,0x80,0x00,0x00,0x7f,0xce,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x00,0x00, +0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0xf8,0x07,0x00,0x00,0x00, +0x07,0x00,0x00,0xc0,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x30,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0xb7,0xb2,0x7e,0x73,0x00,0x00, +0x00,0x03,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x09,0x08,0x00,0x00,0x31,0x00,0x09,0x80,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7f,0xef,0x20,0xf0,0x90,0x3c,0x1d,0x60,0x04,0x00,0x00,0x4f,0x03,0xfe,0x07,0x43,0x0b,0x02, +0x01,0x00,0x00,0x07,0xf4,0x45,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x86,0x8a,0x45,0xf8,0x25,0x10,0x00,0xcc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x82,0xc3,0x1e,0x00,0x7d,0x5e,0x00,0x4e,0x00,0xff,0x03,0x00,0x3c,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x09,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x01,0x32,0x3e,0x7e,0x73,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x5d, +0x0c,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x90,0x6f,0x3b,0xfc,0x01,0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xd0,0xff,0xd7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0xf0,0xff,0xe7,0xff,0xbf,0xf3,0x43,0x3f,0x02,0x00,0xe0,0xe3,0x01,0xff,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x90,0x6f,0x1f,0xfc,0x71,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xd0,0xff,0x57,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0xe0,0xe7,0xff,0xf7,0xc3,0x3f,0x01,0x00,0xe0,0xe3,0x01,0x10,0x5d,0xe6,0x7e,0x73,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x57,0x0b, +0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x01,0x00,0x7f,0x02,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0xff,0x37,0x06,0xea,0x07,0x00,0x07,0x00,0x00,0x00,0x00,0xfc,0xf0,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x01,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x77,0x00,0x00,0x7f,0x9f,0xaa,0x7e,0x73,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x0b,0x00,0x00,0x00,0xd0,0x01,0x00,0x00, +0x06,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x5f,0x00,0x00,0x00,0xce,0x04,0xce,0x00,0x3f,0x00,0x3f,0x00,0xdf,0x24,0x00,0x00,0x7f,0xfc,0x3c,0x00, +0x00,0x00,0x3e,0x28,0x4e,0x50,0x05,0x12,0x51,0xe0,0x00,0x00,0xff,0xff,0xff,0xe2,0xcf,0xe1,0x7d,0x5d,0x51,0x7f,0x00,0x01,0x74,0x42,0xe0,0xac,0x34,0x7e,0x73,0x00, +0x00,0x00,0x03,0x00,0x00,0x00,0x0d,0x00,0x00,0x00,0x39,0x01,0x00,0x00,0x79,0xa6,0xff,0xff,0xff,0xa1,0x1f,0x00,0xdf,0x01,0x00,0x00,0x03,0x40,0x00,0x00,0x00,0x9f, +0x00,0x00,0x00,0x00,0xc0,0x06,0x00,0x00,0x00,0x00,0x5f,0x00,0x00,0x00,0xff,0x37,0xff,0xbf,0x1b,0x05,0x00,0x01,0x2b,0x17,0x7e,0x60,0x00,0x12,0x6a,0x7e,0x60,0x01, +0x9b,0x7b,0x7e,0x82,0x00,0x00,0x00,0x55,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xb7,0x0f,0x00,0x00,0x00,0x00,0x00,0x88,0xf4,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x04,0x00,0xd8,0x8f,0xff,0x3d,0xf8,0x48,0xfa,0x3f,0x06,0x00,0x00,0x19,0x00,0x00,0x00,0x0a,0xe0,0x0f,0x22,0x00,0x00,0x00,0xf8,0x84,0x2f,0x40,0x00,0x00, +0x0a,0x80,0xff,0xef,0x01,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0xe0,0x01,0xff,0x3f,0x82,0x00,0x01, +0x7d,0x5e,0x00,0x00,0x80,0xff,0x00,0x00,0x00,0x00,0xbe,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0x0f,0xfe,0x7f,0x00,0x18,0x00,0x00,0x00,0xe0,0x01,0x00,0x00, +0xc0,0xfd,0xbf,0x95,0x03,0x00,0x00,0x00,0x00,0x00,0x80,0x81,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0xc0,0x3f,0x12,0x8c,0x04,0x00,0x60,0xc8, +0x2f,0xf8,0xe7,0xf9,0xff,0x7f,0xff,0xff,0x07,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03,0xfc,0x6f,0x00,0xc7,0x9f,0x00,0x03,0x80,0xf9,0xfa,0x0f,0x80, +0x7b,0x80,0x37,0x24,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x23,0x8c, +0x0d,0x00,0x00,0x01,0x98,0x04,0x00,0x30,0x00,0x00,0x00,0x00,0x06,0x00,0xf2,0x07,0x00,0x44,0x00,0xf8,0x1f,0x20,0x73,0x7e +}; + +extern int tty2tcp_sockfd; +ssize_t mdm_send_cmd(int ttyfd, const unsigned char *buf, size_t size) { + size_t wc = 0; + + while (wc < size) { + size_t flag = wc; + const unsigned char *cur = buf + wc; + unsigned short len = cur[2] + (((unsigned short)cur[3]) << 8) + 5; + + if (cur[0] == 0x7e && cur[1] == 0x01 && (wc + len) <= size && cur[len - 1] == 0x7e) { + flag += (len - 1); + } + else { + if (flag == 0 && buf[flag] == 0x7E) + flag++; + + while (buf[flag] != 0x7E && flag < size) + flag++; + } + + if (buf[flag] == 0x7E || flag == size) + qlog_poll_write(ttyfd, buf + wc, flag - wc + 1, 1000); + + if (tty2tcp_sockfd > 0 && (flag + 1) < size) { + size_t i = 0; + qlog_dbg("size=%zd, cur=%zd\n", size, flag - wc + 1); + for (i = 0; i < 16; i++) + printf("%02x", buf[i+wc]); + printf("\n"); + } + + wc = flag + 1; + } + + return size; +} + +static int mdm_init_filter(int ttyfd, const char *cfg) { + unsigned char *rbuf; + const size_t rbuf_size = (16*1024); + size_t cfg_size = 0; + +#if 0 + if (cfg == NULL) { + const unsigned char mdm_enter_dump1[] = { + 0x4b, 0x12, 0x18, 0x02, 0x01, 0x00, 0xd2, 0x7e + }; + const unsigned char mdm_enter_dump2[] = { + 0x7e, 0x01, 0x04, 0x00, 0x4b, 0x25, 0x03, 0x00, 0x7e + }; + qlog_dbg("send mdm dump command\n"); + mdm_send_cmd(ttyfd, mdm_enter_dump1, sizeof(mdm_enter_dump1)); + usleep(100*1000); + mdm_send_cmd(ttyfd, mdm_enter_dump2, sizeof(mdm_enter_dump2)); + return 0; + } +#endif + + rbuf = (unsigned char *)malloc(rbuf_size); + if (rbuf == NULL) { + qlog_dbg("Fail to malloc rbuf_size=%zd, errno: %d (%s)\n", rbuf_size, errno, strerror(errno)); + return -1; + } + + if (cfg) { + int cfgfd = open(cfg, O_RDONLY); + if (cfgfd < 0) { + qlog_dbg("Fail to open %s, errno : %d (%s)\n", cfg, errno, strerror(errno)); + } + + cfg_size = read(cfgfd, rbuf, rbuf_size); + close(cfgfd); + } + + if (cfg_size <= 0) { + cfg_size = sizeof(qlog_mdm_default_cfg); + memcpy(rbuf, qlog_mdm_default_cfg, cfg_size); + } + + mdm_send_cmd(ttyfd, rbuf, cfg_size); + + free(rbuf); + + return 0; +} + +qlog_ops_t mdm_qlog_ops = { + .init_filter = mdm_init_filter, +}; diff --git a/rooter/0optionalapps/qlog/src/qlog.h b/rooter/0optionalapps/qlog/src/qlog.h new file mode 100644 index 0000000..6ff8266 --- /dev/null +++ b/rooter/0optionalapps/qlog/src/qlog.h @@ -0,0 +1,44 @@ +#include +#include +#include +#ifndef __QUECTEL_QLOG_H +#define __QUECTEL_QLOG_H +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef unsigned int uint32_t; + +typedef struct { + int (*init_filter)(int ttyfd, const char *conf); + int (*logfile_create)(const char *logfile_dir, const char *logfile_suffix, unsigned logfile_seq); + int (*logfile_init)(int logfd, unsigned logfile_seq); + size_t (*logfile_save)(int logfd, const void *buf, size_t size); + int (*logfile_close)(int logfd); +} qlog_ops_t; + +extern qlog_ops_t mdm_qlog_ops; +extern qlog_ops_t asr_qlog_ops; +extern qlog_ops_t tty2tcp_qlog_ops; +extern int g_is_asr_chip; +extern ssize_t asr_send_cmd(int ttyfd, const unsigned char *buf, size_t size); +extern ssize_t mdm_send_cmd(int ttyfd, const unsigned char *buf, size_t size); + +extern uint32_t qlog_le32 (uint32_t v32); +extern uint64_t qlog_le64 (uint64_t v64); +extern ssize_t qlog_poll_write(int fd, const void *buf, size_t size, unsigned timeout_mesc); + +extern unsigned qlog_msecs(void); +#define qlog_dbg(fmt, arg... ) do { unsigned msec = qlog_msecs(); printf("[%03d.%03d]" fmt, msec/1000, msec%1000, ## arg); } while (0) + int sahara_catch_dump(int port_fd, const char *path_to_save_files, int do_reset); +#endif diff --git a/rooter/0optionalapps/qlog/src/sahara.c b/rooter/0optionalapps/qlog/src/sahara.c new file mode 100644 index 0000000..347f3df --- /dev/null +++ b/rooter/0optionalapps/qlog/src/sahara.c @@ -0,0 +1,660 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +unsigned int inet_addr(const char *cp); + +/* modify macro MIN +* usually we difine it as: (a) < (b) ? (a) : (b) +* but it will cause some problems, here is a case: +* MIN(i++, j++), when calling the macro above, i++ will be run two times, which is wrong. +* so we can modify it as following. +* (void)(&_a == &_b); is use to check wether the type of 'a' and 'b' is same or not. +* (void) is used to eliminated warnning. +*/ +#define MIN(a, b) ({ \ + typeof(a) _a = a; \ + typeof(b) _b = b; \ + (void)(&_a == &_b); \ + _a < _b ? _a : _b; \ + }) + +#include "sahara_protocol.h" +#include "qlog.h" + +sahara_data_t sahara_data = { + NULL, // rx_buffer + NULL, // tx_buffer + NULL, // misc_buffer + SAHARA_WAIT_HELLO, // state + 0, // timed_data_size + -1, // fd + -1, // ram_dump_image + 5, // max_ram_dump_retries + SAHARA_RAW_BUFFER_SIZE, // max_ram_dump_read + SAHARA_MODE_LAST, // mode + SAHARA_MODE_LAST, // prev_mode + 0, // command + false // ram_dump_64bit +}; + +typedef struct { + char *port_name; + int port_fd; + int rx_timeout; + size_t MAX_TO_READ; + size_t MAX_TO_WRITE; +} com_port_t; + +static com_port_t com_port = { + "/dev/ttyUSB0", // port_name + -1, // port_fd + 5, // rx_timeout + 1024 * 64, + 1024 * 64, +}; + +typedef struct { + const char *path_to_save_files; + int verbose; + int do_reset; +} kickstart_options_t; + +static kickstart_options_t kickstart_options = { + NULL, // path_to_save_files + 1, // verbose + 1, +}; + +enum LOG_LEVEL { +LOG_DEBUG = 1, +LOG_EVENT, +LOG_INFO, +LOG_STATUS, +LOG_WARN, +LOG_ERROR +}; + +extern unsigned qlog_msecs(void); +#define dbg( log_level, fmt, arg... ) do {if (kickstart_options.verbose || LOG_ERROR == log_level) { unsigned msec = qlog_msecs(); printf("[%03d.%03d]" fmt "\n", msec/1000, msec%1000, ## arg);}} while (0) + +static bool port_tx_data (void *buffer, size_t bytes_to_send) { + int temp_bytes_sent; + size_t bytes_sent = 0; + + while (bytes_sent < bytes_to_send) { + do { + temp_bytes_sent = write (com_port.port_fd, buffer + bytes_sent, MIN(bytes_to_send - bytes_sent, com_port.MAX_TO_WRITE)); + if (-1 == temp_bytes_sent && (errno == EINTR || errno == EAGAIN)) { + sleep(1); + } else { + break; + } + } while(1); + + if (temp_bytes_sent <= 0) { + dbg(LOG_ERROR, "Write returned failure %d, errno %d, System error code: %s", temp_bytes_sent, errno, strerror (errno)); + return false; + } + else { + bytes_sent += temp_bytes_sent; + } + } + + return true; +} + +static bool port_rx_data(void *buffer, size_t bytes_to_read, size_t *bytes_read) { + fd_set rfds; + struct timeval tv; + int retval; + + // Init read file descriptor + FD_ZERO (&rfds); + FD_SET (com_port.port_fd, &rfds); + + // time out initializtion. + tv.tv_sec = com_port.rx_timeout >= 0 ? com_port.rx_timeout : 0; + tv.tv_usec = 0; + + retval = select (com_port.port_fd + 1, &rfds, NULL, NULL, ((com_port.rx_timeout >= 0) ? (&tv) : (NULL))); + if (retval <= 0) { + dbg(LOG_ERROR, "select returned error: %s", strerror (errno)); + return false; + } + + retval = read (com_port.port_fd, buffer, MIN(bytes_to_read, com_port.MAX_TO_READ)); + if (retval <= 0) { + dbg(LOG_ERROR, "Read/Write File descriptor returned error: %s, error code %d", strerror (errno), retval); + return false; + } + + if (NULL != bytes_read) + *bytes_read = retval; + + return true; +} + +static bool sahara_tx_data (size_t bytes_to_send) { + return port_tx_data(sahara_data.tx_buffer, bytes_to_send); +} + +static bool sahara_rx_data(size_t bytes_to_read) { + sahara_packet_header* command_packet_header = NULL; + size_t temp_bytes_read = 0, bytes_read = 0; + + const char *boot_sahara_cmd_id_str[SAHARA_LAST_CMD_ID] = { + "SAHARA_NO_CMD_ID", // = 0x00, + " SAHARA_HELLO_ID", // = 0x01, // sent from target to host + "SAHARA_HELLO_RESP_ID", // = 0x02, // sent from host to target + "SAHARA_READ_DATA_ID", // = 0x03, // sent from target to host + "SAHARA_END_IMAGE_TX_ID", // = 0x04, // sent from target to host + "SAHARA_DONE_ID", // = 0x05, // sent from host to target + "SAHARA_DONE_RESP_ID", // = 0x06, // sent from target to host + "SAHARA_RESET_ID", // = 0x07, // sent from host to target + "SAHARA_RESET_RESP_ID", // = 0x08, // sent from target to host + "SAHARA_MEMORY_DEBUG_ID", // = 0x09, // sent from target to host + "SAHARA_MEMORY_READ_ID", // = 0x0A, // sent from host to target + "SAHARA_CMD_READY_ID", // = 0x0B, // sent from target to host + "SAHARA_CMD_SWITCH_MODE_ID", // = 0x0C, // sent from host to target + "SAHARA_CMD_EXEC_ID", // = 0x0D, // sent from host to target + "SAHARA_CMD_EXEC_RESP_ID", // = 0x0E, // sent from target to host + "SAHARA_CMD_EXEC_DATA_ID", // = 0x0F, // sent from host to target + "SAHARA_64_BITS_MEMORY_DEBUG_ID", // = 0x10, // sent from target to host + "SAHARA_64_BITS_MEMORY_READ_ID", // = 0x11, // sent from host to target + "SAHARA_64_BITS_READ_DATA_ID", // = 0x12, + }; + + if (0 == bytes_to_read) { + command_packet_header = (sahara_packet_header *) sahara_data.rx_buffer; + memset(command_packet_header, 0x00, sizeof(sahara_packet_header)); + + if (false == port_rx_data(sahara_data.rx_buffer, sizeof(sahara_packet_header), &temp_bytes_read)) + return false; + + dbg(LOG_INFO, "Read %zd bytes, command %d and packet length %d bytes", temp_bytes_read, qlog_le32(command_packet_header->command), qlog_le32(command_packet_header->length)); + if (temp_bytes_read != sizeof(sahara_packet_header)) + return false; + + if (qlog_le32(command_packet_header->command) < SAHARA_LAST_CMD_ID) { + dbg(LOG_EVENT, "RECEIVED <-- %s", boot_sahara_cmd_id_str[qlog_le32(command_packet_header->command)]); + if (false == port_rx_data(sahara_data.rx_buffer + sizeof(sahara_packet_header), qlog_le32(command_packet_header->length) - sizeof(sahara_packet_header), &temp_bytes_read)) + return false; + if (temp_bytes_read != (qlog_le32(command_packet_header->length) - sizeof(sahara_packet_header))) { + dbg(LOG_INFO, "Read %zd bytes", temp_bytes_read + sizeof(sahara_packet_header)); + return false; + } + } else { + dbg(LOG_EVENT, "RECEIVED <-- SAHARA_CMD_UNKONOW_%d", qlog_le32(command_packet_header->command)); + return false; + } + } + else { + while (bytes_read < bytes_to_read) { + if (false == port_rx_data(sahara_data.rx_buffer + bytes_read, bytes_to_read - bytes_read, &temp_bytes_read)) { + dbg(LOG_ERROR, "bytes_read = %zd, bytes_to_read = %zd", bytes_read, bytes_to_read); + return false; + } else + bytes_read += temp_bytes_read; + } + } + + return true; +} + +static int timeval_subtract (struct timeval *result, struct timeval *x, struct timeval *y) { + // Perform the carry for the later subtraction by updating y. + if (x->tv_usec < y->tv_usec) { + int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1; + y->tv_usec -= 1000000 * nsec; + y->tv_sec += nsec; + } + if (x->tv_usec - y->tv_usec > 1000000) { + int nsec = (x->tv_usec - y->tv_usec) / 1000000; + y->tv_usec += 1000000 * nsec; + y->tv_sec -= nsec; + } + + // Compute the time remaining to wait. tv_usec is certainly positive. */ + result->tv_sec = x->tv_sec - y->tv_sec; + result->tv_usec = x->tv_usec - y->tv_usec; + + // Return 1 if result is negative. + return x->tv_sec < y->tv_sec; +} + +static void time_throughput_calculate(struct timeval *start_time, struct timeval *end_time, size_t size_bytes) +{ + struct timeval result; + double TP = 0.0; + + if (size_bytes == 0) { + dbg(LOG_INFO, "Cannot calculate throughput, size is 0"); + return; + } + timeval_subtract(&result, end_time, start_time); + + TP = (double)result.tv_usec/1000000.0; + TP += (double)result.tv_sec; + + if(TP>0.0) + { + TP = (double)((double)size_bytes/TP)/(1024.0*1024.0); + dbg(LOG_STATUS, "%zd bytes transferred in %ld.%06ld seconds (%.4fMBps)", size_bytes, result.tv_sec, result.tv_usec,TP); + } + else + dbg(LOG_STATUS, "%zd bytes transferred in %ld.%06ld seconds", size_bytes, result.tv_sec, result.tv_usec); +} + +static bool send_reset_command () +{ + sahara_packet_reset *sahara_reset = (sahara_packet_reset *)sahara_data.tx_buffer; + sahara_reset->header.command = qlog_le32(SAHARA_RESET_ID); + sahara_reset->header.length = qlog_le32(sizeof(sahara_packet_reset)); + + /* Send the Reset Request */ + dbg(LOG_EVENT, "SENDING --> SAHARA_RESET"); + if (false == sahara_tx_data (sizeof(sahara_packet_reset))) { + dbg(LOG_ERROR, "Sending RESET packet failed"); + return false; + } + + return true; +} + +static bool send_memory_read_packet (uint64_t memory_table_address, uint64_t memory_table_length) { + sahara_packet_memory_read *sahara_memory_read = (sahara_packet_memory_read *)sahara_data.tx_buffer; + sahara_packet_memory_read_64bit *sahara_memory_read_64bit = (sahara_packet_memory_read_64bit *)sahara_data.tx_buffer; + + dbg(LOG_EVENT, "SENDING --> SAHARA_MEMORY_READ, address 0x%08"PRIX64", length 0x%08"PRIX64, memory_table_address, memory_table_length); + + if (true == sahara_data.ram_dump_64bit) { + sahara_memory_read_64bit->header.command = qlog_le32(SAHARA_64_BITS_MEMORY_READ_ID); + sahara_memory_read_64bit->header.length = qlog_le32(sizeof(sahara_packet_memory_read_64bit)); + sahara_memory_read_64bit->memory_addr = qlog_le64(memory_table_address); + sahara_memory_read_64bit->memory_length = qlog_le64(memory_table_length); + + /* Send the Memory Read packet */ + if (false == sahara_tx_data (sizeof(sahara_packet_memory_read_64bit))) { + dbg(LOG_ERROR, "Sending MEMORY_READ packet failed"); + return false; + } + } else { + sahara_memory_read->header.command = qlog_le32(SAHARA_MEMORY_READ_ID); + sahara_memory_read->header.length = qlog_le32(sizeof(sahara_packet_memory_read)); + sahara_memory_read->memory_addr = qlog_le32((uint32_t)memory_table_address); + sahara_memory_read->memory_length = qlog_le32((uint32_t)memory_table_length); + + /* Send the Memory Read packet */ + if (false == sahara_tx_data (sizeof(sahara_packet_memory_read))) { + dbg(LOG_ERROR, "Sending MEMORY_READ packet failed"); + return false; + } + } + + return true; +} + +static bool is_valid_memory_table(uint64_t memory_table_size) +{ + if (true == sahara_data.ram_dump_64bit && memory_table_size % sizeof(dload_debug_type_64bit) == 0) { + return true; + } + else if (false == sahara_data.ram_dump_64bit && memory_table_size % sizeof(dload_debug_type) == 0) { + return true; + } + else { + return false; + } +} + +static bool sahara_start(void) { + int retval = 0; + int num_debug_entries = -1; + int i = 0; + uint64_t memory_table_addr = 0; + uint64_t memory_table_length = 0; + + struct timeval time_start, time_end; + + sahara_packet_hello *sahara_hello = (sahara_packet_hello *)sahara_data.rx_buffer; + sahara_packet_hello_resp *sahara_hello_resp = (sahara_packet_hello_resp *)sahara_data.tx_buffer; + sahara_packet_memory_debug *sahara_memory_debug = (sahara_packet_memory_debug *)sahara_data.rx_buffer; + sahara_packet_memory_debug_64bit *sahara_memory_debug_64bit = (sahara_packet_memory_debug_64bit *)sahara_data.rx_buffer; + dload_debug_type *sahara_memory_table_rx = (dload_debug_type *)sahara_data.rx_buffer; + dload_debug_type_64bit *sahara_memory_table = (dload_debug_type_64bit *)sahara_data.misc_buffer; + sahara_packet_reset_resp *sahara_reset_resp = (sahara_packet_reset_resp *)sahara_data.rx_buffer; + + sahara_data.state = SAHARA_WAIT_HELLO; + kickstart_options.verbose = 1; + + while (1) + { + switch (sahara_data.state) + { + case SAHARA_WAIT_HELLO: + dbg(LOG_EVENT, "STATE <-- SAHARA_WAIT_HELLO"); + if (false == sahara_rx_data(0)) // size 0 means we don't know what to expect. So we'll just try to read the 8 byte header + { + sahara_tx_data(1); + if (false == sahara_rx_data(0)) + return false; + } + + //Check if the received command is a hello command + if (SAHARA_HELLO_ID != qlog_le32(sahara_hello->header.command)) { + dbg(LOG_ERROR, "Received a different command: %x while waiting for hello packet", qlog_le32(sahara_hello->header.command)); + if (false == send_reset_command ()) { + return false; + } + // set the state to SAHARA_WAIT_RESET_RESP + dbg(LOG_EVENT, "STATE <-- SAHARA_WAIT_RESET_RESP\n"); + sahara_data.state = SAHARA_WAIT_RESET_RESP; + } + else { + // Recieved hello, send the hello response + // Create a Hello request + sahara_hello_resp->header.command = qlog_le32(SAHARA_HELLO_RESP_ID); + sahara_hello_resp->header.length = qlog_le32(sizeof(sahara_packet_hello_resp)); + sahara_hello_resp->version = sahara_hello->version; //SAHARA_VERSION; + sahara_hello_resp->version_supported = sahara_hello->version_supported; //SAHARA_VERSION_SUPPORTED; + sahara_hello_resp->status = qlog_le32(SAHARA_STATUS_SUCCESS); + sahara_hello_resp->mode = sahara_hello->mode; + sahara_hello_resp->reserved0 = qlog_le32(1); + sahara_hello_resp->reserved1 = qlog_le32(2); + sahara_hello_resp->reserved2 = qlog_le32(3); + sahara_hello_resp->reserved3 = qlog_le32(4); + sahara_hello_resp->reserved4 = qlog_le32(5); + sahara_hello_resp->reserved5 = qlog_le32(6); + + switch (qlog_le32(sahara_hello->mode)) { + case SAHARA_MODE_IMAGE_TX_PENDING: + dbg(LOG_EVENT, "RECEIVED <-- SAHARA_MODE_IMAGE_TX_PENDING"); + break; + case SAHARA_MODE_IMAGE_TX_COMPLETE: + dbg(LOG_EVENT, "RECEIVED <-- SAHARA_MODE_IMAGE_TX_COMPLETE"); + break; + case SAHARA_MODE_MEMORY_DEBUG: + dbg(LOG_EVENT, "RECEIVED <-- SAHARA_MODE_MEMORY_DEBUG"); + break; + case SAHARA_MODE_COMMAND: + dbg(LOG_EVENT, "RECEIVED <-- SAHARA_MODE_COMMAND"); + break; + default: + dbg(LOG_EVENT, "RECEIVED <-- SAHARA_MODE_0x%x", qlog_le32(sahara_hello->mode)); + break; + } + + if (qlog_le32(sahara_hello->mode) != sahara_data.mode) { + dbg(LOG_ERROR, "Not expect module state "); + return false; + } + + /*Send the Hello Resonse Request*/ + dbg(LOG_EVENT, "SENDING --> SAHARA_HELLO_RESPONSE"); + if (false == sahara_tx_data (sizeof(sahara_packet_hello_resp))) + { + dbg(LOG_ERROR, "Tx Sahara Data Failed "); + return false; + } + sahara_data.state = SAHARA_WAIT_COMMAND; + } + break; + + case SAHARA_WAIT_COMMAND: + dbg(LOG_INFO, "STATE <-- SAHARA_WAIT_COMMAND"); + if (false == sahara_rx_data(0)) + return false; + + // Check if it is an end of image Tx + if (SAHARA_MEMORY_DEBUG_ID == qlog_le32(((sahara_packet_header *)sahara_data.rx_buffer)->command) + || SAHARA_64_BITS_MEMORY_DEBUG_ID == qlog_le32(((sahara_packet_header *)sahara_data.rx_buffer)->command)) { + dbg(LOG_EVENT, "RECEIVED <-- SAHARA_MEMORY_DEBUG"); + + if (SAHARA_64_BITS_MEMORY_DEBUG_ID == qlog_le32(((sahara_packet_header *)sahara_data.rx_buffer)->command)) { + sahara_data.ram_dump_64bit = true; + dbg(LOG_EVENT, "Using 64 bit RAM dump mode"); + memory_table_addr = qlog_le64(sahara_memory_debug_64bit->memory_table_addr); + memory_table_length = qlog_le64(sahara_memory_debug_64bit->memory_table_length); + } + else { + sahara_data.ram_dump_64bit = false; + memory_table_addr = qlog_le32(sahara_memory_debug->memory_table_addr); + memory_table_length = qlog_le32(sahara_memory_debug->memory_table_length); + } + + dbg(LOG_INFO, "Memory Table Address: 0x%08"PRIX64", Memory Table Length: 0x%08"PRIX64, memory_table_addr, memory_table_length); + + if (false == is_valid_memory_table(memory_table_length)) { + dbg(LOG_ERROR, "Invalid memory table received"); + if (false == send_reset_command ()) { + return false; + } + sahara_data.state = SAHARA_WAIT_RESET_RESP; + break; + } + + if (memory_table_length > 0) { + if (false == send_memory_read_packet(memory_table_addr, memory_table_length)) { + return false; + } + + if (memory_table_length > SAHARA_RAW_BUFFER_SIZE) { + dbg(LOG_ERROR, "Memory table length is greater than size of intermediate buffer"); + return false; + } + } + dbg(LOG_EVENT, "STATE <-- SAHARA_WAIT_MEMORY_TABLE"); + sahara_data.state = SAHARA_WAIT_MEMORY_TABLE; + } + else { + dbg(LOG_ERROR, "Received an unknown command: %d ", qlog_le32(((sahara_packet_header *)sahara_data.rx_buffer)->command)); + if (SAHARA_HELLO_ID == qlog_le32(((sahara_packet_header *)sahara_data.rx_buffer)->command)) + continue; + if (false == send_reset_command ()) { + return false; + } + // set the state to SAHARA_WAIT_RESET_RESP + dbg(LOG_EVENT, "STATE <-- SAHARA_WAIT_RESET_RESP"); + sahara_data.state = SAHARA_WAIT_RESET_RESP; + } + break; + + case SAHARA_WAIT_MEMORY_TABLE: + dbg(LOG_INFO, "STATE <-- SAHARA_WAIT_MEMORY_TABLE"); + num_debug_entries = 0; + if (memory_table_length > 0) { + if (false == sahara_rx_data((size_t)memory_table_length)) { + return false; + } + dbg(LOG_INFO, "Memory Debug table received"); + + if (true == sahara_data.ram_dump_64bit) { + memcpy (sahara_data.misc_buffer, sahara_data.rx_buffer, (size_t)memory_table_length); + num_debug_entries = (int)(memory_table_length/sizeof(dload_debug_type_64bit)); + } + else { + num_debug_entries = (int)(memory_table_length/sizeof(dload_debug_type)); + if (num_debug_entries * sizeof(dload_debug_type_64bit) > SAHARA_RAW_BUFFER_SIZE) { + dbg(LOG_ERROR, "Length of memory table converted to 64-bit entries is greater than size of intermediate buffer"); + return false; + } + + for (i = 0; i < num_debug_entries; ++i) { + sahara_memory_table[i].save_pref = (uint64_t) qlog_le32(sahara_memory_table_rx[i].save_pref); + sahara_memory_table[i].mem_base = (uint64_t) qlog_le32(sahara_memory_table_rx[i].mem_base); + sahara_memory_table[i].length = (uint64_t) qlog_le32(sahara_memory_table_rx[i].length); + strncpy(sahara_memory_table[i].filename, sahara_memory_table_rx[i].filename, DLOAD_DEBUG_STRLEN_BYTES); + strncpy(sahara_memory_table[i].desc, sahara_memory_table_rx[i].desc, DLOAD_DEBUG_STRLEN_BYTES); + } // end for (i = 0; i < num_debug_entries; ++i) + } + } + + for(i = 0; i < num_debug_entries; i++) { + dbg(LOG_EVENT, "Base 0x%08"PRIX64" Len 0x%08"PRIX64", '%s', '%s'", sahara_memory_table[i].mem_base, sahara_memory_table[i].length, sahara_memory_table[i].filename, sahara_memory_table[i].desc); + } + sahara_data.state = SAHARA_WAIT_MEMORY_REGION; + break; + + case SAHARA_WAIT_MEMORY_REGION: + dbg(LOG_INFO, "STATE <-- SAHARA_WAIT_MEMORY_REGION"); + for(i = 0; i < num_debug_entries; i++) { + uint64_t cur = 0; + int fd = -1; + char full_filename[255] = {0}; + if (kickstart_options.path_to_save_files) { + strcpy(full_filename, kickstart_options.path_to_save_files); + strcat(full_filename, "/"); + } + strcat(full_filename, sahara_memory_table[i].filename); + + fd = open(full_filename, O_CREAT | O_WRONLY | O_TRUNC, 0444); + if (fd==-1) { + dbg(LOG_ERROR, "ERROR: Your file '%s' does not exist or cannot be created\n\n",sahara_memory_table[num_debug_entries].filename); + exit(0); + } + gettimeofday(&time_start, NULL); + + while (cur < sahara_memory_table[i].length) { + uint64_t len = MIN((uint32_t)(sahara_memory_table[i].length - cur), sahara_data.max_ram_dump_read); + + if (len < sahara_data.max_ram_dump_read || cur == 0 || (cur%(16*1024*1024)) == 0) + kickstart_options.verbose = 1; + else + kickstart_options.verbose = 0; + + retval = send_memory_read_packet(sahara_memory_table[i].mem_base + cur, len); + if (false == retval) { + return false; + } + + retval = sahara_rx_data((size_t)len); + if (false == retval) { + system("fuser /dev/ttyUSB0"); + if ( sahara_data.max_ram_dump_read > (16*1024)) { + sahara_data.max_ram_dump_read = sahara_data.max_ram_dump_read / 2; + continue; + } + return false; + } + + cur += len; + + retval = write(fd, sahara_data.rx_buffer, (unsigned int)len); + if (retval < 0) { + dbg(LOG_ERROR, "file write failed: %s", strerror(errno)); + return false; + } + if ((uint32_t) retval != len) { + dbg(LOG_WARN, "Wrote only %d of 0x%08"PRIX64" bytes", retval, memory_table_length); + } + } + + + kickstart_options.verbose = 1; + dbg(LOG_STATUS, "Received file '%s'", sahara_memory_table[i].filename); + close(fd); + gettimeofday(&time_end, NULL); + time_throughput_calculate(&time_start, &time_end, sahara_memory_table[i].length); + } + + if ( kickstart_options.do_reset) { + if (false == send_reset_command ()) { + return false; + } + sahara_data.state = SAHARA_WAIT_RESET_RESP; + } else { + return true; + } + break; + + case SAHARA_WAIT_DONE_RESP: + dbg(LOG_EVENT, "STATE <-- SAHARA_WAIT_DONE_RESP"); + return false; + break; + + case SAHARA_WAIT_RESET_RESP: + dbg(LOG_EVENT, "STATE <-- SAHARA_WAIT_RESET_RESP"); + if (true == sahara_rx_data(0)) { + if (SAHARA_RESET_RESP_ID != qlog_le32(sahara_reset_resp->header.command)) { + dbg(LOG_INFO,"Waiting for reset response code %i, received %i instead.", SAHARA_RESET_RESP_ID, qlog_le32(sahara_reset_resp->header.command)); + continue; + } + } else { + if (SAHARA_RESET_RESP_ID == qlog_le32(sahara_reset_resp->header.command)) { + dbg(LOG_INFO,"Get reset response code %i", sahara_reset_resp->header.command); + return true; + } else { + dbg(LOG_ERROR, "read failed: Linux system error: %s", strerror(errno)); + return false; + } + } + + return true; + break; + + default: + dbg(LOG_ERROR, "Unrecognized state %d", sahara_data.state); + return false; + } /* end switch */ + } /* end while (1) */ +} + + int sahara_catch_dump(int port_fd, const char *path_to_save_files, int do_reset) { + int retval; + + sahara_data.mode = SAHARA_MODE_MEMORY_DEBUG; + com_port.port_fd = port_fd; + kickstart_options.path_to_save_files = path_to_save_files; + kickstart_options.do_reset = do_reset; + + sahara_data.rx_buffer = malloc (SAHARA_RAW_BUFFER_SIZE); + sahara_data.tx_buffer = malloc (2048); + sahara_data.misc_buffer = malloc (2048); + + if (NULL == sahara_data.rx_buffer || NULL == sahara_data.tx_buffer || NULL == sahara_data.misc_buffer) { + dbg(LOG_ERROR, "Failed to allocate sahara buffers"); + return false; + } + + retval = sahara_start(); + if (false == retval) { + dbg(LOG_ERROR, "Sahara protocol error"); + } + else { + dbg(LOG_ERROR, "Sahara protocol completed"); + } + + free(sahara_data.rx_buffer); + free(sahara_data.tx_buffer); + free(sahara_data.misc_buffer); + + sahara_data.rx_buffer = sahara_data.tx_buffer = sahara_data.misc_buffer = NULL; + + if (retval == false) + dbg(LOG_INFO, "Catch DUMP using Sahara protocol failed\n\n"); + else + dbg(LOG_INFO, "Catch DUMP using Sahara protocol successful\n\n"); + + return retval; +} diff --git a/rooter/0optionalapps/qlog/src/sahara_protocol.h b/rooter/0optionalapps/qlog/src/sahara_protocol.h new file mode 100644 index 0000000..0db7989 --- /dev/null +++ b/rooter/0optionalapps/qlog/src/sahara_protocol.h @@ -0,0 +1,510 @@ +/*=========================================================================== + * FILE: + * sahara_packet.h + * + * DESCRIPTION: + * Sahara protocol states and structure declaration. + * + * Copyright (C) 2012 Qualcomm Technologies, Inc. All rights reserved. + * Qualcomm Technologies Proprietary/GTDR + * + * All data and information contained in or disclosed by this document is + * confidential and proprietary information of Qualcomm Technologies, Inc. and all + * rights therein are expressly reserved. By accepting this material the + * recipient agrees that this material and the information contained therein + * is held in confidence and in trust and will not be used, copied, reproduced + * in whole or in part, nor its contents revealed in any manner to others + * without the express written permission of Qualcomm Technologies, Inc. + * =========================================================================== + * + * sahara_packet.h : Sahara protocol states and structure declaration. + * ========================================================================================== + * $Header: //components/rel/boot.bf/3.1.4/boot_images/core/storage/tools/QSaharaServer/src/sahara_protocol.h#1 $ + * $DateTime: 2017/02/21 04:58:32 $ + * $Author: pwbldsvc $ + * + * Edit History: + * YYYY-MM-DD who why + * ----------------------------------------------------------------------------- + * 2010-09-28 ng Added command mode support + * 2010-10-18 ab Added memory debug mode support + * + * Copyright 2012 by Qualcomm Technologies, Inc. All Rights Reserved. + * + *========================================================================================== + */ + +#ifndef SAHARA_PROTOCOL_H +#define SAHARA_PROTOCOL_H + +/*=========================================================================== + * + * INCLUDE FILES + * + * ===========================================================================*/ + +/*=========================================================================== + * + * PUBLIC DATA DECLARATIONS + * + * ===========================================================================*/ +// Sahara Protocol Version +#define SAHARA_VERSION 2 +#define SAHARA_VERSION_SUPPORTED 4 + +/*Maximum 1 megabyte tx buffer size*/ +#define SAHARA_RAW_BUFFER_SIZE (64*1024) + +// Sahara command IDs +typedef enum +{ + SAHARA_NO_CMD_ID = 0x00, + SAHARA_HELLO_ID = 0x01, // sent from target to host + SAHARA_HELLO_RESP_ID = 0x02, // sent from host to target + SAHARA_READ_DATA_ID = 0x03, // sent from target to host + SAHARA_END_IMAGE_TX_ID = 0x04, // sent from target to host + SAHARA_DONE_ID = 0x05, // sent from host to target + SAHARA_DONE_RESP_ID = 0x06, // sent from target to host + SAHARA_RESET_ID = 0x07, // sent from host to target + SAHARA_RESET_RESP_ID = 0x08, // sent from target to host + SAHARA_MEMORY_DEBUG_ID = 0x09, // sent from target to host + SAHARA_MEMORY_READ_ID = 0x0A, // sent from host to target + SAHARA_CMD_READY_ID = 0x0B, // sent from target to host + SAHARA_CMD_SWITCH_MODE_ID = 0x0C, // sent from host to target + SAHARA_CMD_EXEC_ID = 0x0D, // sent from host to target + SAHARA_CMD_EXEC_RESP_ID = 0x0E, // sent from target to host + SAHARA_CMD_EXEC_DATA_ID = 0x0F, // sent from host to target + SAHARA_64_BITS_MEMORY_DEBUG_ID = 0x10, // sent from target to host + SAHARA_64_BITS_MEMORY_READ_ID = 0x11, // sent from host to target + SAHARA_64_BITS_READ_DATA_ID = 0x12, + // place all new commands above this + SAHARA_LAST_CMD_ID, + SAHARA_MAX_CMD_ID = 0x7FFFFFFF // To ensure 32-bits wide +} boot_sahara_cmd_id; + +typedef enum { + SAHARA_IMAGE_TYPE_BINARY = 0, /* Binary format */ + SAHARA_IMAGE_TYPE_ELF, /* ELF format */ + SAHARA_IMAGE_UNKNOWN = 0x7FFFFFFF /* To ensure 32-bits wide */ +} boot_sahara_image; + +// Status codes for Sahara +typedef enum +{ + // Success + SAHARA_STATUS_SUCCESS = 0x00, + + // Invalid command received in current state + SAHARA_NAK_INVALID_CMD = 0x01, + + // Protocol mismatch between host and target + SAHARA_NAK_PROTOCOL_MISMATCH = 0x02, + + // Invalid target protocol version + SAHARA_NAK_INVALID_TARGET_PROTOCOL = 0x03, + + // Invalid host protocol version + SAHARA_NAK_INVALID_HOST_PROTOCOL = 0x04, + + // Invalid packet size received + SAHARA_NAK_INVALID_PACKET_SIZE = 0x05, + + // Unexpected image ID received + SAHARA_NAK_UNEXPECTED_IMAGE_ID = 0x06, + + // Invalid image header size received + SAHARA_NAK_INVALID_HEADER_SIZE = 0x07, + + // Invalid image data size received + SAHARA_NAK_INVALID_DATA_SIZE = 0x08, + + // Invalid image type received + SAHARA_NAK_INVALID_IMAGE_TYPE = 0x09, + + // Invalid tranmission length + SAHARA_NAK_INVALID_TX_LENGTH = 0x0A, + + // Invalid reception length + SAHARA_NAK_INVALID_RX_LENGTH = 0x0B, + + // General transmission or reception error + SAHARA_NAK_GENERAL_TX_RX_ERROR = 0x0C, + + // Error while transmitting READ_DATA packet + SAHARA_NAK_READ_DATA_ERROR = 0x0D, + + // Cannot receive specified number of program headers + SAHARA_NAK_UNSUPPORTED_NUM_PHDRS = 0x0E, + + // Invalid data length received for program headers + SAHARA_NAK_INVALID_PDHR_SIZE = 0x0F, + + // Multiple shared segments found in ELF image + SAHARA_NAK_MULTIPLE_SHARED_SEG = 0x10, + + // Uninitialized program header location + SAHARA_NAK_UNINIT_PHDR_LOC = 0x11, + + // Invalid destination address + SAHARA_NAK_INVALID_DEST_ADDR = 0x12, + + // Invalid data size receieved in image header + SAHARA_NAK_INVALID_IMG_HDR_DATA_SIZE = 0x13, + + // Invalid ELF header received + SAHARA_NAK_INVALID_ELF_HDR = 0x14, + + // Unknown host error received in HELLO_RESP + SAHARA_NAK_UNKNOWN_HOST_ERROR = 0x15, + + // Timeout while receiving data + SAHARA_NAK_TIMEOUT_RX = 0x16, + + // Timeout while transmitting data + SAHARA_NAK_TIMEOUT_TX = 0x17, + + // Invalid mode received from host + SAHARA_NAK_INVALID_HOST_MODE = 0x18, + + // Invalid memory read access + SAHARA_NAK_INVALID_MEMORY_READ = 0x19, + + // Host cannot handle read data size requested + SAHARA_NAK_INVALID_DATA_SIZE_REQUEST = 0x1A, + + // Memory debug not supported + SAHARA_NAK_MEMORY_DEBUG_NOT_SUPPORTED = 0x1B, + + // Invalid mode switch + SAHARA_NAK_INVALID_MODE_SWITCH = 0x1C, + + // Failed to execute command + SAHARA_NAK_CMD_EXEC_FAILURE = 0x1D, + + // Invalid parameter passed to command execution + SAHARA_NAK_EXEC_CMD_INVALID_PARAM = 0x1E, + + // Unsupported client command received + SAHARA_NAK_EXEC_CMD_UNSUPPORTED = 0x1F, + + // Invalid client command received for data response + SAHARA_NAK_EXEC_DATA_INVALID_CLIENT_CMD = 0x20, + + // Failed to authenticate hash table + SAHARA_NAK_HASH_TABLE_AUTH_FAILURE = 0x21, + + // Failed to verify hash for a given segment of ELF image + SAHARA_NAK_HASH_VERIFICATION_FAILURE = 0x22, + + // Failed to find hash table in ELF image + SAHARA_NAK_HASH_TABLE_NOT_FOUND = 0x23, + + // Place all new error codes above this + SAHARA_NAK_LAST_CODE, + + SAHARA_NAK_MAX_CODE = 0x7FFFFFFF // To ensure 32-bits wide +} boot_sahara_status; + +// Status of all image transfers +typedef enum +{ + SAHARA_MODE_IMAGE_TX_PENDING = 0x0, + SAHARA_MODE_IMAGE_TX_COMPLETE = 0x1, + SAHARA_MODE_MEMORY_DEBUG = 0x2, + SAHARA_MODE_COMMAND = 0x3, + + // place all new commands above this + SAHARA_MODE_LAST, + SAHARA_MODE_MAX = 0x7FFFFFFF +} boot_sahara_mode; + +// Executable commands when target is in command mode +typedef enum +{ + SAHARA_EXEC_CMD_NOP = 0x00, + SAHARA_EXEC_CMD_SERIAL_NUM_READ = 0x01, + SAHARA_EXEC_CMD_MSM_HW_ID_READ = 0x02, + SAHARA_EXEC_CMD_OEM_PK_HASH_READ = 0x03, + SAHARA_EXEC_CMD_SWITCH_DMSS = 0x04, + SAHARA_EXEC_CMD_SWITCH_STREAMING = 0x05, + SAHARA_EXEC_CMD_READ_DEBUG_DATA = 0x06, + + // place all new commands above this + SAHARA_EXEC_CMD_LAST, + SAHARA_EXEC_CMD_MAX = 0x7FFFFFFF +} boot_sahara_exec_cmd_id; + +/* Sahara Protocol states */ +typedef enum { + SAHARA_WAIT_HELLO, + SAHARA_WAIT_COMMAND, + SAHARA_WAIT_RESET_RESP, + SAHARA_WAIT_DONE_RESP, + SAHARA_WAIT_MEMORY_READ, + SAHARA_WAIT_CMD_EXEC_RESP, + SAHARA_WAIT_MEMORY_TABLE, + SAHARA_WAIT_MEMORY_REGION, +} boot_sahara_state; + +/* ============================================================================= */ +/* Sahara protocol packet defintions */ +/* ============================================================================= */ + +typedef struct +{ + uint32_t command; // command ID + uint32_t length; // packet length incl command and length +} sahara_packet_header; + +// HELLO command packet type - sent from target to host +// indicates start of protocol on target side +typedef struct +{ + sahara_packet_header header; + uint32_t version; // target protocol version number + uint32_t version_supported; // minimum protocol version number supported + // on target + uint32_t cmd_packet_length; // maximum packet size supported for command + // packets + uint32_t mode; // expected mode of target operation + uint32_t reserved0; // reserved field + uint32_t reserved1; // reserved field + uint32_t reserved2; // reserved field + uint32_t reserved3; // reserved field + uint32_t reserved4; // reserved field + uint32_t reserved5; // reserved field +} sahara_packet_hello; + +// HELLO_RESP command packet type - sent from host to target +// response to hello, protocol version running on host and status sent +typedef struct +{ + sahara_packet_header header; + uint32_t version; // host protocol version number + uint32_t version_supported; // minimum protocol version number supported + // on host + uint32_t status; // OK or error condition + uint32_t mode; // mode of operation for target to execute + uint32_t reserved0; // reserved field + uint32_t reserved1; // reserved field + uint32_t reserved2; // reserved field + uint32_t reserved3; // reserved field + uint32_t reserved4; // reserved field + uint32_t reserved5; // reserved field +} sahara_packet_hello_resp; + +// READ_DATA command packet type - sent from target to host +// sends data segment offset and length to be read from current host +// image file +typedef struct +{ + sahara_packet_header header; + uint32_t image_id; // ID of image to be transferred + uint32_t data_offset; // offset into image file to read data from + uint32_t data_length; // length of data segment to be retreived + // from image file +} sahara_packet_read_data; + +// READ_DATA_64 command packet type - sent from target to host +// sends data segment offset and length to be read from current host +// image file +/* +#ifdef WINDOWSPC +#define PACK( __Declaration__ ) __pragma( pack(push, 1) ) __Declaration__ __pragma( pack(pop) ) +PACK( +typedef struct // note for gcc use __attribute__((__packed__)) +{ + sahara_packet_header header; + uint32_t image_id; // ID of image to be transferred + uint64_t data_offset; // offset into image file to read data from + uint32_t data_length; // length of data segment to be retreived + // from image file +} sahara_packet_read_data_64bit; +); +#else +typedef __attribute__((__packed__)) struct +{ + sahara_packet_header header; + uint32_t image_id; // ID of image to be transferred + uint64_t data_offset; // offset into image file to read data from + uint32_t data_length; // length of data segment to be retreived + // from image file +} sahara_packet_read_data_64bit; +#endif +*/ +typedef struct +{ + sahara_packet_header header; + uint64_t image_id; // ID of image to be transferred + uint64_t data_offset; // offset into image file to read data from + uint64_t data_length; // length of data segment to be retreived + // from image file +} sahara_packet_read_data_64bit; + +// END_IMAGE_TX command packet type - sent from target to host +// indicates end of a single image transfer and status of transfer +typedef struct +{ + sahara_packet_header header; + uint32_t image_id; // ID of image to be transferred + uint32_t status; // OK or error condition +} sahara_packet_end_image_tx; + +// DONE packet type - sent from host to target +// indicates end of single image transfer +typedef struct +{ + sahara_packet_header header; +} sahara_packet_done; + +// DONE_RESP packet type - sent from target to host +// indicates end of all image transfers +typedef struct +{ + sahara_packet_header header; + uint32_t image_tx_status; // indicates if all images have been + // transferred; + // 0 = IMAGE_TX_PENDING + // 1 = IMAGE_TX_COMPLETE +} sahara_packet_done_resp; + +// RESET packet type - sent from host to target +// indicates to target to reset +typedef struct +{ + sahara_packet_header header; +} sahara_packet_reset; + +// RESET_RESP packet type - sent from target to host +// indicates to host that target has reset +typedef struct +{ + sahara_packet_header header; +} sahara_packet_reset_resp; + +// MEMORY_DEBUG packet type - sent from target to host +// sends host the location and length of memory region table +typedef struct +{ + sahara_packet_header header; + uint32_t memory_table_addr; // location of memory region table + uint32_t memory_table_length; // length of memory table +} sahara_packet_memory_debug; +typedef struct +{ + sahara_packet_header header; + uint64_t memory_table_addr; // location of memory region table + uint64_t memory_table_length; // length of memory table +} sahara_packet_memory_debug_64bit; + +// MEMORY_READ packet type - sent from host to target +// sends memory address and length to read from target memory +typedef struct +{ + sahara_packet_header header; + uint32_t memory_addr; // memory location to read from + uint32_t memory_length; // length of data to send +} sahara_packet_memory_read; +typedef struct +{ + sahara_packet_header header; + uint64_t memory_addr; // memory location to read from + uint64_t memory_length; // length of data to send +} sahara_packet_memory_read_64bit; + +// CMD_READY packet type - sent from target to host +// indicates to host that target is ready to accept commands +typedef struct +{ + sahara_packet_header header; +} sahara_packet_cmd_ready; + +// CMD_SWITCH_MODE packet type - sent from host to target +// indicates to target to switch modes +typedef struct +{ + sahara_packet_header header; + uint32_t mode; // mode of operation for target to execute +} sahara_packet_cmd_switch_mode; + +// CMD_EXEC packet type - sent from host to target +// indicates to target to execute given client_command +typedef struct +{ + sahara_packet_header header; + uint32_t client_command; // command ID for target Sahara client to + // execute +} sahara_packet_cmd_exec; + +// CMD_EXEC_RESP packet type - sent from host to target +// indicates to host that target has successfully executed command +// and length of data response +typedef struct +{ + sahara_packet_header header; + uint32_t client_command; // command ID for target Sahara client to + // execute + uint32_t resp_length; // length of response returned from command + // execution +} sahara_packet_cmd_exec_resp; + +// CMD_EXEC_DATA packet type - sent from target to host +// indicates that host is ready to receive data after command execution +typedef struct +{ + sahara_packet_header header; + uint32_t client_command; // command ID for target Sahara client to + // execute +} sahara_packet_cmd_exec_data; + +#define DLOAD_DEBUG_STRLEN_BYTES 20 +typedef struct +{ + uint32_t save_pref; + uint32_t mem_base; + uint32_t length; + char desc[DLOAD_DEBUG_STRLEN_BYTES]; + char filename[DLOAD_DEBUG_STRLEN_BYTES]; +} dload_debug_type; + +typedef struct +{ + uint64_t save_pref; //force 8 bytes alignment + uint64_t mem_base; + uint64_t length; + char desc[DLOAD_DEBUG_STRLEN_BYTES]; + char filename[DLOAD_DEBUG_STRLEN_BYTES]; +} dload_debug_type_64bit; + +typedef struct { + /* buffer for sahara rx */ + void* rx_buffer; + + /* buffer for sahara tx */ + void* tx_buffer; + + /* buffer for memory table */ + void* misc_buffer; + + /* Sahara state */ + boot_sahara_state state; + + size_t timed_data_size; + + // handle to input image + int fd; + + int ram_dump_image; + + int max_ram_dump_retries; + + uint32_t max_ram_dump_read; + + boot_sahara_mode mode; + boot_sahara_mode prev_mode; + + unsigned int command; + bool ram_dump_64bit; + +} sahara_data_t; +#endif /* SAHARA_PACKET_H */ diff --git a/rooter/0optionalapps/qlog/src/tty2tcp.c b/rooter/0optionalapps/qlog/src/tty2tcp.c new file mode 100644 index 0000000..9d3b6e4 --- /dev/null +++ b/rooter/0optionalapps/qlog/src/tty2tcp.c @@ -0,0 +1,174 @@ +#include "qlog.h" + +unsigned int inet_addr(const char *cp); +char *inet_ntoa(struct in_addr in); + +static int wait_tcp_client_connect(int tcp_port) { + int sockfd, n, connfd; + struct sockaddr_in serveraddr; + struct sockaddr_in clientaddr; + int reuse_addr = 1; + size_t sin_size; + + sockfd = socket(AF_INET, SOCK_STREAM, 0); + if (sockfd == -1) + { + qlog_dbg("Create socket fail!\n"); + return 0; + } + + memset(&serveraddr, 0, sizeof(serveraddr)); + serveraddr.sin_family = AF_INET; + serveraddr.sin_addr.s_addr = htonl(INADDR_ANY); + serveraddr.sin_port = htons(tcp_port); + + qlog_dbg("Starting the TCP server(%d)...\n", tcp_port); + + setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse_addr,sizeof(reuse_addr)); + + n = bind(sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)); + if (n == -1) + { + qlog_dbg("bind fail! errno: %d\n", errno); + close(sockfd); + return 0; + } + qlog_dbg("bind OK!\n"); + + n = listen(sockfd, 1); + if (n == -1) + { + qlog_dbg("listen fail! errno: %d\n", errno); + close(sockfd); + return 0; + } + qlog_dbg("listen OK!\nWaiting the TCP Client...\n"); + + sin_size = sizeof(struct sockaddr_in); + connfd = accept(sockfd, (struct sockaddr *)&clientaddr, (socklen_t *)&sin_size); + close(sockfd); + if (connfd == -1) + { + qlog_dbg("accept fail! errno: %d\n", errno); + return -1; + } + + qlog_dbg("TCP Client %s:%d connect\n", inet_ntoa(clientaddr.sin_addr), clientaddr.sin_port); + + return connfd; +} + +int tty2tcp_sockfd = -1; +static int tty2tcp_ttyfd = -1; +static int tty2tcp_tcpport = 9000; + +static void *tcp_sock_read_Loop(void *arg) { + int sockfd = tty2tcp_sockfd; + int ttyfd = tty2tcp_ttyfd; + void *rbuf; + const size_t rbuf_size = (4*1024); + + rbuf = malloc(rbuf_size); + if (rbuf == NULL) { + qlog_dbg("Fail to malloc rbuf_size=%zd, errno: %d (%s)\n", rbuf_size, errno, strerror(errno)); + return NULL; + } + + while (sockfd > 0) { + ssize_t rc, wc; + int ret; + struct pollfd pollfds[] = {{sockfd, POLLIN, 0}}; + + ret = poll(pollfds, 1, -1); + + if (ret <= 0) { + qlog_dbg("poll(ttyfd) =%d, errno: %d (%s)\n", ret, errno, strerror(errno)); + break; + } + + if (pollfds[0].revents & (POLLERR | POLLHUP | POLLNVAL)) { + tty2tcp_sockfd = -1; + close(sockfd); + qlog_dbg("ttyfd revents = %04x\n", pollfds[0].revents); + sockfd = tty2tcp_sockfd = wait_tcp_client_connect(tty2tcp_tcpport); + } + + if (pollfds[0].revents & (POLLIN)) { + rc = read(sockfd, rbuf, rbuf_size); + + if(rc > 0) { + if (g_is_asr_chip) + wc = asr_send_cmd(ttyfd, rbuf, rc); + else + wc = mdm_send_cmd(ttyfd, rbuf, rc); + + if (wc != rc) { + //qlog_dbg("ttyfd write fail %zd/%zd, break\n", wc, rc); + //break; + } + } + else + { + tty2tcp_sockfd = -1; + close(sockfd); + qlog_dbg("sockfd recv %zd Bytes. maybe terminae by peer!\n", rc); + sockfd = tty2tcp_sockfd = wait_tcp_client_connect(tty2tcp_tcpport); + } + } + } + + free(rbuf); + close(ttyfd); + tty2tcp_sockfd = -1; + qlog_dbg("%s exit\n", __func__); + + return NULL; +} + +static int tty2tcp_init_filter(int ttyfd, const char *cfg) { + int tcp_port = 9000; + int sockfd = -1; + pthread_t tid; + pthread_attr_t attr; + + if (cfg) + tcp_port = atoi(cfg); + + tty2tcp_tcpport = tcp_port; + sockfd = wait_tcp_client_connect(tcp_port); + + if (sockfd <= 0) + return -1; + + fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFL) | O_NONBLOCK); + + pthread_attr_init (&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + + tty2tcp_sockfd = sockfd; + tty2tcp_ttyfd = ttyfd; + pthread_create(&tid, &attr, tcp_sock_read_Loop, &attr); + + return 0; +} + +static int tty2tcp_logfile_create(const char *logfile_dir, const char *logfile_suffix, unsigned logfile_seq) { + return 1; +} + +static size_t tty2tcp_logfile_save(int logfd, const void *buf, size_t size) { + if (tty2tcp_sockfd > 0) + return qlog_poll_write(tty2tcp_sockfd, buf, size, 200); + return size; +} + +static int tty2tcp_logfile_close(int logfd) { + return 0; +} + +qlog_ops_t tty2tcp_qlog_ops = { + .init_filter = tty2tcp_init_filter, + .logfile_create = tty2tcp_logfile_create, + .logfile_save = tty2tcp_logfile_save, + .logfile_close = tty2tcp_logfile_close, +}; diff --git a/rooter/0optionalapps/udp-tunnel/Makefile b/rooter/0optionalapps/udp-tunnel/Makefile new file mode 100644 index 0000000..4d568b5 --- /dev/null +++ b/rooter/0optionalapps/udp-tunnel/Makefile @@ -0,0 +1,40 @@ +# +# Copyright (C) 2011-2014 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=udp-tunnel +PKG_RELEASE:=1 + +PKG_FLAGS:=nonshared + +include $(INCLUDE_DIR)/package.mk + +define Package/udp-tunnel + SECTION:=utils + CATEGORY:=ROOter + SUBMENU:=Optional Applications + TITLE:=UDPTunnel + MAINTAINER:=Dairyman +endef + +define Package/udp-tunnel/description + UDPTunnel +endef + +define Build/Compile + $(MAKE) -C $(PKG_BUILD_DIR) \ + CC="$(TARGET_CC)" \ + CFLAGS="$(TARGET_CFLAGS) -Wall" +endef + +define Package/udp-tunnel/install + $(INSTALL_DIR) $(1)/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/udptunnel $(1)/sbin/udptunnel +endef + +$(eval $(call BuildPackage,udp-tunnel)) diff --git a/rooter/0optionalapps/udp-tunnel/src/Makefile b/rooter/0optionalapps/udp-tunnel/src/Makefile new file mode 100644 index 0000000..0a70e29 --- /dev/null +++ b/rooter/0optionalapps/udp-tunnel/src/Makefile @@ -0,0 +1,36 @@ +prefix = /usr/local + +CFLAGS ?= -g -O2 + +INSTALL ?= install +PKG_CONFIG ?= pkg-config + +ifeq ($(shell $(PKG_CONFIG) --exists libsystemd || echo NO),) +DEFS += -DHAVE_SYSTEMD_SD_DAEMON_H $(shell $(PKG_CONFIG) --cflags libsystemd) +LDADD += $(shell $(PKG_CONFIG) --libs libsystemd) +endif + +CPPFLAGS += $(DEFS) $(INCLUDES) + +OBJECTS := log.o network.o utils.o udptunnel.o + +all: depend udptunnel + +install: + $(INSTALL) -d $(BASEDIR)$(prefix)/sbin/ + $(INSTALL) -m 0755 udptunnel $(BASEDIR)$(prefix)/sbin/ + +clean: + rm -f Makefile.depend $(OBJECTS) udptunnel + +%.o: %.c + $(CC) $(CPPFLAGS) $(CFLAGS) -c $< + +udptunnel: $(OBJECTS) + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LDADD) $(LIBS) + +depend: Makefile.depend +Makefile.depend: + $(CC) $(CPPFLAGS) $(CFLAGS) -MM -MG *.c > $@ + +-include Makefile.depend diff --git a/rooter/0optionalapps/udp-tunnel/src/log.c b/rooter/0optionalapps/udp-tunnel/src/log.c new file mode 100644 index 0000000..91bb04d --- /dev/null +++ b/rooter/0optionalapps/udp-tunnel/src/log.c @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2018 Marco d'Itri + * + * Inspired by log.c from the cowdancer package by James Clarke. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include + +#include "log.h" +#include "utils.h" + +static log_level filter_level = log_info; + +/* + * Return the appropriate file handle (stdout vs. stderr) for the log level. + */ +static FILE *file_for_level(log_level level) +{ + if (level & log_stderr || filter_level & log_stderr) + return stderr; + + if ((level & LOG_LEVEL_MASK) > log_warning) + return stdout; + else + return stderr; +} + +static void log_doit(log_level level, const char *format, va_list args) +{ + static int syslog_initialized; + + if ((level & LOG_LEVEL_MASK) > (filter_level & LOG_LEVEL_MASK)) + return; + + if (level & log_syslog || filter_level & log_syslog) { + if (!syslog_initialized) { + openlog(NULL, LOG_PID, LOG_DAEMON); + syslog_initialized = 1; + } + + if (level & log_strerror) { + int len = strlen(format); + char *format2; + + format2 = NOFAIL(malloc(len + 4 + 1)); + strcpy(format2, format); + strcpy(format2 + len, ": %m"); + vsyslog(level & LOG_LEVEL_MASK, format2, args); + free(format2); + } else { + vsyslog(level & LOG_LEVEL_MASK, format, args); + } + return; + } + + vfprintf(file_for_level(level), format, args); + if (level & log_strerror) + fprintf(file_for_level(level), ": %s", strerror(errno)); + fprintf(file_for_level(level), "\n"); +} + +log_level log_get_filter_level(void) +{ + return filter_level; +} + +void log_set_options(log_level filter_level_new) +{ + filter_level = filter_level_new; +} + +void log_printf(log_level level, const char *format, ...) +{ + va_list args; + + va_start(args, format); + log_doit(level, format, args); + va_end(args); +} + +void log_printf_exit(int status, log_level level, const char *format, ...) +{ + va_list args; + + va_start(args, format); + log_doit(level, format, args); + va_end(args); + + exit(status); +} + +void log_printf_err(log_level level, const char *format, ...) +{ + va_list args; + + va_start(args, format); + log_doit(level | log_strerror, format, args); + va_end(args); +} + +void log_printf_err_exit(int status, log_level level, const char *format, ...) +{ + va_list args; + + va_start(args, format); + log_doit(level | log_strerror, format, args); + va_end(args); + + exit(status); +} + diff --git a/rooter/0optionalapps/udp-tunnel/src/log.h b/rooter/0optionalapps/udp-tunnel/src/log.h new file mode 100644 index 0000000..e42665d --- /dev/null +++ b/rooter/0optionalapps/udp-tunnel/src/log.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2018 Marco d'Itri + * + * Inspired by log.c from the cowdancer package by James Clarke. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __LOG_H__ +#define __LOG_H__ + +#include + +#include "utils.h" + +typedef enum log_level { + /* the value of the first 3 bits matches the syslog(3) levels */ + log_emerg = 0, + log_alert = 1, + log_crit = 2, + log_err = 3, + log_warning = 4, + log_notice = 5, + log_info = 6, + log_debug = 7, + log_nothing = 8, + + /* the following entries are bit flags to be OR'ed with the level */ + log_stderr = 0x10, + log_syslog = 0x20, + log_strerror = 0x40, +} log_level; + +/* remove the flags from log_level */ +#define LOG_LEVEL_MASK 0xf + +log_level log_get_filter_level(void); + +void log_set_options(log_level filter_level_new); + +__attribute__ ((format(printf, 2, 3))) +void log_printf(log_level level, const char *format, ...); + +__attribute__ ((format(printf, 3, 4), noreturn)) +void log_printf_exit(int status, log_level level, const char *format, ...); + +__attribute__ ((format(printf, 2, 3))) +void log_printf_err(log_level level, const char *format, ...); + +__attribute__ ((format(printf, 3, 4), noreturn)) +void log_printf_err_exit(int status, log_level level, const char *format, ...); + +#define err_sys(...) log_printf_err_exit(1, log_err, __VA_ARGS__) + +#endif /* !__LOG_H__ */ diff --git a/rooter/0optionalapps/udp-tunnel/src/network.c b/rooter/0optionalapps/udp-tunnel/src/network.c new file mode 100644 index 0000000..2c0f2c1 --- /dev/null +++ b/rooter/0optionalapps/udp-tunnel/src/network.c @@ -0,0 +1,401 @@ +/* + * Copyright (C) 2018 Marco d'Itri + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* for getaddrinfo... */ +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "network.h" +#include "utils.h" +#include "log.h" + +char *print_addr_port(const struct sockaddr *addr, socklen_t addrlen) +{ + static char buf[1100], address[1025], port[32]; + int err; + + err = getnameinfo(addr, addrlen, address, sizeof(address), + port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV); + if (err == EAI_SYSTEM) + err_sys("getnameinfo"); + else if (err) + log_printf_exit(1, log_err, "getnameinfo: %s", gai_strerror(err)); + + if (addr->sa_family == AF_INET6) + snprintf(buf, sizeof(buf) - 1, "[%s]:%s", address, port); + else + snprintf(buf, sizeof(buf) - 1, "%s:%s", address, port); + + return buf; +} + +static char *ai_print_addr_port(struct addrinfo *ai) +{ + return print_addr_port((struct sockaddr *) ai->ai_addr, ai->ai_addrlen); +} + +/* + * Try to parse anything that looks like: + * - an IPv4 or IPv6 address or a domain, with an optional port number + * - a port number + * + * address and/or port will be NULL if not found in the input. + * If address and port are not NULL then they must be freed by the caller. + */ +static void parse_address_port(const char *input, char **address, char **port) +{ + const char *p; + + *address = NULL; + *port = NULL; + + if (*input == '\0') { + return; + } else if (*input == '[' && (p = strchr(input, ']'))) { /* IPv6 */ + char *s; + int len = p - input - 1; + + *address = s = NOFAIL(malloc(len + 1)); + memcpy(s, input + 1, len); + *(s + len) = '\0'; + + p = strchr(p, ':'); + if (p && *(p + 1) != '\0') + *port = NOFAIL(strdup(p + 1)); /* IPv6 + port */ + } else if ((p = strchr(input, ':')) && /* IPv6, no port */ + strchr(p + 1, ':')) { /* and no brackets */ + *address = NOFAIL(strdup(input)); + } else if ((p = strchr(input, ':'))) { /* IPv4 + port */ + char *s; + int len = p - input; + + if (len) { + *address = s = NOFAIL(malloc(len + 1)); + memcpy(s, input, len); + *(s + len) = '\0'; + } + + p++; + if (*p != '\0') + *port = NOFAIL(strdup(p)); + } else { + for (p = input; *p; p++) + if (!isdigit(p[0])) + break; + if (*p) + *address = NOFAIL(strdup(input)); /* IPv4, no port */ + else + *port = NOFAIL(strdup(input)); /* just the port */ + } +} + +int udp_listener(const char *s) +{ + char *address, *port; + struct addrinfo hints, *res, *ai; + int err, fd; + + parse_address_port(s, &address, &port); + + if (!port) + log_printf_exit(2, log_err, "Missing port in '%s'!", s); + + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; + hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE | AI_IDN; + + err = getaddrinfo(address, port, &hints, &res); + if (err == EAI_SYSTEM) + err_sys("getaddrinfo(%s:%s)", address, port); + else if (err) + log_printf_exit(1, log_err, "Cannot resolve %s:%s: %s", + address, port, gai_strerror(err)); + + if (address) + free(address); + if (port) + free(port); + + for (ai = res; ai; ai = ai->ai_next) { + if ((fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol)) < 0) + continue; /* ignore */ + if (bind(fd, (struct sockaddr *) ai->ai_addr, ai->ai_addrlen) == 0) + break; /* success */ + close(fd); + } + + if (!ai) + err_sys("Cannot bind to %s", s); + + log_printf(log_info, "Listening for UDP connections on %s", + ai_print_addr_port(ai)); + + freeaddrinfo(res); + + return fd; +} + +int *tcp_listener(const char *s) +{ + char *address, *port; + struct addrinfo hints, *res, *ai; + int err, fd, opt; + int fd_num = 0; + int *fd_list = NULL; + size_t allocated_fds = 0; + + parse_address_port(s, &address, &port); + + if (!port) + log_printf_exit(2, log_err, "Missing port in '%s'!", s); + + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE | AI_IDN; + + err = getaddrinfo(address, port, &hints, &res); + if (err == EAI_SYSTEM) + err_sys("getaddrinfo(%s:%s)", address, port); + else if (err) + log_printf_exit(1, log_err, "Cannot resolve %s:%s: %s", + address, port, gai_strerror(err)); + + if (address) + free(address); + if (port) + free(port); + + /* add to fd_list all the sockets which match ai_flags */ + for (ai = res; ai; ai = ai->ai_next) { + if ((fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol)) < 0) + continue; /* ignore */ + opt = 1; + if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) + err_sys("setsockopt(SOL_SOCKET, SO_REUSEADDR)"); + if (bind(fd, (struct sockaddr *) ai->ai_addr, ai->ai_addrlen) < 0) + err_sys("Cannot bind to %s", s); + + /* success */ + if (listen(fd, 128) < 0) + err_sys("listen"); + + if (allocated_fds < fd_num + 1 + 1) { + allocated_fds += 8; + fd_list = realloc(fd_list, allocated_fds * sizeof(int)); + } + fd_list[fd_num++] = fd; + + log_printf(log_info, "Listening for TCP connections on %s", + ai_print_addr_port(ai)); + } + + /* and then add -1 as the list terminator */ + if (allocated_fds < fd_num + 1 + 1) + fd_list = realloc(fd_list, ++allocated_fds * sizeof(int)); + fd_list[fd_num] = -1; + + if (!fd_list) + err_sys("socket"); + + freeaddrinfo(res); + + return fd_list; +} + +/* + * Accept new connections and return after forking for each one. + */ +int accept_connections(int listening_sockets[]) +{ + while (1) { + int max = 0; + int i, fd; + fd_set readfds; + pid_t pid; + + FD_ZERO(&readfds); + for (i = 0; listening_sockets[i] != -1; i++) { + int flags; + + if ((flags = fcntl(listening_sockets[i], F_GETFL, 0)) < 0) + err_sys("fcntl(F_GETFL)"); + if (fcntl(listening_sockets[i], F_SETFL, flags | O_NONBLOCK) < 0) + err_sys("fcntl(F_SETFL, O_NONBLOCK)"); + + FD_SET(listening_sockets[i], &readfds); + SET_MAX(listening_sockets[i]); + } + + if (select(max, &readfds, NULL, NULL, NULL) < 0) { + if (errno == EINTR || errno == EAGAIN) + continue; + err_sys("select"); + } + + for (i = 0; listening_sockets[i] != -1; i++) { + int listen_sock; + struct sockaddr_storage client_addr; + socklen_t addrlen = sizeof(client_addr); + + if (!FD_ISSET(listening_sockets[i], &readfds)) + continue; + listen_sock = listening_sockets[i]; + + fd = accept(listen_sock, (struct sockaddr *) &client_addr, &addrlen); + if (fd < 0) { + if (errno == EAGAIN) + continue; + err_sys("accept"); + } + + log_printf(log_notice, "Received a TCP connection from %s", + print_addr_port((struct sockaddr *) &client_addr, addrlen)); + +#if 0 + /* do not fork, for testing */ + pid = 0; +#else + pid = fork(); +#endif + + if (pid < 0) + err_sys("fork"); + + if (pid > 0) { + close(fd); + } else { + for (i = 0; listening_sockets[i] != -1; i++) + close(listening_sockets[i]); + return fd; + } + } + } +} + +int udp_client(const char *s, struct sockaddr_storage *remote_udpaddr) +{ + char *address, *port; + struct addrinfo hints, *res, *ai; + int err, fd; + + parse_address_port(s, &address, &port); + + if (!address || !port) + log_printf_exit(2, log_err, "Missing address or port in '%s'!", s); + + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; + hints.ai_flags = AI_ADDRCONFIG | AI_IDN; + + err = getaddrinfo(address, port, &hints, &res); + if (err == EAI_SYSTEM) + err_sys("getaddrinfo(%s:%s)", address, port); + else if (err) + log_printf_exit(1, log_err, "Cannot resolve %s:%s: %s", + address, port, gai_strerror(err)); + + if (address) + free(address); + if (port) + free(port); + + /* continue with the first socket which matches ai_flags */ + for (ai = res; ai; ai = ai->ai_next) { + if ((fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol)) < 0) + continue; /* ignore */ + break; /* success */ + } + + if (!ai) + err_sys("socket"); + + log_printf(log_debug, "The UDP destination is %s", ai_print_addr_port(ai)); + + /* + * Return to the caller the resolved address, to be able to use it as the + * destination address of the next UDP packet. + */ + if (remote_udpaddr) + memcpy(remote_udpaddr, ai->ai_addr, ai->ai_addrlen); + + freeaddrinfo(res); + + return fd; +} + +int tcp_client(const char *s) +{ + char *address, *port; + struct addrinfo hints, *res, *ai; + int err, fd; + + parse_address_port(s, &address, &port); + + if (!address || !port) + log_printf_exit(2, log_err, "Missing address or port in '%s'!", s); + + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_ADDRCONFIG | AI_IDN; + + err = getaddrinfo(address, port, &hints, &res); + if (err == EAI_SYSTEM) + err_sys("getaddrinfo(%s:%s)", address, port); + else if (err) + log_printf_exit(1, log_err, "Cannot resolve %s:%s: %s", + address, port, gai_strerror(err)); + + if (address) + free(address); + if (port) + free(port); + + for (ai = res; ai; ai = ai->ai_next) { + if ((fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol)) < 0) + continue; /* ignore */ + if (connect(fd, (struct sockaddr *) ai->ai_addr, ai->ai_addrlen) == 0) + break; /* success */ + close(fd); + } + + if (!ai) + err_sys("Cannot connect to %s", s); + + log_printf(log_info, "TCP connection opened to %s", + ai_print_addr_port(ai)); + + freeaddrinfo(res); + + return fd; +} + diff --git a/rooter/0optionalapps/udp-tunnel/src/network.h b/rooter/0optionalapps/udp-tunnel/src/network.h new file mode 100644 index 0000000..2fafdc1 --- /dev/null +++ b/rooter/0optionalapps/udp-tunnel/src/network.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2018 Marco d'Itri + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __NETWORK_H__ +#define __NETWORK_H__ + +#define SET_MAX(fd) do { if (max < (fd) + 1) { max = (fd) + 1; } } while (0) + +char *print_addr_port(const struct sockaddr *addr, socklen_t addrlen); + +int udp_listener(const char *s); + +int *tcp_listener(const char *s); + +int udp_listener_sa(const int num); + +int *tcp_listener_sa(const int num); + +int udp_client(const char *s, struct sockaddr_storage *remote_udpaddr); + +int tcp_client(const char *s); + +int accept_connections(int listening_sockets[]); + +#endif diff --git a/rooter/0optionalapps/udp-tunnel/src/udptunnel.c b/rooter/0optionalapps/udp-tunnel/src/udptunnel.c new file mode 100644 index 0000000..8dd9c17 --- /dev/null +++ b/rooter/0optionalapps/udp-tunnel/src/udptunnel.c @@ -0,0 +1,523 @@ +/* + * Copyright (C) 2018 Marco d'Itri + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * + * Parts of this program are derived from udptunnel.c by Jonathan Lennox. + * This is the license of the original code: + * + * Copyright 1999, 2001 by Columbia University. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS + * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* for sigaction... */ +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_SYSTEMD_SD_DAEMON_H +#include +#endif + +#include "utils.h" +#include "log.h" +#include "network.h" + +#ifdef HAVE_GETOPT_LONG +#include +#endif + +#define TCPBUFFERSIZE 65536 +#define UDPBUFFERSIZE (TCPBUFFERSIZE - 2) /* TCP packet - length */ + +struct out_packet { + uint16_t length; + char buf[UDPBUFFERSIZE]; +}; + +struct opts { + const char *udpaddr, *tcpaddr; + + int is_server; + int use_inetd; + char *handshake; + int timeout; +}; + +struct relay { + struct sockaddr_storage remote_udpaddr; + + int udp_sock, tcp_sock; + + int expect_handshake; + char handshake[32]; + int udp_timeout, tcp_timeout; + char buf[TCPBUFFERSIZE]; + char *buf_ptr, *packet_start; + int packet_length; + enum { + uninitialized = 0, + reading_handshake, + reading_length, + reading_packet, + } state; +}; + +static void usage(int status) +{ + FILE *fp = status == 0 ? stdout : stderr; + + fprintf(fp, "Usage: udptunnel [OPTION]... [[SOURCE:]PORT] DESTINATION:PORT\n\n"); + fprintf(fp, "-s --server listen for TCP connections\n"); + fprintf(fp, "-i --inetd expect to be started by inetd\n"); + fprintf(fp, "-T N --timeout N close the source connection after N seconds\n"); + fprintf(fp, " where no data was received\n"); + fprintf(fp, "-S --syslog log to syslog instead of standard error\n"); + fprintf(fp, "-v --verbose explain what is being done\n"); + fprintf(fp, "-h --help display this help and exit\n"); + fprintf(fp, "\nSOURCE:PORT must not be specified when using inetd or socket activation.\n\n"); + fprintf(fp, "If the -s option is used then the program will listen on SOURCE:PORT for TCP\n"); + fprintf(fp, "connections and relay the encapsulated packets with UDP to DESTINATION:PORT.\n"); + fprintf(fp, "Otherwise it will listen on SOURCE:PORT for UDP packets and encapsulate\n"); + fprintf(fp, "them in a TCP connection to DESTINATION:PORT.\n"); + + exit(status); +} + +static void parse_args(int argc, char *argv[], struct opts *opts) +{ +#ifdef HAVE_GETOPT_LONG + const struct option longopts[] = { + {"inetd", no_argument, NULL, 'i' }, + {"server", no_argument, NULL, 's' }, + {"syslog", no_argument, NULL, 'S' }, + {"timeout", required_argument, NULL, 'T' }, + {"help", no_argument, NULL, 'h' }, + {"verbose", no_argument, NULL, 'v' }, + {NULL, 0, NULL, 0 }, + }; + int longindex; +#endif + int c; + int expected_args; + int verbose = 0; + int use_syslog = 0; + + /* defaults */ + opts->handshake = NOFAIL(malloc(32)); + memcpy(opts->handshake, "udptunnel by md.\0\0\0\x01\x03\x06\x10\x15\x21\x28\x36\x45\x55\x66\x78\x91", 32); + + while ((c = GETOPT_LONGISH(argc, argv, "ihsvST:", + longopts, &longindex)) > 0) { + switch (c) { + case 'i': + opts->use_inetd = 1; + break; + case 's': + opts->is_server = 1; + break; + case 'S': + use_syslog = 1; + break; + case 'T': + opts->timeout = atol(optarg); + break; + case 'v': + verbose++; + break; + case 'h': + usage(0); + break; + default: + usage(2); + break; + } + } + + /* + * Look for 2 command line arguments (source and destination) + * if used in standalone mode or only 1 argument (destination) + * if used in inetd or socket activated modes. + */ + expected_args = (sd_listen_fds(0) || opts->use_inetd) ? 1 : 2; + + if (argc - optind == 0) + usage(2); + if (argc - optind != expected_args) { + fprintf(stderr, "Expected %d argument(s)!\n\n", expected_args); + usage(2); + } + + /* the source and destination addresses */ + if (opts->is_server) { + if (expected_args == 2) + opts->tcpaddr = NOFAIL(strdup(argv[optind++])); + opts->udpaddr = NOFAIL(strdup(argv[optind++])); + } else { + if (expected_args == 2) + opts->udpaddr = NOFAIL(strdup(argv[optind++])); + opts->tcpaddr = NOFAIL(strdup(argv[optind++])); + } + + if (!verbose) + log_set_options(log_warning); + else if (verbose == 1) + log_set_options(log_notice); + else if (verbose == 2) + log_set_options(log_info); + else + log_set_options(log_debug); + + if (use_syslog) + log_set_options(log_get_filter_level() | log_syslog); +} + +int udp_listener_sa(const int num) +{ + int fd = SD_LISTEN_FDS_START; + + if (num != 1) + log_printf_exit(2, log_err, + "UDP socket activation supports a single socket."); + + if (sd_is_socket(fd, AF_UNSPEC, SOCK_DGRAM, -1) <= 0) + log_printf_exit(2, log_err, + "UDP socket activation fd %d is not valid.", fd); + + return fd; +} + +int *tcp_listener_sa(const int num) +{ + int fd; + int *fds; + int fd_num = 0; + + fds = NOFAIL(malloc((num + 1) * sizeof(int))); + + for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + num; fd++) { + if (sd_is_socket(fd, AF_UNSPEC, SOCK_STREAM, 1) <= 0) + log_printf_exit(2, log_err, + "TCP socket activation fd %d is not valid.", fd); + fds[fd_num++] = fd; + } + + fds[fd_num] = -1; + + return fds; +} + +static void udp_to_tcp(struct relay *relay) +{ + struct out_packet p; + int buflen; + struct sockaddr_storage remote_udpaddr; + socklen_t addrlen = sizeof(remote_udpaddr); + + buflen = recvfrom(relay->udp_sock, p.buf, UDPBUFFERSIZE, 0, + (struct sockaddr *) &remote_udpaddr, &addrlen); + if (buflen < 0) + err_sys("recvfrom(udp)"); + if (buflen == 0) + return; /* ignore empty packets */ + + /* + * Store the source address of the received UDP packet, to be able to use + * it in send_udp_packet as the destination address of the next UDP reply. + */ + memcpy(&(relay->remote_udpaddr), &remote_udpaddr, addrlen); + +#ifdef DEBUG + log_printf(log_debug, "Received a %d bytes UDP packet from %s", buflen, + print_addr_port((struct sockaddr *) &remote_udpaddr, addrlen)); +#endif + + p.length = htons(buflen); + if (send(relay->tcp_sock, &p, buflen + sizeof(p.length), 0) < 0) + err_sys("send(tcp)"); +} + +static void send_udp_packet(struct relay *relay) +{ + int opt = 0; + socklen_t len = sizeof(opt); + + if (relay->remote_udpaddr.ss_family == 0) { + log_printf(log_info, + "Ignoring a packet for a still unknown UDP destination!"); + return; + } + + if (sendto(relay->udp_sock, relay->packet_start, relay->packet_length, 0, + (struct sockaddr *) &relay->remote_udpaddr, + sizeof(relay->remote_udpaddr)) >= 0) + return; + + /* this is the error path */ + if (errno != ECONNREFUSED) + err_sys("sendto(udp)"); + + /* clear the error if there is no UDP listener yet on the other end */ + log_printf(log_info, "sendto(udp) returned ECONNREFUSED: ignored"); + if (getsockopt(relay->udp_sock, SOL_SOCKET, SO_ERROR, &opt, &len) < 0) + err_sys("getsockopt(udp, SOL_SOCKET, SO_ERROR)"); + + return; +} + +static void tcp_to_udp(struct relay *relay) +{ + int read_len; + + if (relay->state == uninitialized) { + if (relay->expect_handshake) { + relay->state = reading_handshake; + relay->packet_length = sizeof(relay->handshake); + } else { + relay->state = reading_length; + relay->packet_length = sizeof(uint16_t); + } + relay->buf_ptr = relay->buf; + relay->packet_start = relay->buf; + } + + read_len = read(relay->tcp_sock, relay->buf_ptr, + (relay->buf + TCPBUFFERSIZE - relay->buf_ptr)); + if (read_len < 0) + err_sys("read(tcp)"); + + if (read_len == 0) + log_printf_exit(0, log_notice, "Remote closed the connection"); + + relay->buf_ptr += read_len; + + while (relay->buf_ptr - relay->packet_start >= relay->packet_length) { + if (relay->state == reading_handshake) { + /* check the handshake string */ + if (memcmp(relay->packet_start, &(relay->handshake), + sizeof(relay->handshake)) != 0) + log_printf_exit(0, log_info, + "Received a bad handshake, exiting"); + log_printf(log_debug, "Received a good handshake"); + relay->packet_start += sizeof(relay->handshake); + relay->state = reading_length; + relay->packet_length = sizeof(uint16_t); + } else if (relay->state == reading_length) { + /* read the lenght of the next packet */ + relay->packet_length = ntohs(*(uint16_t *) relay->packet_start); + relay->packet_start += sizeof(uint16_t); + relay->state = reading_packet; + } else if (relay->state == reading_packet) { + /* read an encapsulated packet and send it as UDP */ +#ifdef DEBUG + log_printf(log_debug, "Received a %u bytes TCP packet", + relay->packet_length); +#endif + + send_udp_packet(relay); + + memmove(relay->buf, relay->packet_start + relay->packet_length, + relay->buf_ptr - + (relay->packet_start + relay->packet_length)); + relay->buf_ptr -= + relay->packet_length + (relay->packet_start - relay->buf); + relay->packet_start = relay->buf; + relay->state = reading_length; + relay->packet_length = sizeof(uint16_t); + } + } +} + +static void send_handshake(struct relay *relay) +{ + if (sendto(relay->tcp_sock, relay->handshake, sizeof(relay->handshake), 0, + (struct sockaddr *) &relay->remote_udpaddr, + sizeof(relay->remote_udpaddr)) < 0) + err_sys("sendto(tcp, handshake)"); +} + +static void wait_for_child(int sig) +{ + while (waitpid(-1, NULL, WNOHANG) > 0); +} + +static void main_loop(struct relay *relay) +{ + time_t last_udp_input, last_tcp_input; + + last_udp_input = relay->udp_timeout ? time(NULL) : 0; + last_tcp_input = relay->tcp_timeout ? time(NULL) : 0; + + while (1) { + int ready_fds; + int max = 0; + fd_set readfds; + struct timeval tv, *ptv; + + FD_ZERO(&readfds); + FD_SET(relay->tcp_sock, &readfds); + SET_MAX(relay->tcp_sock); + FD_SET(relay->udp_sock, &readfds); + SET_MAX(relay->udp_sock); + + /* + * If a data timeout was configured then set a 10s timeout for + * select. + */ + if (last_udp_input || last_tcp_input) { + tv.tv_usec = 0; + tv.tv_sec = 10; + ptv = &tv; + } else { + ptv = NULL; + } + + ready_fds = select(max, &readfds, NULL, NULL, ptv); + if (ready_fds < 0) { + if (errno == EINTR || errno == EAGAIN) + continue; + err_sys("select"); + } + + /* check the timeout if one was configured and select(2) timed out */ + if (last_udp_input && !ready_fds) { /* timeout */ + if (time(NULL) - last_udp_input > relay->udp_timeout) + log_printf_exit(0, log_notice, + "Exiting after a %ds timeout for UDP input", + relay->udp_timeout); + } + if (last_tcp_input && !ready_fds) { /* timeout */ + if (time(NULL) - last_tcp_input > relay->tcp_timeout) + log_printf_exit(0, log_notice, + "Exiting after a %ds timeout for TCP input", + relay->tcp_timeout); + } + + if (FD_ISSET(relay->tcp_sock, &readfds)) { + tcp_to_udp(relay); + if (last_tcp_input) + last_tcp_input = time(NULL); + } + if (FD_ISSET(relay->udp_sock, &readfds)) { + udp_to_tcp(relay); + if (last_udp_input) + last_udp_input = time(NULL); + } + } +} + +int main(int argc, char *argv[]) +{ + struct opts opts; + struct relay relay; + + memset(&relay, 0, sizeof(relay)); + relay.tcp_sock = -1; + + memset(&opts, 0, sizeof(opts)); + parse_args(argc, argv, &opts); + if (opts.handshake) + memcpy(relay.handshake, opts.handshake, sizeof(relay.handshake)); + + sd_notify(0, "READY=1"); + + if (opts.is_server) { + struct sigaction sa; + + sa.sa_handler = wait_for_child; + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_RESTART; + if (sigaction(SIGCHLD, &sa, NULL) == -1) + err_sys("sigaction"); + + if (opts.timeout) + relay.tcp_timeout = opts.timeout; + relay.expect_handshake = 1; + + if (opts.use_inetd) { + relay.tcp_sock = 0; + log_set_options(log_get_filter_level() | log_syslog); + } else { + int socket_activation_fds = sd_listen_fds(0); + int *listening_sockets; + + if (socket_activation_fds) + listening_sockets = tcp_listener_sa(socket_activation_fds); + else + listening_sockets = tcp_listener(opts.tcpaddr); + relay.tcp_sock = accept_connections(listening_sockets); + } + relay.udp_sock = udp_client(opts.udpaddr, &relay.remote_udpaddr); + } else { + if (opts.timeout) + relay.udp_timeout = opts.timeout; + + if (opts.use_inetd) { + relay.udp_sock = 0; + log_set_options(log_get_filter_level() | log_syslog); + } else { + int socket_activation_fds = sd_listen_fds(0); + + if (socket_activation_fds) + relay.udp_sock = udp_listener_sa(socket_activation_fds); + else + relay.udp_sock = udp_listener(opts.udpaddr); + } + relay.tcp_sock = tcp_client(opts.tcpaddr); + + send_handshake(&relay); + } + + main_loop(&relay); + exit(0); +} + diff --git a/rooter/0optionalapps/udp-tunnel/src/utils.c b/rooter/0optionalapps/udp-tunnel/src/utils.c new file mode 100644 index 0000000..088ffe8 --- /dev/null +++ b/rooter/0optionalapps/udp-tunnel/src/utils.c @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2018 Marco d'Itri + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +#include "utils.h" + +void *do_nofail(void *ptr, const char *file, const int line) +{ + if (ptr) + return ptr; + + fprintf(stderr, "Memory allocation failure at %s:%d.", file, line); + exit(1); +} + diff --git a/rooter/0optionalapps/udp-tunnel/src/utils.h b/rooter/0optionalapps/udp-tunnel/src/utils.h new file mode 100644 index 0000000..be91197 --- /dev/null +++ b/rooter/0optionalapps/udp-tunnel/src/utils.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2018 Marco d'Itri + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __UTILS_H__ +#define __UTILS_H__ + +#if !defined __GNUC__ && !defined __attribute__ +#define __attribute__(x) /*NOTHING*/ +#endif + +#ifndef AI_IDN +#define AI_IDN 0 +#endif + +#ifndef AI_ADDRCONFIG +#define AI_ADDRCONFIG 0 +#endif + +#ifndef SD_LISTEN_FDS_START +#define SD_LISTEN_FDS_START 0 +#define sd_listen_fds(a) 0 +#define sd_notify(a, b) +#define sd_is_socket(a, b, c, d) -1 +#endif + +#if defined __GLIBC__ || (defined __APPLE__ && defined __MACH__) +#define HAVE_GETOPT_LONG +#endif + +#ifdef HAVE_GETOPT_LONG +#define GETOPT_LONGISH(c, v, o, l, i) getopt_long(c, v, o, l, i) +#else +#define GETOPT_LONGISH(c, v, o, l, i) getopt(c, v, o) +#endif + +#define NOFAIL(ptr) do_nofail((ptr), __FILE__, __LINE__) + +void *do_nofail(void *ptr, const char *file, const int line); + +#endif diff --git a/rooter/0optionalapps/webconsole/Makefile b/rooter/0optionalapps/webconsole/Makefile new file mode 100644 index 0000000..eb8cc4b --- /dev/null +++ b/rooter/0optionalapps/webconsole/Makefile @@ -0,0 +1,35 @@ +#Owned by DairyMan@Whirlpool +# +#Copyright GNU act. +include $(TOPDIR)/rules.mk + +PKG_NAME:=webconsole +PKG_VERSION:=1.000 +PKG_RELEASE:=1 + +PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool +include $(INCLUDE_DIR)/package.mk + +define Package/webconsole + SECTION:=utils + CATEGORY:=ROOter + SUBMENU:=Optional Applications + TITLE:=Install scripts for Web Console + PKGARCH:=all +endef + +define Package/webconsole/description + Helper scripts to install scripts for Web Console +endef + + +define Build/Compile +endef + +define Package/webconsole/install + $(CP) ./files/* $(1)/ + + +endef + +$(eval $(call BuildPackage,webconsole)) diff --git a/rooter/0optionalapps/webconsole/files/usr/lib/lua/luci/controller/webconsole.lua b/rooter/0optionalapps/webconsole/files/usr/lib/lua/luci/controller/webconsole.lua new file mode 100644 index 0000000..d65745a --- /dev/null +++ b/rooter/0optionalapps/webconsole/files/usr/lib/lua/luci/controller/webconsole.lua @@ -0,0 +1,31 @@ +-- A simple web console in case you don't have access to the shell +-- +-- Hua Shao + +module("luci.controller.webconsole", package.seeall) +local http = require("luci.http") + +I18N = require "luci.i18n" +translate = I18N.translate + +function index() + 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 + entry({"admin", "system", "console"}, template("web/web_console"), _(translate("Web Console")), 66) + end + entry({"admin", "system", "webcmd"}, call("action_webcmd")) +end + +function action_webcmd() + local cmd = http.formvalue("cmd") + if cmd then + local fp = io.popen(tostring(cmd).." 2>&1") + local result = fp:read("*a") + fp:close() + result = result:gsub("<", "<") + http.write(tostring(result)) + else + http.write_json(http.formvalue()) + end +end diff --git a/rooter/0optionalapps/webconsole/files/usr/lib/lua/luci/view/web/web_console.htm b/rooter/0optionalapps/webconsole/files/usr/lib/lua/luci/view/web/web_console.htm new file mode 100644 index 0000000..682dcad --- /dev/null +++ b/rooter/0optionalapps/webconsole/files/usr/lib/lua/luci/view/web/web_console.htm @@ -0,0 +1,51 @@ +<%+header%> + +

                          <%:Web Console%>

                          +
                          +
                          + <%:Execute shell commands or scripts as root.%><%:Be Careful%>. +

                          <%:Press%> Enter <%:to execute. Press%> Shift+Enter <%:to start a new line.%>

                          +

                          +

                          + + + + + + + +

                          
                          +    
                          +
                          + + + +<%+footer%> + diff --git a/rooter/0protocols/luci-proto-3x/Makefile b/rooter/0protocols/luci-proto-3x/Makefile new file mode 100644 index 0000000..ee45aba --- /dev/null +++ b/rooter/0protocols/luci-proto-3x/Makefile @@ -0,0 +1,53 @@ +# +# Copyright (C) 2007-2013 OpenWrt.org +# Copyright (C) 2010 Vertical Communications +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=luci-proto-3x +PKG_VERSION:=1.0 +PKG_RELEASE:=1 +PKG_MAINTAINER:=Dairyman +PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)-$(PKG_RELEASE) + +include $(INCLUDE_DIR)/package.mk + +define Package/luci-proto-3x/Default + VERSION:=$(PKG_VERSION)-$(PKG_RELEASE) + URL:=http://openwrt.org/ + MAINTAINER:=Dairyman +endef + +define Package/luci-proto-3x +$(call Package/luci-proto-3x/Default) + SECTION:=net + CATEGORY:=ROOter + SUBMENU:=Protocols + TITLE:=Support for 3x +endef + +define Package/luci-proto-3x/description + This package contains LuCI support for 3x +endef + +define Build/Prepare + mkdir -p $(PKG_BUILD_DIR) +endef + +define Build/Configure +endef + +define Build/Compile/Default +endef + +Build/Compile = $(Build/Compile/Default) + +define Package/luci-proto-3x/install + $(CP) ./files/* $(1)/ +endef + +$(eval $(call BuildPackage,luci-proto-3x)) diff --git a/rooter/0protocols/luci-proto-3x/files/usr/lib/lua/luci/model/cbi/admin_network/proto_3x.lua b/rooter/0protocols/luci-proto-3x/files/usr/lib/lua/luci/model/cbi/admin_network/proto_3x.lua new file mode 100644 index 0000000..59bf2f6 --- /dev/null +++ b/rooter/0protocols/luci-proto-3x/files/usr/lib/lua/luci/model/cbi/admin_network/proto_3x.lua @@ -0,0 +1,146 @@ +-- Copyright 2011 Jo-Philipp Wich +-- Licensed to the public under the Apache License 2.0. + +local map, section, net = ... + +local device, apn, service, pincode, username, password, dialnumber +local ipv6, maxwait, defaultroute, metric, peerdns, dns, + keepalive_failure, keepalive_interval, demand + + +device = section:taboption("general", Value, "device", translate("Modem device")) +device.rmempty = false + +local device_suggestions = nixio.fs.glob("/dev/tty[A-Z]*") + or nixio.fs.glob("/dev/tts/*") + +if device_suggestions then + local node + for node in device_suggestions do + device:value(node) + end +end + + +service = section:taboption("general", Value, "service", translate("Service Type")) +service:value("", translate("-- Please choose --")) +service:value("umts", "UMTS/GPRS") +service:value("umts_only", translate("UMTS only")) +service:value("gprs_only", translate("GPRS only")) +service:value("evdo", "CDMA/EV-DO") + + +apn = section:taboption("general", Value, "apn", translate("APN")) + + +pincode = section:taboption("general", Value, "pincode", translate("PIN")) + + +username = section:taboption("general", Value, "username", translate("PAP/CHAP username")) + + +password = section:taboption("general", Value, "password", translate("PAP/CHAP password")) +password.password = true + +dialnumber = section:taboption("general", Value, "dialnumber", translate("Dial number")) +dialnumber.placeholder = "*99***1#" + +if luci.model.network:has_ipv6() then + + ipv6 = section:taboption("advanced", Flag, "ipv6", + translate("Enable IPv6 negotiation on the PPP link")) + + ipv6.default = ipv6.disabled + +end + + +maxwait = section:taboption("advanced", Value, "maxwait", + translate("Modem init timeout"), + translate("Maximum amount of seconds to wait for the modem to become ready")) + +maxwait.placeholder = "20" +maxwait.datatype = "min(1)" + + +defaultroute = section:taboption("advanced", Flag, "defaultroute", + translate("Use default gateway"), + translate("If unchecked, no default route is configured")) + +defaultroute.default = defaultroute.enabled + + +metric = section:taboption("advanced", Value, "metric", + translate("Use gateway metric")) + +metric.placeholder = "0" +metric.datatype = "uinteger" +metric:depends("defaultroute", defaultroute.enabled) + + +peerdns = section:taboption("advanced", Flag, "peerdns", + translate("Use DNS servers advertised by peer"), + translate("If unchecked, the advertised DNS server addresses are ignored")) + +peerdns.default = peerdns.enabled + + +dns = section:taboption("advanced", DynamicList, "dns", + translate("Use custom DNS servers")) + +dns:depends("peerdns", "") +dns.datatype = "ipaddr" +dns.cast = "string" + + +keepalive_failure = section:taboption("advanced", Value, "_keepalive_failure", + translate("LCP echo failure threshold"), + translate("Presume peer to be dead after given amount of LCP echo failures, use 0 to ignore failures")) + +function keepalive_failure.cfgvalue(self, section) + local v = m:get(section, "keepalive") + if v and #v > 0 then + return tonumber(v:match("^(%d+)[ ,]+%d+") or v) + end +end + +function keepalive_failure.write() end +function keepalive_failure.remove() end + +keepalive_failure.placeholder = "0" +keepalive_failure.datatype = "uinteger" + + +keepalive_interval = section:taboption("advanced", Value, "_keepalive_interval", + translate("LCP echo interval"), + translate("Send LCP echo requests at the given interval in seconds, only effective in conjunction with failure threshold")) + +function keepalive_interval.cfgvalue(self, section) + local v = m:get(section, "keepalive") + if v and #v > 0 then + return tonumber(v:match("^%d+[ ,]+(%d+)")) + end +end + +function keepalive_interval.write(self, section, value) + local f = tonumber(keepalive_failure:formvalue(section)) or 0 + local i = tonumber(value) or 5 + if i < 1 then i = 1 end + if f > 0 then + m:set(section, "keepalive", "%d %d" %{ f, i }) + else + m:del(section, "keepalive") + end +end + +keepalive_interval.remove = keepalive_interval.write +keepalive_interval.placeholder = "5" +keepalive_interval.datatype = "min(1)" + + +demand = section:taboption("advanced", Value, "demand", + translate("Inactivity timeout"), + translate("Close inactive connection after the given amount of seconds, use 0 to persist connection")) + +demand.placeholder = "0" +demand.datatype = "uinteger" diff --git a/rooter/0protocols/luci-proto-3x/files/usr/lib/lua/luci/model/network/proto_3x.lua b/rooter/0protocols/luci-proto-3x/files/usr/lib/lua/luci/model/network/proto_3x.lua new file mode 100644 index 0000000..e2ff6b9 --- /dev/null +++ b/rooter/0protocols/luci-proto-3x/files/usr/lib/lua/luci/model/network/proto_3x.lua @@ -0,0 +1,49 @@ +-- Copyright 2018 Florian Eckert +-- Licensed to the public under the Apache License 2.0. + +local netmod = luci.model.network +local interface = luci.model.network.interface + +local proto = netmod:register_protocol("3x") + +function proto.get_i18n(self) + return luci.i18n.translate("UMTS/GPRS/EV-DO") +end + +function proto.ifname(self) + return "3x-" .. self.sid +end + +function proto.get_interface(self) + return interface(self:ifname(), self) +end + +function proto.is_installed(self) + return nixio.fs.access("/lib/netifd/proto/3x.sh") +end + +function proto.opkg_package(self) + return "comgt" +end + +function proto.is_floating(self) + return true +end + +function proto.is_virtual(self) + return true +end + +function proto.get_interfaces(self) + return nil +end + +function proto.contains_interface(self, ifc) + if self:is_floating() then + return (netmod:ifnameof(ifc) == self:ifname()) + else + return netmod.protocol.contains_interface(self, ifc) + end +end + +netmod:register_pattern_virtual("^3x%-%w") diff --git a/rooter/0protocols/luci-proto-3x/files/www/luci-static/resources/protocol/3x.js b/rooter/0protocols/luci-proto-3x/files/www/luci-static/resources/protocol/3x.js new file mode 100644 index 0000000..a1c213b --- /dev/null +++ b/rooter/0protocols/luci-proto-3x/files/www/luci-static/resources/protocol/3x.js @@ -0,0 +1,11 @@ +'use strict';'require rpc';'require uci';'require form';'require network';var callFileList=rpc.declare({object:'file',method:'list',params:['path'],expect:{entries:[]},filter:function(list,params){var rv=[];for(var i=0;i0) +uci.set('network',section_id,'keepalive','%d %d'.format(f,i));else +uci.unset('network',section_id,'keepalive');} +return network.registerProtocol('3x',{getI18n:function(){return _('UMTS/GPRS/EV-DO');},getIfname:function(){return this._ubus('l3_device')||'3x-%s'.format(this.sid);},getOpkgPackage:function(){return'comgt';},isFloating:function(){return true;},isVirtual:function(){return true;},getDevices:function(){return null;},containsDevice:function(ifname){return(network.getIfnameOf(ifname)==this.getIfname());},renderFormOptions:function(s){var o;o=s.taboption('general',form.Value,'device',_('Modem device'));o.rmempty=false;o.load=function(section_id){return callFileList('/dev/').then(L.bind(function(devices){for(var i=0;i +-- Licensed to the public under the Apache License 2.0. + +local map, section, net = ... + +local device, apn, pincode, username, password +local auth, ipv6 + + +device = section:taboption("general", Value, "device", translate("Modem device")) +device.rmempty = false + +local device_suggestions = nixio.fs.glob("/dev/cdc-wdm*") + +if device_suggestions then + local node + for node in device_suggestions do + device:value(node) + end +end + + +apn = section:taboption("general", Value, "apn", translate("APN")) + + +pincode = section:taboption("general", Value, "pincode", translate("PIN")) + + +username = section:taboption("general", Value, "username", translate("PAP/CHAP username")) + + +password = section:taboption("general", Value, "password", translate("PAP/CHAP password")) +password.password = true + +auth = section:taboption("general", Value, "auth", translate("Authentication Type")) +auth:value("", translate("-- Please choose --")) +auth:value("both", "PAP/CHAP (both)") +auth:value("pap", "PAP") +auth:value("chap", "CHAP") +auth:value("none", "NONE") + +if luci.model.network:has_ipv6() then + ipv6 = section:taboption("advanced", Flag, "ipv6", translate("Enable IPv6 negotiation")) + ipv6.default = ipv6.disabled +end \ No newline at end of file diff --git a/rooter/0protocols/luci-proto-mbim/files/usr/lib/lua/luci/model/network/proto_mbim.lua b/rooter/0protocols/luci-proto-mbim/files/usr/lib/lua/luci/model/network/proto_mbim.lua new file mode 100644 index 0000000..3007480 --- /dev/null +++ b/rooter/0protocols/luci-proto-mbim/files/usr/lib/lua/luci/model/network/proto_mbim.lua @@ -0,0 +1,55 @@ +-- Copyright 2016 David Thornley +-- Licensed to the public under the Apache License 2.0. + +local netmod = luci.model.network +local interface = luci.model.network.interface +local proto = netmod:register_protocol("mbim") + +function proto.get_i18n(self) + return luci.i18n.translate("MBIM Cellular") +end + +function proto.ifname(self) + local base = netmod._M.protocol + local ifname = base.ifname(self) -- call base class "protocol.ifname(self)" + + -- Note: ifname might be nil if the adapter could not be determined through ubus (default name to mbim-wan in this case) + if ifname == nil then + ifname = "mbim-" .. self.sid + end + return ifname +end + +function proto.get_interface(self) + return interface(self:ifname(), self) +end + +function proto.opkg_package(self) + return "rmbim" +end + +function proto.is_installed(self) + return nixio.fs.access("/lib/netifd/proto/mbim.sh") +end + +function proto.is_floating(self) + return true +end + +function proto.is_virtual(self) + return true +end + +function proto.get_interfaces(self) + return nil +end + +function proto.contains_interface(self, ifc) + return (netmod:ifnameof(ifc) == self:ifname()) +end + +netmod:register_pattern_virtual("^mbim%-%w") + +netmod:register_error_code("CALL_FAILED", luci.i18n.translate("Call failed")) +netmod:register_error_code("NO_CID", luci.i18n.translate("Unable to obtain client ID")) +netmod:register_error_code("PLMN_FAILED", luci.i18n.translate("Setting PLMN failed")) diff --git a/rooter/0protocols/luci-proto-mbim/files/www/luci-static/resources/protocol/mbim.js b/rooter/0protocols/luci-proto-mbim/files/www/luci-static/resources/protocol/mbim.js new file mode 100644 index 0000000..337cdd3 --- /dev/null +++ b/rooter/0protocols/luci-proto-mbim/files/www/luci-static/resources/protocol/mbim.js @@ -0,0 +1,107 @@ +'use strict'; +'require rpc'; +'require form'; +'require network'; + +var callFileList = rpc.declare({ + object: 'file', + method: 'list', + params: [ 'path' ], + expect: { entries: [] }, + filter: function(list, params) { + var rv = []; + for (var i = 0; i < list.length; i++) + if (list[i].name.match(/^cdc-wdm/)) + rv.push(params.path + list[i].name); + return rv.sort(); + } +}); + +network.registerPatternVirtual(/^mbim-.+$/); +network.registerErrorCode('CALL_FAILED', _('Call failed')); +network.registerErrorCode('NO_CID', _('Unable to obtain client ID')); +network.registerErrorCode('PLMN_FAILED', _('Setting PLMN failed')); + +return network.registerProtocol('mbim', { + getI18n: function() { + return _('MBIM Cellular'); + }, + + getIfname: function() { + return this._ubus('l3_device') || 'mbim-%s'.format(this.sid); + }, + + getOpkgPackage: function() { + return 'rmbim'; + }, + + isFloating: function() { + return true; + }, + + isVirtual: function() { + return true; + }, + + getDevices: function() { + return null; + }, + + containsDevice: function(ifname) { + return (network.getIfnameOf(ifname) == this.getIfname()); + }, + + renderFormOptions: function(s) { + var dev = this.getL3Device() || this.getDevice(), o; + + o = s.taboption('general', form.Value, 'device', _('Modem device')); + o.rmempty = false; + o.load = function(section_id) { + return callFileList('/dev/').then(L.bind(function(devices) { + for (var i = 0; i < devices.length; i++) + this.value(devices[i]); + return form.Value.prototype.load.apply(this, [section_id]); + }, this)); + }; + + s.taboption('general', form.Value, 'apn', _('APN')); + s.taboption('general', form.Value, 'pincode', _('PIN')); + + o = s.taboption('general', form.ListValue, 'auth', _('Authentication Type')); + o.value('both', 'PAP/CHAP'); + o.value('pap', 'PAP'); + o.value('chap', 'CHAP'); + o.value('none', 'NONE'); + o.default = 'none'; + + o = s.taboption('general', form.Value, 'username', _('PAP/CHAP username')); + o.depends('auth', 'pap'); + o.depends('auth', 'chap'); + o.depends('auth', 'both'); + + o = s.taboption('general', form.Value, 'password', _('PAP/CHAP password')); + o.depends('auth', 'pap'); + o.depends('auth', 'chap'); + o.depends('auth', 'both'); + o.password = true; + + if (L.hasSystemFeature('ipv6')) { + o = s.taboption('advanced', form.Flag, 'ipv6', _('Enable IPv6 negotiation')); + o.default = o.disabled; + } + + o = s.taboption('advanced', form.Value, 'delay', _('Modem init timeout'), _('Maximum amount of seconds to wait for the modem to become ready')); + o.placeholder = '10'; + o.datatype = 'min(1)'; + + o = s.taboption('advanced', form.Value, 'mtu', _('Override MTU')); + o.placeholder = dev ? (dev.getMTU() || '1500') : '1500'; + o.datatype = 'max(9200)'; + + o = s.taboption('general', form.ListValue, 'pdptype', _('PDP Type')); + o.value('ipv4v6', 'IPv4/IPv6'); + o.value('ipv4', 'IPv4'); + o.value('ipv6', 'IPv6'); + o.default = 'ipv4v6'; + } +}); diff --git a/rooter/0routerspecfic/alix2d13/Makefile b/rooter/0routerspecfic/alix2d13/Makefile new file mode 100644 index 0000000..baa4245 --- /dev/null +++ b/rooter/0routerspecfic/alix2d13/Makefile @@ -0,0 +1,35 @@ +#Owned by DairyMan@Whirlpool +# +#Copyright GNU act. +include $(TOPDIR)/rules.mk + +PKG_NAME:=alix2d13 +PKG_VERSION:=1.000 +PKG_RELEASE:=1 + +PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool +include $(INCLUDE_DIR)/package.mk + +define Package/alix2d13 + SECTION:=utils + CATEGORY:=ROOter + SUBMENU:=Router Specific + TITLE:=Install scripts for alix2d13 + PKGARCH:=all +endef + +define Package/alix2d13/description + Helper scripts to install scripts for alix2d13 +endef + + +define Build/Compile +endef + +define Package/alix2d13/install + $(CP) ./files/* $(1)/ + + +endef + +$(eval $(call BuildPackage,alix2d13)) diff --git a/rooter/0routerspecfic/alix2d13/files/usr/lib/rooter/special.sh b/rooter/0routerspecfic/alix2d13/files/usr/lib/rooter/special.sh new file mode 100644 index 0000000..3c46608 --- /dev/null +++ b/rooter/0routerspecfic/alix2d13/files/usr/lib/rooter/special.sh @@ -0,0 +1,7 @@ +#!/bin/sh +. /lib/functions.sh + +mkdir /tmp/sysinfo +echo -n "PC Engines Alix.2D" > /tmp/sysinfo/model + +echo 'SDA="'"sda"'"' > /etc/sda_drop \ No newline at end of file diff --git a/rooter/0routerspecfic/apu2c4/Makefile b/rooter/0routerspecfic/apu2c4/Makefile new file mode 100644 index 0000000..d021b91 --- /dev/null +++ b/rooter/0routerspecfic/apu2c4/Makefile @@ -0,0 +1,33 @@ +#Owned by DairyMan@Whirlpool +# +#Copyright GNU act. +include $(TOPDIR)/rules.mk + +PKG_NAME:=apu2c4 +PKG_VERSION:=1.000 +PKG_RELEASE:=1 + +PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool +include $(INCLUDE_DIR)/package.mk + +define Package/apu2c4 + SECTION:=utils + CATEGORY:=ROOter + SUBMENU:=Router Specific + DEPENDS:=+kmod-leds-gpio +kmod-crypto-hw-ccp \ + +kmod-gpio-nct5104d +kmod-gpio-button-hotplug \ + +kmod-usb-core +kmod-usb-ohci +kmod-usb2 +kmod-usb3 \ + +kmod-sound-core +kmod-pcspkr + TITLE:=Install scripts for apu2c4 + PKGARCH:=all +endef + +define Package/apu2c4/description + Helper scripts to install scripts for apu2c4 +endef + + +define Build/Compile +endef + +$(eval $(call BuildPackage,apu2c4)) diff --git a/rooter/0routerspecfic/b1300/Makefile b/rooter/0routerspecfic/b1300/Makefile new file mode 100644 index 0000000..d61dae0 --- /dev/null +++ b/rooter/0routerspecfic/b1300/Makefile @@ -0,0 +1,35 @@ +#Owned by DairyMan@Whirlpool +# +#Copyright GNU act. +include $(TOPDIR)/rules.mk + +PKG_NAME:=b1300 +PKG_VERSION:=1.000 +PKG_RELEASE:=1 + +PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool +include $(INCLUDE_DIR)/package.mk + +define Package/b1300 + SECTION:=utils + CATEGORY:=ROOter + SUBMENU:=Router Specific + TITLE:=Install scripts for B1300 + PKGARCH:=all +endef + +define Package/b1300/description + Helper scripts to install scripts for B1300 +endef + + +define Build/Compile +endef + +define Package/b1300/install + $(CP) ./files/* $(1)/ + + +endef + +$(eval $(call BuildPackage,b1300)) diff --git a/rooter/0routerspecfic/b1300/files/usr/lib/rooter/special.sh b/rooter/0routerspecfic/b1300/files/usr/lib/rooter/special.sh new file mode 100644 index 0000000..95767a9 --- /dev/null +++ b/rooter/0routerspecfic/b1300/files/usr/lib/rooter/special.sh @@ -0,0 +1,30 @@ +#!/bin/sh + +LED=0 +SM=$(uci get system.led_wifi0) +if [ -z $SM ]; then + uci set system.led_wifi0=led + uci set system.led_wifi0.default="0" + uci set system.led_wifi0.name="WIFI0" + uci set system.led_wifi0.sysfs="b1300:green:wlan" + uci set system.led_wifi0.trigger="netdev" + uci set system.led_wifi0.dev="wlan0" + uci set system.led_wifi0.mode="link tx rx" + LED=1 +fi +SM=$(uci get system.led_wifi1) +if [ -z $SM ]; then + uci set system.led_wifi1=led + uci set system.led_wifi1.default="0" + uci set system.led_wifi1.name="WIFI1" + uci set system.led_wifi1.sysfs="b1300:green:wlan" + uci set system.led_wifi1.trigger="netdev" + uci set system.led_wifi1.dev="wlan1" + uci set system.led_wifi1.mode="link tx rx" + LED=1 +fi + +if [ $LED -eq 1 ]; then + uci commit system + /etc/init.d/led restart +fi diff --git a/rooter/0routerspecfic/d240/Makefile b/rooter/0routerspecfic/d240/Makefile new file mode 100644 index 0000000..2929121 --- /dev/null +++ b/rooter/0routerspecfic/d240/Makefile @@ -0,0 +1,35 @@ +#Owned by DairyMan@Whirlpool +# +#Copyright GNU act. +include $(TOPDIR)/rules.mk + +PKG_NAME:=d240 +PKG_VERSION:=1.000 +PKG_RELEASE:=1 + +PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool +include $(INCLUDE_DIR)/package.mk + +define Package/d240 + SECTION:=utils + CATEGORY:=ROOter + SUBMENU:=Router Specific + TITLE:=Install scripts for D240 + PKGARCH:=all +endef + +define Package/d240/description + Helper scripts to install scripts for D240 +endef + + +define Build/Compile +endef + +define Package/d240/install + $(CP) ./files/* $(1)/ + + +endef + +$(eval $(call BuildPackage,d240)) diff --git a/rooter/0routerspecfic/d240/files/usr/lib/sdcard/sdcard.sh b/rooter/0routerspecfic/d240/files/usr/lib/sdcard/sdcard.sh new file mode 100644 index 0000000..0c1f7ed --- /dev/null +++ b/rooter/0routerspecfic/d240/files/usr/lib/sdcard/sdcard.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +log() { + logger -t "sdcard" "$@" +} + +ACTION=$1 + +if [ $ACTION = "add" ]; then + log "add" +else + log "remove" +fi + diff --git a/rooter/0routerspecfic/dir860l/Makefile b/rooter/0routerspecfic/dir860l/Makefile new file mode 100644 index 0000000..9efceea --- /dev/null +++ b/rooter/0routerspecfic/dir860l/Makefile @@ -0,0 +1,35 @@ +#Owned by DairyMan@Whirlpool +# +#Copyright GNU act. +include $(TOPDIR)/rules.mk + +PKG_NAME:=dir860l +PKG_VERSION:=1.000 +PKG_RELEASE:=1 + +PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool +include $(INCLUDE_DIR)/package.mk + +define Package/dir860l + SECTION:=utils + CATEGORY:=ROOter + SUBMENU:=Router Specific + TITLE:=Install scripts for Dlink DIR-860L + PKGARCH:=all +endef + +define Package/dir860l/description + Helper scripts to install scripts for Dlink DIR-860L +endef + + +define Build/Compile +endef + +define Package/dir860l/install + $(CP) ./files/* $(1)/ + + +endef + +$(eval $(call BuildPackage,dir860l)) diff --git a/rooter/0routerspecfic/dir860l/files/etc/hotplug.d/iface/99-dir860-led b/rooter/0routerspecfic/dir860l/files/etc/hotplug.d/iface/99-dir860-led new file mode 100644 index 0000000..682d050 --- /dev/null +++ b/rooter/0routerspecfic/dir860l/files/etc/hotplug.d/iface/99-dir860-led @@ -0,0 +1,13 @@ +#!/bin/sh + +[ "$INTERFACE" != wan ] && exit 0 + +if [ "$ACTION" = ifup ]; then + set_gpio 14 1 + set_gpio 16 0 +fi + +if [ "$ACTION" = ifdown ]; then + set_gpio 14 0 + set_gpio 16 1 +fi \ No newline at end of file diff --git a/rooter/0routerspecfic/dir860l/files/usr/lib/rooter/special.sh b/rooter/0routerspecfic/dir860l/files/usr/lib/rooter/special.sh new file mode 100644 index 0000000..5ebc3e8 --- /dev/null +++ b/rooter/0routerspecfic/dir860l/files/usr/lib/rooter/special.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +# turn power led green +set_gpio 13 1 +set_gpio 15 0 + +# signal that we are waiting for internets +set_gpio 14 0 \ No newline at end of file diff --git a/rooter/0routerspecfic/ext-ssh/Makefile b/rooter/0routerspecfic/ext-ssh/Makefile new file mode 100644 index 0000000..03ac236 --- /dev/null +++ b/rooter/0routerspecfic/ext-ssh/Makefile @@ -0,0 +1,36 @@ +#Owned by DairyMan@Whirlpool +# +#Copyright GNU act. +include $(TOPDIR)/rules.mk + +PKG_NAME:=ext-ssh +PKG_VERSION:=1.000 +PKG_RELEASE:=1 + +PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool +include $(INCLUDE_DIR)/package.mk + +define Package/ext-ssh + SECTION:=utils + CATEGORY:=ROOter + SUBMENU:=Router Specific + DEPENDS:=+openssh-client +openssh-client-utils +openssh-keygen +openssh-moduli +openssh-server + TITLE:=Install scripts for SSH + PKGARCH:=all +endef + +define Package/ext-ssh/description + Helper scripts to install scripts for SSH +endef + + +define Build/Compile +endef + +define Package/ext-ssh/install + $(CP) ./files/* $(1)/ + + +endef + +$(eval $(call BuildPackage,ext-ssh)) diff --git a/rooter/0routerspecfic/ext-ssh/files/etc/init.d/sshd b/rooter/0routerspecfic/ext-ssh/files/etc/init.d/sshd new file mode 100644 index 0000000..44a0bd3 --- /dev/null +++ b/rooter/0routerspecfic/ext-ssh/files/etc/init.d/sshd @@ -0,0 +1,54 @@ +#!/bin/sh /etc/rc.common +# Copyright (C) 2006-2011 OpenWrt.org + +START=50 +STOP=50 + +USE_PROCD=1 +PROG=/usr/sbin/sshd + +log() { + logger -t "OPENSSH" "$@" +} + +start_service() { + log "Starting SSH" + + for type in rsa ecdsa ed25519; do { + # check for keys + key=/etc/ssh/ssh_host_${type}_key + [ ! -f $key ] && { + # generate missing keys + [ -x /usr/bin/ssh-keygen ] && { + /usr/bin/ssh-keygen -N '' -t $type -f $key 2>&- >&- + } + } + }; done + mkdir -m 0700 -p /var/empty + + local lport=`grep ^Port /etc/ssh/sshd_config | cut -d " " -f 2` + [ -z $lport ] && lport=22 + + #procd_open_instance + #procd_add_mdns "ssh" "tcp" "$lport" + #procd_set_param command $PROG -D + #procd_close_instance + + /usr/sbin/sshd & +} + +shutdown() { + local pid + local pids + local pid_mine + + stop + + # kill active clients + pid_mine="$$" + pids="$(pidof sshd)" + for pid in $pids; do + [ "$pid" = "$pid_mine" ] && continue + [ -e "/proc/$pid/stat" ] && kill $pid + done +} diff --git a/rooter/0routerspecfic/ext-ssh/files/etc/ssh/moduli b/rooter/0routerspecfic/ext-ssh/files/etc/ssh/moduli new file mode 100644 index 0000000..cf28bd3 --- /dev/null +++ b/rooter/0routerspecfic/ext-ssh/files/etc/ssh/moduli @@ -0,0 +1,407 @@ +# $OpenBSD: moduli,v 1.20 2017/11/29 05:49:54 dtucker Exp $ +# Time Type Tests Tries Size Generator Modulus +20170623034823 2 6 100 2047 2 F740D04A6CFD4547DDBE874AEED3DF220F4ABD1EEA9BB022EDB3019835812EB327F3F0BBD0D137702856B499924C1A0D78D467EFBCB2215008FC3918FF88710ED5CA4F3554494F3AC374C8695B1DA006470F1C5C751825389DF3FBAC83DFEFAE2B07FA30E3B6B13D2BF9FAA27DCBD03FEB6847F08C3C6C89B04366A78D8C43E1E26B63ED5BB9A3E1AAE00BD4A4BF058B41B70E9F599C7DAE2E42701C68FDDEFE7213432E77342F785D64B723FF33A2D9C6F85F149776F898EF8BEFE3D03D2163974A3C0F13520F4BE92A246DED5A6FC997B2657D1A72A1210E881D0A0F14E93522268E3D8FFB84ABB3B9B064985E891C7C0DC09E166008A5E13A777EAE4E76CB +20170623034906 2 6 100 2047 2 F740D04A6CFD4547DDBE874AEED3DF220F4ABD1EEA9BB022EDB3019835812EB327F3F0BBD0D137702856B499924C1A0D78D467EFBCB2215008FC3918FF88710ED5CA4F3554494F3AC374C8695B1DA006470F1C5C751825389DF3FBAC83DFEFAE2B07FA30E3B6B13D2BF9FAA27DCBD03FEB6847F08C3C6C89B04366A78D8C43E1E26B63ED5BB9A3E1AAE00BD4A4BF058B41B70E9F599C7DAE2E42701C68FDDEFE7213432E77342F785D64B723FF33A2D9C6F85F149776F898EF8BEFE3D03D2163974A3C0F13520F4BE92A246DED5A6FC997B2657D1A72A1210E881D0A0F14E93522268E3D8FFB84ABB3B9B064985E891C7C0DC09E166008A5E13A777EAEB63283 +20170623034928 2 6 100 2047 5 F740D04A6CFD4547DDBE874AEED3DF220F4ABD1EEA9BB022EDB3019835812EB327F3F0BBD0D137702856B499924C1A0D78D467EFBCB2215008FC3918FF88710ED5CA4F3554494F3AC374C8695B1DA006470F1C5C751825389DF3FBAC83DFEFAE2B07FA30E3B6B13D2BF9FAA27DCBD03FEB6847F08C3C6C89B04366A78D8C43E1E26B63ED5BB9A3E1AAE00BD4A4BF058B41B70E9F599C7DAE2E42701C68FDDEFE7213432E77342F785D64B723FF33A2D9C6F85F149776F898EF8BEFE3D03D2163974A3C0F13520F4BE92A246DED5A6FC997B2657D1A72A1210E881D0A0F14E93522268E3D8FFB84ABB3B9B064985E891C7C0DC09E166008A5E13A777EAEE49C27 +20170623034936 2 6 100 2047 2 F740D04A6CFD4547DDBE874AEED3DF220F4ABD1EEA9BB022EDB3019835812EB327F3F0BBD0D137702856B499924C1A0D78D467EFBCB2215008FC3918FF88710ED5CA4F3554494F3AC374C8695B1DA006470F1C5C751825389DF3FBAC83DFEFAE2B07FA30E3B6B13D2BF9FAA27DCBD03FEB6847F08C3C6C89B04366A78D8C43E1E26B63ED5BB9A3E1AAE00BD4A4BF058B41B70E9F599C7DAE2E42701C68FDDEFE7213432E77342F785D64B723FF33A2D9C6F85F149776F898EF8BEFE3D03D2163974A3C0F13520F4BE92A246DED5A6FC997B2657D1A72A1210E881D0A0F14E93522268E3D8FFB84ABB3B9B064985E891C7C0DC09E166008A5E13A777EAEF2BE1B +20170623034957 2 6 100 2047 5 F740D04A6CFD4547DDBE874AEED3DF220F4ABD1EEA9BB022EDB3019835812EB327F3F0BBD0D137702856B499924C1A0D78D467EFBCB2215008FC3918FF88710ED5CA4F3554494F3AC374C8695B1DA006470F1C5C751825389DF3FBAC83DFEFAE2B07FA30E3B6B13D2BF9FAA27DCBD03FEB6847F08C3C6C89B04366A78D8C43E1E26B63ED5BB9A3E1AAE00BD4A4BF058B41B70E9F599C7DAE2E42701C68FDDEFE7213432E77342F785D64B723FF33A2D9C6F85F149776F898EF8BEFE3D03D2163974A3C0F13520F4BE92A246DED5A6FC997B2657D1A72A1210E881D0A0F14E93522268E3D8FFB84ABB3B9B064985E891C7C0DC09E166008A5E13A777EAF22F2D7 +20170623035029 2 6 100 2047 5 F740D04A6CFD4547DDBE874AEED3DF220F4ABD1EEA9BB022EDB3019835812EB327F3F0BBD0D137702856B499924C1A0D78D467EFBCB2215008FC3918FF88710ED5CA4F3554494F3AC374C8695B1DA006470F1C5C751825389DF3FBAC83DFEFAE2B07FA30E3B6B13D2BF9FAA27DCBD03FEB6847F08C3C6C89B04366A78D8C43E1E26B63ED5BB9A3E1AAE00BD4A4BF058B41B70E9F599C7DAE2E42701C68FDDEFE7213432E77342F785D64B723FF33A2D9C6F85F149776F898EF8BEFE3D03D2163974A3C0F13520F4BE92A246DED5A6FC997B2657D1A72A1210E881D0A0F14E93522268E3D8FFB84ABB3B9B064985E891C7C0DC09E166008A5E13A777EAF68D3A7 +20170623035052 2 6 100 2047 2 F740D04A6CFD4547DDBE874AEED3DF220F4ABD1EEA9BB022EDB3019835812EB327F3F0BBD0D137702856B499924C1A0D78D467EFBCB2215008FC3918FF88710ED5CA4F3554494F3AC374C8695B1DA006470F1C5C751825389DF3FBAC83DFEFAE2B07FA30E3B6B13D2BF9FAA27DCBD03FEB6847F08C3C6C89B04366A78D8C43E1E26B63ED5BB9A3E1AAE00BD4A4BF058B41B70E9F599C7DAE2E42701C68FDDEFE7213432E77342F785D64B723FF33A2D9C6F85F149776F898EF8BEFE3D03D2163974A3C0F13520F4BE92A246DED5A6FC997B2657D1A72A1210E881D0A0F14E93522268E3D8FFB84ABB3B9B064985E891C7C0DC09E166008A5E13A777EAF9A9793 +20170623035228 2 6 100 2047 2 F740D04A6CFD4547DDBE874AEED3DF220F4ABD1EEA9BB022EDB3019835812EB327F3F0BBD0D137702856B499924C1A0D78D467EFBCB2215008FC3918FF88710ED5CA4F3554494F3AC374C8695B1DA006470F1C5C751825389DF3FBAC83DFEFAE2B07FA30E3B6B13D2BF9FAA27DCBD03FEB6847F08C3C6C89B04366A78D8C43E1E26B63ED5BB9A3E1AAE00BD4A4BF058B41B70E9F599C7DAE2E42701C68FDDEFE7213432E77342F785D64B723FF33A2D9C6F85F149776F898EF8BEFE3D03D2163974A3C0F13520F4BE92A246DED5A6FC997B2657D1A72A1210E881D0A0F14E93522268E3D8FFB84ABB3B9B064985E891C7C0DC09E166008A5E13A777EB085C01B +20170623035326 2 6 100 2047 5 F740D04A6CFD4547DDBE874AEED3DF220F4ABD1EEA9BB022EDB3019835812EB327F3F0BBD0D137702856B499924C1A0D78D467EFBCB2215008FC3918FF88710ED5CA4F3554494F3AC374C8695B1DA006470F1C5C751825389DF3FBAC83DFEFAE2B07FA30E3B6B13D2BF9FAA27DCBD03FEB6847F08C3C6C89B04366A78D8C43E1E26B63ED5BB9A3E1AAE00BD4A4BF058B41B70E9F599C7DAE2E42701C68FDDEFE7213432E77342F785D64B723FF33A2D9C6F85F149776F898EF8BEFE3D03D2163974A3C0F13520F4BE92A246DED5A6FC997B2657D1A72A1210E881D0A0F14E93522268E3D8FFB84ABB3B9B064985E891C7C0DC09E166008A5E13A777EB1140217 +20170623035332 2 6 100 2047 5 F740D04A6CFD4547DDBE874AEED3DF220F4ABD1EEA9BB022EDB3019835812EB327F3F0BBD0D137702856B499924C1A0D78D467EFBCB2215008FC3918FF88710ED5CA4F3554494F3AC374C8695B1DA006470F1C5C751825389DF3FBAC83DFEFAE2B07FA30E3B6B13D2BF9FAA27DCBD03FEB6847F08C3C6C89B04366A78D8C43E1E26B63ED5BB9A3E1AAE00BD4A4BF058B41B70E9F599C7DAE2E42701C68FDDEFE7213432E77342F785D64B723FF33A2D9C6F85F149776F898EF8BEFE3D03D2163974A3C0F13520F4BE92A246DED5A6FC997B2657D1A72A1210E881D0A0F14E93522268E3D8FFB84ABB3B9B064985E891C7C0DC09E166008A5E13A777EB11ACBD7 +20170623035408 2 6 100 2047 5 F740D04A6CFD4547DDBE874AEED3DF220F4ABD1EEA9BB022EDB3019835812EB327F3F0BBD0D137702856B499924C1A0D78D467EFBCB2215008FC3918FF88710ED5CA4F3554494F3AC374C8695B1DA006470F1C5C751825389DF3FBAC83DFEFAE2B07FA30E3B6B13D2BF9FAA27DCBD03FEB6847F08C3C6C89B04366A78D8C43E1E26B63ED5BB9A3E1AAE00BD4A4BF058B41B70E9F599C7DAE2E42701C68FDDEFE7213432E77342F785D64B723FF33A2D9C6F85F149776F898EF8BEFE3D03D2163974A3C0F13520F4BE92A246DED5A6FC997B2657D1A72A1210E881D0A0F14E93522268E3D8FFB84ABB3B9B064985E891C7C0DC09E166008A5E13A777EB16AD187 +20170623035414 2 6 100 2047 2 F740D04A6CFD4547DDBE874AEED3DF220F4ABD1EEA9BB022EDB3019835812EB327F3F0BBD0D137702856B499924C1A0D78D467EFBCB2215008FC3918FF88710ED5CA4F3554494F3AC374C8695B1DA006470F1C5C751825389DF3FBAC83DFEFAE2B07FA30E3B6B13D2BF9FAA27DCBD03FEB6847F08C3C6C89B04366A78D8C43E1E26B63ED5BB9A3E1AAE00BD4A4BF058B41B70E9F599C7DAE2E42701C68FDDEFE7213432E77342F785D64B723FF33A2D9C6F85F149776F898EF8BEFE3D03D2163974A3C0F13520F4BE92A246DED5A6FC997B2657D1A72A1210E881D0A0F14E93522268E3D8FFB84ABB3B9B064985E891C7C0DC09E166008A5E13A777EB1737B53 +20170623035442 2 6 100 2047 2 F740D04A6CFD4547DDBE874AEED3DF220F4ABD1EEA9BB022EDB3019835812EB327F3F0BBD0D137702856B499924C1A0D78D467EFBCB2215008FC3918FF88710ED5CA4F3554494F3AC374C8695B1DA006470F1C5C751825389DF3FBAC83DFEFAE2B07FA30E3B6B13D2BF9FAA27DCBD03FEB6847F08C3C6C89B04366A78D8C43E1E26B63ED5BB9A3E1AAE00BD4A4BF058B41B70E9F599C7DAE2E42701C68FDDEFE7213432E77342F785D64B723FF33A2D9C6F85F149776F898EF8BEFE3D03D2163974A3C0F13520F4BE92A246DED5A6FC997B2657D1A72A1210E881D0A0F14E93522268E3D8FFB84ABB3B9B064985E891C7C0DC09E166008A5E13A777EB1B1C483 +20170623035454 2 6 100 2047 2 F740D04A6CFD4547DDBE874AEED3DF220F4ABD1EEA9BB022EDB3019835812EB327F3F0BBD0D137702856B499924C1A0D78D467EFBCB2215008FC3918FF88710ED5CA4F3554494F3AC374C8695B1DA006470F1C5C751825389DF3FBAC83DFEFAE2B07FA30E3B6B13D2BF9FAA27DCBD03FEB6847F08C3C6C89B04366A78D8C43E1E26B63ED5BB9A3E1AAE00BD4A4BF058B41B70E9F599C7DAE2E42701C68FDDEFE7213432E77342F785D64B723FF33A2D9C6F85F149776F898EF8BEFE3D03D2163974A3C0F13520F4BE92A246DED5A6FC997B2657D1A72A1210E881D0A0F14E93522268E3D8FFB84ABB3B9B064985E891C7C0DC09E166008A5E13A777EB1C8B93B +20170623035510 2 6 100 2047 2 F740D04A6CFD4547DDBE874AEED3DF220F4ABD1EEA9BB022EDB3019835812EB327F3F0BBD0D137702856B499924C1A0D78D467EFBCB2215008FC3918FF88710ED5CA4F3554494F3AC374C8695B1DA006470F1C5C751825389DF3FBAC83DFEFAE2B07FA30E3B6B13D2BF9FAA27DCBD03FEB6847F08C3C6C89B04366A78D8C43E1E26B63ED5BB9A3E1AAE00BD4A4BF058B41B70E9F599C7DAE2E42701C68FDDEFE7213432E77342F785D64B723FF33A2D9C6F85F149776F898EF8BEFE3D03D2163974A3C0F13520F4BE92A246DED5A6FC997B2657D1A72A1210E881D0A0F14E93522268E3D8FFB84ABB3B9B064985E891C7C0DC09E166008A5E13A777EB1EAD06B +20170623035525 2 6 100 2047 2 F740D04A6CFD4547DDBE874AEED3DF220F4ABD1EEA9BB022EDB3019835812EB327F3F0BBD0D137702856B499924C1A0D78D467EFBCB2215008FC3918FF88710ED5CA4F3554494F3AC374C8695B1DA006470F1C5C751825389DF3FBAC83DFEFAE2B07FA30E3B6B13D2BF9FAA27DCBD03FEB6847F08C3C6C89B04366A78D8C43E1E26B63ED5BB9A3E1AAE00BD4A4BF058B41B70E9F599C7DAE2E42701C68FDDEFE7213432E77342F785D64B723FF33A2D9C6F85F149776F898EF8BEFE3D03D2163974A3C0F13520F4BE92A246DED5A6FC997B2657D1A72A1210E881D0A0F14E93522268E3D8FFB84ABB3B9B064985E891C7C0DC09E166008A5E13A777EB208DA8B +20170623035553 2 6 100 2047 5 F740D04A6CFD4547DDBE874AEED3DF220F4ABD1EEA9BB022EDB3019835812EB327F3F0BBD0D137702856B499924C1A0D78D467EFBCB2215008FC3918FF88710ED5CA4F3554494F3AC374C8695B1DA006470F1C5C751825389DF3FBAC83DFEFAE2B07FA30E3B6B13D2BF9FAA27DCBD03FEB6847F08C3C6C89B04366A78D8C43E1E26B63ED5BB9A3E1AAE00BD4A4BF058B41B70E9F599C7DAE2E42701C68FDDEFE7213432E77342F785D64B723FF33A2D9C6F85F149776F898EF8BEFE3D03D2163974A3C0F13520F4BE92A246DED5A6FC997B2657D1A72A1210E881D0A0F14E93522268E3D8FFB84ABB3B9B064985E891C7C0DC09E166008A5E13A777EB2498F17 +20170623035604 2 6 100 2047 2 F740D04A6CFD4547DDBE874AEED3DF220F4ABD1EEA9BB022EDB3019835812EB327F3F0BBD0D137702856B499924C1A0D78D467EFBCB2215008FC3918FF88710ED5CA4F3554494F3AC374C8695B1DA006470F1C5C751825389DF3FBAC83DFEFAE2B07FA30E3B6B13D2BF9FAA27DCBD03FEB6847F08C3C6C89B04366A78D8C43E1E26B63ED5BB9A3E1AAE00BD4A4BF058B41B70E9F599C7DAE2E42701C68FDDEFE7213432E77342F785D64B723FF33A2D9C6F85F149776F898EF8BEFE3D03D2163974A3C0F13520F4BE92A246DED5A6FC997B2657D1A72A1210E881D0A0F14E93522268E3D8FFB84ABB3B9B064985E891C7C0DC09E166008A5E13A777EB25D82D3 +20170623035609 2 6 100 2047 5 F740D04A6CFD4547DDBE874AEED3DF220F4ABD1EEA9BB022EDB3019835812EB327F3F0BBD0D137702856B499924C1A0D78D467EFBCB2215008FC3918FF88710ED5CA4F3554494F3AC374C8695B1DA006470F1C5C751825389DF3FBAC83DFEFAE2B07FA30E3B6B13D2BF9FAA27DCBD03FEB6847F08C3C6C89B04366A78D8C43E1E26B63ED5BB9A3E1AAE00BD4A4BF058B41B70E9F599C7DAE2E42701C68FDDEFE7213432E77342F785D64B723FF33A2D9C6F85F149776F898EF8BEFE3D03D2163974A3C0F13520F4BE92A246DED5A6FC997B2657D1A72A1210E881D0A0F14E93522268E3D8FFB84ABB3B9B064985E891C7C0DC09E166008A5E13A777EB262420F +20170623035735 2 6 100 2047 5 F740D04A6CFD4547DDBE874AEED3DF220F4ABD1EEA9BB022EDB3019835812EB327F3F0BBD0D137702856B499924C1A0D78D467EFBCB2215008FC3918FF88710ED5CA4F3554494F3AC374C8695B1DA006470F1C5C751825389DF3FBAC83DFEFAE2B07FA30E3B6B13D2BF9FAA27DCBD03FEB6847F08C3C6C89B04366A78D8C43E1E26B63ED5BB9A3E1AAE00BD4A4BF058B41B70E9F599C7DAE2E42701C68FDDEFE7213432E77342F785D64B723FF33A2D9C6F85F149776F898EF8BEFE3D03D2163974A3C0F13520F4BE92A246DED5A6FC997B2657D1A72A1210E881D0A0F14E93522268E3D8FFB84ABB3B9B064985E891C7C0DC09E166008A5E13A777EB3376DEF +20170623035801 2 6 100 2047 2 F740D04A6CFD4547DDBE874AEED3DF220F4ABD1EEA9BB022EDB3019835812EB327F3F0BBD0D137702856B499924C1A0D78D467EFBCB2215008FC3918FF88710ED5CA4F3554494F3AC374C8695B1DA006470F1C5C751825389DF3FBAC83DFEFAE2B07FA30E3B6B13D2BF9FAA27DCBD03FEB6847F08C3C6C89B04366A78D8C43E1E26B63ED5BB9A3E1AAE00BD4A4BF058B41B70E9F599C7DAE2E42701C68FDDEFE7213432E77342F785D64B723FF33A2D9C6F85F149776F898EF8BEFE3D03D2163974A3C0F13520F4BE92A246DED5A6FC997B2657D1A72A1210E881D0A0F14E93522268E3D8FFB84ABB3B9B064985E891C7C0DC09E166008A5E13A777EB370E193 +20170623035916 2 6 100 2047 5 F740D04A6CFD4547DDBE874AEED3DF220F4ABD1EEA9BB022EDB3019835812EB327F3F0BBD0D137702856B499924C1A0D78D467EFBCB2215008FC3918FF88710ED5CA4F3554494F3AC374C8695B1DA006470F1C5C751825389DF3FBAC83DFEFAE2B07FA30E3B6B13D2BF9FAA27DCBD03FEB6847F08C3C6C89B04366A78D8C43E1E26B63ED5BB9A3E1AAE00BD4A4BF058B41B70E9F599C7DAE2E42701C68FDDEFE7213432E77342F785D64B723FF33A2D9C6F85F149776F898EF8BEFE3D03D2163974A3C0F13520F4BE92A246DED5A6FC997B2657D1A72A1210E881D0A0F14E93522268E3D8FFB84ABB3B9B064985E891C7C0DC09E166008A5E13A777EB426D9CF +20170623035935 2 6 100 2047 2 F740D04A6CFD4547DDBE874AEED3DF220F4ABD1EEA9BB022EDB3019835812EB327F3F0BBD0D137702856B499924C1A0D78D467EFBCB2215008FC3918FF88710ED5CA4F3554494F3AC374C8695B1DA006470F1C5C751825389DF3FBAC83DFEFAE2B07FA30E3B6B13D2BF9FAA27DCBD03FEB6847F08C3C6C89B04366A78D8C43E1E26B63ED5BB9A3E1AAE00BD4A4BF058B41B70E9F599C7DAE2E42701C68FDDEFE7213432E77342F785D64B723FF33A2D9C6F85F149776F898EF8BEFE3D03D2163974A3C0F13520F4BE92A246DED5A6FC997B2657D1A72A1210E881D0A0F14E93522268E3D8FFB84ABB3B9B064985E891C7C0DC09E166008A5E13A777EB44E559B +20170623035955 2 6 100 2047 5 F740D04A6CFD4547DDBE874AEED3DF220F4ABD1EEA9BB022EDB3019835812EB327F3F0BBD0D137702856B499924C1A0D78D467EFBCB2215008FC3918FF88710ED5CA4F3554494F3AC374C8695B1DA006470F1C5C751825389DF3FBAC83DFEFAE2B07FA30E3B6B13D2BF9FAA27DCBD03FEB6847F08C3C6C89B04366A78D8C43E1E26B63ED5BB9A3E1AAE00BD4A4BF058B41B70E9F599C7DAE2E42701C68FDDEFE7213432E77342F785D64B723FF33A2D9C6F85F149776F898EF8BEFE3D03D2163974A3C0F13520F4BE92A246DED5A6FC997B2657D1A72A1210E881D0A0F14E93522268E3D8FFB84ABB3B9B064985E891C7C0DC09E166008A5E13A777EB4777177 +20170623040012 2 6 100 2047 5 F740D04A6CFD4547DDBE874AEED3DF220F4ABD1EEA9BB022EDB3019835812EB327F3F0BBD0D137702856B499924C1A0D78D467EFBCB2215008FC3918FF88710ED5CA4F3554494F3AC374C8695B1DA006470F1C5C751825389DF3FBAC83DFEFAE2B07FA30E3B6B13D2BF9FAA27DCBD03FEB6847F08C3C6C89B04366A78D8C43E1E26B63ED5BB9A3E1AAE00BD4A4BF058B41B70E9F599C7DAE2E42701C68FDDEFE7213432E77342F785D64B723FF33A2D9C6F85F149776F898EF8BEFE3D03D2163974A3C0F13520F4BE92A246DED5A6FC997B2657D1A72A1210E881D0A0F14E93522268E3D8FFB84ABB3B9B064985E891C7C0DC09E166008A5E13A777EB4995E77 +20170623040023 2 6 100 2047 2 F740D04A6CFD4547DDBE874AEED3DF220F4ABD1EEA9BB022EDB3019835812EB327F3F0BBD0D137702856B499924C1A0D78D467EFBCB2215008FC3918FF88710ED5CA4F3554494F3AC374C8695B1DA006470F1C5C751825389DF3FBAC83DFEFAE2B07FA30E3B6B13D2BF9FAA27DCBD03FEB6847F08C3C6C89B04366A78D8C43E1E26B63ED5BB9A3E1AAE00BD4A4BF058B41B70E9F599C7DAE2E42701C68FDDEFE7213432E77342F785D64B723FF33A2D9C6F85F149776F898EF8BEFE3D03D2163974A3C0F13520F4BE92A246DED5A6FC997B2657D1A72A1210E881D0A0F14E93522268E3D8FFB84ABB3B9B064985E891C7C0DC09E166008A5E13A777EB4ACAF8B +20170623040032 2 6 100 2047 2 F740D04A6CFD4547DDBE874AEED3DF220F4ABD1EEA9BB022EDB3019835812EB327F3F0BBD0D137702856B499924C1A0D78D467EFBCB2215008FC3918FF88710ED5CA4F3554494F3AC374C8695B1DA006470F1C5C751825389DF3FBAC83DFEFAE2B07FA30E3B6B13D2BF9FAA27DCBD03FEB6847F08C3C6C89B04366A78D8C43E1E26B63ED5BB9A3E1AAE00BD4A4BF058B41B70E9F599C7DAE2E42701C68FDDEFE7213432E77342F785D64B723FF33A2D9C6F85F149776F898EF8BEFE3D03D2163974A3C0F13520F4BE92A246DED5A6FC997B2657D1A72A1210E881D0A0F14E93522268E3D8FFB84ABB3B9B064985E891C7C0DC09E166008A5E13A777EB4BB1ADB +20170623040120 2 6 100 2047 5 F740D04A6CFD4547DDBE874AEED3DF220F4ABD1EEA9BB022EDB3019835812EB327F3F0BBD0D137702856B499924C1A0D78D467EFBCB2215008FC3918FF88710ED5CA4F3554494F3AC374C8695B1DA006470F1C5C751825389DF3FBAC83DFEFAE2B07FA30E3B6B13D2BF9FAA27DCBD03FEB6847F08C3C6C89B04366A78D8C43E1E26B63ED5BB9A3E1AAE00BD4A4BF058B41B70E9F599C7DAE2E42701C68FDDEFE7213432E77342F785D64B723FF33A2D9C6F85F149776F898EF8BEFE3D03D2163974A3C0F13520F4BE92A246DED5A6FC997B2657D1A72A1210E881D0A0F14E93522268E3D8FFB84ABB3B9B064985E891C7C0DC09E166008A5E13A777EB52D4F1F +20170623040131 2 6 100 2047 2 F740D04A6CFD4547DDBE874AEED3DF220F4ABD1EEA9BB022EDB3019835812EB327F3F0BBD0D137702856B499924C1A0D78D467EFBCB2215008FC3918FF88710ED5CA4F3554494F3AC374C8695B1DA006470F1C5C751825389DF3FBAC83DFEFAE2B07FA30E3B6B13D2BF9FAA27DCBD03FEB6847F08C3C6C89B04366A78D8C43E1E26B63ED5BB9A3E1AAE00BD4A4BF058B41B70E9F599C7DAE2E42701C68FDDEFE7213432E77342F785D64B723FF33A2D9C6F85F149776F898EF8BEFE3D03D2163974A3C0F13520F4BE92A246DED5A6FC997B2657D1A72A1210E881D0A0F14E93522268E3D8FFB84ABB3B9B064985E891C7C0DC09E166008A5E13A777EB542306B +20170623040202 2 6 100 2047 5 F740D04A6CFD4547DDBE874AEED3DF220F4ABD1EEA9BB022EDB3019835812EB327F3F0BBD0D137702856B499924C1A0D78D467EFBCB2215008FC3918FF88710ED5CA4F3554494F3AC374C8695B1DA006470F1C5C751825389DF3FBAC83DFEFAE2B07FA30E3B6B13D2BF9FAA27DCBD03FEB6847F08C3C6C89B04366A78D8C43E1E26B63ED5BB9A3E1AAE00BD4A4BF058B41B70E9F599C7DAE2E42701C68FDDEFE7213432E77342F785D64B723FF33A2D9C6F85F149776F898EF8BEFE3D03D2163974A3C0F13520F4BE92A246DED5A6FC997B2657D1A72A1210E881D0A0F14E93522268E3D8FFB84ABB3B9B064985E891C7C0DC09E166008A5E13A777EB5899CB7 +20170623040216 2 6 100 2047 2 F740D04A6CFD4547DDBE874AEED3DF220F4ABD1EEA9BB022EDB3019835812EB327F3F0BBD0D137702856B499924C1A0D78D467EFBCB2215008FC3918FF88710ED5CA4F3554494F3AC374C8695B1DA006470F1C5C751825389DF3FBAC83DFEFAE2B07FA30E3B6B13D2BF9FAA27DCBD03FEB6847F08C3C6C89B04366A78D8C43E1E26B63ED5BB9A3E1AAE00BD4A4BF058B41B70E9F599C7DAE2E42701C68FDDEFE7213432E77342F785D64B723FF33A2D9C6F85F149776F898EF8BEFE3D03D2163974A3C0F13520F4BE92A246DED5A6FC997B2657D1A72A1210E881D0A0F14E93522268E3D8FFB84ABB3B9B064985E891C7C0DC09E166008A5E13A777EB5A317FB +20170623040224 2 6 100 2047 2 F740D04A6CFD4547DDBE874AEED3DF220F4ABD1EEA9BB022EDB3019835812EB327F3F0BBD0D137702856B499924C1A0D78D467EFBCB2215008FC3918FF88710ED5CA4F3554494F3AC374C8695B1DA006470F1C5C751825389DF3FBAC83DFEFAE2B07FA30E3B6B13D2BF9FAA27DCBD03FEB6847F08C3C6C89B04366A78D8C43E1E26B63ED5BB9A3E1AAE00BD4A4BF058B41B70E9F599C7DAE2E42701C68FDDEFE7213432E77342F785D64B723FF33A2D9C6F85F149776F898EF8BEFE3D03D2163974A3C0F13520F4BE92A246DED5A6FC997B2657D1A72A1210E881D0A0F14E93522268E3D8FFB84ABB3B9B064985E891C7C0DC09E166008A5E13A777EB5AEBE43 +20170623040246 2 6 100 2047 5 F740D04A6CFD4547DDBE874AEED3DF220F4ABD1EEA9BB022EDB3019835812EB327F3F0BBD0D137702856B499924C1A0D78D467EFBCB2215008FC3918FF88710ED5CA4F3554494F3AC374C8695B1DA006470F1C5C751825389DF3FBAC83DFEFAE2B07FA30E3B6B13D2BF9FAA27DCBD03FEB6847F08C3C6C89B04366A78D8C43E1E26B63ED5BB9A3E1AAE00BD4A4BF058B41B70E9F599C7DAE2E42701C68FDDEFE7213432E77342F785D64B723FF33A2D9C6F85F149776F898EF8BEFE3D03D2163974A3C0F13520F4BE92A246DED5A6FC997B2657D1A72A1210E881D0A0F14E93522268E3D8FFB84ABB3B9B064985E891C7C0DC09E166008A5E13A777EB5E190BF +20170623040254 2 6 100 2047 2 F740D04A6CFD4547DDBE874AEED3DF220F4ABD1EEA9BB022EDB3019835812EB327F3F0BBD0D137702856B499924C1A0D78D467EFBCB2215008FC3918FF88710ED5CA4F3554494F3AC374C8695B1DA006470F1C5C751825389DF3FBAC83DFEFAE2B07FA30E3B6B13D2BF9FAA27DCBD03FEB6847F08C3C6C89B04366A78D8C43E1E26B63ED5BB9A3E1AAE00BD4A4BF058B41B70E9F599C7DAE2E42701C68FDDEFE7213432E77342F785D64B723FF33A2D9C6F85F149776F898EF8BEFE3D03D2163974A3C0F13520F4BE92A246DED5A6FC997B2657D1A72A1210E881D0A0F14E93522268E3D8FFB84ABB3B9B064985E891C7C0DC09E166008A5E13A777EB5EBE533 +20170623040334 2 6 100 2047 5 F740D04A6CFD4547DDBE874AEED3DF220F4ABD1EEA9BB022EDB3019835812EB327F3F0BBD0D137702856B499924C1A0D78D467EFBCB2215008FC3918FF88710ED5CA4F3554494F3AC374C8695B1DA006470F1C5C751825389DF3FBAC83DFEFAE2B07FA30E3B6B13D2BF9FAA27DCBD03FEB6847F08C3C6C89B04366A78D8C43E1E26B63ED5BB9A3E1AAE00BD4A4BF058B41B70E9F599C7DAE2E42701C68FDDEFE7213432E77342F785D64B723FF33A2D9C6F85F149776F898EF8BEFE3D03D2163974A3C0F13520F4BE92A246DED5A6FC997B2657D1A72A1210E881D0A0F14E93522268E3D8FFB84ABB3B9B064985E891C7C0DC09E166008A5E13A777EB649ECAF +20170623040448 2 6 100 2047 2 EDB5FA2E865AD05F06510EFBFC71F9DFBAA5C1EEF3F6FDC2650C1D8C507DECA3422AE18746EA7D7BEA600C0AE9A0812A3DC02C099F8AF046EF014EC2A58734A716F156FCE4F19E3A9EB38F225A1CA0B868F70B3BE0CAE3AC2A20F330EF3CC33CB27D1FCB2D27505409144F957AC592567AC0B2A8099F6D58B546C7EE734FD806CDFDDE5F41C38966EB61005CA78D970BFA2C77F099BB19543B559AA118B6F303644D541E83B293138BEF5B8F0B0382ACA8DBDD693845FF6B7EE6ABF1B8B4733998F31DBF74F9CBA5145A0C5345EDC5B056CDCAA3AF605701C56651B8A968AD6D7E421DD3B5F3765865D5FDC55252F25C9661CD71A43A20B13A16CFF3C4B50D13 +20170623040459 2 6 100 2047 5 EDB5FA2E865AD05F06510EFBFC71F9DFBAA5C1EEF3F6FDC2650C1D8C507DECA3422AE18746EA7D7BEA600C0AE9A0812A3DC02C099F8AF046EF014EC2A58734A716F156FCE4F19E3A9EB38F225A1CA0B868F70B3BE0CAE3AC2A20F330EF3CC33CB27D1FCB2D27505409144F957AC592567AC0B2A8099F6D58B546C7EE734FD806CDFDDE5F41C38966EB61005CA78D970BFA2C77F099BB19543B559AA118B6F303644D541E83B293138BEF5B8F0B0382ACA8DBDD693845FF6B7EE6ABF1B8B4733998F31DBF74F9CBA5145A0C5345EDC5B056CDCAA3AF605701C56651B8A968AD6D7E421DD3B5F3765865D5FDC55252F25C9661CD71A43A20B13A16CFF3C4C9F477 +20170623040510 2 6 100 2047 2 EDB5FA2E865AD05F06510EFBFC71F9DFBAA5C1EEF3F6FDC2650C1D8C507DECA3422AE18746EA7D7BEA600C0AE9A0812A3DC02C099F8AF046EF014EC2A58734A716F156FCE4F19E3A9EB38F225A1CA0B868F70B3BE0CAE3AC2A20F330EF3CC33CB27D1FCB2D27505409144F957AC592567AC0B2A8099F6D58B546C7EE734FD806CDFDDE5F41C38966EB61005CA78D970BFA2C77F099BB19543B559AA118B6F303644D541E83B293138BEF5B8F0B0382ACA8DBDD693845FF6B7EE6ABF1B8B4733998F31DBF74F9CBA5145A0C5345EDC5B056CDCAA3AF605701C56651B8A968AD6D7E421DD3B5F3765865D5FDC55252F25C9661CD71A43A20B13A16CFF3C4DDC50B +20170623040603 2 6 100 2047 5 EDB5FA2E865AD05F06510EFBFC71F9DFBAA5C1EEF3F6FDC2650C1D8C507DECA3422AE18746EA7D7BEA600C0AE9A0812A3DC02C099F8AF046EF014EC2A58734A716F156FCE4F19E3A9EB38F225A1CA0B868F70B3BE0CAE3AC2A20F330EF3CC33CB27D1FCB2D27505409144F957AC592567AC0B2A8099F6D58B546C7EE734FD806CDFDDE5F41C38966EB61005CA78D970BFA2C77F099BB19543B559AA118B6F303644D541E83B293138BEF5B8F0B0382ACA8DBDD693845FF6B7EE6ABF1B8B4733998F31DBF74F9CBA5145A0C5345EDC5B056CDCAA3AF605701C56651B8A968AD6D7E421DD3B5F3765865D5FDC55252F25C9661CD71A43A20B13A16CFF3C55E2BE7 +20170623040614 2 6 100 2047 5 EDB5FA2E865AD05F06510EFBFC71F9DFBAA5C1EEF3F6FDC2650C1D8C507DECA3422AE18746EA7D7BEA600C0AE9A0812A3DC02C099F8AF046EF014EC2A58734A716F156FCE4F19E3A9EB38F225A1CA0B868F70B3BE0CAE3AC2A20F330EF3CC33CB27D1FCB2D27505409144F957AC592567AC0B2A8099F6D58B546C7EE734FD806CDFDDE5F41C38966EB61005CA78D970BFA2C77F099BB19543B559AA118B6F303644D541E83B293138BEF5B8F0B0382ACA8DBDD693845FF6B7EE6ABF1B8B4733998F31DBF74F9CBA5145A0C5345EDC5B056CDCAA3AF605701C56651B8A968AD6D7E421DD3B5F3765865D5FDC55252F25C9661CD71A43A20B13A16CFF3C5715757 +20170623040626 2 6 100 2047 5 EDB5FA2E865AD05F06510EFBFC71F9DFBAA5C1EEF3F6FDC2650C1D8C507DECA3422AE18746EA7D7BEA600C0AE9A0812A3DC02C099F8AF046EF014EC2A58734A716F156FCE4F19E3A9EB38F225A1CA0B868F70B3BE0CAE3AC2A20F330EF3CC33CB27D1FCB2D27505409144F957AC592567AC0B2A8099F6D58B546C7EE734FD806CDFDDE5F41C38966EB61005CA78D970BFA2C77F099BB19543B559AA118B6F303644D541E83B293138BEF5B8F0B0382ACA8DBDD693845FF6B7EE6ABF1B8B4733998F31DBF74F9CBA5145A0C5345EDC5B056CDCAA3AF605701C56651B8A968AD6D7E421DD3B5F3765865D5FDC55252F25C9661CD71A43A20B13A16CFF3C58A0617 +20170623040632 2 6 100 2047 5 EDB5FA2E865AD05F06510EFBFC71F9DFBAA5C1EEF3F6FDC2650C1D8C507DECA3422AE18746EA7D7BEA600C0AE9A0812A3DC02C099F8AF046EF014EC2A58734A716F156FCE4F19E3A9EB38F225A1CA0B868F70B3BE0CAE3AC2A20F330EF3CC33CB27D1FCB2D27505409144F957AC592567AC0B2A8099F6D58B546C7EE734FD806CDFDDE5F41C38966EB61005CA78D970BFA2C77F099BB19543B559AA118B6F303644D541E83B293138BEF5B8F0B0382ACA8DBDD693845FF6B7EE6ABF1B8B4733998F31DBF74F9CBA5145A0C5345EDC5B056CDCAA3AF605701C56651B8A968AD6D7E421DD3B5F3765865D5FDC55252F25C9661CD71A43A20B13A16CFF3C5910FF7 +20170623040709 2 6 100 2047 2 EDB5FA2E865AD05F06510EFBFC71F9DFBAA5C1EEF3F6FDC2650C1D8C507DECA3422AE18746EA7D7BEA600C0AE9A0812A3DC02C099F8AF046EF014EC2A58734A716F156FCE4F19E3A9EB38F225A1CA0B868F70B3BE0CAE3AC2A20F330EF3CC33CB27D1FCB2D27505409144F957AC592567AC0B2A8099F6D58B546C7EE734FD806CDFDDE5F41C38966EB61005CA78D970BFA2C77F099BB19543B559AA118B6F303644D541E83B293138BEF5B8F0B0382ACA8DBDD693845FF6B7EE6ABF1B8B4733998F31DBF74F9CBA5145A0C5345EDC5B056CDCAA3AF605701C56651B8A968AD6D7E421DD3B5F3765865D5FDC55252F25C9661CD71A43A20B13A16CFF3C5E85ABB +20170623040729 2 6 100 2047 5 EDB5FA2E865AD05F06510EFBFC71F9DFBAA5C1EEF3F6FDC2650C1D8C507DECA3422AE18746EA7D7BEA600C0AE9A0812A3DC02C099F8AF046EF014EC2A58734A716F156FCE4F19E3A9EB38F225A1CA0B868F70B3BE0CAE3AC2A20F330EF3CC33CB27D1FCB2D27505409144F957AC592567AC0B2A8099F6D58B546C7EE734FD806CDFDDE5F41C38966EB61005CA78D970BFA2C77F099BB19543B559AA118B6F303644D541E83B293138BEF5B8F0B0382ACA8DBDD693845FF6B7EE6ABF1B8B4733998F31DBF74F9CBA5145A0C5345EDC5B056CDCAA3AF605701C56651B8A968AD6D7E421DD3B5F3765865D5FDC55252F25C9661CD71A43A20B13A16CFF3C61714B7 +20170623040745 2 6 100 2047 5 EDB5FA2E865AD05F06510EFBFC71F9DFBAA5C1EEF3F6FDC2650C1D8C507DECA3422AE18746EA7D7BEA600C0AE9A0812A3DC02C099F8AF046EF014EC2A58734A716F156FCE4F19E3A9EB38F225A1CA0B868F70B3BE0CAE3AC2A20F330EF3CC33CB27D1FCB2D27505409144F957AC592567AC0B2A8099F6D58B546C7EE734FD806CDFDDE5F41C38966EB61005CA78D970BFA2C77F099BB19543B559AA118B6F303644D541E83B293138BEF5B8F0B0382ACA8DBDD693845FF6B7EE6ABF1B8B4733998F31DBF74F9CBA5145A0C5345EDC5B056CDCAA3AF605701C56651B8A968AD6D7E421DD3B5F3765865D5FDC55252F25C9661CD71A43A20B13A16CFF3C6362DF7 +20170623040759 2 6 100 2047 2 EDB5FA2E865AD05F06510EFBFC71F9DFBAA5C1EEF3F6FDC2650C1D8C507DECA3422AE18746EA7D7BEA600C0AE9A0812A3DC02C099F8AF046EF014EC2A58734A716F156FCE4F19E3A9EB38F225A1CA0B868F70B3BE0CAE3AC2A20F330EF3CC33CB27D1FCB2D27505409144F957AC592567AC0B2A8099F6D58B546C7EE734FD806CDFDDE5F41C38966EB61005CA78D970BFA2C77F099BB19543B559AA118B6F303644D541E83B293138BEF5B8F0B0382ACA8DBDD693845FF6B7EE6ABF1B8B4733998F31DBF74F9CBA5145A0C5345EDC5B056CDCAA3AF605701C56651B8A968AD6D7E421DD3B5F3765865D5FDC55252F25C9661CD71A43A20B13A16CFF3C64F9EEB +20170623040829 2 6 100 2047 5 EDB5FA2E865AD05F06510EFBFC71F9DFBAA5C1EEF3F6FDC2650C1D8C507DECA3422AE18746EA7D7BEA600C0AE9A0812A3DC02C099F8AF046EF014EC2A58734A716F156FCE4F19E3A9EB38F225A1CA0B868F70B3BE0CAE3AC2A20F330EF3CC33CB27D1FCB2D27505409144F957AC592567AC0B2A8099F6D58B546C7EE734FD806CDFDDE5F41C38966EB61005CA78D970BFA2C77F099BB19543B559AA118B6F303644D541E83B293138BEF5B8F0B0382ACA8DBDD693845FF6B7EE6ABF1B8B4733998F31DBF74F9CBA5145A0C5345EDC5B056CDCAA3AF605701C56651B8A968AD6D7E421DD3B5F3765865D5FDC55252F25C9661CD71A43A20B13A16CFF3C6949627 +20170623040836 2 6 100 2047 2 EDB5FA2E865AD05F06510EFBFC71F9DFBAA5C1EEF3F6FDC2650C1D8C507DECA3422AE18746EA7D7BEA600C0AE9A0812A3DC02C099F8AF046EF014EC2A58734A716F156FCE4F19E3A9EB38F225A1CA0B868F70B3BE0CAE3AC2A20F330EF3CC33CB27D1FCB2D27505409144F957AC592567AC0B2A8099F6D58B546C7EE734FD806CDFDDE5F41C38966EB61005CA78D970BFA2C77F099BB19543B559AA118B6F303644D541E83B293138BEF5B8F0B0382ACA8DBDD693845FF6B7EE6ABF1B8B4733998F31DBF74F9CBA5145A0C5345EDC5B056CDCAA3AF605701C56651B8A968AD6D7E421DD3B5F3765865D5FDC55252F25C9661CD71A43A20B13A16CFF3C69F6763 +20170623040925 2 6 100 2047 2 EDB5FA2E865AD05F06510EFBFC71F9DFBAA5C1EEF3F6FDC2650C1D8C507DECA3422AE18746EA7D7BEA600C0AE9A0812A3DC02C099F8AF046EF014EC2A58734A716F156FCE4F19E3A9EB38F225A1CA0B868F70B3BE0CAE3AC2A20F330EF3CC33CB27D1FCB2D27505409144F957AC592567AC0B2A8099F6D58B546C7EE734FD806CDFDDE5F41C38966EB61005CA78D970BFA2C77F099BB19543B559AA118B6F303644D541E83B293138BEF5B8F0B0382ACA8DBDD693845FF6B7EE6ABF1B8B4733998F31DBF74F9CBA5145A0C5345EDC5B056CDCAA3AF605701C56651B8A968AD6D7E421DD3B5F3765865D5FDC55252F25C9661CD71A43A20B13A16CFF3C712B23B +20170623040941 2 6 100 2047 5 EDB5FA2E865AD05F06510EFBFC71F9DFBAA5C1EEF3F6FDC2650C1D8C507DECA3422AE18746EA7D7BEA600C0AE9A0812A3DC02C099F8AF046EF014EC2A58734A716F156FCE4F19E3A9EB38F225A1CA0B868F70B3BE0CAE3AC2A20F330EF3CC33CB27D1FCB2D27505409144F957AC592567AC0B2A8099F6D58B546C7EE734FD806CDFDDE5F41C38966EB61005CA78D970BFA2C77F099BB19543B559AA118B6F303644D541E83B293138BEF5B8F0B0382ACA8DBDD693845FF6B7EE6ABF1B8B4733998F31DBF74F9CBA5145A0C5345EDC5B056CDCAA3AF605701C56651B8A968AD6D7E421DD3B5F3765865D5FDC55252F25C9661CD71A43A20B13A16CFF3C7336C6F +20170623041004 2 6 100 2047 2 EDB5FA2E865AD05F06510EFBFC71F9DFBAA5C1EEF3F6FDC2650C1D8C507DECA3422AE18746EA7D7BEA600C0AE9A0812A3DC02C099F8AF046EF014EC2A58734A716F156FCE4F19E3A9EB38F225A1CA0B868F70B3BE0CAE3AC2A20F330EF3CC33CB27D1FCB2D27505409144F957AC592567AC0B2A8099F6D58B546C7EE734FD806CDFDDE5F41C38966EB61005CA78D970BFA2C77F099BB19543B559AA118B6F303644D541E83B293138BEF5B8F0B0382ACA8DBDD693845FF6B7EE6ABF1B8B4733998F31DBF74F9CBA5145A0C5345EDC5B056CDCAA3AF605701C56651B8A968AD6D7E421DD3B5F3765865D5FDC55252F25C9661CD71A43A20B13A16CFF3C76418FB +20170623041040 2 6 100 2047 2 EDB5FA2E865AD05F06510EFBFC71F9DFBAA5C1EEF3F6FDC2650C1D8C507DECA3422AE18746EA7D7BEA600C0AE9A0812A3DC02C099F8AF046EF014EC2A58734A716F156FCE4F19E3A9EB38F225A1CA0B868F70B3BE0CAE3AC2A20F330EF3CC33CB27D1FCB2D27505409144F957AC592567AC0B2A8099F6D58B546C7EE734FD806CDFDDE5F41C38966EB61005CA78D970BFA2C77F099BB19543B559AA118B6F303644D541E83B293138BEF5B8F0B0382ACA8DBDD693845FF6B7EE6ABF1B8B4733998F31DBF74F9CBA5145A0C5345EDC5B056CDCAA3AF605701C56651B8A968AD6D7E421DD3B5F3765865D5FDC55252F25C9661CD71A43A20B13A16CFF3C7B6A153 +20170623041049 2 6 100 2047 5 EDB5FA2E865AD05F06510EFBFC71F9DFBAA5C1EEF3F6FDC2650C1D8C507DECA3422AE18746EA7D7BEA600C0AE9A0812A3DC02C099F8AF046EF014EC2A58734A716F156FCE4F19E3A9EB38F225A1CA0B868F70B3BE0CAE3AC2A20F330EF3CC33CB27D1FCB2D27505409144F957AC592567AC0B2A8099F6D58B546C7EE734FD806CDFDDE5F41C38966EB61005CA78D970BFA2C77F099BB19543B559AA118B6F303644D541E83B293138BEF5B8F0B0382ACA8DBDD693845FF6B7EE6ABF1B8B4733998F31DBF74F9CBA5145A0C5345EDC5B056CDCAA3AF605701C56651B8A968AD6D7E421DD3B5F3765865D5FDC55252F25C9661CD71A43A20B13A16CFF3C7C6F12F +20170623041059 2 6 100 2047 5 EDB5FA2E865AD05F06510EFBFC71F9DFBAA5C1EEF3F6FDC2650C1D8C507DECA3422AE18746EA7D7BEA600C0AE9A0812A3DC02C099F8AF046EF014EC2A58734A716F156FCE4F19E3A9EB38F225A1CA0B868F70B3BE0CAE3AC2A20F330EF3CC33CB27D1FCB2D27505409144F957AC592567AC0B2A8099F6D58B546C7EE734FD806CDFDDE5F41C38966EB61005CA78D970BFA2C77F099BB19543B559AA118B6F303644D541E83B293138BEF5B8F0B0382ACA8DBDD693845FF6B7EE6ABF1B8B4733998F31DBF74F9CBA5145A0C5345EDC5B056CDCAA3AF605701C56651B8A968AD6D7E421DD3B5F3765865D5FDC55252F25C9661CD71A43A20B13A16CFF3C7D798EF +20170623041129 2 6 100 2047 2 EDB5FA2E865AD05F06510EFBFC71F9DFBAA5C1EEF3F6FDC2650C1D8C507DECA3422AE18746EA7D7BEA600C0AE9A0812A3DC02C099F8AF046EF014EC2A58734A716F156FCE4F19E3A9EB38F225A1CA0B868F70B3BE0CAE3AC2A20F330EF3CC33CB27D1FCB2D27505409144F957AC592567AC0B2A8099F6D58B546C7EE734FD806CDFDDE5F41C38966EB61005CA78D970BFA2C77F099BB19543B559AA118B6F303644D541E83B293138BEF5B8F0B0382ACA8DBDD693845FF6B7EE6ABF1B8B4733998F31DBF74F9CBA5145A0C5345EDC5B056CDCAA3AF605701C56651B8A968AD6D7E421DD3B5F3765865D5FDC55252F25C9661CD71A43A20B13A16CFF3C81D54F3 +20170623041311 2 6 100 2047 5 EDB5FA2E865AD05F06510EFBFC71F9DFBAA5C1EEF3F6FDC2650C1D8C507DECA3422AE18746EA7D7BEA600C0AE9A0812A3DC02C099F8AF046EF014EC2A58734A716F156FCE4F19E3A9EB38F225A1CA0B868F70B3BE0CAE3AC2A20F330EF3CC33CB27D1FCB2D27505409144F957AC592567AC0B2A8099F6D58B546C7EE734FD806CDFDDE5F41C38966EB61005CA78D970BFA2C77F099BB19543B559AA118B6F303644D541E83B293138BEF5B8F0B0382ACA8DBDD693845FF6B7EE6ABF1B8B4733998F31DBF74F9CBA5145A0C5345EDC5B056CDCAA3AF605701C56651B8A968AD6D7E421DD3B5F3765865D5FDC55252F25C9661CD71A43A20B13A16CFF3C919987F +20170623041314 2 6 100 2047 2 EDB5FA2E865AD05F06510EFBFC71F9DFBAA5C1EEF3F6FDC2650C1D8C507DECA3422AE18746EA7D7BEA600C0AE9A0812A3DC02C099F8AF046EF014EC2A58734A716F156FCE4F19E3A9EB38F225A1CA0B868F70B3BE0CAE3AC2A20F330EF3CC33CB27D1FCB2D27505409144F957AC592567AC0B2A8099F6D58B546C7EE734FD806CDFDDE5F41C38966EB61005CA78D970BFA2C77F099BB19543B559AA118B6F303644D541E83B293138BEF5B8F0B0382ACA8DBDD693845FF6B7EE6ABF1B8B4733998F31DBF74F9CBA5145A0C5345EDC5B056CDCAA3AF605701C56651B8A968AD6D7E421DD3B5F3765865D5FDC55252F25C9661CD71A43A20B13A16CFF3C91A831B +20170623041341 2 6 100 2047 5 EDB5FA2E865AD05F06510EFBFC71F9DFBAA5C1EEF3F6FDC2650C1D8C507DECA3422AE18746EA7D7BEA600C0AE9A0812A3DC02C099F8AF046EF014EC2A58734A716F156FCE4F19E3A9EB38F225A1CA0B868F70B3BE0CAE3AC2A20F330EF3CC33CB27D1FCB2D27505409144F957AC592567AC0B2A8099F6D58B546C7EE734FD806CDFDDE5F41C38966EB61005CA78D970BFA2C77F099BB19543B559AA118B6F303644D541E83B293138BEF5B8F0B0382ACA8DBDD693845FF6B7EE6ABF1B8B4733998F31DBF74F9CBA5145A0C5345EDC5B056CDCAA3AF605701C56651B8A968AD6D7E421DD3B5F3765865D5FDC55252F25C9661CD71A43A20B13A16CFF3C95422FF +20170623041350 2 6 100 2047 5 EDB5FA2E865AD05F06510EFBFC71F9DFBAA5C1EEF3F6FDC2650C1D8C507DECA3422AE18746EA7D7BEA600C0AE9A0812A3DC02C099F8AF046EF014EC2A58734A716F156FCE4F19E3A9EB38F225A1CA0B868F70B3BE0CAE3AC2A20F330EF3CC33CB27D1FCB2D27505409144F957AC592567AC0B2A8099F6D58B546C7EE734FD806CDFDDE5F41C38966EB61005CA78D970BFA2C77F099BB19543B559AA118B6F303644D541E83B293138BEF5B8F0B0382ACA8DBDD693845FF6B7EE6ABF1B8B4733998F31DBF74F9CBA5145A0C5345EDC5B056CDCAA3AF605701C56651B8A968AD6D7E421DD3B5F3765865D5FDC55252F25C9661CD71A43A20B13A16CFF3C9646B7F +20170623041354 2 6 100 2047 5 EDB5FA2E865AD05F06510EFBFC71F9DFBAA5C1EEF3F6FDC2650C1D8C507DECA3422AE18746EA7D7BEA600C0AE9A0812A3DC02C099F8AF046EF014EC2A58734A716F156FCE4F19E3A9EB38F225A1CA0B868F70B3BE0CAE3AC2A20F330EF3CC33CB27D1FCB2D27505409144F957AC592567AC0B2A8099F6D58B546C7EE734FD806CDFDDE5F41C38966EB61005CA78D970BFA2C77F099BB19543B559AA118B6F303644D541E83B293138BEF5B8F0B0382ACA8DBDD693845FF6B7EE6ABF1B8B4733998F31DBF74F9CBA5145A0C5345EDC5B056CDCAA3AF605701C56651B8A968AD6D7E421DD3B5F3765865D5FDC55252F25C9661CD71A43A20B13A16CFF3C9662E87 +20170623041503 2 6 100 2047 2 EDB5FA2E865AD05F06510EFBFC71F9DFBAA5C1EEF3F6FDC2650C1D8C507DECA3422AE18746EA7D7BEA600C0AE9A0812A3DC02C099F8AF046EF014EC2A58734A716F156FCE4F19E3A9EB38F225A1CA0B868F70B3BE0CAE3AC2A20F330EF3CC33CB27D1FCB2D27505409144F957AC592567AC0B2A8099F6D58B546C7EE734FD806CDFDDE5F41C38966EB61005CA78D970BFA2C77F099BB19543B559AA118B6F303644D541E83B293138BEF5B8F0B0382ACA8DBDD693845FF6B7EE6ABF1B8B4733998F31DBF74F9CBA5145A0C5345EDC5B056CDCAA3AF605701C56651B8A968AD6D7E421DD3B5F3765865D5FDC55252F25C9661CD71A43A20B13A16CFF3CA105123 +20170623041522 2 6 100 2047 5 EDB5FA2E865AD05F06510EFBFC71F9DFBAA5C1EEF3F6FDC2650C1D8C507DECA3422AE18746EA7D7BEA600C0AE9A0812A3DC02C099F8AF046EF014EC2A58734A716F156FCE4F19E3A9EB38F225A1CA0B868F70B3BE0CAE3AC2A20F330EF3CC33CB27D1FCB2D27505409144F957AC592567AC0B2A8099F6D58B546C7EE734FD806CDFDDE5F41C38966EB61005CA78D970BFA2C77F099BB19543B559AA118B6F303644D541E83B293138BEF5B8F0B0382ACA8DBDD693845FF6B7EE6ABF1B8B4733998F31DBF74F9CBA5145A0C5345EDC5B056CDCAA3AF605701C56651B8A968AD6D7E421DD3B5F3765865D5FDC55252F25C9661CD71A43A20B13A16CFF3CA3BE707 +20170623041541 2 6 100 2047 2 EDB5FA2E865AD05F06510EFBFC71F9DFBAA5C1EEF3F6FDC2650C1D8C507DECA3422AE18746EA7D7BEA600C0AE9A0812A3DC02C099F8AF046EF014EC2A58734A716F156FCE4F19E3A9EB38F225A1CA0B868F70B3BE0CAE3AC2A20F330EF3CC33CB27D1FCB2D27505409144F957AC592567AC0B2A8099F6D58B546C7EE734FD806CDFDDE5F41C38966EB61005CA78D970BFA2C77F099BB19543B559AA118B6F303644D541E83B293138BEF5B8F0B0382ACA8DBDD693845FF6B7EE6ABF1B8B4733998F31DBF74F9CBA5145A0C5345EDC5B056CDCAA3AF605701C56651B8A968AD6D7E421DD3B5F3765865D5FDC55252F25C9661CD71A43A20B13A16CFF3CA620DAB +20170623041546 2 6 100 2047 2 EDB5FA2E865AD05F06510EFBFC71F9DFBAA5C1EEF3F6FDC2650C1D8C507DECA3422AE18746EA7D7BEA600C0AE9A0812A3DC02C099F8AF046EF014EC2A58734A716F156FCE4F19E3A9EB38F225A1CA0B868F70B3BE0CAE3AC2A20F330EF3CC33CB27D1FCB2D27505409144F957AC592567AC0B2A8099F6D58B546C7EE734FD806CDFDDE5F41C38966EB61005CA78D970BFA2C77F099BB19543B559AA118B6F303644D541E83B293138BEF5B8F0B0382ACA8DBDD693845FF6B7EE6ABF1B8B4733998F31DBF74F9CBA5145A0C5345EDC5B056CDCAA3AF605701C56651B8A968AD6D7E421DD3B5F3765865D5FDC55252F25C9661CD71A43A20B13A16CFF3CA66FFC3 +20170623041620 2 6 100 2047 2 EDB5FA2E865AD05F06510EFBFC71F9DFBAA5C1EEF3F6FDC2650C1D8C507DECA3422AE18746EA7D7BEA600C0AE9A0812A3DC02C099F8AF046EF014EC2A58734A716F156FCE4F19E3A9EB38F225A1CA0B868F70B3BE0CAE3AC2A20F330EF3CC33CB27D1FCB2D27505409144F957AC592567AC0B2A8099F6D58B546C7EE734FD806CDFDDE5F41C38966EB61005CA78D970BFA2C77F099BB19543B559AA118B6F303644D541E83B293138BEF5B8F0B0382ACA8DBDD693845FF6B7EE6ABF1B8B4733998F31DBF74F9CBA5145A0C5345EDC5B056CDCAA3AF605701C56651B8A968AD6D7E421DD3B5F3765865D5FDC55252F25C9661CD71A43A20B13A16CFF3CAB69493 +20170623041704 2 6 100 2047 2 EDB5FA2E865AD05F06510EFBFC71F9DFBAA5C1EEF3F6FDC2650C1D8C507DECA3422AE18746EA7D7BEA600C0AE9A0812A3DC02C099F8AF046EF014EC2A58734A716F156FCE4F19E3A9EB38F225A1CA0B868F70B3BE0CAE3AC2A20F330EF3CC33CB27D1FCB2D27505409144F957AC592567AC0B2A8099F6D58B546C7EE734FD806CDFDDE5F41C38966EB61005CA78D970BFA2C77F099BB19543B559AA118B6F303644D541E83B293138BEF5B8F0B0382ACA8DBDD693845FF6B7EE6ABF1B8B4733998F31DBF74F9CBA5145A0C5345EDC5B056CDCAA3AF605701C56651B8A968AD6D7E421DD3B5F3765865D5FDC55252F25C9661CD71A43A20B13A16CFF3CB1C2B4B +20170623041709 2 6 100 2047 2 EDB5FA2E865AD05F06510EFBFC71F9DFBAA5C1EEF3F6FDC2650C1D8C507DECA3422AE18746EA7D7BEA600C0AE9A0812A3DC02C099F8AF046EF014EC2A58734A716F156FCE4F19E3A9EB38F225A1CA0B868F70B3BE0CAE3AC2A20F330EF3CC33CB27D1FCB2D27505409144F957AC592567AC0B2A8099F6D58B546C7EE734FD806CDFDDE5F41C38966EB61005CA78D970BFA2C77F099BB19543B559AA118B6F303644D541E83B293138BEF5B8F0B0382ACA8DBDD693845FF6B7EE6ABF1B8B4733998F31DBF74F9CBA5145A0C5345EDC5B056CDCAA3AF605701C56651B8A968AD6D7E421DD3B5F3765865D5FDC55252F25C9661CD71A43A20B13A16CFF3CB1FD10B +20170623041747 2 6 100 2047 2 EDB5FA2E865AD05F06510EFBFC71F9DFBAA5C1EEF3F6FDC2650C1D8C507DECA3422AE18746EA7D7BEA600C0AE9A0812A3DC02C099F8AF046EF014EC2A58734A716F156FCE4F19E3A9EB38F225A1CA0B868F70B3BE0CAE3AC2A20F330EF3CC33CB27D1FCB2D27505409144F957AC592567AC0B2A8099F6D58B546C7EE734FD806CDFDDE5F41C38966EB61005CA78D970BFA2C77F099BB19543B559AA118B6F303644D541E83B293138BEF5B8F0B0382ACA8DBDD693845FF6B7EE6ABF1B8B4733998F31DBF74F9CBA5145A0C5345EDC5B056CDCAA3AF605701C56651B8A968AD6D7E421DD3B5F3765865D5FDC55252F25C9661CD71A43A20B13A16CFF3CB7550DB +20170623041822 2 6 100 2047 2 EDB5FA2E865AD05F06510EFBFC71F9DFBAA5C1EEF3F6FDC2650C1D8C507DECA3422AE18746EA7D7BEA600C0AE9A0812A3DC02C099F8AF046EF014EC2A58734A716F156FCE4F19E3A9EB38F225A1CA0B868F70B3BE0CAE3AC2A20F330EF3CC33CB27D1FCB2D27505409144F957AC592567AC0B2A8099F6D58B546C7EE734FD806CDFDDE5F41C38966EB61005CA78D970BFA2C77F099BB19543B559AA118B6F303644D541E83B293138BEF5B8F0B0382ACA8DBDD693845FF6B7EE6ABF1B8B4733998F31DBF74F9CBA5145A0C5345EDC5B056CDCAA3AF605701C56651B8A968AD6D7E421DD3B5F3765865D5FDC55252F25C9661CD71A43A20B13A16CFF3CBC63D2B +20170623041830 2 6 100 2047 2 EDB5FA2E865AD05F06510EFBFC71F9DFBAA5C1EEF3F6FDC2650C1D8C507DECA3422AE18746EA7D7BEA600C0AE9A0812A3DC02C099F8AF046EF014EC2A58734A716F156FCE4F19E3A9EB38F225A1CA0B868F70B3BE0CAE3AC2A20F330EF3CC33CB27D1FCB2D27505409144F957AC592567AC0B2A8099F6D58B546C7EE734FD806CDFDDE5F41C38966EB61005CA78D970BFA2C77F099BB19543B559AA118B6F303644D541E83B293138BEF5B8F0B0382ACA8DBDD693845FF6B7EE6ABF1B8B4733998F31DBF74F9CBA5145A0C5345EDC5B056CDCAA3AF605701C56651B8A968AD6D7E421DD3B5F3765865D5FDC55252F25C9661CD71A43A20B13A16CFF3CBD499AB +20170623043901 2 6 100 3071 2 E795DA675C82260F11D7C50B677AE8A8D94BF342724BB06FA0D426CE2E83E8971A1BE2AC59516488B25D561568B14DBBFFB5F33686D2952409B9C20FC19A13CB91C9176420F59F464DC198E254B87C765DC12B885CF1A463858C3CB0A918AF66C6A2CA06A48B4D5BDEB5A56B24C36BA330488DFCBDD499957E755CCE704F183CB4549441A7D761C22B7F7CB66BE50F0A6591F17778F51E73544B765E83A3C00BD3309F8CE1B135A3DD481DBE8C2CEE54E8DDF1351015E70D9012662E69F654A5A9F68C416167685A1695C8139BA1825287C98680945506D5AB750BEB68C6D2B430E7E4043D0A00DECDA77F81A2432929F530C5BC0CBBC011095D897BD81FB98792345F5372BA53E53F31FB09730C58E8FDA9F7C1EBA0AEA4FE50B2B5CE146043CB18BFB3A12F06ED1D3287242D3D59E85E0A5E243626525D3EAD946126B9F32590011EEA0EDD5E2025037D51940B3E1A45B614A23F48278977535E3773F0AA2A24413F4A397AC0881582E8832C7B140C0BA4818A55C8620FD2BEBB5508B03E93 +20170623044452 2 6 100 3071 5 E795DA675C82260F11D7C50B677AE8A8D94BF342724BB06FA0D426CE2E83E8971A1BE2AC59516488B25D561568B14DBBFFB5F33686D2952409B9C20FC19A13CB91C9176420F59F464DC198E254B87C765DC12B885CF1A463858C3CB0A918AF66C6A2CA06A48B4D5BDEB5A56B24C36BA330488DFCBDD499957E755CCE704F183CB4549441A7D761C22B7F7CB66BE50F0A6591F17778F51E73544B765E83A3C00BD3309F8CE1B135A3DD481DBE8C2CEE54E8DDF1351015E70D9012662E69F654A5A9F68C416167685A1695C8139BA1825287C98680945506D5AB750BEB68C6D2B430E7E4043D0A00DECDA77F81A2432929F530C5BC0CBBC011095D897BD81FB98792345F5372BA53E53F31FB09730C58E8FDA9F7C1EBA0AEA4FE50B2B5CE146043CB18BFB3A12F06ED1D3287242D3D59E85E0A5E243626525D3EAD946126B9F32590011EEA0EDD5E2025037D51940B3E1A45B614A23F48278977535E3773F0AA2A24413F4A397AC0881582E8832C7B140C0BA4818A55C8620FD2BEBB5509C5C937 +20170623044600 2 6 100 3071 2 E795DA675C82260F11D7C50B677AE8A8D94BF342724BB06FA0D426CE2E83E8971A1BE2AC59516488B25D561568B14DBBFFB5F33686D2952409B9C20FC19A13CB91C9176420F59F464DC198E254B87C765DC12B885CF1A463858C3CB0A918AF66C6A2CA06A48B4D5BDEB5A56B24C36BA330488DFCBDD499957E755CCE704F183CB4549441A7D761C22B7F7CB66BE50F0A6591F17778F51E73544B765E83A3C00BD3309F8CE1B135A3DD481DBE8C2CEE54E8DDF1351015E70D9012662E69F654A5A9F68C416167685A1695C8139BA1825287C98680945506D5AB750BEB68C6D2B430E7E4043D0A00DECDA77F81A2432929F530C5BC0CBBC011095D897BD81FB98792345F5372BA53E53F31FB09730C58E8FDA9F7C1EBA0AEA4FE50B2B5CE146043CB18BFB3A12F06ED1D3287242D3D59E85E0A5E243626525D3EAD946126B9F32590011EEA0EDD5E2025037D51940B3E1A45B614A23F48278977535E3773F0AA2A24413F4A397AC0881582E8832C7B140C0BA4818A55C8620FD2BEBB5509F436FB +20170623044825 2 6 100 3071 2 E795DA675C82260F11D7C50B677AE8A8D94BF342724BB06FA0D426CE2E83E8971A1BE2AC59516488B25D561568B14DBBFFB5F33686D2952409B9C20FC19A13CB91C9176420F59F464DC198E254B87C765DC12B885CF1A463858C3CB0A918AF66C6A2CA06A48B4D5BDEB5A56B24C36BA330488DFCBDD499957E755CCE704F183CB4549441A7D761C22B7F7CB66BE50F0A6591F17778F51E73544B765E83A3C00BD3309F8CE1B135A3DD481DBE8C2CEE54E8DDF1351015E70D9012662E69F654A5A9F68C416167685A1695C8139BA1825287C98680945506D5AB750BEB68C6D2B430E7E4043D0A00DECDA77F81A2432929F530C5BC0CBBC011095D897BD81FB98792345F5372BA53E53F31FB09730C58E8FDA9F7C1EBA0AEA4FE50B2B5CE146043CB18BFB3A12F06ED1D3287242D3D59E85E0A5E243626525D3EAD946126B9F32590011EEA0EDD5E2025037D51940B3E1A45B614A23F48278977535E3773F0AA2A24413F4A397AC0881582E8832C7B140C0BA4818A55C8620FD2BEBB550A640733 +20170623045050 2 6 100 3071 2 E795DA675C82260F11D7C50B677AE8A8D94BF342724BB06FA0D426CE2E83E8971A1BE2AC59516488B25D561568B14DBBFFB5F33686D2952409B9C20FC19A13CB91C9176420F59F464DC198E254B87C765DC12B885CF1A463858C3CB0A918AF66C6A2CA06A48B4D5BDEB5A56B24C36BA330488DFCBDD499957E755CCE704F183CB4549441A7D761C22B7F7CB66BE50F0A6591F17778F51E73544B765E83A3C00BD3309F8CE1B135A3DD481DBE8C2CEE54E8DDF1351015E70D9012662E69F654A5A9F68C416167685A1695C8139BA1825287C98680945506D5AB750BEB68C6D2B430E7E4043D0A00DECDA77F81A2432929F530C5BC0CBBC011095D897BD81FB98792345F5372BA53E53F31FB09730C58E8FDA9F7C1EBA0AEA4FE50B2B5CE146043CB18BFB3A12F06ED1D3287242D3D59E85E0A5E243626525D3EAD946126B9F32590011EEA0EDD5E2025037D51940B3E1A45B614A23F48278977535E3773F0AA2A24413F4A397AC0881582E8832C7B140C0BA4818A55C8620FD2BEBB550AD6755B +20170623045124 2 6 100 3071 2 E795DA675C82260F11D7C50B677AE8A8D94BF342724BB06FA0D426CE2E83E8971A1BE2AC59516488B25D561568B14DBBFFB5F33686D2952409B9C20FC19A13CB91C9176420F59F464DC198E254B87C765DC12B885CF1A463858C3CB0A918AF66C6A2CA06A48B4D5BDEB5A56B24C36BA330488DFCBDD499957E755CCE704F183CB4549441A7D761C22B7F7CB66BE50F0A6591F17778F51E73544B765E83A3C00BD3309F8CE1B135A3DD481DBE8C2CEE54E8DDF1351015E70D9012662E69F654A5A9F68C416167685A1695C8139BA1825287C98680945506D5AB750BEB68C6D2B430E7E4043D0A00DECDA77F81A2432929F530C5BC0CBBC011095D897BD81FB98792345F5372BA53E53F31FB09730C58E8FDA9F7C1EBA0AEA4FE50B2B5CE146043CB18BFB3A12F06ED1D3287242D3D59E85E0A5E243626525D3EAD946126B9F32590011EEA0EDD5E2025037D51940B3E1A45B614A23F48278977535E3773F0AA2A24413F4A397AC0881582E8832C7B140C0BA4818A55C8620FD2BEBB550AE93B43 +20170623045420 2 6 100 3071 2 E795DA675C82260F11D7C50B677AE8A8D94BF342724BB06FA0D426CE2E83E8971A1BE2AC59516488B25D561568B14DBBFFB5F33686D2952409B9C20FC19A13CB91C9176420F59F464DC198E254B87C765DC12B885CF1A463858C3CB0A918AF66C6A2CA06A48B4D5BDEB5A56B24C36BA330488DFCBDD499957E755CCE704F183CB4549441A7D761C22B7F7CB66BE50F0A6591F17778F51E73544B765E83A3C00BD3309F8CE1B135A3DD481DBE8C2CEE54E8DDF1351015E70D9012662E69F654A5A9F68C416167685A1695C8139BA1825287C98680945506D5AB750BEB68C6D2B430E7E4043D0A00DECDA77F81A2432929F530C5BC0CBBC011095D897BD81FB98792345F5372BA53E53F31FB09730C58E8FDA9F7C1EBA0AEA4FE50B2B5CE146043CB18BFB3A12F06ED1D3287242D3D59E85E0A5E243626525D3EAD946126B9F32590011EEA0EDD5E2025037D51940B3E1A45B614A23F48278977535E3773F0AA2A24413F4A397AC0881582E8832C7B140C0BA4818A55C8620FD2BEBB550B6F1ED3 +20170623045805 2 6 100 3071 5 E795DA675C82260F11D7C50B677AE8A8D94BF342724BB06FA0D426CE2E83E8971A1BE2AC59516488B25D561568B14DBBFFB5F33686D2952409B9C20FC19A13CB91C9176420F59F464DC198E254B87C765DC12B885CF1A463858C3CB0A918AF66C6A2CA06A48B4D5BDEB5A56B24C36BA330488DFCBDD499957E755CCE704F183CB4549441A7D761C22B7F7CB66BE50F0A6591F17778F51E73544B765E83A3C00BD3309F8CE1B135A3DD481DBE8C2CEE54E8DDF1351015E70D9012662E69F654A5A9F68C416167685A1695C8139BA1825287C98680945506D5AB750BEB68C6D2B430E7E4043D0A00DECDA77F81A2432929F530C5BC0CBBC011095D897BD81FB98792345F5372BA53E53F31FB09730C58E8FDA9F7C1EBA0AEA4FE50B2B5CE146043CB18BFB3A12F06ED1D3287242D3D59E85E0A5E243626525D3EAD946126B9F32590011EEA0EDD5E2025037D51940B3E1A45B614A23F48278977535E3773F0AA2A24413F4A397AC0881582E8832C7B140C0BA4818A55C8620FD2BEBB550C20298F +20170623045930 2 6 100 3071 5 E795DA675C82260F11D7C50B677AE8A8D94BF342724BB06FA0D426CE2E83E8971A1BE2AC59516488B25D561568B14DBBFFB5F33686D2952409B9C20FC19A13CB91C9176420F59F464DC198E254B87C765DC12B885CF1A463858C3CB0A918AF66C6A2CA06A48B4D5BDEB5A56B24C36BA330488DFCBDD499957E755CCE704F183CB4549441A7D761C22B7F7CB66BE50F0A6591F17778F51E73544B765E83A3C00BD3309F8CE1B135A3DD481DBE8C2CEE54E8DDF1351015E70D9012662E69F654A5A9F68C416167685A1695C8139BA1825287C98680945506D5AB750BEB68C6D2B430E7E4043D0A00DECDA77F81A2432929F530C5BC0CBBC011095D897BD81FB98792345F5372BA53E53F31FB09730C58E8FDA9F7C1EBA0AEA4FE50B2B5CE146043CB18BFB3A12F06ED1D3287242D3D59E85E0A5E243626525D3EAD946126B9F32590011EEA0EDD5E2025037D51940B3E1A45B614A23F48278977535E3773F0AA2A24413F4A397AC0881582E8832C7B140C0BA4818A55C8620FD2BEBB550C5914BF +20170623050341 2 6 100 3071 2 E795DA675C82260F11D7C50B677AE8A8D94BF342724BB06FA0D426CE2E83E8971A1BE2AC59516488B25D561568B14DBBFFB5F33686D2952409B9C20FC19A13CB91C9176420F59F464DC198E254B87C765DC12B885CF1A463858C3CB0A918AF66C6A2CA06A48B4D5BDEB5A56B24C36BA330488DFCBDD499957E755CCE704F183CB4549441A7D761C22B7F7CB66BE50F0A6591F17778F51E73544B765E83A3C00BD3309F8CE1B135A3DD481DBE8C2CEE54E8DDF1351015E70D9012662E69F654A5A9F68C416167685A1695C8139BA1825287C98680945506D5AB750BEB68C6D2B430E7E4043D0A00DECDA77F81A2432929F530C5BC0CBBC011095D897BD81FB98792345F5372BA53E53F31FB09730C58E8FDA9F7C1EBA0AEA4FE50B2B5CE146043CB18BFB3A12F06ED1D3287242D3D59E85E0A5E243626525D3EAD946126B9F32590011EEA0EDD5E2025037D51940B3E1A45B614A23F48278977535E3773F0AA2A24413F4A397AC0881582E8832C7B140C0BA4818A55C8620FD2BEBB550D1A1773 +20170623050720 2 6 100 3071 2 E795DA675C82260F11D7C50B677AE8A8D94BF342724BB06FA0D426CE2E83E8971A1BE2AC59516488B25D561568B14DBBFFB5F33686D2952409B9C20FC19A13CB91C9176420F59F464DC198E254B87C765DC12B885CF1A463858C3CB0A918AF66C6A2CA06A48B4D5BDEB5A56B24C36BA330488DFCBDD499957E755CCE704F183CB4549441A7D761C22B7F7CB66BE50F0A6591F17778F51E73544B765E83A3C00BD3309F8CE1B135A3DD481DBE8C2CEE54E8DDF1351015E70D9012662E69F654A5A9F68C416167685A1695C8139BA1825287C98680945506D5AB750BEB68C6D2B430E7E4043D0A00DECDA77F81A2432929F530C5BC0CBBC011095D897BD81FB98792345F5372BA53E53F31FB09730C58E8FDA9F7C1EBA0AEA4FE50B2B5CE146043CB18BFB3A12F06ED1D3287242D3D59E85E0A5E243626525D3EAD946126B9F32590011EEA0EDD5E2025037D51940B3E1A45B614A23F48278977535E3773F0AA2A24413F4A397AC0881582E8832C7B140C0BA4818A55C8620FD2BEBB550DC219FB +20170623051801 2 6 100 3071 5 E795DA675C82260F11D7C50B677AE8A8D94BF342724BB06FA0D426CE2E83E8971A1BE2AC59516488B25D561568B14DBBFFB5F33686D2952409B9C20FC19A13CB91C9176420F59F464DC198E254B87C765DC12B885CF1A463858C3CB0A918AF66C6A2CA06A48B4D5BDEB5A56B24C36BA330488DFCBDD499957E755CCE704F183CB4549441A7D761C22B7F7CB66BE50F0A6591F17778F51E73544B765E83A3C00BD3309F8CE1B135A3DD481DBE8C2CEE54E8DDF1351015E70D9012662E69F654A5A9F68C416167685A1695C8139BA1825287C98680945506D5AB750BEB68C6D2B430E7E4043D0A00DECDA77F81A2432929F530C5BC0CBBC011095D897BD81FB98792345F5372BA53E53F31FB09730C58E8FDA9F7C1EBA0AEA4FE50B2B5CE146043CB18BFB3A12F06ED1D3287242D3D59E85E0A5E243626525D3EAD946126B9F32590011EEA0EDD5E2025037D51940B3E1A45B614A23F48278977535E3773F0AA2A24413F4A397AC0881582E8832C7B140C0BA4818A55C8620FD2BEBB550FBDD1AF +20170623052216 2 6 100 3071 2 E795DA675C82260F11D7C50B677AE8A8D94BF342724BB06FA0D426CE2E83E8971A1BE2AC59516488B25D561568B14DBBFFB5F33686D2952409B9C20FC19A13CB91C9176420F59F464DC198E254B87C765DC12B885CF1A463858C3CB0A918AF66C6A2CA06A48B4D5BDEB5A56B24C36BA330488DFCBDD499957E755CCE704F183CB4549441A7D761C22B7F7CB66BE50F0A6591F17778F51E73544B765E83A3C00BD3309F8CE1B135A3DD481DBE8C2CEE54E8DDF1351015E70D9012662E69F654A5A9F68C416167685A1695C8139BA1825287C98680945506D5AB750BEB68C6D2B430E7E4043D0A00DECDA77F81A2432929F530C5BC0CBBC011095D897BD81FB98792345F5372BA53E53F31FB09730C58E8FDA9F7C1EBA0AEA4FE50B2B5CE146043CB18BFB3A12F06ED1D3287242D3D59E85E0A5E243626525D3EAD946126B9F32590011EEA0EDD5E2025037D51940B3E1A45B614A23F48278977535E3773F0AA2A24413F4A397AC0881582E8832C7B140C0BA4818A55C8620FD2BEBB5510842093 +20170623052416 2 6 100 3071 5 E795DA675C82260F11D7C50B677AE8A8D94BF342724BB06FA0D426CE2E83E8971A1BE2AC59516488B25D561568B14DBBFFB5F33686D2952409B9C20FC19A13CB91C9176420F59F464DC198E254B87C765DC12B885CF1A463858C3CB0A918AF66C6A2CA06A48B4D5BDEB5A56B24C36BA330488DFCBDD499957E755CCE704F183CB4549441A7D761C22B7F7CB66BE50F0A6591F17778F51E73544B765E83A3C00BD3309F8CE1B135A3DD481DBE8C2CEE54E8DDF1351015E70D9012662E69F654A5A9F68C416167685A1695C8139BA1825287C98680945506D5AB750BEB68C6D2B430E7E4043D0A00DECDA77F81A2432929F530C5BC0CBBC011095D897BD81FB98792345F5372BA53E53F31FB09730C58E8FDA9F7C1EBA0AEA4FE50B2B5CE146043CB18BFB3A12F06ED1D3287242D3D59E85E0A5E243626525D3EAD946126B9F32590011EEA0EDD5E2025037D51940B3E1A45B614A23F48278977535E3773F0AA2A24413F4A397AC0881582E8832C7B140C0BA4818A55C8620FD2BEBB5510DBFCD7 +20170623052526 2 6 100 3071 2 E795DA675C82260F11D7C50B677AE8A8D94BF342724BB06FA0D426CE2E83E8971A1BE2AC59516488B25D561568B14DBBFFB5F33686D2952409B9C20FC19A13CB91C9176420F59F464DC198E254B87C765DC12B885CF1A463858C3CB0A918AF66C6A2CA06A48B4D5BDEB5A56B24C36BA330488DFCBDD499957E755CCE704F183CB4549441A7D761C22B7F7CB66BE50F0A6591F17778F51E73544B765E83A3C00BD3309F8CE1B135A3DD481DBE8C2CEE54E8DDF1351015E70D9012662E69F654A5A9F68C416167685A1695C8139BA1825287C98680945506D5AB750BEB68C6D2B430E7E4043D0A00DECDA77F81A2432929F530C5BC0CBBC011095D897BD81FB98792345F5372BA53E53F31FB09730C58E8FDA9F7C1EBA0AEA4FE50B2B5CE146043CB18BFB3A12F06ED1D3287242D3D59E85E0A5E243626525D3EAD946126B9F32590011EEA0EDD5E2025037D51940B3E1A45B614A23F48278977535E3773F0AA2A24413F4A397AC0881582E8832C7B140C0BA4818A55C8620FD2BEBB55110BB843 +20170623052831 2 6 100 3071 2 E795DA675C82260F11D7C50B677AE8A8D94BF342724BB06FA0D426CE2E83E8971A1BE2AC59516488B25D561568B14DBBFFB5F33686D2952409B9C20FC19A13CB91C9176420F59F464DC198E254B87C765DC12B885CF1A463858C3CB0A918AF66C6A2CA06A48B4D5BDEB5A56B24C36BA330488DFCBDD499957E755CCE704F183CB4549441A7D761C22B7F7CB66BE50F0A6591F17778F51E73544B765E83A3C00BD3309F8CE1B135A3DD481DBE8C2CEE54E8DDF1351015E70D9012662E69F654A5A9F68C416167685A1695C8139BA1825287C98680945506D5AB750BEB68C6D2B430E7E4043D0A00DECDA77F81A2432929F530C5BC0CBBC011095D897BD81FB98792345F5372BA53E53F31FB09730C58E8FDA9F7C1EBA0AEA4FE50B2B5CE146043CB18BFB3A12F06ED1D3287242D3D59E85E0A5E243626525D3EAD946126B9F32590011EEA0EDD5E2025037D51940B3E1A45B614A23F48278977535E3773F0AA2A24413F4A397AC0881582E8832C7B140C0BA4818A55C8620FD2BEBB551196B36B +20170623053119 2 6 100 3071 5 E795DA675C82260F11D7C50B677AE8A8D94BF342724BB06FA0D426CE2E83E8971A1BE2AC59516488B25D561568B14DBBFFB5F33686D2952409B9C20FC19A13CB91C9176420F59F464DC198E254B87C765DC12B885CF1A463858C3CB0A918AF66C6A2CA06A48B4D5BDEB5A56B24C36BA330488DFCBDD499957E755CCE704F183CB4549441A7D761C22B7F7CB66BE50F0A6591F17778F51E73544B765E83A3C00BD3309F8CE1B135A3DD481DBE8C2CEE54E8DDF1351015E70D9012662E69F654A5A9F68C416167685A1695C8139BA1825287C98680945506D5AB750BEB68C6D2B430E7E4043D0A00DECDA77F81A2432929F530C5BC0CBBC011095D897BD81FB98792345F5372BA53E53F31FB09730C58E8FDA9F7C1EBA0AEA4FE50B2B5CE146043CB18BFB3A12F06ED1D3287242D3D59E85E0A5E243626525D3EAD946126B9F32590011EEA0EDD5E2025037D51940B3E1A45B614A23F48278977535E3773F0AA2A24413F4A397AC0881582E8832C7B140C0BA4818A55C8620FD2BEBB551217A237 +20170623053458 2 6 100 3071 5 E795DA675C82260F11D7C50B677AE8A8D94BF342724BB06FA0D426CE2E83E8971A1BE2AC59516488B25D561568B14DBBFFB5F33686D2952409B9C20FC19A13CB91C9176420F59F464DC198E254B87C765DC12B885CF1A463858C3CB0A918AF66C6A2CA06A48B4D5BDEB5A56B24C36BA330488DFCBDD499957E755CCE704F183CB4549441A7D761C22B7F7CB66BE50F0A6591F17778F51E73544B765E83A3C00BD3309F8CE1B135A3DD481DBE8C2CEE54E8DDF1351015E70D9012662E69F654A5A9F68C416167685A1695C8139BA1825287C98680945506D5AB750BEB68C6D2B430E7E4043D0A00DECDA77F81A2432929F530C5BC0CBBC011095D897BD81FB98792345F5372BA53E53F31FB09730C58E8FDA9F7C1EBA0AEA4FE50B2B5CE146043CB18BFB3A12F06ED1D3287242D3D59E85E0A5E243626525D3EAD946126B9F32590011EEA0EDD5E2025037D51940B3E1A45B614A23F48278977535E3773F0AA2A24413F4A397AC0881582E8832C7B140C0BA4818A55C8620FD2BEBB5512C20307 +20170623053734 2 6 100 3071 2 E795DA675C82260F11D7C50B677AE8A8D94BF342724BB06FA0D426CE2E83E8971A1BE2AC59516488B25D561568B14DBBFFB5F33686D2952409B9C20FC19A13CB91C9176420F59F464DC198E254B87C765DC12B885CF1A463858C3CB0A918AF66C6A2CA06A48B4D5BDEB5A56B24C36BA330488DFCBDD499957E755CCE704F183CB4549441A7D761C22B7F7CB66BE50F0A6591F17778F51E73544B765E83A3C00BD3309F8CE1B135A3DD481DBE8C2CEE54E8DDF1351015E70D9012662E69F654A5A9F68C416167685A1695C8139BA1825287C98680945506D5AB750BEB68C6D2B430E7E4043D0A00DECDA77F81A2432929F530C5BC0CBBC011095D897BD81FB98792345F5372BA53E53F31FB09730C58E8FDA9F7C1EBA0AEA4FE50B2B5CE146043CB18BFB3A12F06ED1D3287242D3D59E85E0A5E243626525D3EAD946126B9F32590011EEA0EDD5E2025037D51940B3E1A45B614A23F48278977535E3773F0AA2A24413F4A397AC0881582E8832C7B140C0BA4818A55C8620FD2BEBB55133990CB +20170623054412 2 6 100 3071 2 E795DA675C82260F11D7C50B677AE8A8D94BF342724BB06FA0D426CE2E83E8971A1BE2AC59516488B25D561568B14DBBFFB5F33686D2952409B9C20FC19A13CB91C9176420F59F464DC198E254B87C765DC12B885CF1A463858C3CB0A918AF66C6A2CA06A48B4D5BDEB5A56B24C36BA330488DFCBDD499957E755CCE704F183CB4549441A7D761C22B7F7CB66BE50F0A6591F17778F51E73544B765E83A3C00BD3309F8CE1B135A3DD481DBE8C2CEE54E8DDF1351015E70D9012662E69F654A5A9F68C416167685A1695C8139BA1825287C98680945506D5AB750BEB68C6D2B430E7E4043D0A00DECDA77F81A2432929F530C5BC0CBBC011095D897BD81FB98792345F5372BA53E53F31FB09730C58E8FDA9F7C1EBA0AEA4FE50B2B5CE146043CB18BFB3A12F06ED1D3287242D3D59E85E0A5E243626525D3EAD946126B9F32590011EEA0EDD5E2025037D51940B3E1A45B614A23F48278977535E3773F0AA2A24413F4A397AC0881582E8832C7B140C0BA4818A55C8620FD2BEBB5514721AB3 +20170623054517 2 6 100 3071 2 E795DA675C82260F11D7C50B677AE8A8D94BF342724BB06FA0D426CE2E83E8971A1BE2AC59516488B25D561568B14DBBFFB5F33686D2952409B9C20FC19A13CB91C9176420F59F464DC198E254B87C765DC12B885CF1A463858C3CB0A918AF66C6A2CA06A48B4D5BDEB5A56B24C36BA330488DFCBDD499957E755CCE704F183CB4549441A7D761C22B7F7CB66BE50F0A6591F17778F51E73544B765E83A3C00BD3309F8CE1B135A3DD481DBE8C2CEE54E8DDF1351015E70D9012662E69F654A5A9F68C416167685A1695C8139BA1825287C98680945506D5AB750BEB68C6D2B430E7E4043D0A00DECDA77F81A2432929F530C5BC0CBBC011095D897BD81FB98792345F5372BA53E53F31FB09730C58E8FDA9F7C1EBA0AEA4FE50B2B5CE146043CB18BFB3A12F06ED1D3287242D3D59E85E0A5E243626525D3EAD946126B9F32590011EEA0EDD5E2025037D51940B3E1A45B614A23F48278977535E3773F0AA2A24413F4A397AC0881582E8832C7B140C0BA4818A55C8620FD2BEBB55149F4D0B +20170623055017 2 6 100 3071 2 E795DA675C82260F11D7C50B677AE8A8D94BF342724BB06FA0D426CE2E83E8971A1BE2AC59516488B25D561568B14DBBFFB5F33686D2952409B9C20FC19A13CB91C9176420F59F464DC198E254B87C765DC12B885CF1A463858C3CB0A918AF66C6A2CA06A48B4D5BDEB5A56B24C36BA330488DFCBDD499957E755CCE704F183CB4549441A7D761C22B7F7CB66BE50F0A6591F17778F51E73544B765E83A3C00BD3309F8CE1B135A3DD481DBE8C2CEE54E8DDF1351015E70D9012662E69F654A5A9F68C416167685A1695C8139BA1825287C98680945506D5AB750BEB68C6D2B430E7E4043D0A00DECDA77F81A2432929F530C5BC0CBBC011095D897BD81FB98792345F5372BA53E53F31FB09730C58E8FDA9F7C1EBA0AEA4FE50B2B5CE146043CB18BFB3A12F06ED1D3287242D3D59E85E0A5E243626525D3EAD946126B9F32590011EEA0EDD5E2025037D51940B3E1A45B614A23F48278977535E3773F0AA2A24413F4A397AC0881582E8832C7B140C0BA4818A55C8620FD2BEBB551583DD9B +20170623055422 2 6 100 3071 2 E795DA675C82260F11D7C50B677AE8A8D94BF342724BB06FA0D426CE2E83E8971A1BE2AC59516488B25D561568B14DBBFFB5F33686D2952409B9C20FC19A13CB91C9176420F59F464DC198E254B87C765DC12B885CF1A463858C3CB0A918AF66C6A2CA06A48B4D5BDEB5A56B24C36BA330488DFCBDD499957E755CCE704F183CB4549441A7D761C22B7F7CB66BE50F0A6591F17778F51E73544B765E83A3C00BD3309F8CE1B135A3DD481DBE8C2CEE54E8DDF1351015E70D9012662E69F654A5A9F68C416167685A1695C8139BA1825287C98680945506D5AB750BEB68C6D2B430E7E4043D0A00DECDA77F81A2432929F530C5BC0CBBC011095D897BD81FB98792345F5372BA53E53F31FB09730C58E8FDA9F7C1EBA0AEA4FE50B2B5CE146043CB18BFB3A12F06ED1D3287242D3D59E85E0A5E243626525D3EAD946126B9F32590011EEA0EDD5E2025037D51940B3E1A45B614A23F48278977535E3773F0AA2A24413F4A397AC0881582E8832C7B140C0BA4818A55C8620FD2BEBB55163A7903 +20170623055449 2 6 100 3071 5 E795DA675C82260F11D7C50B677AE8A8D94BF342724BB06FA0D426CE2E83E8971A1BE2AC59516488B25D561568B14DBBFFB5F33686D2952409B9C20FC19A13CB91C9176420F59F464DC198E254B87C765DC12B885CF1A463858C3CB0A918AF66C6A2CA06A48B4D5BDEB5A56B24C36BA330488DFCBDD499957E755CCE704F183CB4549441A7D761C22B7F7CB66BE50F0A6591F17778F51E73544B765E83A3C00BD3309F8CE1B135A3DD481DBE8C2CEE54E8DDF1351015E70D9012662E69F654A5A9F68C416167685A1695C8139BA1825287C98680945506D5AB750BEB68C6D2B430E7E4043D0A00DECDA77F81A2432929F530C5BC0CBBC011095D897BD81FB98792345F5372BA53E53F31FB09730C58E8FDA9F7C1EBA0AEA4FE50B2B5CE146043CB18BFB3A12F06ED1D3287242D3D59E85E0A5E243626525D3EAD946126B9F32590011EEA0EDD5E2025037D51940B3E1A45B614A23F48278977535E3773F0AA2A24413F4A397AC0881582E8832C7B140C0BA4818A55C8620FD2BEBB5516475E5F +20170623055516 2 6 100 3071 5 E795DA675C82260F11D7C50B677AE8A8D94BF342724BB06FA0D426CE2E83E8971A1BE2AC59516488B25D561568B14DBBFFB5F33686D2952409B9C20FC19A13CB91C9176420F59F464DC198E254B87C765DC12B885CF1A463858C3CB0A918AF66C6A2CA06A48B4D5BDEB5A56B24C36BA330488DFCBDD499957E755CCE704F183CB4549441A7D761C22B7F7CB66BE50F0A6591F17778F51E73544B765E83A3C00BD3309F8CE1B135A3DD481DBE8C2CEE54E8DDF1351015E70D9012662E69F654A5A9F68C416167685A1695C8139BA1825287C98680945506D5AB750BEB68C6D2B430E7E4043D0A00DECDA77F81A2432929F530C5BC0CBBC011095D897BD81FB98792345F5372BA53E53F31FB09730C58E8FDA9F7C1EBA0AEA4FE50B2B5CE146043CB18BFB3A12F06ED1D3287242D3D59E85E0A5E243626525D3EAD946126B9F32590011EEA0EDD5E2025037D51940B3E1A45B614A23F48278977535E3773F0AA2A24413F4A397AC0881582E8832C7B140C0BA4818A55C8620FD2BEBB5516556F37 +20170623055539 2 6 100 3071 5 E795DA675C82260F11D7C50B677AE8A8D94BF342724BB06FA0D426CE2E83E8971A1BE2AC59516488B25D561568B14DBBFFB5F33686D2952409B9C20FC19A13CB91C9176420F59F464DC198E254B87C765DC12B885CF1A463858C3CB0A918AF66C6A2CA06A48B4D5BDEB5A56B24C36BA330488DFCBDD499957E755CCE704F183CB4549441A7D761C22B7F7CB66BE50F0A6591F17778F51E73544B765E83A3C00BD3309F8CE1B135A3DD481DBE8C2CEE54E8DDF1351015E70D9012662E69F654A5A9F68C416167685A1695C8139BA1825287C98680945506D5AB750BEB68C6D2B430E7E4043D0A00DECDA77F81A2432929F530C5BC0CBBC011095D897BD81FB98792345F5372BA53E53F31FB09730C58E8FDA9F7C1EBA0AEA4FE50B2B5CE146043CB18BFB3A12F06ED1D3287242D3D59E85E0A5E243626525D3EAD946126B9F32590011EEA0EDD5E2025037D51940B3E1A45B614A23F48278977535E3773F0AA2A24413F4A397AC0881582E8832C7B140C0BA4818A55C8620FD2BEBB55165F8F67 +20170623055716 2 6 100 3071 2 E795DA675C82260F11D7C50B677AE8A8D94BF342724BB06FA0D426CE2E83E8971A1BE2AC59516488B25D561568B14DBBFFB5F33686D2952409B9C20FC19A13CB91C9176420F59F464DC198E254B87C765DC12B885CF1A463858C3CB0A918AF66C6A2CA06A48B4D5BDEB5A56B24C36BA330488DFCBDD499957E755CCE704F183CB4549441A7D761C22B7F7CB66BE50F0A6591F17778F51E73544B765E83A3C00BD3309F8CE1B135A3DD481DBE8C2CEE54E8DDF1351015E70D9012662E69F654A5A9F68C416167685A1695C8139BA1825287C98680945506D5AB750BEB68C6D2B430E7E4043D0A00DECDA77F81A2432929F530C5BC0CBBC011095D897BD81FB98792345F5372BA53E53F31FB09730C58E8FDA9F7C1EBA0AEA4FE50B2B5CE146043CB18BFB3A12F06ED1D3287242D3D59E85E0A5E243626525D3EAD946126B9F32590011EEA0EDD5E2025037D51940B3E1A45B614A23F48278977535E3773F0AA2A24413F4A397AC0881582E8832C7B140C0BA4818A55C8620FD2BEBB5516A5CA13 +20170623055812 2 6 100 3071 2 E795DA675C82260F11D7C50B677AE8A8D94BF342724BB06FA0D426CE2E83E8971A1BE2AC59516488B25D561568B14DBBFFB5F33686D2952409B9C20FC19A13CB91C9176420F59F464DC198E254B87C765DC12B885CF1A463858C3CB0A918AF66C6A2CA06A48B4D5BDEB5A56B24C36BA330488DFCBDD499957E755CCE704F183CB4549441A7D761C22B7F7CB66BE50F0A6591F17778F51E73544B765E83A3C00BD3309F8CE1B135A3DD481DBE8C2CEE54E8DDF1351015E70D9012662E69F654A5A9F68C416167685A1695C8139BA1825287C98680945506D5AB750BEB68C6D2B430E7E4043D0A00DECDA77F81A2432929F530C5BC0CBBC011095D897BD81FB98792345F5372BA53E53F31FB09730C58E8FDA9F7C1EBA0AEA4FE50B2B5CE146043CB18BFB3A12F06ED1D3287242D3D59E85E0A5E243626525D3EAD946126B9F32590011EEA0EDD5E2025037D51940B3E1A45B614A23F48278977535E3773F0AA2A24413F4A397AC0881582E8832C7B140C0BA4818A55C8620FD2BEBB5516C8A4A3 +20170623055846 2 6 100 3071 2 E795DA675C82260F11D7C50B677AE8A8D94BF342724BB06FA0D426CE2E83E8971A1BE2AC59516488B25D561568B14DBBFFB5F33686D2952409B9C20FC19A13CB91C9176420F59F464DC198E254B87C765DC12B885CF1A463858C3CB0A918AF66C6A2CA06A48B4D5BDEB5A56B24C36BA330488DFCBDD499957E755CCE704F183CB4549441A7D761C22B7F7CB66BE50F0A6591F17778F51E73544B765E83A3C00BD3309F8CE1B135A3DD481DBE8C2CEE54E8DDF1351015E70D9012662E69F654A5A9F68C416167685A1695C8139BA1825287C98680945506D5AB750BEB68C6D2B430E7E4043D0A00DECDA77F81A2432929F530C5BC0CBBC011095D897BD81FB98792345F5372BA53E53F31FB09730C58E8FDA9F7C1EBA0AEA4FE50B2B5CE146043CB18BFB3A12F06ED1D3287242D3D59E85E0A5E243626525D3EAD946126B9F32590011EEA0EDD5E2025037D51940B3E1A45B614A23F48278977535E3773F0AA2A24413F4A397AC0881582E8832C7B140C0BA4818A55C8620FD2BEBB5516DBF96B +20170623060438 2 6 100 3071 2 E795DA675C82260F11D7C50B677AE8A8D94BF342724BB06FA0D426CE2E83E8971A1BE2AC59516488B25D561568B14DBBFFB5F33686D2952409B9C20FC19A13CB91C9176420F59F464DC198E254B87C765DC12B885CF1A463858C3CB0A918AF66C6A2CA06A48B4D5BDEB5A56B24C36BA330488DFCBDD499957E755CCE704F183CB4549441A7D761C22B7F7CB66BE50F0A6591F17778F51E73544B765E83A3C00BD3309F8CE1B135A3DD481DBE8C2CEE54E8DDF1351015E70D9012662E69F654A5A9F68C416167685A1695C8139BA1825287C98680945506D5AB750BEB68C6D2B430E7E4043D0A00DECDA77F81A2432929F530C5BC0CBBC011095D897BD81FB98792345F5372BA53E53F31FB09730C58E8FDA9F7C1EBA0AEA4FE50B2B5CE146043CB18BFB3A12F06ED1D3287242D3D59E85E0A5E243626525D3EAD946126B9F32590011EEA0EDD5E2025037D51940B3E1A45B614A23F48278977535E3773F0AA2A24413F4A397AC0881582E8832C7B140C0BA4818A55C8620FD2BEBB5517E20F03 +20170623060534 2 6 100 3071 5 E795DA675C82260F11D7C50B677AE8A8D94BF342724BB06FA0D426CE2E83E8971A1BE2AC59516488B25D561568B14DBBFFB5F33686D2952409B9C20FC19A13CB91C9176420F59F464DC198E254B87C765DC12B885CF1A463858C3CB0A918AF66C6A2CA06A48B4D5BDEB5A56B24C36BA330488DFCBDD499957E755CCE704F183CB4549441A7D761C22B7F7CB66BE50F0A6591F17778F51E73544B765E83A3C00BD3309F8CE1B135A3DD481DBE8C2CEE54E8DDF1351015E70D9012662E69F654A5A9F68C416167685A1695C8139BA1825287C98680945506D5AB750BEB68C6D2B430E7E4043D0A00DECDA77F81A2432929F530C5BC0CBBC011095D897BD81FB98792345F5372BA53E53F31FB09730C58E8FDA9F7C1EBA0AEA4FE50B2B5CE146043CB18BFB3A12F06ED1D3287242D3D59E85E0A5E243626525D3EAD946126B9F32590011EEA0EDD5E2025037D51940B3E1A45B614A23F48278977535E3773F0AA2A24413F4A397AC0881582E8832C7B140C0BA4818A55C8620FD2BEBB551803F1D7 +20170623060551 2 6 100 3071 5 E795DA675C82260F11D7C50B677AE8A8D94BF342724BB06FA0D426CE2E83E8971A1BE2AC59516488B25D561568B14DBBFFB5F33686D2952409B9C20FC19A13CB91C9176420F59F464DC198E254B87C765DC12B885CF1A463858C3CB0A918AF66C6A2CA06A48B4D5BDEB5A56B24C36BA330488DFCBDD499957E755CCE704F183CB4549441A7D761C22B7F7CB66BE50F0A6591F17778F51E73544B765E83A3C00BD3309F8CE1B135A3DD481DBE8C2CEE54E8DDF1351015E70D9012662E69F654A5A9F68C416167685A1695C8139BA1825287C98680945506D5AB750BEB68C6D2B430E7E4043D0A00DECDA77F81A2432929F530C5BC0CBBC011095D897BD81FB98792345F5372BA53E53F31FB09730C58E8FDA9F7C1EBA0AEA4FE50B2B5CE146043CB18BFB3A12F06ED1D3287242D3D59E85E0A5E243626525D3EAD946126B9F32590011EEA0EDD5E2025037D51940B3E1A45B614A23F48278977535E3773F0AA2A24413F4A397AC0881582E8832C7B140C0BA4818A55C8620FD2BEBB55180824C7 +20170623060759 2 6 100 3071 5 E795DA675C82260F11D7C50B677AE8A8D94BF342724BB06FA0D426CE2E83E8971A1BE2AC59516488B25D561568B14DBBFFB5F33686D2952409B9C20FC19A13CB91C9176420F59F464DC198E254B87C765DC12B885CF1A463858C3CB0A918AF66C6A2CA06A48B4D5BDEB5A56B24C36BA330488DFCBDD499957E755CCE704F183CB4549441A7D761C22B7F7CB66BE50F0A6591F17778F51E73544B765E83A3C00BD3309F8CE1B135A3DD481DBE8C2CEE54E8DDF1351015E70D9012662E69F654A5A9F68C416167685A1695C8139BA1825287C98680945506D5AB750BEB68C6D2B430E7E4043D0A00DECDA77F81A2432929F530C5BC0CBBC011095D897BD81FB98792345F5372BA53E53F31FB09730C58E8FDA9F7C1EBA0AEA4FE50B2B5CE146043CB18BFB3A12F06ED1D3287242D3D59E85E0A5E243626525D3EAD946126B9F32590011EEA0EDD5E2025037D51940B3E1A45B614A23F48278977535E3773F0AA2A24413F4A397AC0881582E8832C7B140C0BA4818A55C8620FD2BEBB5518622977 +20170623061152 2 6 100 3071 5 E795DA675C82260F11D7C50B677AE8A8D94BF342724BB06FA0D426CE2E83E8971A1BE2AC59516488B25D561568B14DBBFFB5F33686D2952409B9C20FC19A13CB91C9176420F59F464DC198E254B87C765DC12B885CF1A463858C3CB0A918AF66C6A2CA06A48B4D5BDEB5A56B24C36BA330488DFCBDD499957E755CCE704F183CB4549441A7D761C22B7F7CB66BE50F0A6591F17778F51E73544B765E83A3C00BD3309F8CE1B135A3DD481DBE8C2CEE54E8DDF1351015E70D9012662E69F654A5A9F68C416167685A1695C8139BA1825287C98680945506D5AB750BEB68C6D2B430E7E4043D0A00DECDA77F81A2432929F530C5BC0CBBC011095D897BD81FB98792345F5372BA53E53F31FB09730C58E8FDA9F7C1EBA0AEA4FE50B2B5CE146043CB18BFB3A12F06ED1D3287242D3D59E85E0A5E243626525D3EAD946126B9F32590011EEA0EDD5E2025037D51940B3E1A45B614A23F48278977535E3773F0AA2A24413F4A397AC0881582E8832C7B140C0BA4818A55C8620FD2BEBB55190DD957 +20170623061950 2 6 100 3071 5 E787C1EA14A0022F3F98A02847D293441332B2EB8BFF8C4D74ECFF730CCA9D1AFC6433A6DD4BA7089EC18D8D314550FCDC6DA23FEFDE48622BB6FFD89AB71CC0BA6C8C0930593E85A442A9C589ECF35E17D9CC7E2AE713B3704D69B61EF6E79A41AE02ADBF7966DF94B1C6861795B7EDFA8D7418EBAEB47F26F158AEF3DB418FD1632DBB93B431204964B78C7AE9ED796E39F1B6DE1FEE4CE77815462F36342E80B44B052BADC06F78CFEA7D3D0B294C5C8E8E623F95F5D3C1A17D911A0E78FE7754AA4A440FE75498D9AA47AACF2FC2F716630AEF10950F1FACD4CF847A7E4B0C20F507A7322996DBC4D2250A99CB213CB95AAF7A8B6A0B5317BE8FF728D3A0A0AAEA1B86729DDD59566916640F9AF7A455145CE29CB58884CC2E9DD705B1E87D10E139945FBE70D20D718FED9AF202A22673D76128A5FCB2860419675ADB97512628C7C65C7078B0C730A258C8979912C18EC065367791A404C71318B78FE29CC115ECD74C4EFCDE86C35BD0CFC3ADC41B4F24243A262B251F6E21EBBB813F +20170623062054 2 6 100 3071 2 E787C1EA14A0022F3F98A02847D293441332B2EB8BFF8C4D74ECFF730CCA9D1AFC6433A6DD4BA7089EC18D8D314550FCDC6DA23FEFDE48622BB6FFD89AB71CC0BA6C8C0930593E85A442A9C589ECF35E17D9CC7E2AE713B3704D69B61EF6E79A41AE02ADBF7966DF94B1C6861795B7EDFA8D7418EBAEB47F26F158AEF3DB418FD1632DBB93B431204964B78C7AE9ED796E39F1B6DE1FEE4CE77815462F36342E80B44B052BADC06F78CFEA7D3D0B294C5C8E8E623F95F5D3C1A17D911A0E78FE7754AA4A440FE75498D9AA47AACF2FC2F716630AEF10950F1FACD4CF847A7E4B0C20F507A7322996DBC4D2250A99CB213CB95AAF7A8B6A0B5317BE8FF728D3A0A0AAEA1B86729DDD59566916640F9AF7A455145CE29CB58884CC2E9DD705B1E87D10E139945FBE70D20D718FED9AF202A22673D76128A5FCB2860419675ADB97512628C7C65C7078B0C730A258C8979912C18EC065367791A404C71318B78FE29CC115ECD74C4EFCDE86C35BD0CFC3ADC41B4F24243A262B251F6E21EBE73A63 +20170623062250 2 6 100 3071 2 E787C1EA14A0022F3F98A02847D293441332B2EB8BFF8C4D74ECFF730CCA9D1AFC6433A6DD4BA7089EC18D8D314550FCDC6DA23FEFDE48622BB6FFD89AB71CC0BA6C8C0930593E85A442A9C589ECF35E17D9CC7E2AE713B3704D69B61EF6E79A41AE02ADBF7966DF94B1C6861795B7EDFA8D7418EBAEB47F26F158AEF3DB418FD1632DBB93B431204964B78C7AE9ED796E39F1B6DE1FEE4CE77815462F36342E80B44B052BADC06F78CFEA7D3D0B294C5C8E8E623F95F5D3C1A17D911A0E78FE7754AA4A440FE75498D9AA47AACF2FC2F716630AEF10950F1FACD4CF847A7E4B0C20F507A7322996DBC4D2250A99CB213CB95AAF7A8B6A0B5317BE8FF728D3A0A0AAEA1B86729DDD59566916640F9AF7A455145CE29CB58884CC2E9DD705B1E87D10E139945FBE70D20D718FED9AF202A22673D76128A5FCB2860419675ADB97512628C7C65C7078B0C730A258C8979912C18EC065367791A404C71318B78FE29CC115ECD74C4EFCDE86C35BD0CFC3ADC41B4F24243A262B251F6E21EC3B7BBB +20170623062850 2 6 100 3071 5 E787C1EA14A0022F3F98A02847D293441332B2EB8BFF8C4D74ECFF730CCA9D1AFC6433A6DD4BA7089EC18D8D314550FCDC6DA23FEFDE48622BB6FFD89AB71CC0BA6C8C0930593E85A442A9C589ECF35E17D9CC7E2AE713B3704D69B61EF6E79A41AE02ADBF7966DF94B1C6861795B7EDFA8D7418EBAEB47F26F158AEF3DB418FD1632DBB93B431204964B78C7AE9ED796E39F1B6DE1FEE4CE77815462F36342E80B44B052BADC06F78CFEA7D3D0B294C5C8E8E623F95F5D3C1A17D911A0E78FE7754AA4A440FE75498D9AA47AACF2FC2F716630AEF10950F1FACD4CF847A7E4B0C20F507A7322996DBC4D2250A99CB213CB95AAF7A8B6A0B5317BE8FF728D3A0A0AAEA1B86729DDD59566916640F9AF7A455145CE29CB58884CC2E9DD705B1E87D10E139945FBE70D20D718FED9AF202A22673D76128A5FCB2860419675ADB97512628C7C65C7078B0C730A258C8979912C18EC065367791A404C71318B78FE29CC115ECD74C4EFCDE86C35BD0CFC3ADC41B4F24243A262B251F6E21ED5538D7 +20170623063051 2 6 100 3071 5 E787C1EA14A0022F3F98A02847D293441332B2EB8BFF8C4D74ECFF730CCA9D1AFC6433A6DD4BA7089EC18D8D314550FCDC6DA23FEFDE48622BB6FFD89AB71CC0BA6C8C0930593E85A442A9C589ECF35E17D9CC7E2AE713B3704D69B61EF6E79A41AE02ADBF7966DF94B1C6861795B7EDFA8D7418EBAEB47F26F158AEF3DB418FD1632DBB93B431204964B78C7AE9ED796E39F1B6DE1FEE4CE77815462F36342E80B44B052BADC06F78CFEA7D3D0B294C5C8E8E623F95F5D3C1A17D911A0E78FE7754AA4A440FE75498D9AA47AACF2FC2F716630AEF10950F1FACD4CF847A7E4B0C20F507A7322996DBC4D2250A99CB213CB95AAF7A8B6A0B5317BE8FF728D3A0A0AAEA1B86729DDD59566916640F9AF7A455145CE29CB58884CC2E9DD705B1E87D10E139945FBE70D20D718FED9AF202A22673D76128A5FCB2860419675ADB97512628C7C65C7078B0C730A258C8979912C18EC065367791A404C71318B78FE29CC115ECD74C4EFCDE86C35BD0CFC3ADC41B4F24243A262B251F6E21EDADBD87 +20170623063106 2 6 100 3071 5 E787C1EA14A0022F3F98A02847D293441332B2EB8BFF8C4D74ECFF730CCA9D1AFC6433A6DD4BA7089EC18D8D314550FCDC6DA23FEFDE48622BB6FFD89AB71CC0BA6C8C0930593E85A442A9C589ECF35E17D9CC7E2AE713B3704D69B61EF6E79A41AE02ADBF7966DF94B1C6861795B7EDFA8D7418EBAEB47F26F158AEF3DB418FD1632DBB93B431204964B78C7AE9ED796E39F1B6DE1FEE4CE77815462F36342E80B44B052BADC06F78CFEA7D3D0B294C5C8E8E623F95F5D3C1A17D911A0E78FE7754AA4A440FE75498D9AA47AACF2FC2F716630AEF10950F1FACD4CF847A7E4B0C20F507A7322996DBC4D2250A99CB213CB95AAF7A8B6A0B5317BE8FF728D3A0A0AAEA1B86729DDD59566916640F9AF7A455145CE29CB58884CC2E9DD705B1E87D10E139945FBE70D20D718FED9AF202A22673D76128A5FCB2860419675ADB97512628C7C65C7078B0C730A258C8979912C18EC065367791A404C71318B78FE29CC115ECD74C4EFCDE86C35BD0CFC3ADC41B4F24243A262B251F6E21EDB14127 +20170623063228 2 6 100 3071 2 E787C1EA14A0022F3F98A02847D293441332B2EB8BFF8C4D74ECFF730CCA9D1AFC6433A6DD4BA7089EC18D8D314550FCDC6DA23FEFDE48622BB6FFD89AB71CC0BA6C8C0930593E85A442A9C589ECF35E17D9CC7E2AE713B3704D69B61EF6E79A41AE02ADBF7966DF94B1C6861795B7EDFA8D7418EBAEB47F26F158AEF3DB418FD1632DBB93B431204964B78C7AE9ED796E39F1B6DE1FEE4CE77815462F36342E80B44B052BADC06F78CFEA7D3D0B294C5C8E8E623F95F5D3C1A17D911A0E78FE7754AA4A440FE75498D9AA47AACF2FC2F716630AEF10950F1FACD4CF847A7E4B0C20F507A7322996DBC4D2250A99CB213CB95AAF7A8B6A0B5317BE8FF728D3A0A0AAEA1B86729DDD59566916640F9AF7A455145CE29CB58884CC2E9DD705B1E87D10E139945FBE70D20D718FED9AF202A22673D76128A5FCB2860419675ADB97512628C7C65C7078B0C730A258C8979912C18EC065367791A404C71318B78FE29CC115ECD74C4EFCDE86C35BD0CFC3ADC41B4F24243A262B251F6E21EDEBD58B +20170623063242 2 6 100 3071 2 E787C1EA14A0022F3F98A02847D293441332B2EB8BFF8C4D74ECFF730CCA9D1AFC6433A6DD4BA7089EC18D8D314550FCDC6DA23FEFDE48622BB6FFD89AB71CC0BA6C8C0930593E85A442A9C589ECF35E17D9CC7E2AE713B3704D69B61EF6E79A41AE02ADBF7966DF94B1C6861795B7EDFA8D7418EBAEB47F26F158AEF3DB418FD1632DBB93B431204964B78C7AE9ED796E39F1B6DE1FEE4CE77815462F36342E80B44B052BADC06F78CFEA7D3D0B294C5C8E8E623F95F5D3C1A17D911A0E78FE7754AA4A440FE75498D9AA47AACF2FC2F716630AEF10950F1FACD4CF847A7E4B0C20F507A7322996DBC4D2250A99CB213CB95AAF7A8B6A0B5317BE8FF728D3A0A0AAEA1B86729DDD59566916640F9AF7A455145CE29CB58884CC2E9DD705B1E87D10E139945FBE70D20D718FED9AF202A22673D76128A5FCB2860419675ADB97512628C7C65C7078B0C730A258C8979912C18EC065367791A404C71318B78FE29CC115ECD74C4EFCDE86C35BD0CFC3ADC41B4F24243A262B251F6E21EDEE14B3 +20170623063301 2 6 100 3071 5 E787C1EA14A0022F3F98A02847D293441332B2EB8BFF8C4D74ECFF730CCA9D1AFC6433A6DD4BA7089EC18D8D314550FCDC6DA23FEFDE48622BB6FFD89AB71CC0BA6C8C0930593E85A442A9C589ECF35E17D9CC7E2AE713B3704D69B61EF6E79A41AE02ADBF7966DF94B1C6861795B7EDFA8D7418EBAEB47F26F158AEF3DB418FD1632DBB93B431204964B78C7AE9ED796E39F1B6DE1FEE4CE77815462F36342E80B44B052BADC06F78CFEA7D3D0B294C5C8E8E623F95F5D3C1A17D911A0E78FE7754AA4A440FE75498D9AA47AACF2FC2F716630AEF10950F1FACD4CF847A7E4B0C20F507A7322996DBC4D2250A99CB213CB95AAF7A8B6A0B5317BE8FF728D3A0A0AAEA1B86729DDD59566916640F9AF7A455145CE29CB58884CC2E9DD705B1E87D10E139945FBE70D20D718FED9AF202A22673D76128A5FCB2860419675ADB97512628C7C65C7078B0C730A258C8979912C18EC065367791A404C71318B78FE29CC115ECD74C4EFCDE86C35BD0CFC3ADC41B4F24243A262B251F6E21EDF542E7 +20170623063538 2 6 100 3071 2 E787C1EA14A0022F3F98A02847D293441332B2EB8BFF8C4D74ECFF730CCA9D1AFC6433A6DD4BA7089EC18D8D314550FCDC6DA23FEFDE48622BB6FFD89AB71CC0BA6C8C0930593E85A442A9C589ECF35E17D9CC7E2AE713B3704D69B61EF6E79A41AE02ADBF7966DF94B1C6861795B7EDFA8D7418EBAEB47F26F158AEF3DB418FD1632DBB93B431204964B78C7AE9ED796E39F1B6DE1FEE4CE77815462F36342E80B44B052BADC06F78CFEA7D3D0B294C5C8E8E623F95F5D3C1A17D911A0E78FE7754AA4A440FE75498D9AA47AACF2FC2F716630AEF10950F1FACD4CF847A7E4B0C20F507A7322996DBC4D2250A99CB213CB95AAF7A8B6A0B5317BE8FF728D3A0A0AAEA1B86729DDD59566916640F9AF7A455145CE29CB58884CC2E9DD705B1E87D10E139945FBE70D20D718FED9AF202A22673D76128A5FCB2860419675ADB97512628C7C65C7078B0C730A258C8979912C18EC065367791A404C71318B78FE29CC115ECD74C4EFCDE86C35BD0CFC3ADC41B4F24243A262B251F6E21EE64F8A3 +20170623063759 2 6 100 3071 5 E787C1EA14A0022F3F98A02847D293441332B2EB8BFF8C4D74ECFF730CCA9D1AFC6433A6DD4BA7089EC18D8D314550FCDC6DA23FEFDE48622BB6FFD89AB71CC0BA6C8C0930593E85A442A9C589ECF35E17D9CC7E2AE713B3704D69B61EF6E79A41AE02ADBF7966DF94B1C6861795B7EDFA8D7418EBAEB47F26F158AEF3DB418FD1632DBB93B431204964B78C7AE9ED796E39F1B6DE1FEE4CE77815462F36342E80B44B052BADC06F78CFEA7D3D0B294C5C8E8E623F95F5D3C1A17D911A0E78FE7754AA4A440FE75498D9AA47AACF2FC2F716630AEF10950F1FACD4CF847A7E4B0C20F507A7322996DBC4D2250A99CB213CB95AAF7A8B6A0B5317BE8FF728D3A0A0AAEA1B86729DDD59566916640F9AF7A455145CE29CB58884CC2E9DD705B1E87D10E139945FBE70D20D718FED9AF202A22673D76128A5FCB2860419675ADB97512628C7C65C7078B0C730A258C8979912C18EC065367791A404C71318B78FE29CC115ECD74C4EFCDE86C35BD0CFC3ADC41B4F24243A262B251F6E21EEC9D597 +20170623064815 2 6 100 3071 5 E787C1EA14A0022F3F98A02847D293441332B2EB8BFF8C4D74ECFF730CCA9D1AFC6433A6DD4BA7089EC18D8D314550FCDC6DA23FEFDE48622BB6FFD89AB71CC0BA6C8C0930593E85A442A9C589ECF35E17D9CC7E2AE713B3704D69B61EF6E79A41AE02ADBF7966DF94B1C6861795B7EDFA8D7418EBAEB47F26F158AEF3DB418FD1632DBB93B431204964B78C7AE9ED796E39F1B6DE1FEE4CE77815462F36342E80B44B052BADC06F78CFEA7D3D0B294C5C8E8E623F95F5D3C1A17D911A0E78FE7754AA4A440FE75498D9AA47AACF2FC2F716630AEF10950F1FACD4CF847A7E4B0C20F507A7322996DBC4D2250A99CB213CB95AAF7A8B6A0B5317BE8FF728D3A0A0AAEA1B86729DDD59566916640F9AF7A455145CE29CB58884CC2E9DD705B1E87D10E139945FBE70D20D718FED9AF202A22673D76128A5FCB2860419675ADB97512628C7C65C7078B0C730A258C8979912C18EC065367791A404C71318B78FE29CC115ECD74C4EFCDE86C35BD0CFC3ADC41B4F24243A262B251F6E21F0A8EB1F +20170623065609 2 6 100 3071 5 E787C1EA14A0022F3F98A02847D293441332B2EB8BFF8C4D74ECFF730CCA9D1AFC6433A6DD4BA7089EC18D8D314550FCDC6DA23FEFDE48622BB6FFD89AB71CC0BA6C8C0930593E85A442A9C589ECF35E17D9CC7E2AE713B3704D69B61EF6E79A41AE02ADBF7966DF94B1C6861795B7EDFA8D7418EBAEB47F26F158AEF3DB418FD1632DBB93B431204964B78C7AE9ED796E39F1B6DE1FEE4CE77815462F36342E80B44B052BADC06F78CFEA7D3D0B294C5C8E8E623F95F5D3C1A17D911A0E78FE7754AA4A440FE75498D9AA47AACF2FC2F716630AEF10950F1FACD4CF847A7E4B0C20F507A7322996DBC4D2250A99CB213CB95AAF7A8B6A0B5317BE8FF728D3A0A0AAEA1B86729DDD59566916640F9AF7A455145CE29CB58884CC2E9DD705B1E87D10E139945FBE70D20D718FED9AF202A22673D76128A5FCB2860419675ADB97512628C7C65C7078B0C730A258C8979912C18EC065367791A404C71318B78FE29CC115ECD74C4EFCDE86C35BD0CFC3ADC41B4F24243A262B251F6E21F21F5CB7 +20170623070150 2 6 100 3071 2 E787C1EA14A0022F3F98A02847D293441332B2EB8BFF8C4D74ECFF730CCA9D1AFC6433A6DD4BA7089EC18D8D314550FCDC6DA23FEFDE48622BB6FFD89AB71CC0BA6C8C0930593E85A442A9C589ECF35E17D9CC7E2AE713B3704D69B61EF6E79A41AE02ADBF7966DF94B1C6861795B7EDFA8D7418EBAEB47F26F158AEF3DB418FD1632DBB93B431204964B78C7AE9ED796E39F1B6DE1FEE4CE77815462F36342E80B44B052BADC06F78CFEA7D3D0B294C5C8E8E623F95F5D3C1A17D911A0E78FE7754AA4A440FE75498D9AA47AACF2FC2F716630AEF10950F1FACD4CF847A7E4B0C20F507A7322996DBC4D2250A99CB213CB95AAF7A8B6A0B5317BE8FF728D3A0A0AAEA1B86729DDD59566916640F9AF7A455145CE29CB58884CC2E9DD705B1E87D10E139945FBE70D20D718FED9AF202A22673D76128A5FCB2860419675ADB97512628C7C65C7078B0C730A258C8979912C18EC065367791A404C71318B78FE29CC115ECD74C4EFCDE86C35BD0CFC3ADC41B4F24243A262B251F6E21F32604CB +20170623070933 2 6 100 3071 2 E787C1EA14A0022F3F98A02847D293441332B2EB8BFF8C4D74ECFF730CCA9D1AFC6433A6DD4BA7089EC18D8D314550FCDC6DA23FEFDE48622BB6FFD89AB71CC0BA6C8C0930593E85A442A9C589ECF35E17D9CC7E2AE713B3704D69B61EF6E79A41AE02ADBF7966DF94B1C6861795B7EDFA8D7418EBAEB47F26F158AEF3DB418FD1632DBB93B431204964B78C7AE9ED796E39F1B6DE1FEE4CE77815462F36342E80B44B052BADC06F78CFEA7D3D0B294C5C8E8E623F95F5D3C1A17D911A0E78FE7754AA4A440FE75498D9AA47AACF2FC2F716630AEF10950F1FACD4CF847A7E4B0C20F507A7322996DBC4D2250A99CB213CB95AAF7A8B6A0B5317BE8FF728D3A0A0AAEA1B86729DDD59566916640F9AF7A455145CE29CB58884CC2E9DD705B1E87D10E139945FBE70D20D718FED9AF202A22673D76128A5FCB2860419675ADB97512628C7C65C7078B0C730A258C8979912C18EC065367791A404C71318B78FE29CC115ECD74C4EFCDE86C35BD0CFC3ADC41B4F24243A262B251F6E21F48C5ED3 +20170623071215 2 6 100 3071 2 E787C1EA14A0022F3F98A02847D293441332B2EB8BFF8C4D74ECFF730CCA9D1AFC6433A6DD4BA7089EC18D8D314550FCDC6DA23FEFDE48622BB6FFD89AB71CC0BA6C8C0930593E85A442A9C589ECF35E17D9CC7E2AE713B3704D69B61EF6E79A41AE02ADBF7966DF94B1C6861795B7EDFA8D7418EBAEB47F26F158AEF3DB418FD1632DBB93B431204964B78C7AE9ED796E39F1B6DE1FEE4CE77815462F36342E80B44B052BADC06F78CFEA7D3D0B294C5C8E8E623F95F5D3C1A17D911A0E78FE7754AA4A440FE75498D9AA47AACF2FC2F716630AEF10950F1FACD4CF847A7E4B0C20F507A7322996DBC4D2250A99CB213CB95AAF7A8B6A0B5317BE8FF728D3A0A0AAEA1B86729DDD59566916640F9AF7A455145CE29CB58884CC2E9DD705B1E87D10E139945FBE70D20D718FED9AF202A22673D76128A5FCB2860419675ADB97512628C7C65C7078B0C730A258C8979912C18EC065367791A404C71318B78FE29CC115ECD74C4EFCDE86C35BD0CFC3ADC41B4F24243A262B251F6E21F5044ECB +20170623071504 2 6 100 3071 2 E787C1EA14A0022F3F98A02847D293441332B2EB8BFF8C4D74ECFF730CCA9D1AFC6433A6DD4BA7089EC18D8D314550FCDC6DA23FEFDE48622BB6FFD89AB71CC0BA6C8C0930593E85A442A9C589ECF35E17D9CC7E2AE713B3704D69B61EF6E79A41AE02ADBF7966DF94B1C6861795B7EDFA8D7418EBAEB47F26F158AEF3DB418FD1632DBB93B431204964B78C7AE9ED796E39F1B6DE1FEE4CE77815462F36342E80B44B052BADC06F78CFEA7D3D0B294C5C8E8E623F95F5D3C1A17D911A0E78FE7754AA4A440FE75498D9AA47AACF2FC2F716630AEF10950F1FACD4CF847A7E4B0C20F507A7322996DBC4D2250A99CB213CB95AAF7A8B6A0B5317BE8FF728D3A0A0AAEA1B86729DDD59566916640F9AF7A455145CE29CB58884CC2E9DD705B1E87D10E139945FBE70D20D718FED9AF202A22673D76128A5FCB2860419675ADB97512628C7C65C7078B0C730A258C8979912C18EC065367791A404C71318B78FE29CC115ECD74C4EFCDE86C35BD0CFC3ADC41B4F24243A262B251F6E21F5815613 +20170623071625 2 6 100 3071 2 E787C1EA14A0022F3F98A02847D293441332B2EB8BFF8C4D74ECFF730CCA9D1AFC6433A6DD4BA7089EC18D8D314550FCDC6DA23FEFDE48622BB6FFD89AB71CC0BA6C8C0930593E85A442A9C589ECF35E17D9CC7E2AE713B3704D69B61EF6E79A41AE02ADBF7966DF94B1C6861795B7EDFA8D7418EBAEB47F26F158AEF3DB418FD1632DBB93B431204964B78C7AE9ED796E39F1B6DE1FEE4CE77815462F36342E80B44B052BADC06F78CFEA7D3D0B294C5C8E8E623F95F5D3C1A17D911A0E78FE7754AA4A440FE75498D9AA47AACF2FC2F716630AEF10950F1FACD4CF847A7E4B0C20F507A7322996DBC4D2250A99CB213CB95AAF7A8B6A0B5317BE8FF728D3A0A0AAEA1B86729DDD59566916640F9AF7A455145CE29CB58884CC2E9DD705B1E87D10E139945FBE70D20D718FED9AF202A22673D76128A5FCB2860419675ADB97512628C7C65C7078B0C730A258C8979912C18EC065367791A404C71318B78FE29CC115ECD74C4EFCDE86C35BD0CFC3ADC41B4F24243A262B251F6E21F5B8F8AB +20170623071723 2 6 100 3071 2 E787C1EA14A0022F3F98A02847D293441332B2EB8BFF8C4D74ECFF730CCA9D1AFC6433A6DD4BA7089EC18D8D314550FCDC6DA23FEFDE48622BB6FFD89AB71CC0BA6C8C0930593E85A442A9C589ECF35E17D9CC7E2AE713B3704D69B61EF6E79A41AE02ADBF7966DF94B1C6861795B7EDFA8D7418EBAEB47F26F158AEF3DB418FD1632DBB93B431204964B78C7AE9ED796E39F1B6DE1FEE4CE77815462F36342E80B44B052BADC06F78CFEA7D3D0B294C5C8E8E623F95F5D3C1A17D911A0E78FE7754AA4A440FE75498D9AA47AACF2FC2F716630AEF10950F1FACD4CF847A7E4B0C20F507A7322996DBC4D2250A99CB213CB95AAF7A8B6A0B5317BE8FF728D3A0A0AAEA1B86729DDD59566916640F9AF7A455145CE29CB58884CC2E9DD705B1E87D10E139945FBE70D20D718FED9AF202A22673D76128A5FCB2860419675ADB97512628C7C65C7078B0C730A258C8979912C18EC065367791A404C71318B78FE29CC115ECD74C4EFCDE86C35BD0CFC3ADC41B4F24243A262B251F6E21F5DE3F7B +20170623071945 2 6 100 3071 2 E787C1EA14A0022F3F98A02847D293441332B2EB8BFF8C4D74ECFF730CCA9D1AFC6433A6DD4BA7089EC18D8D314550FCDC6DA23FEFDE48622BB6FFD89AB71CC0BA6C8C0930593E85A442A9C589ECF35E17D9CC7E2AE713B3704D69B61EF6E79A41AE02ADBF7966DF94B1C6861795B7EDFA8D7418EBAEB47F26F158AEF3DB418FD1632DBB93B431204964B78C7AE9ED796E39F1B6DE1FEE4CE77815462F36342E80B44B052BADC06F78CFEA7D3D0B294C5C8E8E623F95F5D3C1A17D911A0E78FE7754AA4A440FE75498D9AA47AACF2FC2F716630AEF10950F1FACD4CF847A7E4B0C20F507A7322996DBC4D2250A99CB213CB95AAF7A8B6A0B5317BE8FF728D3A0A0AAEA1B86729DDD59566916640F9AF7A455145CE29CB58884CC2E9DD705B1E87D10E139945FBE70D20D718FED9AF202A22673D76128A5FCB2860419675ADB97512628C7C65C7078B0C730A258C8979912C18EC065367791A404C71318B78FE29CC115ECD74C4EFCDE86C35BD0CFC3ADC41B4F24243A262B251F6E21F645009B +20170623072445 2 6 100 3071 5 E787C1EA14A0022F3F98A02847D293441332B2EB8BFF8C4D74ECFF730CCA9D1AFC6433A6DD4BA7089EC18D8D314550FCDC6DA23FEFDE48622BB6FFD89AB71CC0BA6C8C0930593E85A442A9C589ECF35E17D9CC7E2AE713B3704D69B61EF6E79A41AE02ADBF7966DF94B1C6861795B7EDFA8D7418EBAEB47F26F158AEF3DB418FD1632DBB93B431204964B78C7AE9ED796E39F1B6DE1FEE4CE77815462F36342E80B44B052BADC06F78CFEA7D3D0B294C5C8E8E623F95F5D3C1A17D911A0E78FE7754AA4A440FE75498D9AA47AACF2FC2F716630AEF10950F1FACD4CF847A7E4B0C20F507A7322996DBC4D2250A99CB213CB95AAF7A8B6A0B5317BE8FF728D3A0A0AAEA1B86729DDD59566916640F9AF7A455145CE29CB58884CC2E9DD705B1E87D10E139945FBE70D20D718FED9AF202A22673D76128A5FCB2860419675ADB97512628C7C65C7078B0C730A258C8979912C18EC065367791A404C71318B78FE29CC115ECD74C4EFCDE86C35BD0CFC3ADC41B4F24243A262B251F6E21F721A837 +20170623072516 2 6 100 3071 5 E787C1EA14A0022F3F98A02847D293441332B2EB8BFF8C4D74ECFF730CCA9D1AFC6433A6DD4BA7089EC18D8D314550FCDC6DA23FEFDE48622BB6FFD89AB71CC0BA6C8C0930593E85A442A9C589ECF35E17D9CC7E2AE713B3704D69B61EF6E79A41AE02ADBF7966DF94B1C6861795B7EDFA8D7418EBAEB47F26F158AEF3DB418FD1632DBB93B431204964B78C7AE9ED796E39F1B6DE1FEE4CE77815462F36342E80B44B052BADC06F78CFEA7D3D0B294C5C8E8E623F95F5D3C1A17D911A0E78FE7754AA4A440FE75498D9AA47AACF2FC2F716630AEF10950F1FACD4CF847A7E4B0C20F507A7322996DBC4D2250A99CB213CB95AAF7A8B6A0B5317BE8FF728D3A0A0AAEA1B86729DDD59566916640F9AF7A455145CE29CB58884CC2E9DD705B1E87D10E139945FBE70D20D718FED9AF202A22673D76128A5FCB2860419675ADB97512628C7C65C7078B0C730A258C8979912C18EC065367791A404C71318B78FE29CC115ECD74C4EFCDE86C35BD0CFC3ADC41B4F24243A262B251F6E21F731AF17 +20170623073343 2 6 100 3071 5 E787C1EA14A0022F3F98A02847D293441332B2EB8BFF8C4D74ECFF730CCA9D1AFC6433A6DD4BA7089EC18D8D314550FCDC6DA23FEFDE48622BB6FFD89AB71CC0BA6C8C0930593E85A442A9C589ECF35E17D9CC7E2AE713B3704D69B61EF6E79A41AE02ADBF7966DF94B1C6861795B7EDFA8D7418EBAEB47F26F158AEF3DB418FD1632DBB93B431204964B78C7AE9ED796E39F1B6DE1FEE4CE77815462F36342E80B44B052BADC06F78CFEA7D3D0B294C5C8E8E623F95F5D3C1A17D911A0E78FE7754AA4A440FE75498D9AA47AACF2FC2F716630AEF10950F1FACD4CF847A7E4B0C20F507A7322996DBC4D2250A99CB213CB95AAF7A8B6A0B5317BE8FF728D3A0A0AAEA1B86729DDD59566916640F9AF7A455145CE29CB58884CC2E9DD705B1E87D10E139945FBE70D20D718FED9AF202A22673D76128A5FCB2860419675ADB97512628C7C65C7078B0C730A258C8979912C18EC065367791A404C71318B78FE29CC115ECD74C4EFCDE86C35BD0CFC3ADC41B4F24243A262B251F6E21F8B6F58F +20170623073442 2 6 100 3071 5 E787C1EA14A0022F3F98A02847D293441332B2EB8BFF8C4D74ECFF730CCA9D1AFC6433A6DD4BA7089EC18D8D314550FCDC6DA23FEFDE48622BB6FFD89AB71CC0BA6C8C0930593E85A442A9C589ECF35E17D9CC7E2AE713B3704D69B61EF6E79A41AE02ADBF7966DF94B1C6861795B7EDFA8D7418EBAEB47F26F158AEF3DB418FD1632DBB93B431204964B78C7AE9ED796E39F1B6DE1FEE4CE77815462F36342E80B44B052BADC06F78CFEA7D3D0B294C5C8E8E623F95F5D3C1A17D911A0E78FE7754AA4A440FE75498D9AA47AACF2FC2F716630AEF10950F1FACD4CF847A7E4B0C20F507A7322996DBC4D2250A99CB213CB95AAF7A8B6A0B5317BE8FF728D3A0A0AAEA1B86729DDD59566916640F9AF7A455145CE29CB58884CC2E9DD705B1E87D10E139945FBE70D20D718FED9AF202A22673D76128A5FCB2860419675ADB97512628C7C65C7078B0C730A258C8979912C18EC065367791A404C71318B78FE29CC115ECD74C4EFCDE86C35BD0CFC3ADC41B4F24243A262B251F6E21F8DA7A47 +20170623073826 2 6 100 3071 2 E787C1EA14A0022F3F98A02847D293441332B2EB8BFF8C4D74ECFF730CCA9D1AFC6433A6DD4BA7089EC18D8D314550FCDC6DA23FEFDE48622BB6FFD89AB71CC0BA6C8C0930593E85A442A9C589ECF35E17D9CC7E2AE713B3704D69B61EF6E79A41AE02ADBF7966DF94B1C6861795B7EDFA8D7418EBAEB47F26F158AEF3DB418FD1632DBB93B431204964B78C7AE9ED796E39F1B6DE1FEE4CE77815462F36342E80B44B052BADC06F78CFEA7D3D0B294C5C8E8E623F95F5D3C1A17D911A0E78FE7754AA4A440FE75498D9AA47AACF2FC2F716630AEF10950F1FACD4CF847A7E4B0C20F507A7322996DBC4D2250A99CB213CB95AAF7A8B6A0B5317BE8FF728D3A0A0AAEA1B86729DDD59566916640F9AF7A455145CE29CB58884CC2E9DD705B1E87D10E139945FBE70D20D718FED9AF202A22673D76128A5FCB2860419675ADB97512628C7C65C7078B0C730A258C8979912C18EC065367791A404C71318B78FE29CC115ECD74C4EFCDE86C35BD0CFC3ADC41B4F24243A262B251F6E21F983F783 +20170623074239 2 6 100 3071 5 E787C1EA14A0022F3F98A02847D293441332B2EB8BFF8C4D74ECFF730CCA9D1AFC6433A6DD4BA7089EC18D8D314550FCDC6DA23FEFDE48622BB6FFD89AB71CC0BA6C8C0930593E85A442A9C589ECF35E17D9CC7E2AE713B3704D69B61EF6E79A41AE02ADBF7966DF94B1C6861795B7EDFA8D7418EBAEB47F26F158AEF3DB418FD1632DBB93B431204964B78C7AE9ED796E39F1B6DE1FEE4CE77815462F36342E80B44B052BADC06F78CFEA7D3D0B294C5C8E8E623F95F5D3C1A17D911A0E78FE7754AA4A440FE75498D9AA47AACF2FC2F716630AEF10950F1FACD4CF847A7E4B0C20F507A7322996DBC4D2250A99CB213CB95AAF7A8B6A0B5317BE8FF728D3A0A0AAEA1B86729DDD59566916640F9AF7A455145CE29CB58884CC2E9DD705B1E87D10E139945FBE70D20D718FED9AF202A22673D76128A5FCB2860419675ADB97512628C7C65C7078B0C730A258C8979912C18EC065367791A404C71318B78FE29CC115ECD74C4EFCDE86C35BD0CFC3ADC41B4F24243A262B251F6E21FA40B7CF +20170623074307 2 6 100 3071 2 E787C1EA14A0022F3F98A02847D293441332B2EB8BFF8C4D74ECFF730CCA9D1AFC6433A6DD4BA7089EC18D8D314550FCDC6DA23FEFDE48622BB6FFD89AB71CC0BA6C8C0930593E85A442A9C589ECF35E17D9CC7E2AE713B3704D69B61EF6E79A41AE02ADBF7966DF94B1C6861795B7EDFA8D7418EBAEB47F26F158AEF3DB418FD1632DBB93B431204964B78C7AE9ED796E39F1B6DE1FEE4CE77815462F36342E80B44B052BADC06F78CFEA7D3D0B294C5C8E8E623F95F5D3C1A17D911A0E78FE7754AA4A440FE75498D9AA47AACF2FC2F716630AEF10950F1FACD4CF847A7E4B0C20F507A7322996DBC4D2250A99CB213CB95AAF7A8B6A0B5317BE8FF728D3A0A0AAEA1B86729DDD59566916640F9AF7A455145CE29CB58884CC2E9DD705B1E87D10E139945FBE70D20D718FED9AF202A22673D76128A5FCB2860419675ADB97512628C7C65C7078B0C730A258C8979912C18EC065367791A404C71318B78FE29CC115ECD74C4EFCDE86C35BD0CFC3ADC41B4F24243A262B251F6E21FA4F193B +20170623074345 2 6 100 3071 2 E787C1EA14A0022F3F98A02847D293441332B2EB8BFF8C4D74ECFF730CCA9D1AFC6433A6DD4BA7089EC18D8D314550FCDC6DA23FEFDE48622BB6FFD89AB71CC0BA6C8C0930593E85A442A9C589ECF35E17D9CC7E2AE713B3704D69B61EF6E79A41AE02ADBF7966DF94B1C6861795B7EDFA8D7418EBAEB47F26F158AEF3DB418FD1632DBB93B431204964B78C7AE9ED796E39F1B6DE1FEE4CE77815462F36342E80B44B052BADC06F78CFEA7D3D0B294C5C8E8E623F95F5D3C1A17D911A0E78FE7754AA4A440FE75498D9AA47AACF2FC2F716630AEF10950F1FACD4CF847A7E4B0C20F507A7322996DBC4D2250A99CB213CB95AAF7A8B6A0B5317BE8FF728D3A0A0AAEA1B86729DDD59566916640F9AF7A455145CE29CB58884CC2E9DD705B1E87D10E139945FBE70D20D718FED9AF202A22673D76128A5FCB2860419675ADB97512628C7C65C7078B0C730A258C8979912C18EC065367791A404C71318B78FE29CC115ECD74C4EFCDE86C35BD0CFC3ADC41B4F24243A262B251F6E21FA61D323 +20170623074648 2 6 100 3071 2 E787C1EA14A0022F3F98A02847D293441332B2EB8BFF8C4D74ECFF730CCA9D1AFC6433A6DD4BA7089EC18D8D314550FCDC6DA23FEFDE48622BB6FFD89AB71CC0BA6C8C0930593E85A442A9C589ECF35E17D9CC7E2AE713B3704D69B61EF6E79A41AE02ADBF7966DF94B1C6861795B7EDFA8D7418EBAEB47F26F158AEF3DB418FD1632DBB93B431204964B78C7AE9ED796E39F1B6DE1FEE4CE77815462F36342E80B44B052BADC06F78CFEA7D3D0B294C5C8E8E623F95F5D3C1A17D911A0E78FE7754AA4A440FE75498D9AA47AACF2FC2F716630AEF10950F1FACD4CF847A7E4B0C20F507A7322996DBC4D2250A99CB213CB95AAF7A8B6A0B5317BE8FF728D3A0A0AAEA1B86729DDD59566916640F9AF7A455145CE29CB58884CC2E9DD705B1E87D10E139945FBE70D20D718FED9AF202A22673D76128A5FCB2860419675ADB97512628C7C65C7078B0C730A258C8979912C18EC065367791A404C71318B78FE29CC115ECD74C4EFCDE86C35BD0CFC3ADC41B4F24243A262B251F6E21FAEB991B +20170623074919 2 6 100 3071 5 E787C1EA14A0022F3F98A02847D293441332B2EB8BFF8C4D74ECFF730CCA9D1AFC6433A6DD4BA7089EC18D8D314550FCDC6DA23FEFDE48622BB6FFD89AB71CC0BA6C8C0930593E85A442A9C589ECF35E17D9CC7E2AE713B3704D69B61EF6E79A41AE02ADBF7966DF94B1C6861795B7EDFA8D7418EBAEB47F26F158AEF3DB418FD1632DBB93B431204964B78C7AE9ED796E39F1B6DE1FEE4CE77815462F36342E80B44B052BADC06F78CFEA7D3D0B294C5C8E8E623F95F5D3C1A17D911A0E78FE7754AA4A440FE75498D9AA47AACF2FC2F716630AEF10950F1FACD4CF847A7E4B0C20F507A7322996DBC4D2250A99CB213CB95AAF7A8B6A0B5317BE8FF728D3A0A0AAEA1B86729DDD59566916640F9AF7A455145CE29CB58884CC2E9DD705B1E87D10E139945FBE70D20D718FED9AF202A22673D76128A5FCB2860419675ADB97512628C7C65C7078B0C730A258C8979912C18EC065367791A404C71318B78FE29CC115ECD74C4EFCDE86C35BD0CFC3ADC41B4F24243A262B251F6E21FB5876F7 +20170623075011 2 6 100 3071 5 E787C1EA14A0022F3F98A02847D293441332B2EB8BFF8C4D74ECFF730CCA9D1AFC6433A6DD4BA7089EC18D8D314550FCDC6DA23FEFDE48622BB6FFD89AB71CC0BA6C8C0930593E85A442A9C589ECF35E17D9CC7E2AE713B3704D69B61EF6E79A41AE02ADBF7966DF94B1C6861795B7EDFA8D7418EBAEB47F26F158AEF3DB418FD1632DBB93B431204964B78C7AE9ED796E39F1B6DE1FEE4CE77815462F36342E80B44B052BADC06F78CFEA7D3D0B294C5C8E8E623F95F5D3C1A17D911A0E78FE7754AA4A440FE75498D9AA47AACF2FC2F716630AEF10950F1FACD4CF847A7E4B0C20F507A7322996DBC4D2250A99CB213CB95AAF7A8B6A0B5317BE8FF728D3A0A0AAEA1B86729DDD59566916640F9AF7A455145CE29CB58884CC2E9DD705B1E87D10E139945FBE70D20D718FED9AF202A22673D76128A5FCB2860419675ADB97512628C7C65C7078B0C730A258C8979912C18EC065367791A404C71318B78FE29CC115ECD74C4EFCDE86C35BD0CFC3ADC41B4F24243A262B251F6E21FB79557F +20170623075040 2 6 100 3071 5 E787C1EA14A0022F3F98A02847D293441332B2EB8BFF8C4D74ECFF730CCA9D1AFC6433A6DD4BA7089EC18D8D314550FCDC6DA23FEFDE48622BB6FFD89AB71CC0BA6C8C0930593E85A442A9C589ECF35E17D9CC7E2AE713B3704D69B61EF6E79A41AE02ADBF7966DF94B1C6861795B7EDFA8D7418EBAEB47F26F158AEF3DB418FD1632DBB93B431204964B78C7AE9ED796E39F1B6DE1FEE4CE77815462F36342E80B44B052BADC06F78CFEA7D3D0B294C5C8E8E623F95F5D3C1A17D911A0E78FE7754AA4A440FE75498D9AA47AACF2FC2F716630AEF10950F1FACD4CF847A7E4B0C20F507A7322996DBC4D2250A99CB213CB95AAF7A8B6A0B5317BE8FF728D3A0A0AAEA1B86729DDD59566916640F9AF7A455145CE29CB58884CC2E9DD705B1E87D10E139945FBE70D20D718FED9AF202A22673D76128A5FCB2860419675ADB97512628C7C65C7078B0C730A258C8979912C18EC065367791A404C71318B78FE29CC115ECD74C4EFCDE86C35BD0CFC3ADC41B4F24243A262B251F6E21FB88E5F7 +20170623075211 2 6 100 3071 2 E787C1EA14A0022F3F98A02847D293441332B2EB8BFF8C4D74ECFF730CCA9D1AFC6433A6DD4BA7089EC18D8D314550FCDC6DA23FEFDE48622BB6FFD89AB71CC0BA6C8C0930593E85A442A9C589ECF35E17D9CC7E2AE713B3704D69B61EF6E79A41AE02ADBF7966DF94B1C6861795B7EDFA8D7418EBAEB47F26F158AEF3DB418FD1632DBB93B431204964B78C7AE9ED796E39F1B6DE1FEE4CE77815462F36342E80B44B052BADC06F78CFEA7D3D0B294C5C8E8E623F95F5D3C1A17D911A0E78FE7754AA4A440FE75498D9AA47AACF2FC2F716630AEF10950F1FACD4CF847A7E4B0C20F507A7322996DBC4D2250A99CB213CB95AAF7A8B6A0B5317BE8FF728D3A0A0AAEA1B86729DDD59566916640F9AF7A455145CE29CB58884CC2E9DD705B1E87D10E139945FBE70D20D718FED9AF202A22673D76128A5FCB2860419675ADB97512628C7C65C7078B0C730A258C8979912C18EC065367791A404C71318B78FE29CC115ECD74C4EFCDE86C35BD0CFC3ADC41B4F24243A262B251F6E21FBC86DF3 +20170623075233 2 6 100 3071 2 E787C1EA14A0022F3F98A02847D293441332B2EB8BFF8C4D74ECFF730CCA9D1AFC6433A6DD4BA7089EC18D8D314550FCDC6DA23FEFDE48622BB6FFD89AB71CC0BA6C8C0930593E85A442A9C589ECF35E17D9CC7E2AE713B3704D69B61EF6E79A41AE02ADBF7966DF94B1C6861795B7EDFA8D7418EBAEB47F26F158AEF3DB418FD1632DBB93B431204964B78C7AE9ED796E39F1B6DE1FEE4CE77815462F36342E80B44B052BADC06F78CFEA7D3D0B294C5C8E8E623F95F5D3C1A17D911A0E78FE7754AA4A440FE75498D9AA47AACF2FC2F716630AEF10950F1FACD4CF847A7E4B0C20F507A7322996DBC4D2250A99CB213CB95AAF7A8B6A0B5317BE8FF728D3A0A0AAEA1B86729DDD59566916640F9AF7A455145CE29CB58884CC2E9DD705B1E87D10E139945FBE70D20D718FED9AF202A22673D76128A5FCB2860419675ADB97512628C7C65C7078B0C730A258C8979912C18EC065367791A404C71318B78FE29CC115ECD74C4EFCDE86C35BD0CFC3ADC41B4F24243A262B251F6E21FBD19D1B +20170623075313 2 6 100 3071 5 E787C1EA14A0022F3F98A02847D293441332B2EB8BFF8C4D74ECFF730CCA9D1AFC6433A6DD4BA7089EC18D8D314550FCDC6DA23FEFDE48622BB6FFD89AB71CC0BA6C8C0930593E85A442A9C589ECF35E17D9CC7E2AE713B3704D69B61EF6E79A41AE02ADBF7966DF94B1C6861795B7EDFA8D7418EBAEB47F26F158AEF3DB418FD1632DBB93B431204964B78C7AE9ED796E39F1B6DE1FEE4CE77815462F36342E80B44B052BADC06F78CFEA7D3D0B294C5C8E8E623F95F5D3C1A17D911A0E78FE7754AA4A440FE75498D9AA47AACF2FC2F716630AEF10950F1FACD4CF847A7E4B0C20F507A7322996DBC4D2250A99CB213CB95AAF7A8B6A0B5317BE8FF728D3A0A0AAEA1B86729DDD59566916640F9AF7A455145CE29CB58884CC2E9DD705B1E87D10E139945FBE70D20D718FED9AF202A22673D76128A5FCB2860419675ADB97512628C7C65C7078B0C730A258C8979912C18EC065367791A404C71318B78FE29CC115ECD74C4EFCDE86C35BD0CFC3ADC41B4F24243A262B251F6E21FBE8A97F +20170623080026 2 6 100 3071 2 E787C1EA14A0022F3F98A02847D293441332B2EB8BFF8C4D74ECFF730CCA9D1AFC6433A6DD4BA7089EC18D8D314550FCDC6DA23FEFDE48622BB6FFD89AB71CC0BA6C8C0930593E85A442A9C589ECF35E17D9CC7E2AE713B3704D69B61EF6E79A41AE02ADBF7966DF94B1C6861795B7EDFA8D7418EBAEB47F26F158AEF3DB418FD1632DBB93B431204964B78C7AE9ED796E39F1B6DE1FEE4CE77815462F36342E80B44B052BADC06F78CFEA7D3D0B294C5C8E8E623F95F5D3C1A17D911A0E78FE7754AA4A440FE75498D9AA47AACF2FC2F716630AEF10950F1FACD4CF847A7E4B0C20F507A7322996DBC4D2250A99CB213CB95AAF7A8B6A0B5317BE8FF728D3A0A0AAEA1B86729DDD59566916640F9AF7A455145CE29CB58884CC2E9DD705B1E87D10E139945FBE70D20D718FED9AF202A22673D76128A5FCB2860419675ADB97512628C7C65C7078B0C730A258C8979912C18EC065367791A404C71318B78FE29CC115ECD74C4EFCDE86C35BD0CFC3ADC41B4F24243A262B251F6E21FD35417B +20170623082844 2 6 100 4095 2 DCFD3F9E0CF8187E955D8AEB347A5E4250C2B78E67E73E1DCDB99D67EC98180AE5FEF9119D38E50CBDBF46C8B2F62240FF5E1B28FB01276B82DB7422A777AA30AC5A9423D9AC3D33C9FECCC85823BD1138919E8F831364B093CF13B11CDD11394AA8D2256D58264266F780EABBA494E99EF63EC1F69997D180ABBA50B091AFD7FF478DAFF435CE2529E5F8FC81316AB0EA636014E125715FC77D653B142734C93FCD825C28CB928D579E9ED2C6C11E89C64B9C4B91CA962FB11C824F302BDEF7F67D1F7AC95F52B49FD4A044101BA3BDDD59C7663AB270D24DC846B90925F615EBFA5182F261938182E301C83FDC027381BD0FA753C84E57CC51531E7D0C468988B67D0B312E73C65E21D93C69C7862553F60BC9B26C6B5FB68BEDA3D7B0770C1116FF2B88484C7FB29A9D46D01719E89CB76A25C1B8349E3F8DA38CC00B3C1502BA6775BE363D27FA71A72DE0094E6805DEABB343B4A6DC98CD5F5191017B4E1CB0E5EE2FA979642305B8FDE9EE6A26E469C03C8B806F9492C0C544D7A0FE7773B3940812AE6B76C447BC28AA8127D9A7FEB7F98B9720C889CE2FF4806225B012B06F2FC0737D2A73A3046BD7ACBF0A8CF02BB3FAB81A60A29C0AA5B3B731541F62B542F4EF8224C6BAF6A087D0A9FE43492E5CE13F855E80457A516155CCA04A6144E402A1A3D71D657556B9124837730953505EB479984819069919E3F0A3 +20170623084111 2 6 100 4095 2 DCFD3F9E0CF8187E955D8AEB347A5E4250C2B78E67E73E1DCDB99D67EC98180AE5FEF9119D38E50CBDBF46C8B2F62240FF5E1B28FB01276B82DB7422A777AA30AC5A9423D9AC3D33C9FECCC85823BD1138919E8F831364B093CF13B11CDD11394AA8D2256D58264266F780EABBA494E99EF63EC1F69997D180ABBA50B091AFD7FF478DAFF435CE2529E5F8FC81316AB0EA636014E125715FC77D653B142734C93FCD825C28CB928D579E9ED2C6C11E89C64B9C4B91CA962FB11C824F302BDEF7F67D1F7AC95F52B49FD4A044101BA3BDDD59C7663AB270D24DC846B90925F615EBFA5182F261938182E301C83FDC027381BD0FA753C84E57CC51531E7D0C468988B67D0B312E73C65E21D93C69C7862553F60BC9B26C6B5FB68BEDA3D7B0770C1116FF2B88484C7FB29A9D46D01719E89CB76A25C1B8349E3F8DA38CC00B3C1502BA6775BE363D27FA71A72DE0094E6805DEABB343B4A6DC98CD5F5191017B4E1CB0E5EE2FA979642305B8FDE9EE6A26E469C03C8B806F9492C0C544D7A0FE7773B3940812AE6B76C447BC28AA8127D9A7FEB7F98B9720C889CE2FF4806225B012B06F2FC0737D2A73A3046BD7ACBF0A8CF02BB3FAB81A60A29C0AA5B3B731541F62B542F4EF8224C6BAF6A087D0A9FE43492E5CE13F855E80457A516155CCA04A6144E402A1A3D71D657556B9124837730953505EB47998481906991AE37AEB +20170623091322 2 6 100 4095 5 DCFD3F9E0CF8187E955D8AEB347A5E4250C2B78E67E73E1DCDB99D67EC98180AE5FEF9119D38E50CBDBF46C8B2F62240FF5E1B28FB01276B82DB7422A777AA30AC5A9423D9AC3D33C9FECCC85823BD1138919E8F831364B093CF13B11CDD11394AA8D2256D58264266F780EABBA494E99EF63EC1F69997D180ABBA50B091AFD7FF478DAFF435CE2529E5F8FC81316AB0EA636014E125715FC77D653B142734C93FCD825C28CB928D579E9ED2C6C11E89C64B9C4B91CA962FB11C824F302BDEF7F67D1F7AC95F52B49FD4A044101BA3BDDD59C7663AB270D24DC846B90925F615EBFA5182F261938182E301C83FDC027381BD0FA753C84E57CC51531E7D0C468988B67D0B312E73C65E21D93C69C7862553F60BC9B26C6B5FB68BEDA3D7B0770C1116FF2B88484C7FB29A9D46D01719E89CB76A25C1B8349E3F8DA38CC00B3C1502BA6775BE363D27FA71A72DE0094E6805DEABB343B4A6DC98CD5F5191017B4E1CB0E5EE2FA979642305B8FDE9EE6A26E469C03C8B806F9492C0C544D7A0FE7773B3940812AE6B76C447BC28AA8127D9A7FEB7F98B9720C889CE2FF4806225B012B06F2FC0737D2A73A3046BD7ACBF0A8CF02BB3FAB81A60A29C0AA5B3B731541F62B542F4EF8224C6BAF6A087D0A9FE43492E5CE13F855E80457A516155CCA04A6144E402A1A3D71D657556B9124837730953505EB47998481906991D857A5F +20170623095654 2 6 100 4095 5 DCFD3F9E0CF8187E955D8AEB347A5E4250C2B78E67E73E1DCDB99D67EC98180AE5FEF9119D38E50CBDBF46C8B2F62240FF5E1B28FB01276B82DB7422A777AA30AC5A9423D9AC3D33C9FECCC85823BD1138919E8F831364B093CF13B11CDD11394AA8D2256D58264266F780EABBA494E99EF63EC1F69997D180ABBA50B091AFD7FF478DAFF435CE2529E5F8FC81316AB0EA636014E125715FC77D653B142734C93FCD825C28CB928D579E9ED2C6C11E89C64B9C4B91CA962FB11C824F302BDEF7F67D1F7AC95F52B49FD4A044101BA3BDDD59C7663AB270D24DC846B90925F615EBFA5182F261938182E301C83FDC027381BD0FA753C84E57CC51531E7D0C468988B67D0B312E73C65E21D93C69C7862553F60BC9B26C6B5FB68BEDA3D7B0770C1116FF2B88484C7FB29A9D46D01719E89CB76A25C1B8349E3F8DA38CC00B3C1502BA6775BE363D27FA71A72DE0094E6805DEABB343B4A6DC98CD5F5191017B4E1CB0E5EE2FA979642305B8FDE9EE6A26E469C03C8B806F9492C0C544D7A0FE7773B3940812AE6B76C447BC28AA8127D9A7FEB7F98B9720C889CE2FF4806225B012B06F2FC0737D2A73A3046BD7ACBF0A8CF02BB3FAB81A60A29C0AA5B3B731541F62B542F4EF8224C6BAF6A087D0A9FE43492E5CE13F855E80457A516155CCA04A6144E402A1A3D71D657556B9124837730953505EB4799848190699210172E7 +20170623095828 2 6 100 4095 2 DCFD3F9E0CF8187E955D8AEB347A5E4250C2B78E67E73E1DCDB99D67EC98180AE5FEF9119D38E50CBDBF46C8B2F62240FF5E1B28FB01276B82DB7422A777AA30AC5A9423D9AC3D33C9FECCC85823BD1138919E8F831364B093CF13B11CDD11394AA8D2256D58264266F780EABBA494E99EF63EC1F69997D180ABBA50B091AFD7FF478DAFF435CE2529E5F8FC81316AB0EA636014E125715FC77D653B142734C93FCD825C28CB928D579E9ED2C6C11E89C64B9C4B91CA962FB11C824F302BDEF7F67D1F7AC95F52B49FD4A044101BA3BDDD59C7663AB270D24DC846B90925F615EBFA5182F261938182E301C83FDC027381BD0FA753C84E57CC51531E7D0C468988B67D0B312E73C65E21D93C69C7862553F60BC9B26C6B5FB68BEDA3D7B0770C1116FF2B88484C7FB29A9D46D01719E89CB76A25C1B8349E3F8DA38CC00B3C1502BA6775BE363D27FA71A72DE0094E6805DEABB343B4A6DC98CD5F5191017B4E1CB0E5EE2FA979642305B8FDE9EE6A26E469C03C8B806F9492C0C544D7A0FE7773B3940812AE6B76C447BC28AA8127D9A7FEB7F98B9720C889CE2FF4806225B012B06F2FC0737D2A73A3046BD7ACBF0A8CF02BB3FAB81A60A29C0AA5B3B731541F62B542F4EF8224C6BAF6A087D0A9FE43492E5CE13F855E80457A516155CCA04A6144E402A1A3D71D657556B9124837730953505EB479984819069921188C6B +20170623095901 2 6 100 4095 5 DCFD3F9E0CF8187E955D8AEB347A5E4250C2B78E67E73E1DCDB99D67EC98180AE5FEF9119D38E50CBDBF46C8B2F62240FF5E1B28FB01276B82DB7422A777AA30AC5A9423D9AC3D33C9FECCC85823BD1138919E8F831364B093CF13B11CDD11394AA8D2256D58264266F780EABBA494E99EF63EC1F69997D180ABBA50B091AFD7FF478DAFF435CE2529E5F8FC81316AB0EA636014E125715FC77D653B142734C93FCD825C28CB928D579E9ED2C6C11E89C64B9C4B91CA962FB11C824F302BDEF7F67D1F7AC95F52B49FD4A044101BA3BDDD59C7663AB270D24DC846B90925F615EBFA5182F261938182E301C83FDC027381BD0FA753C84E57CC51531E7D0C468988B67D0B312E73C65E21D93C69C7862553F60BC9B26C6B5FB68BEDA3D7B0770C1116FF2B88484C7FB29A9D46D01719E89CB76A25C1B8349E3F8DA38CC00B3C1502BA6775BE363D27FA71A72DE0094E6805DEABB343B4A6DC98CD5F5191017B4E1CB0E5EE2FA979642305B8FDE9EE6A26E469C03C8B806F9492C0C544D7A0FE7773B3940812AE6B76C447BC28AA8127D9A7FEB7F98B9720C889CE2FF4806225B012B06F2FC0737D2A73A3046BD7ACBF0A8CF02BB3FAB81A60A29C0AA5B3B731541F62B542F4EF8224C6BAF6A087D0A9FE43492E5CE13F855E80457A516155CCA04A6144E402A1A3D71D657556B9124837730953505EB4799848190699211B667F +20170623100423 2 6 100 4095 2 DCFD3F9E0CF8187E955D8AEB347A5E4250C2B78E67E73E1DCDB99D67EC98180AE5FEF9119D38E50CBDBF46C8B2F62240FF5E1B28FB01276B82DB7422A777AA30AC5A9423D9AC3D33C9FECCC85823BD1138919E8F831364B093CF13B11CDD11394AA8D2256D58264266F780EABBA494E99EF63EC1F69997D180ABBA50B091AFD7FF478DAFF435CE2529E5F8FC81316AB0EA636014E125715FC77D653B142734C93FCD825C28CB928D579E9ED2C6C11E89C64B9C4B91CA962FB11C824F302BDEF7F67D1F7AC95F52B49FD4A044101BA3BDDD59C7663AB270D24DC846B90925F615EBFA5182F261938182E301C83FDC027381BD0FA753C84E57CC51531E7D0C468988B67D0B312E73C65E21D93C69C7862553F60BC9B26C6B5FB68BEDA3D7B0770C1116FF2B88484C7FB29A9D46D01719E89CB76A25C1B8349E3F8DA38CC00B3C1502BA6775BE363D27FA71A72DE0094E6805DEABB343B4A6DC98CD5F5191017B4E1CB0E5EE2FA979642305B8FDE9EE6A26E469C03C8B806F9492C0C544D7A0FE7773B3940812AE6B76C447BC28AA8127D9A7FEB7F98B9720C889CE2FF4806225B012B06F2FC0737D2A73A3046BD7ACBF0A8CF02BB3FAB81A60A29C0AA5B3B731541F62B542F4EF8224C6BAF6A087D0A9FE43492E5CE13F855E80457A516155CCA04A6144E402A1A3D71D657556B9124837730953505EB479984819069921818383 +20170623101338 2 6 100 4095 2 DCFD3F9E0CF8187E955D8AEB347A5E4250C2B78E67E73E1DCDB99D67EC98180AE5FEF9119D38E50CBDBF46C8B2F62240FF5E1B28FB01276B82DB7422A777AA30AC5A9423D9AC3D33C9FECCC85823BD1138919E8F831364B093CF13B11CDD11394AA8D2256D58264266F780EABBA494E99EF63EC1F69997D180ABBA50B091AFD7FF478DAFF435CE2529E5F8FC81316AB0EA636014E125715FC77D653B142734C93FCD825C28CB928D579E9ED2C6C11E89C64B9C4B91CA962FB11C824F302BDEF7F67D1F7AC95F52B49FD4A044101BA3BDDD59C7663AB270D24DC846B90925F615EBFA5182F261938182E301C83FDC027381BD0FA753C84E57CC51531E7D0C468988B67D0B312E73C65E21D93C69C7862553F60BC9B26C6B5FB68BEDA3D7B0770C1116FF2B88484C7FB29A9D46D01719E89CB76A25C1B8349E3F8DA38CC00B3C1502BA6775BE363D27FA71A72DE0094E6805DEABB343B4A6DC98CD5F5191017B4E1CB0E5EE2FA979642305B8FDE9EE6A26E469C03C8B806F9492C0C544D7A0FE7773B3940812AE6B76C447BC28AA8127D9A7FEB7F98B9720C889CE2FF4806225B012B06F2FC0737D2A73A3046BD7ACBF0A8CF02BB3FAB81A60A29C0AA5B3B731541F62B542F4EF8224C6BAF6A087D0A9FE43492E5CE13F855E80457A516155CCA04A6144E402A1A3D71D657556B9124837730953505EB4799848190699223C1F3B +20170623101757 2 6 100 4095 2 DCFD3F9E0CF8187E955D8AEB347A5E4250C2B78E67E73E1DCDB99D67EC98180AE5FEF9119D38E50CBDBF46C8B2F62240FF5E1B28FB01276B82DB7422A777AA30AC5A9423D9AC3D33C9FECCC85823BD1138919E8F831364B093CF13B11CDD11394AA8D2256D58264266F780EABBA494E99EF63EC1F69997D180ABBA50B091AFD7FF478DAFF435CE2529E5F8FC81316AB0EA636014E125715FC77D653B142734C93FCD825C28CB928D579E9ED2C6C11E89C64B9C4B91CA962FB11C824F302BDEF7F67D1F7AC95F52B49FD4A044101BA3BDDD59C7663AB270D24DC846B90925F615EBFA5182F261938182E301C83FDC027381BD0FA753C84E57CC51531E7D0C468988B67D0B312E73C65E21D93C69C7862553F60BC9B26C6B5FB68BEDA3D7B0770C1116FF2B88484C7FB29A9D46D01719E89CB76A25C1B8349E3F8DA38CC00B3C1502BA6775BE363D27FA71A72DE0094E6805DEABB343B4A6DC98CD5F5191017B4E1CB0E5EE2FA979642305B8FDE9EE6A26E469C03C8B806F9492C0C544D7A0FE7773B3940812AE6B76C447BC28AA8127D9A7FEB7F98B9720C889CE2FF4806225B012B06F2FC0737D2A73A3046BD7ACBF0A8CF02BB3FAB81A60A29C0AA5B3B731541F62B542F4EF8224C6BAF6A087D0A9FE43492E5CE13F855E80457A516155CCA04A6144E402A1A3D71D657556B9124837730953505EB4799848190699228B3683 +20170623104910 2 6 100 4095 2 DCFD3F9E0CF8187E955D8AEB347A5E4250C2B78E67E73E1DCDB99D67EC98180AE5FEF9119D38E50CBDBF46C8B2F62240FF5E1B28FB01276B82DB7422A777AA30AC5A9423D9AC3D33C9FECCC85823BD1138919E8F831364B093CF13B11CDD11394AA8D2256D58264266F780EABBA494E99EF63EC1F69997D180ABBA50B091AFD7FF478DAFF435CE2529E5F8FC81316AB0EA636014E125715FC77D653B142734C93FCD825C28CB928D579E9ED2C6C11E89C64B9C4B91CA962FB11C824F302BDEF7F67D1F7AC95F52B49FD4A044101BA3BDDD59C7663AB270D24DC846B90925F615EBFA5182F261938182E301C83FDC027381BD0FA753C84E57CC51531E7D0C468988B67D0B312E73C65E21D93C69C7862553F60BC9B26C6B5FB68BEDA3D7B0770C1116FF2B88484C7FB29A9D46D01719E89CB76A25C1B8349E3F8DA38CC00B3C1502BA6775BE363D27FA71A72DE0094E6805DEABB343B4A6DC98CD5F5191017B4E1CB0E5EE2FA979642305B8FDE9EE6A26E469C03C8B806F9492C0C544D7A0FE7773B3940812AE6B76C447BC28AA8127D9A7FEB7F98B9720C889CE2FF4806225B012B06F2FC0737D2A73A3046BD7ACBF0A8CF02BB3FAB81A60A29C0AA5B3B731541F62B542F4EF8224C6BAF6A087D0A9FE43492E5CE13F855E80457A516155CCA04A6144E402A1A3D71D657556B9124837730953505EB4799848190699250221BB +20170623110231 2 6 100 4095 2 DCFD3F9E0CF8187E955D8AEB347A5E4250C2B78E67E73E1DCDB99D67EC98180AE5FEF9119D38E50CBDBF46C8B2F62240FF5E1B28FB01276B82DB7422A777AA30AC5A9423D9AC3D33C9FECCC85823BD1138919E8F831364B093CF13B11CDD11394AA8D2256D58264266F780EABBA494E99EF63EC1F69997D180ABBA50B091AFD7FF478DAFF435CE2529E5F8FC81316AB0EA636014E125715FC77D653B142734C93FCD825C28CB928D579E9ED2C6C11E89C64B9C4B91CA962FB11C824F302BDEF7F67D1F7AC95F52B49FD4A044101BA3BDDD59C7663AB270D24DC846B90925F615EBFA5182F261938182E301C83FDC027381BD0FA753C84E57CC51531E7D0C468988B67D0B312E73C65E21D93C69C7862553F60BC9B26C6B5FB68BEDA3D7B0770C1116FF2B88484C7FB29A9D46D01719E89CB76A25C1B8349E3F8DA38CC00B3C1502BA6775BE363D27FA71A72DE0094E6805DEABB343B4A6DC98CD5F5191017B4E1CB0E5EE2FA979642305B8FDE9EE6A26E469C03C8B806F9492C0C544D7A0FE7773B3940812AE6B76C447BC28AA8127D9A7FEB7F98B9720C889CE2FF4806225B012B06F2FC0737D2A73A3046BD7ACBF0A8CF02BB3FAB81A60A29C0AA5B3B731541F62B542F4EF8224C6BAF6A087D0A9FE43492E5CE13F855E80457A516155CCA04A6144E402A1A3D71D657556B9124837730953505EB4799848190699260AC373 +20170623110814 2 6 100 4095 2 DCFD3F9E0CF8187E955D8AEB347A5E4250C2B78E67E73E1DCDB99D67EC98180AE5FEF9119D38E50CBDBF46C8B2F62240FF5E1B28FB01276B82DB7422A777AA30AC5A9423D9AC3D33C9FECCC85823BD1138919E8F831364B093CF13B11CDD11394AA8D2256D58264266F780EABBA494E99EF63EC1F69997D180ABBA50B091AFD7FF478DAFF435CE2529E5F8FC81316AB0EA636014E125715FC77D653B142734C93FCD825C28CB928D579E9ED2C6C11E89C64B9C4B91CA962FB11C824F302BDEF7F67D1F7AC95F52B49FD4A044101BA3BDDD59C7663AB270D24DC846B90925F615EBFA5182F261938182E301C83FDC027381BD0FA753C84E57CC51531E7D0C468988B67D0B312E73C65E21D93C69C7862553F60BC9B26C6B5FB68BEDA3D7B0770C1116FF2B88484C7FB29A9D46D01719E89CB76A25C1B8349E3F8DA38CC00B3C1502BA6775BE363D27FA71A72DE0094E6805DEABB343B4A6DC98CD5F5191017B4E1CB0E5EE2FA979642305B8FDE9EE6A26E469C03C8B806F9492C0C544D7A0FE7773B3940812AE6B76C447BC28AA8127D9A7FEB7F98B9720C889CE2FF4806225B012B06F2FC0737D2A73A3046BD7ACBF0A8CF02BB3FAB81A60A29C0AA5B3B731541F62B542F4EF8224C6BAF6A087D0A9FE43492E5CE13F855E80457A516155CCA04A6144E402A1A3D71D657556B9124837730953505EB47998481906992672C113 +20170623113826 2 6 100 4095 5 DCFD3F9E0CF8187E955D8AEB347A5E4250C2B78E67E73E1DCDB99D67EC98180AE5FEF9119D38E50CBDBF46C8B2F62240FF5E1B28FB01276B82DB7422A777AA30AC5A9423D9AC3D33C9FECCC85823BD1138919E8F831364B093CF13B11CDD11394AA8D2256D58264266F780EABBA494E99EF63EC1F69997D180ABBA50B091AFD7FF478DAFF435CE2529E5F8FC81316AB0EA636014E125715FC77D653B142734C93FCD825C28CB928D579E9ED2C6C11E89C64B9C4B91CA962FB11C824F302BDEF7F67D1F7AC95F52B49FD4A044101BA3BDDD59C7663AB270D24DC846B90925F615EBFA5182F261938182E301C83FDC027381BD0FA753C84E57CC51531E7D0C468988B67D0B312E73C65E21D93C69C7862553F60BC9B26C6B5FB68BEDA3D7B0770C1116FF2B88484C7FB29A9D46D01719E89CB76A25C1B8349E3F8DA38CC00B3C1502BA6775BE363D27FA71A72DE0094E6805DEABB343B4A6DC98CD5F5191017B4E1CB0E5EE2FA979642305B8FDE9EE6A26E469C03C8B806F9492C0C544D7A0FE7773B3940812AE6B76C447BC28AA8127D9A7FEB7F98B9720C889CE2FF4806225B012B06F2FC0737D2A73A3046BD7ACBF0A8CF02BB3FAB81A60A29C0AA5B3B731541F62B542F4EF8224C6BAF6A087D0A9FE43492E5CE13F855E80457A516155CCA04A6144E402A1A3D71D657556B9124837730953505EB479984819069928D90D4F +20170623120249 2 6 100 4095 5 DCFD3F9E0CF8187E955D8AEB347A5E4250C2B78E67E73E1DCDB99D67EC98180AE5FEF9119D38E50CBDBF46C8B2F62240FF5E1B28FB01276B82DB7422A777AA30AC5A9423D9AC3D33C9FECCC85823BD1138919E8F831364B093CF13B11CDD11394AA8D2256D58264266F780EABBA494E99EF63EC1F69997D180ABBA50B091AFD7FF478DAFF435CE2529E5F8FC81316AB0EA636014E125715FC77D653B142734C93FCD825C28CB928D579E9ED2C6C11E89C64B9C4B91CA962FB11C824F302BDEF7F67D1F7AC95F52B49FD4A044101BA3BDDD59C7663AB270D24DC846B90925F615EBFA5182F261938182E301C83FDC027381BD0FA753C84E57CC51531E7D0C468988B67D0B312E73C65E21D93C69C7862553F60BC9B26C6B5FB68BEDA3D7B0770C1116FF2B88484C7FB29A9D46D01719E89CB76A25C1B8349E3F8DA38CC00B3C1502BA6775BE363D27FA71A72DE0094E6805DEABB343B4A6DC98CD5F5191017B4E1CB0E5EE2FA979642305B8FDE9EE6A26E469C03C8B806F9492C0C544D7A0FE7773B3940812AE6B76C447BC28AA8127D9A7FEB7F98B9720C889CE2FF4806225B012B06F2FC0737D2A73A3046BD7ACBF0A8CF02BB3FAB81A60A29C0AA5B3B731541F62B542F4EF8224C6BAF6A087D0A9FE43492E5CE13F855E80457A516155CCA04A6144E402A1A3D71D657556B9124837730953505EB47998481906992AC1BA3F +20170623121815 2 6 100 4095 2 DCFD3F9E0CF8187E955D8AEB347A5E4250C2B78E67E73E1DCDB99D67EC98180AE5FEF9119D38E50CBDBF46C8B2F62240FF5E1B28FB01276B82DB7422A777AA30AC5A9423D9AC3D33C9FECCC85823BD1138919E8F831364B093CF13B11CDD11394AA8D2256D58264266F780EABBA494E99EF63EC1F69997D180ABBA50B091AFD7FF478DAFF435CE2529E5F8FC81316AB0EA636014E125715FC77D653B142734C93FCD825C28CB928D579E9ED2C6C11E89C64B9C4B91CA962FB11C824F302BDEF7F67D1F7AC95F52B49FD4A044101BA3BDDD59C7663AB270D24DC846B90925F615EBFA5182F261938182E301C83FDC027381BD0FA753C84E57CC51531E7D0C468988B67D0B312E73C65E21D93C69C7862553F60BC9B26C6B5FB68BEDA3D7B0770C1116FF2B88484C7FB29A9D46D01719E89CB76A25C1B8349E3F8DA38CC00B3C1502BA6775BE363D27FA71A72DE0094E6805DEABB343B4A6DC98CD5F5191017B4E1CB0E5EE2FA979642305B8FDE9EE6A26E469C03C8B806F9492C0C544D7A0FE7773B3940812AE6B76C447BC28AA8127D9A7FEB7F98B9720C889CE2FF4806225B012B06F2FC0737D2A73A3046BD7ACBF0A8CF02BB3FAB81A60A29C0AA5B3B731541F62B542F4EF8224C6BAF6A087D0A9FE43492E5CE13F855E80457A516155CCA04A6144E402A1A3D71D657556B9124837730953505EB47998481906992BFC1B7B +20170623122456 2 6 100 4095 5 DCFD3F9E0CF8187E955D8AEB347A5E4250C2B78E67E73E1DCDB99D67EC98180AE5FEF9119D38E50CBDBF46C8B2F62240FF5E1B28FB01276B82DB7422A777AA30AC5A9423D9AC3D33C9FECCC85823BD1138919E8F831364B093CF13B11CDD11394AA8D2256D58264266F780EABBA494E99EF63EC1F69997D180ABBA50B091AFD7FF478DAFF435CE2529E5F8FC81316AB0EA636014E125715FC77D653B142734C93FCD825C28CB928D579E9ED2C6C11E89C64B9C4B91CA962FB11C824F302BDEF7F67D1F7AC95F52B49FD4A044101BA3BDDD59C7663AB270D24DC846B90925F615EBFA5182F261938182E301C83FDC027381BD0FA753C84E57CC51531E7D0C468988B67D0B312E73C65E21D93C69C7862553F60BC9B26C6B5FB68BEDA3D7B0770C1116FF2B88484C7FB29A9D46D01719E89CB76A25C1B8349E3F8DA38CC00B3C1502BA6775BE363D27FA71A72DE0094E6805DEABB343B4A6DC98CD5F5191017B4E1CB0E5EE2FA979642305B8FDE9EE6A26E469C03C8B806F9492C0C544D7A0FE7773B3940812AE6B76C447BC28AA8127D9A7FEB7F98B9720C889CE2FF4806225B012B06F2FC0737D2A73A3046BD7ACBF0A8CF02BB3FAB81A60A29C0AA5B3B731541F62B542F4EF8224C6BAF6A087D0A9FE43492E5CE13F855E80457A516155CCA04A6144E402A1A3D71D657556B9124837730953505EB47998481906992C7EB0CF +20170623123432 2 6 100 4095 2 DCFD3F9E0CF8187E955D8AEB347A5E4250C2B78E67E73E1DCDB99D67EC98180AE5FEF9119D38E50CBDBF46C8B2F62240FF5E1B28FB01276B82DB7422A777AA30AC5A9423D9AC3D33C9FECCC85823BD1138919E8F831364B093CF13B11CDD11394AA8D2256D58264266F780EABBA494E99EF63EC1F69997D180ABBA50B091AFD7FF478DAFF435CE2529E5F8FC81316AB0EA636014E125715FC77D653B142734C93FCD825C28CB928D579E9ED2C6C11E89C64B9C4B91CA962FB11C824F302BDEF7F67D1F7AC95F52B49FD4A044101BA3BDDD59C7663AB270D24DC846B90925F615EBFA5182F261938182E301C83FDC027381BD0FA753C84E57CC51531E7D0C468988B67D0B312E73C65E21D93C69C7862553F60BC9B26C6B5FB68BEDA3D7B0770C1116FF2B88484C7FB29A9D46D01719E89CB76A25C1B8349E3F8DA38CC00B3C1502BA6775BE363D27FA71A72DE0094E6805DEABB343B4A6DC98CD5F5191017B4E1CB0E5EE2FA979642305B8FDE9EE6A26E469C03C8B806F9492C0C544D7A0FE7773B3940812AE6B76C447BC28AA8127D9A7FEB7F98B9720C889CE2FF4806225B012B06F2FC0737D2A73A3046BD7ACBF0A8CF02BB3FAB81A60A29C0AA5B3B731541F62B542F4EF8224C6BAF6A087D0A9FE43492E5CE13F855E80457A516155CCA04A6144E402A1A3D71D657556B9124837730953505EB47998481906992D3D886B +20170623125910 2 6 100 4095 2 DCFD3F9E0CF8187E955D8AEB347A5E4250C2B78E67E73E1DCDB99D67EC98180AE5FEF9119D38E50CBDBF46C8B2F62240FF5E1B28FB01276B82DB7422A777AA30AC5A9423D9AC3D33C9FECCC85823BD1138919E8F831364B093CF13B11CDD11394AA8D2256D58264266F780EABBA494E99EF63EC1F69997D180ABBA50B091AFD7FF478DAFF435CE2529E5F8FC81316AB0EA636014E125715FC77D653B142734C93FCD825C28CB928D579E9ED2C6C11E89C64B9C4B91CA962FB11C824F302BDEF7F67D1F7AC95F52B49FD4A044101BA3BDDD59C7663AB270D24DC846B90925F615EBFA5182F261938182E301C83FDC027381BD0FA753C84E57CC51531E7D0C468988B67D0B312E73C65E21D93C69C7862553F60BC9B26C6B5FB68BEDA3D7B0770C1116FF2B88484C7FB29A9D46D01719E89CB76A25C1B8349E3F8DA38CC00B3C1502BA6775BE363D27FA71A72DE0094E6805DEABB343B4A6DC98CD5F5191017B4E1CB0E5EE2FA979642305B8FDE9EE6A26E469C03C8B806F9492C0C544D7A0FE7773B3940812AE6B76C447BC28AA8127D9A7FEB7F98B9720C889CE2FF4806225B012B06F2FC0737D2A73A3046BD7ACBF0A8CF02BB3FAB81A60A29C0AA5B3B731541F62B542F4EF8224C6BAF6A087D0A9FE43492E5CE13F855E80457A516155CCA04A6144E402A1A3D71D657556B9124837730953505EB47998481906992F34AA0B +20170623130350 2 6 100 4095 5 DCFD3F9E0CF8187E955D8AEB347A5E4250C2B78E67E73E1DCDB99D67EC98180AE5FEF9119D38E50CBDBF46C8B2F62240FF5E1B28FB01276B82DB7422A777AA30AC5A9423D9AC3D33C9FECCC85823BD1138919E8F831364B093CF13B11CDD11394AA8D2256D58264266F780EABBA494E99EF63EC1F69997D180ABBA50B091AFD7FF478DAFF435CE2529E5F8FC81316AB0EA636014E125715FC77D653B142734C93FCD825C28CB928D579E9ED2C6C11E89C64B9C4B91CA962FB11C824F302BDEF7F67D1F7AC95F52B49FD4A044101BA3BDDD59C7663AB270D24DC846B90925F615EBFA5182F261938182E301C83FDC027381BD0FA753C84E57CC51531E7D0C468988B67D0B312E73C65E21D93C69C7862553F60BC9B26C6B5FB68BEDA3D7B0770C1116FF2B88484C7FB29A9D46D01719E89CB76A25C1B8349E3F8DA38CC00B3C1502BA6775BE363D27FA71A72DE0094E6805DEABB343B4A6DC98CD5F5191017B4E1CB0E5EE2FA979642305B8FDE9EE6A26E469C03C8B806F9492C0C544D7A0FE7773B3940812AE6B76C447BC28AA8127D9A7FEB7F98B9720C889CE2FF4806225B012B06F2FC0737D2A73A3046BD7ACBF0A8CF02BB3FAB81A60A29C0AA5B3B731541F62B542F4EF8224C6BAF6A087D0A9FE43492E5CE13F855E80457A516155CCA04A6144E402A1A3D71D657556B9124837730953505EB47998481906992F8B1CFF +20170623131900 2 6 100 4095 2 DCFD3F9E0CF8187E955D8AEB347A5E4250C2B78E67E73E1DCDB99D67EC98180AE5FEF9119D38E50CBDBF46C8B2F62240FF5E1B28FB01276B82DB7422A777AA30AC5A9423D9AC3D33C9FECCC85823BD1138919E8F831364B093CF13B11CDD11394AA8D2256D58264266F780EABBA494E99EF63EC1F69997D180ABBA50B091AFD7FF478DAFF435CE2529E5F8FC81316AB0EA636014E125715FC77D653B142734C93FCD825C28CB928D579E9ED2C6C11E89C64B9C4B91CA962FB11C824F302BDEF7F67D1F7AC95F52B49FD4A044101BA3BDDD59C7663AB270D24DC846B90925F615EBFA5182F261938182E301C83FDC027381BD0FA753C84E57CC51531E7D0C468988B67D0B312E73C65E21D93C69C7862553F60BC9B26C6B5FB68BEDA3D7B0770C1116FF2B88484C7FB29A9D46D01719E89CB76A25C1B8349E3F8DA38CC00B3C1502BA6775BE363D27FA71A72DE0094E6805DEABB343B4A6DC98CD5F5191017B4E1CB0E5EE2FA979642305B8FDE9EE6A26E469C03C8B806F9492C0C544D7A0FE7773B3940812AE6B76C447BC28AA8127D9A7FEB7F98B9720C889CE2FF4806225B012B06F2FC0737D2A73A3046BD7ACBF0A8CF02BB3FAB81A60A29C0AA5B3B731541F62B542F4EF8224C6BAF6A087D0A9FE43492E5CE13F855E80457A516155CCA04A6144E402A1A3D71D657556B9124837730953505EB479984819069930BE28FB +20170623132006 2 6 100 4095 2 DCFD3F9E0CF8187E955D8AEB347A5E4250C2B78E67E73E1DCDB99D67EC98180AE5FEF9119D38E50CBDBF46C8B2F62240FF5E1B28FB01276B82DB7422A777AA30AC5A9423D9AC3D33C9FECCC85823BD1138919E8F831364B093CF13B11CDD11394AA8D2256D58264266F780EABBA494E99EF63EC1F69997D180ABBA50B091AFD7FF478DAFF435CE2529E5F8FC81316AB0EA636014E125715FC77D653B142734C93FCD825C28CB928D579E9ED2C6C11E89C64B9C4B91CA962FB11C824F302BDEF7F67D1F7AC95F52B49FD4A044101BA3BDDD59C7663AB270D24DC846B90925F615EBFA5182F261938182E301C83FDC027381BD0FA753C84E57CC51531E7D0C468988B67D0B312E73C65E21D93C69C7862553F60BC9B26C6B5FB68BEDA3D7B0770C1116FF2B88484C7FB29A9D46D01719E89CB76A25C1B8349E3F8DA38CC00B3C1502BA6775BE363D27FA71A72DE0094E6805DEABB343B4A6DC98CD5F5191017B4E1CB0E5EE2FA979642305B8FDE9EE6A26E469C03C8B806F9492C0C544D7A0FE7773B3940812AE6B76C447BC28AA8127D9A7FEB7F98B9720C889CE2FF4806225B012B06F2FC0737D2A73A3046BD7ACBF0A8CF02BB3FAB81A60A29C0AA5B3B731541F62B542F4EF8224C6BAF6A087D0A9FE43492E5CE13F855E80457A516155CCA04A6144E402A1A3D71D657556B9124837730953505EB479984819069930CCBBC3 +20170623134400 2 6 100 4095 5 DCFD3F9E0CF8187E955D8AEB347A5E4250C2B78E67E73E1DCDB99D67EC98180AE5FEF9119D38E50CBDBF46C8B2F62240FF5E1B28FB01276B82DB7422A777AA30AC5A9423D9AC3D33C9FECCC85823BD1138919E8F831364B093CF13B11CDD11394AA8D2256D58264266F780EABBA494E99EF63EC1F69997D180ABBA50B091AFD7FF478DAFF435CE2529E5F8FC81316AB0EA636014E125715FC77D653B142734C93FCD825C28CB928D579E9ED2C6C11E89C64B9C4B91CA962FB11C824F302BDEF7F67D1F7AC95F52B49FD4A044101BA3BDDD59C7663AB270D24DC846B90925F615EBFA5182F261938182E301C83FDC027381BD0FA753C84E57CC51531E7D0C468988B67D0B312E73C65E21D93C69C7862553F60BC9B26C6B5FB68BEDA3D7B0770C1116FF2B88484C7FB29A9D46D01719E89CB76A25C1B8349E3F8DA38CC00B3C1502BA6775BE363D27FA71A72DE0094E6805DEABB343B4A6DC98CD5F5191017B4E1CB0E5EE2FA979642305B8FDE9EE6A26E469C03C8B806F9492C0C544D7A0FE7773B3940812AE6B76C447BC28AA8127D9A7FEB7F98B9720C889CE2FF4806225B012B06F2FC0737D2A73A3046BD7ACBF0A8CF02BB3FAB81A60A29C0AA5B3B731541F62B542F4EF8224C6BAF6A087D0A9FE43492E5CE13F855E80457A516155CCA04A6144E402A1A3D71D657556B9124837730953505EB479984819069932B40887 +20170623134659 2 6 100 4095 5 DCFD3F9E0CF8187E955D8AEB347A5E4250C2B78E67E73E1DCDB99D67EC98180AE5FEF9119D38E50CBDBF46C8B2F62240FF5E1B28FB01276B82DB7422A777AA30AC5A9423D9AC3D33C9FECCC85823BD1138919E8F831364B093CF13B11CDD11394AA8D2256D58264266F780EABBA494E99EF63EC1F69997D180ABBA50B091AFD7FF478DAFF435CE2529E5F8FC81316AB0EA636014E125715FC77D653B142734C93FCD825C28CB928D579E9ED2C6C11E89C64B9C4B91CA962FB11C824F302BDEF7F67D1F7AC95F52B49FD4A044101BA3BDDD59C7663AB270D24DC846B90925F615EBFA5182F261938182E301C83FDC027381BD0FA753C84E57CC51531E7D0C468988B67D0B312E73C65E21D93C69C7862553F60BC9B26C6B5FB68BEDA3D7B0770C1116FF2B88484C7FB29A9D46D01719E89CB76A25C1B8349E3F8DA38CC00B3C1502BA6775BE363D27FA71A72DE0094E6805DEABB343B4A6DC98CD5F5191017B4E1CB0E5EE2FA979642305B8FDE9EE6A26E469C03C8B806F9492C0C544D7A0FE7773B3940812AE6B76C447BC28AA8127D9A7FEB7F98B9720C889CE2FF4806225B012B06F2FC0737D2A73A3046BD7ACBF0A8CF02BB3FAB81A60A29C0AA5B3B731541F62B542F4EF8224C6BAF6A087D0A9FE43492E5CE13F855E80457A516155CCA04A6144E402A1A3D71D657556B9124837730953505EB479984819069932E77127 +20170623140059 2 6 100 4095 2 DCFD3F9E0CF8187E955D8AEB347A5E4250C2B78E67E73E1DCDB99D67EC98180AE5FEF9119D38E50CBDBF46C8B2F62240FF5E1B28FB01276B82DB7422A777AA30AC5A9423D9AC3D33C9FECCC85823BD1138919E8F831364B093CF13B11CDD11394AA8D2256D58264266F780EABBA494E99EF63EC1F69997D180ABBA50B091AFD7FF478DAFF435CE2529E5F8FC81316AB0EA636014E125715FC77D653B142734C93FCD825C28CB928D579E9ED2C6C11E89C64B9C4B91CA962FB11C824F302BDEF7F67D1F7AC95F52B49FD4A044101BA3BDDD59C7663AB270D24DC846B90925F615EBFA5182F261938182E301C83FDC027381BD0FA753C84E57CC51531E7D0C468988B67D0B312E73C65E21D93C69C7862553F60BC9B26C6B5FB68BEDA3D7B0770C1116FF2B88484C7FB29A9D46D01719E89CB76A25C1B8349E3F8DA38CC00B3C1502BA6775BE363D27FA71A72DE0094E6805DEABB343B4A6DC98CD5F5191017B4E1CB0E5EE2FA979642305B8FDE9EE6A26E469C03C8B806F9492C0C544D7A0FE7773B3940812AE6B76C447BC28AA8127D9A7FEB7F98B9720C889CE2FF4806225B012B06F2FC0737D2A73A3046BD7ACBF0A8CF02BB3FAB81A60A29C0AA5B3B731541F62B542F4EF8224C6BAF6A087D0A9FE43492E5CE13F855E80457A516155CCA04A6144E402A1A3D71D657556B9124837730953505EB479984819069934031953 +20170623140936 2 6 100 4095 5 DCFD3F9E0CF8187E955D8AEB347A5E4250C2B78E67E73E1DCDB99D67EC98180AE5FEF9119D38E50CBDBF46C8B2F62240FF5E1B28FB01276B82DB7422A777AA30AC5A9423D9AC3D33C9FECCC85823BD1138919E8F831364B093CF13B11CDD11394AA8D2256D58264266F780EABBA494E99EF63EC1F69997D180ABBA50B091AFD7FF478DAFF435CE2529E5F8FC81316AB0EA636014E125715FC77D653B142734C93FCD825C28CB928D579E9ED2C6C11E89C64B9C4B91CA962FB11C824F302BDEF7F67D1F7AC95F52B49FD4A044101BA3BDDD59C7663AB270D24DC846B90925F615EBFA5182F261938182E301C83FDC027381BD0FA753C84E57CC51531E7D0C468988B67D0B312E73C65E21D93C69C7862553F60BC9B26C6B5FB68BEDA3D7B0770C1116FF2B88484C7FB29A9D46D01719E89CB76A25C1B8349E3F8DA38CC00B3C1502BA6775BE363D27FA71A72DE0094E6805DEABB343B4A6DC98CD5F5191017B4E1CB0E5EE2FA979642305B8FDE9EE6A26E469C03C8B806F9492C0C544D7A0FE7773B3940812AE6B76C447BC28AA8127D9A7FEB7F98B9720C889CE2FF4806225B012B06F2FC0737D2A73A3046BD7ACBF0A8CF02BB3FAB81A60A29C0AA5B3B731541F62B542F4EF8224C6BAF6A087D0A9FE43492E5CE13F855E80457A516155CCA04A6144E402A1A3D71D657556B9124837730953505EB479984819069934AC3B0F +20170623142309 2 6 100 4095 2 DCFD3F9E0CF8187E955D8AEB347A5E4250C2B78E67E73E1DCDB99D67EC98180AE5FEF9119D38E50CBDBF46C8B2F62240FF5E1B28FB01276B82DB7422A777AA30AC5A9423D9AC3D33C9FECCC85823BD1138919E8F831364B093CF13B11CDD11394AA8D2256D58264266F780EABBA494E99EF63EC1F69997D180ABBA50B091AFD7FF478DAFF435CE2529E5F8FC81316AB0EA636014E125715FC77D653B142734C93FCD825C28CB928D579E9ED2C6C11E89C64B9C4B91CA962FB11C824F302BDEF7F67D1F7AC95F52B49FD4A044101BA3BDDD59C7663AB270D24DC846B90925F615EBFA5182F261938182E301C83FDC027381BD0FA753C84E57CC51531E7D0C468988B67D0B312E73C65E21D93C69C7862553F60BC9B26C6B5FB68BEDA3D7B0770C1116FF2B88484C7FB29A9D46D01719E89CB76A25C1B8349E3F8DA38CC00B3C1502BA6775BE363D27FA71A72DE0094E6805DEABB343B4A6DC98CD5F5191017B4E1CB0E5EE2FA979642305B8FDE9EE6A26E469C03C8B806F9492C0C544D7A0FE7773B3940812AE6B76C447BC28AA8127D9A7FEB7F98B9720C889CE2FF4806225B012B06F2FC0737D2A73A3046BD7ACBF0A8CF02BB3FAB81A60A29C0AA5B3B731541F62B542F4EF8224C6BAF6A087D0A9FE43492E5CE13F855E80457A516155CCA04A6144E402A1A3D71D657556B9124837730953505EB479984819069935BCCF33 +20170623142743 2 6 100 4095 2 DCFD3F9E0CF8187E955D8AEB347A5E4250C2B78E67E73E1DCDB99D67EC98180AE5FEF9119D38E50CBDBF46C8B2F62240FF5E1B28FB01276B82DB7422A777AA30AC5A9423D9AC3D33C9FECCC85823BD1138919E8F831364B093CF13B11CDD11394AA8D2256D58264266F780EABBA494E99EF63EC1F69997D180ABBA50B091AFD7FF478DAFF435CE2529E5F8FC81316AB0EA636014E125715FC77D653B142734C93FCD825C28CB928D579E9ED2C6C11E89C64B9C4B91CA962FB11C824F302BDEF7F67D1F7AC95F52B49FD4A044101BA3BDDD59C7663AB270D24DC846B90925F615EBFA5182F261938182E301C83FDC027381BD0FA753C84E57CC51531E7D0C468988B67D0B312E73C65E21D93C69C7862553F60BC9B26C6B5FB68BEDA3D7B0770C1116FF2B88484C7FB29A9D46D01719E89CB76A25C1B8349E3F8DA38CC00B3C1502BA6775BE363D27FA71A72DE0094E6805DEABB343B4A6DC98CD5F5191017B4E1CB0E5EE2FA979642305B8FDE9EE6A26E469C03C8B806F9492C0C544D7A0FE7773B3940812AE6B76C447BC28AA8127D9A7FEB7F98B9720C889CE2FF4806225B012B06F2FC0737D2A73A3046BD7ACBF0A8CF02BB3FAB81A60A29C0AA5B3B731541F62B542F4EF8224C6BAF6A087D0A9FE43492E5CE13F855E80457A516155CCA04A6144E402A1A3D71D657556B9124837730953505EB47998481906993611A26B +20170623150027 2 6 100 4095 2 DCFD3F9E0CF8187E955D8AEB347A5E4250C2B78E67E73E1DCDB99D67EC98180AE5FEF9119D38E50CBDBF46C8B2F62240FF5E1B28FB01276B82DB7422A777AA30AC5A9423D9AC3D33C9FECCC85823BD1138919E8F831364B093CF13B11CDD11394AA8D2256D58264266F780EABBA494E99EF63EC1F69997D180ABBA50B091AFD7FF478DAFF435CE2529E5F8FC81316AB0EA636014E125715FC77D653B142734C93FCD825C28CB928D579E9ED2C6C11E89C64B9C4B91CA962FB11C824F302BDEF7F67D1F7AC95F52B49FD4A044101BA3BDDD59C7663AB270D24DC846B90925F615EBFA5182F261938182E301C83FDC027381BD0FA753C84E57CC51531E7D0C468988B67D0B312E73C65E21D93C69C7862553F60BC9B26C6B5FB68BEDA3D7B0770C1116FF2B88484C7FB29A9D46D01719E89CB76A25C1B8349E3F8DA38CC00B3C1502BA6775BE363D27FA71A72DE0094E6805DEABB343B4A6DC98CD5F5191017B4E1CB0E5EE2FA979642305B8FDE9EE6A26E469C03C8B806F9492C0C544D7A0FE7773B3940812AE6B76C447BC28AA8127D9A7FEB7F98B9720C889CE2FF4806225B012B06F2FC0737D2A73A3046BD7ACBF0A8CF02BB3FAB81A60A29C0AA5B3B731541F62B542F4EF8224C6BAF6A087D0A9FE43492E5CE13F855E80457A516155CCA04A6144E402A1A3D71D657556B9124837730953505EB479984819069938A6965B +20170623150107 2 6 100 4095 2 DCFD3F9E0CF8187E955D8AEB347A5E4250C2B78E67E73E1DCDB99D67EC98180AE5FEF9119D38E50CBDBF46C8B2F62240FF5E1B28FB01276B82DB7422A777AA30AC5A9423D9AC3D33C9FECCC85823BD1138919E8F831364B093CF13B11CDD11394AA8D2256D58264266F780EABBA494E99EF63EC1F69997D180ABBA50B091AFD7FF478DAFF435CE2529E5F8FC81316AB0EA636014E125715FC77D653B142734C93FCD825C28CB928D579E9ED2C6C11E89C64B9C4B91CA962FB11C824F302BDEF7F67D1F7AC95F52B49FD4A044101BA3BDDD59C7663AB270D24DC846B90925F615EBFA5182F261938182E301C83FDC027381BD0FA753C84E57CC51531E7D0C468988B67D0B312E73C65E21D93C69C7862553F60BC9B26C6B5FB68BEDA3D7B0770C1116FF2B88484C7FB29A9D46D01719E89CB76A25C1B8349E3F8DA38CC00B3C1502BA6775BE363D27FA71A72DE0094E6805DEABB343B4A6DC98CD5F5191017B4E1CB0E5EE2FA979642305B8FDE9EE6A26E469C03C8B806F9492C0C544D7A0FE7773B3940812AE6B76C447BC28AA8127D9A7FEB7F98B9720C889CE2FF4806225B012B06F2FC0737D2A73A3046BD7ACBF0A8CF02BB3FAB81A60A29C0AA5B3B731541F62B542F4EF8224C6BAF6A087D0A9FE43492E5CE13F855E80457A516155CCA04A6144E402A1A3D71D657556B9124837730953505EB479984819069938AB78CB +20170623150738 2 6 100 4095 5 DCFD3F9E0CF8187E955D8AEB347A5E4250C2B78E67E73E1DCDB99D67EC98180AE5FEF9119D38E50CBDBF46C8B2F62240FF5E1B28FB01276B82DB7422A777AA30AC5A9423D9AC3D33C9FECCC85823BD1138919E8F831364B093CF13B11CDD11394AA8D2256D58264266F780EABBA494E99EF63EC1F69997D180ABBA50B091AFD7FF478DAFF435CE2529E5F8FC81316AB0EA636014E125715FC77D653B142734C93FCD825C28CB928D579E9ED2C6C11E89C64B9C4B91CA962FB11C824F302BDEF7F67D1F7AC95F52B49FD4A044101BA3BDDD59C7663AB270D24DC846B90925F615EBFA5182F261938182E301C83FDC027381BD0FA753C84E57CC51531E7D0C468988B67D0B312E73C65E21D93C69C7862553F60BC9B26C6B5FB68BEDA3D7B0770C1116FF2B88484C7FB29A9D46D01719E89CB76A25C1B8349E3F8DA38CC00B3C1502BA6775BE363D27FA71A72DE0094E6805DEABB343B4A6DC98CD5F5191017B4E1CB0E5EE2FA979642305B8FDE9EE6A26E469C03C8B806F9492C0C544D7A0FE7773B3940812AE6B76C447BC28AA8127D9A7FEB7F98B9720C889CE2FF4806225B012B06F2FC0737D2A73A3046BD7ACBF0A8CF02BB3FAB81A60A29C0AA5B3B731541F62B542F4EF8224C6BAF6A087D0A9FE43492E5CE13F855E80457A516155CCA04A6144E402A1A3D71D657556B9124837730953505EB4799848190699392AA267 +20170623152234 2 6 100 4095 2 F2D0058FA043FB189699D118DE484B66A10DCE703B27209CFC6D23D9178067C9D560D7D8BA9D4439A22AED66322F25D886C0A5CD41821B49AAE3D7A7B72F9B0E2D823709AF5444C7E9474DF5867E605E638923A2FAD546A86B8014BA460D238A939B445D7489C91977B54AB531D75B0F4264F187218F885129751EC78654F4B21191365FEA1B7FEFC40842BBC07C4F1D1AD153F6A39B582406F6B5895336A1199F7556EE957EAC716AE6678CBE5390730F0EBB3CC5210242A80CB128BFD747ED1B61AF6BBD5B5DC07B34C5CA7AF73D1EE973B93E13918801AEFD674DF92A0AD84BFA2A8CEE1AD26140DA1D5FC0C450A1EAEBC88F8EA8E703A0F3A814E1F6975AA5BE732473575D16F137D2CE5F7A546CE4371ECB5E8052295E122A9CF89A026E2D09BDE56B8B04CC4CAE66CD0C5E0DFE30695DD798C50E39C911C887FEBACAAEFD2BFE7D454E051C432D66AD84680DA7C126F1A9C7C540283CCB863B9414BB536BA358259104ECB406B4976F97558FA4E5854888A8D13C96A14025DA0C55F869F6AF954B1E7AA1D317262C52099860E870A7EAF72F9910ACA809FF2DEA37FCA3EFB31FD43A308E4138E40178BEAC0FBB0E79ED7D1DCF8F8A81A4ABBFE6749F4C1B96BD65A14822490BC0A71E854BC8077C7A8F2C6FE308F86DEC97F600A4A0015F086B021F7F0BCAFDE3DA4D7E38A9AA1E992539389E99412FD22988DA657F33 +20170623152823 2 6 100 4095 5 F2D0058FA043FB189699D118DE484B66A10DCE703B27209CFC6D23D9178067C9D560D7D8BA9D4439A22AED66322F25D886C0A5CD41821B49AAE3D7A7B72F9B0E2D823709AF5444C7E9474DF5867E605E638923A2FAD546A86B8014BA460D238A939B445D7489C91977B54AB531D75B0F4264F187218F885129751EC78654F4B21191365FEA1B7FEFC40842BBC07C4F1D1AD153F6A39B582406F6B5895336A1199F7556EE957EAC716AE6678CBE5390730F0EBB3CC5210242A80CB128BFD747ED1B61AF6BBD5B5DC07B34C5CA7AF73D1EE973B93E13918801AEFD674DF92A0AD84BFA2A8CEE1AD26140DA1D5FC0C450A1EAEBC88F8EA8E703A0F3A814E1F6975AA5BE732473575D16F137D2CE5F7A546CE4371ECB5E8052295E122A9CF89A026E2D09BDE56B8B04CC4CAE66CD0C5E0DFE30695DD798C50E39C911C887FEBACAAEFD2BFE7D454E051C432D66AD84680DA7C126F1A9C7C540283CCB863B9414BB536BA358259104ECB406B4976F97558FA4E5854888A8D13C96A14025DA0C55F869F6AF954B1E7AA1D317262C52099860E870A7EAF72F9910ACA809FF2DEA37FCA3EFB31FD43A308E4138E40178BEAC0FBB0E79ED7D1DCF8F8A81A4ABBFE6749F4C1B96BD65A14822490BC0A71E854BC8077C7A8F2C6FE308F86DEC97F600A4A0015F086B021F7F0BCAFDE3DA4D7E38A9AA1E992539389E99412FD22988DAD58DFF +20170623153243 2 6 100 4095 2 F2D0058FA043FB189699D118DE484B66A10DCE703B27209CFC6D23D9178067C9D560D7D8BA9D4439A22AED66322F25D886C0A5CD41821B49AAE3D7A7B72F9B0E2D823709AF5444C7E9474DF5867E605E638923A2FAD546A86B8014BA460D238A939B445D7489C91977B54AB531D75B0F4264F187218F885129751EC78654F4B21191365FEA1B7FEFC40842BBC07C4F1D1AD153F6A39B582406F6B5895336A1199F7556EE957EAC716AE6678CBE5390730F0EBB3CC5210242A80CB128BFD747ED1B61AF6BBD5B5DC07B34C5CA7AF73D1EE973B93E13918801AEFD674DF92A0AD84BFA2A8CEE1AD26140DA1D5FC0C450A1EAEBC88F8EA8E703A0F3A814E1F6975AA5BE732473575D16F137D2CE5F7A546CE4371ECB5E8052295E122A9CF89A026E2D09BDE56B8B04CC4CAE66CD0C5E0DFE30695DD798C50E39C911C887FEBACAAEFD2BFE7D454E051C432D66AD84680DA7C126F1A9C7C540283CCB863B9414BB536BA358259104ECB406B4976F97558FA4E5854888A8D13C96A14025DA0C55F869F6AF954B1E7AA1D317262C52099860E870A7EAF72F9910ACA809FF2DEA37FCA3EFB31FD43A308E4138E40178BEAC0FBB0E79ED7D1DCF8F8A81A4ABBFE6749F4C1B96BD65A14822490BC0A71E854BC8077C7A8F2C6FE308F86DEC97F600A4A0015F086B021F7F0BCAFDE3DA4D7E38A9AA1E992539389E99412FD22988DB1F719B +20170623153719 2 6 100 4095 5 F2D0058FA043FB189699D118DE484B66A10DCE703B27209CFC6D23D9178067C9D560D7D8BA9D4439A22AED66322F25D886C0A5CD41821B49AAE3D7A7B72F9B0E2D823709AF5444C7E9474DF5867E605E638923A2FAD546A86B8014BA460D238A939B445D7489C91977B54AB531D75B0F4264F187218F885129751EC78654F4B21191365FEA1B7FEFC40842BBC07C4F1D1AD153F6A39B582406F6B5895336A1199F7556EE957EAC716AE6678CBE5390730F0EBB3CC5210242A80CB128BFD747ED1B61AF6BBD5B5DC07B34C5CA7AF73D1EE973B93E13918801AEFD674DF92A0AD84BFA2A8CEE1AD26140DA1D5FC0C450A1EAEBC88F8EA8E703A0F3A814E1F6975AA5BE732473575D16F137D2CE5F7A546CE4371ECB5E8052295E122A9CF89A026E2D09BDE56B8B04CC4CAE66CD0C5E0DFE30695DD798C50E39C911C887FEBACAAEFD2BFE7D454E051C432D66AD84680DA7C126F1A9C7C540283CCB863B9414BB536BA358259104ECB406B4976F97558FA4E5854888A8D13C96A14025DA0C55F869F6AF954B1E7AA1D317262C52099860E870A7EAF72F9910ACA809FF2DEA37FCA3EFB31FD43A308E4138E40178BEAC0FBB0E79ED7D1DCF8F8A81A4ABBFE6749F4C1B96BD65A14822490BC0A71E854BC8077C7A8F2C6FE308F86DEC97F600A4A0015F086B021F7F0BCAFDE3DA4D7E38A9AA1E992539389E99412FD22988DB76316F +20170623154606 2 6 100 4095 2 F2D0058FA043FB189699D118DE484B66A10DCE703B27209CFC6D23D9178067C9D560D7D8BA9D4439A22AED66322F25D886C0A5CD41821B49AAE3D7A7B72F9B0E2D823709AF5444C7E9474DF5867E605E638923A2FAD546A86B8014BA460D238A939B445D7489C91977B54AB531D75B0F4264F187218F885129751EC78654F4B21191365FEA1B7FEFC40842BBC07C4F1D1AD153F6A39B582406F6B5895336A1199F7556EE957EAC716AE6678CBE5390730F0EBB3CC5210242A80CB128BFD747ED1B61AF6BBD5B5DC07B34C5CA7AF73D1EE973B93E13918801AEFD674DF92A0AD84BFA2A8CEE1AD26140DA1D5FC0C450A1EAEBC88F8EA8E703A0F3A814E1F6975AA5BE732473575D16F137D2CE5F7A546CE4371ECB5E8052295E122A9CF89A026E2D09BDE56B8B04CC4CAE66CD0C5E0DFE30695DD798C50E39C911C887FEBACAAEFD2BFE7D454E051C432D66AD84680DA7C126F1A9C7C540283CCB863B9414BB536BA358259104ECB406B4976F97558FA4E5854888A8D13C96A14025DA0C55F869F6AF954B1E7AA1D317262C52099860E870A7EAF72F9910ACA809FF2DEA37FCA3EFB31FD43A308E4138E40178BEAC0FBB0E79ED7D1DCF8F8A81A4ABBFE6749F4C1B96BD65A14822490BC0A71E854BC8077C7A8F2C6FE308F86DEC97F600A4A0015F086B021F7F0BCAFDE3DA4D7E38A9AA1E992539389E99412FD22988DC289BA3 +20170623155435 2 6 100 4095 5 F2D0058FA043FB189699D118DE484B66A10DCE703B27209CFC6D23D9178067C9D560D7D8BA9D4439A22AED66322F25D886C0A5CD41821B49AAE3D7A7B72F9B0E2D823709AF5444C7E9474DF5867E605E638923A2FAD546A86B8014BA460D238A939B445D7489C91977B54AB531D75B0F4264F187218F885129751EC78654F4B21191365FEA1B7FEFC40842BBC07C4F1D1AD153F6A39B582406F6B5895336A1199F7556EE957EAC716AE6678CBE5390730F0EBB3CC5210242A80CB128BFD747ED1B61AF6BBD5B5DC07B34C5CA7AF73D1EE973B93E13918801AEFD674DF92A0AD84BFA2A8CEE1AD26140DA1D5FC0C450A1EAEBC88F8EA8E703A0F3A814E1F6975AA5BE732473575D16F137D2CE5F7A546CE4371ECB5E8052295E122A9CF89A026E2D09BDE56B8B04CC4CAE66CD0C5E0DFE30695DD798C50E39C911C887FEBACAAEFD2BFE7D454E051C432D66AD84680DA7C126F1A9C7C540283CCB863B9414BB536BA358259104ECB406B4976F97558FA4E5854888A8D13C96A14025DA0C55F869F6AF954B1E7AA1D317262C52099860E870A7EAF72F9910ACA809FF2DEA37FCA3EFB31FD43A308E4138E40178BEAC0FBB0E79ED7D1DCF8F8A81A4ABBFE6749F4C1B96BD65A14822490BC0A71E854BC8077C7A8F2C6FE308F86DEC97F600A4A0015F086B021F7F0BCAFDE3DA4D7E38A9AA1E992539389E99412FD22988DCCFF757 +20170623161905 2 6 100 4095 2 F2D0058FA043FB189699D118DE484B66A10DCE703B27209CFC6D23D9178067C9D560D7D8BA9D4439A22AED66322F25D886C0A5CD41821B49AAE3D7A7B72F9B0E2D823709AF5444C7E9474DF5867E605E638923A2FAD546A86B8014BA460D238A939B445D7489C91977B54AB531D75B0F4264F187218F885129751EC78654F4B21191365FEA1B7FEFC40842BBC07C4F1D1AD153F6A39B582406F6B5895336A1199F7556EE957EAC716AE6678CBE5390730F0EBB3CC5210242A80CB128BFD747ED1B61AF6BBD5B5DC07B34C5CA7AF73D1EE973B93E13918801AEFD674DF92A0AD84BFA2A8CEE1AD26140DA1D5FC0C450A1EAEBC88F8EA8E703A0F3A814E1F6975AA5BE732473575D16F137D2CE5F7A546CE4371ECB5E8052295E122A9CF89A026E2D09BDE56B8B04CC4CAE66CD0C5E0DFE30695DD798C50E39C911C887FEBACAAEFD2BFE7D454E051C432D66AD84680DA7C126F1A9C7C540283CCB863B9414BB536BA358259104ECB406B4976F97558FA4E5854888A8D13C96A14025DA0C55F869F6AF954B1E7AA1D317262C52099860E870A7EAF72F9910ACA809FF2DEA37FCA3EFB31FD43A308E4138E40178BEAC0FBB0E79ED7D1DCF8F8A81A4ABBFE6749F4C1B96BD65A14822490BC0A71E854BC8077C7A8F2C6FE308F86DEC97F600A4A0015F086B021F7F0BCAFDE3DA4D7E38A9AA1E992539389E99412FD22988DEC7BD43 +20170623163928 2 6 100 4095 2 F2D0058FA043FB189699D118DE484B66A10DCE703B27209CFC6D23D9178067C9D560D7D8BA9D4439A22AED66322F25D886C0A5CD41821B49AAE3D7A7B72F9B0E2D823709AF5444C7E9474DF5867E605E638923A2FAD546A86B8014BA460D238A939B445D7489C91977B54AB531D75B0F4264F187218F885129751EC78654F4B21191365FEA1B7FEFC40842BBC07C4F1D1AD153F6A39B582406F6B5895336A1199F7556EE957EAC716AE6678CBE5390730F0EBB3CC5210242A80CB128BFD747ED1B61AF6BBD5B5DC07B34C5CA7AF73D1EE973B93E13918801AEFD674DF92A0AD84BFA2A8CEE1AD26140DA1D5FC0C450A1EAEBC88F8EA8E703A0F3A814E1F6975AA5BE732473575D16F137D2CE5F7A546CE4371ECB5E8052295E122A9CF89A026E2D09BDE56B8B04CC4CAE66CD0C5E0DFE30695DD798C50E39C911C887FEBACAAEFD2BFE7D454E051C432D66AD84680DA7C126F1A9C7C540283CCB863B9414BB536BA358259104ECB406B4976F97558FA4E5854888A8D13C96A14025DA0C55F869F6AF954B1E7AA1D317262C52099860E870A7EAF72F9910ACA809FF2DEA37FCA3EFB31FD43A308E4138E40178BEAC0FBB0E79ED7D1DCF8F8A81A4ABBFE6749F4C1B96BD65A14822490BC0A71E854BC8077C7A8F2C6FE308F86DEC97F600A4A0015F086B021F7F0BCAFDE3DA4D7E38A9AA1E992539389E99412FD22988E064A38B +20170623164410 2 6 100 4095 2 F2D0058FA043FB189699D118DE484B66A10DCE703B27209CFC6D23D9178067C9D560D7D8BA9D4439A22AED66322F25D886C0A5CD41821B49AAE3D7A7B72F9B0E2D823709AF5444C7E9474DF5867E605E638923A2FAD546A86B8014BA460D238A939B445D7489C91977B54AB531D75B0F4264F187218F885129751EC78654F4B21191365FEA1B7FEFC40842BBC07C4F1D1AD153F6A39B582406F6B5895336A1199F7556EE957EAC716AE6678CBE5390730F0EBB3CC5210242A80CB128BFD747ED1B61AF6BBD5B5DC07B34C5CA7AF73D1EE973B93E13918801AEFD674DF92A0AD84BFA2A8CEE1AD26140DA1D5FC0C450A1EAEBC88F8EA8E703A0F3A814E1F6975AA5BE732473575D16F137D2CE5F7A546CE4371ECB5E8052295E122A9CF89A026E2D09BDE56B8B04CC4CAE66CD0C5E0DFE30695DD798C50E39C911C887FEBACAAEFD2BFE7D454E051C432D66AD84680DA7C126F1A9C7C540283CCB863B9414BB536BA358259104ECB406B4976F97558FA4E5854888A8D13C96A14025DA0C55F869F6AF954B1E7AA1D317262C52099860E870A7EAF72F9910ACA809FF2DEA37FCA3EFB31FD43A308E4138E40178BEAC0FBB0E79ED7D1DCF8F8A81A4ABBFE6749F4C1B96BD65A14822490BC0A71E854BC8077C7A8F2C6FE308F86DEC97F600A4A0015F086B021F7F0BCAFDE3DA4D7E38A9AA1E992539389E99412FD22988E0BD160B +20170623172908 2 6 100 4095 2 F2D0058FA043FB189699D118DE484B66A10DCE703B27209CFC6D23D9178067C9D560D7D8BA9D4439A22AED66322F25D886C0A5CD41821B49AAE3D7A7B72F9B0E2D823709AF5444C7E9474DF5867E605E638923A2FAD546A86B8014BA460D238A939B445D7489C91977B54AB531D75B0F4264F187218F885129751EC78654F4B21191365FEA1B7FEFC40842BBC07C4F1D1AD153F6A39B582406F6B5895336A1199F7556EE957EAC716AE6678CBE5390730F0EBB3CC5210242A80CB128BFD747ED1B61AF6BBD5B5DC07B34C5CA7AF73D1EE973B93E13918801AEFD674DF92A0AD84BFA2A8CEE1AD26140DA1D5FC0C450A1EAEBC88F8EA8E703A0F3A814E1F6975AA5BE732473575D16F137D2CE5F7A546CE4371ECB5E8052295E122A9CF89A026E2D09BDE56B8B04CC4CAE66CD0C5E0DFE30695DD798C50E39C911C887FEBACAAEFD2BFE7D454E051C432D66AD84680DA7C126F1A9C7C540283CCB863B9414BB536BA358259104ECB406B4976F97558FA4E5854888A8D13C96A14025DA0C55F869F6AF954B1E7AA1D317262C52099860E870A7EAF72F9910ACA809FF2DEA37FCA3EFB31FD43A308E4138E40178BEAC0FBB0E79ED7D1DCF8F8A81A4ABBFE6749F4C1B96BD65A14822490BC0A71E854BC8077C7A8F2C6FE308F86DEC97F600A4A0015F086B021F7F0BCAFDE3DA4D7E38A9AA1E992539389E99412FD22988E467E87B +20170623174045 2 6 100 4095 5 F2D0058FA043FB189699D118DE484B66A10DCE703B27209CFC6D23D9178067C9D560D7D8BA9D4439A22AED66322F25D886C0A5CD41821B49AAE3D7A7B72F9B0E2D823709AF5444C7E9474DF5867E605E638923A2FAD546A86B8014BA460D238A939B445D7489C91977B54AB531D75B0F4264F187218F885129751EC78654F4B21191365FEA1B7FEFC40842BBC07C4F1D1AD153F6A39B582406F6B5895336A1199F7556EE957EAC716AE6678CBE5390730F0EBB3CC5210242A80CB128BFD747ED1B61AF6BBD5B5DC07B34C5CA7AF73D1EE973B93E13918801AEFD674DF92A0AD84BFA2A8CEE1AD26140DA1D5FC0C450A1EAEBC88F8EA8E703A0F3A814E1F6975AA5BE732473575D16F137D2CE5F7A546CE4371ECB5E8052295E122A9CF89A026E2D09BDE56B8B04CC4CAE66CD0C5E0DFE30695DD798C50E39C911C887FEBACAAEFD2BFE7D454E051C432D66AD84680DA7C126F1A9C7C540283CCB863B9414BB536BA358259104ECB406B4976F97558FA4E5854888A8D13C96A14025DA0C55F869F6AF954B1E7AA1D317262C52099860E870A7EAF72F9910ACA809FF2DEA37FCA3EFB31FD43A308E4138E40178BEAC0FBB0E79ED7D1DCF8F8A81A4ABBFE6749F4C1B96BD65A14822490BC0A71E854BC8077C7A8F2C6FE308F86DEC97F600A4A0015F086B021F7F0BCAFDE3DA4D7E38A9AA1E992539389E99412FD22988E54CE16F +20170623175902 2 6 100 4095 5 F2D0058FA043FB189699D118DE484B66A10DCE703B27209CFC6D23D9178067C9D560D7D8BA9D4439A22AED66322F25D886C0A5CD41821B49AAE3D7A7B72F9B0E2D823709AF5444C7E9474DF5867E605E638923A2FAD546A86B8014BA460D238A939B445D7489C91977B54AB531D75B0F4264F187218F885129751EC78654F4B21191365FEA1B7FEFC40842BBC07C4F1D1AD153F6A39B582406F6B5895336A1199F7556EE957EAC716AE6678CBE5390730F0EBB3CC5210242A80CB128BFD747ED1B61AF6BBD5B5DC07B34C5CA7AF73D1EE973B93E13918801AEFD674DF92A0AD84BFA2A8CEE1AD26140DA1D5FC0C450A1EAEBC88F8EA8E703A0F3A814E1F6975AA5BE732473575D16F137D2CE5F7A546CE4371ECB5E8052295E122A9CF89A026E2D09BDE56B8B04CC4CAE66CD0C5E0DFE30695DD798C50E39C911C887FEBACAAEFD2BFE7D454E051C432D66AD84680DA7C126F1A9C7C540283CCB863B9414BB536BA358259104ECB406B4976F97558FA4E5854888A8D13C96A14025DA0C55F869F6AF954B1E7AA1D317262C52099860E870A7EAF72F9910ACA809FF2DEA37FCA3EFB31FD43A308E4138E40178BEAC0FBB0E79ED7D1DCF8F8A81A4ABBFE6749F4C1B96BD65A14822490BC0A71E854BC8077C7A8F2C6FE308F86DEC97F600A4A0015F086B021F7F0BCAFDE3DA4D7E38A9AA1E992539389E99412FD22988E6CA185F +20170623180229 2 6 100 4095 2 F2D0058FA043FB189699D118DE484B66A10DCE703B27209CFC6D23D9178067C9D560D7D8BA9D4439A22AED66322F25D886C0A5CD41821B49AAE3D7A7B72F9B0E2D823709AF5444C7E9474DF5867E605E638923A2FAD546A86B8014BA460D238A939B445D7489C91977B54AB531D75B0F4264F187218F885129751EC78654F4B21191365FEA1B7FEFC40842BBC07C4F1D1AD153F6A39B582406F6B5895336A1199F7556EE957EAC716AE6678CBE5390730F0EBB3CC5210242A80CB128BFD747ED1B61AF6BBD5B5DC07B34C5CA7AF73D1EE973B93E13918801AEFD674DF92A0AD84BFA2A8CEE1AD26140DA1D5FC0C450A1EAEBC88F8EA8E703A0F3A814E1F6975AA5BE732473575D16F137D2CE5F7A546CE4371ECB5E8052295E122A9CF89A026E2D09BDE56B8B04CC4CAE66CD0C5E0DFE30695DD798C50E39C911C887FEBACAAEFD2BFE7D454E051C432D66AD84680DA7C126F1A9C7C540283CCB863B9414BB536BA358259104ECB406B4976F97558FA4E5854888A8D13C96A14025DA0C55F869F6AF954B1E7AA1D317262C52099860E870A7EAF72F9910ACA809FF2DEA37FCA3EFB31FD43A308E4138E40178BEAC0FBB0E79ED7D1DCF8F8A81A4ABBFE6749F4C1B96BD65A14822490BC0A71E854BC8077C7A8F2C6FE308F86DEC97F600A4A0015F086B021F7F0BCAFDE3DA4D7E38A9AA1E992539389E99412FD22988E706D14B +20170623180811 2 6 100 4095 2 F2D0058FA043FB189699D118DE484B66A10DCE703B27209CFC6D23D9178067C9D560D7D8BA9D4439A22AED66322F25D886C0A5CD41821B49AAE3D7A7B72F9B0E2D823709AF5444C7E9474DF5867E605E638923A2FAD546A86B8014BA460D238A939B445D7489C91977B54AB531D75B0F4264F187218F885129751EC78654F4B21191365FEA1B7FEFC40842BBC07C4F1D1AD153F6A39B582406F6B5895336A1199F7556EE957EAC716AE6678CBE5390730F0EBB3CC5210242A80CB128BFD747ED1B61AF6BBD5B5DC07B34C5CA7AF73D1EE973B93E13918801AEFD674DF92A0AD84BFA2A8CEE1AD26140DA1D5FC0C450A1EAEBC88F8EA8E703A0F3A814E1F6975AA5BE732473575D16F137D2CE5F7A546CE4371ECB5E8052295E122A9CF89A026E2D09BDE56B8B04CC4CAE66CD0C5E0DFE30695DD798C50E39C911C887FEBACAAEFD2BFE7D454E051C432D66AD84680DA7C126F1A9C7C540283CCB863B9414BB536BA358259104ECB406B4976F97558FA4E5854888A8D13C96A14025DA0C55F869F6AF954B1E7AA1D317262C52099860E870A7EAF72F9910ACA809FF2DEA37FCA3EFB31FD43A308E4138E40178BEAC0FBB0E79ED7D1DCF8F8A81A4ABBFE6749F4C1B96BD65A14822490BC0A71E854BC8077C7A8F2C6FE308F86DEC97F600A4A0015F086B021F7F0BCAFDE3DA4D7E38A9AA1E992539389E99412FD22988E76F7CD3 +20170623180923 2 6 100 4095 2 F2D0058FA043FB189699D118DE484B66A10DCE703B27209CFC6D23D9178067C9D560D7D8BA9D4439A22AED66322F25D886C0A5CD41821B49AAE3D7A7B72F9B0E2D823709AF5444C7E9474DF5867E605E638923A2FAD546A86B8014BA460D238A939B445D7489C91977B54AB531D75B0F4264F187218F885129751EC78654F4B21191365FEA1B7FEFC40842BBC07C4F1D1AD153F6A39B582406F6B5895336A1199F7556EE957EAC716AE6678CBE5390730F0EBB3CC5210242A80CB128BFD747ED1B61AF6BBD5B5DC07B34C5CA7AF73D1EE973B93E13918801AEFD674DF92A0AD84BFA2A8CEE1AD26140DA1D5FC0C450A1EAEBC88F8EA8E703A0F3A814E1F6975AA5BE732473575D16F137D2CE5F7A546CE4371ECB5E8052295E122A9CF89A026E2D09BDE56B8B04CC4CAE66CD0C5E0DFE30695DD798C50E39C911C887FEBACAAEFD2BFE7D454E051C432D66AD84680DA7C126F1A9C7C540283CCB863B9414BB536BA358259104ECB406B4976F97558FA4E5854888A8D13C96A14025DA0C55F869F6AF954B1E7AA1D317262C52099860E870A7EAF72F9910ACA809FF2DEA37FCA3EFB31FD43A308E4138E40178BEAC0FBB0E79ED7D1DCF8F8A81A4ABBFE6749F4C1B96BD65A14822490BC0A71E854BC8077C7A8F2C6FE308F86DEC97F600A4A0015F086B021F7F0BCAFDE3DA4D7E38A9AA1E992539389E99412FD22988E77E8123 +20170623182724 2 6 100 4095 2 F2D0058FA043FB189699D118DE484B66A10DCE703B27209CFC6D23D9178067C9D560D7D8BA9D4439A22AED66322F25D886C0A5CD41821B49AAE3D7A7B72F9B0E2D823709AF5444C7E9474DF5867E605E638923A2FAD546A86B8014BA460D238A939B445D7489C91977B54AB531D75B0F4264F187218F885129751EC78654F4B21191365FEA1B7FEFC40842BBC07C4F1D1AD153F6A39B582406F6B5895336A1199F7556EE957EAC716AE6678CBE5390730F0EBB3CC5210242A80CB128BFD747ED1B61AF6BBD5B5DC07B34C5CA7AF73D1EE973B93E13918801AEFD674DF92A0AD84BFA2A8CEE1AD26140DA1D5FC0C450A1EAEBC88F8EA8E703A0F3A814E1F6975AA5BE732473575D16F137D2CE5F7A546CE4371ECB5E8052295E122A9CF89A026E2D09BDE56B8B04CC4CAE66CD0C5E0DFE30695DD798C50E39C911C887FEBACAAEFD2BFE7D454E051C432D66AD84680DA7C126F1A9C7C540283CCB863B9414BB536BA358259104ECB406B4976F97558FA4E5854888A8D13C96A14025DA0C55F869F6AF954B1E7AA1D317262C52099860E870A7EAF72F9910ACA809FF2DEA37FCA3EFB31FD43A308E4138E40178BEAC0FBB0E79ED7D1DCF8F8A81A4ABBFE6749F4C1B96BD65A14822490BC0A71E854BC8077C7A8F2C6FE308F86DEC97F600A4A0015F086B021F7F0BCAFDE3DA4D7E38A9AA1E992539389E99412FD22988E8D82A2B +20170623185420 2 6 100 4095 5 F2D0058FA043FB189699D118DE484B66A10DCE703B27209CFC6D23D9178067C9D560D7D8BA9D4439A22AED66322F25D886C0A5CD41821B49AAE3D7A7B72F9B0E2D823709AF5444C7E9474DF5867E605E638923A2FAD546A86B8014BA460D238A939B445D7489C91977B54AB531D75B0F4264F187218F885129751EC78654F4B21191365FEA1B7FEFC40842BBC07C4F1D1AD153F6A39B582406F6B5895336A1199F7556EE957EAC716AE6678CBE5390730F0EBB3CC5210242A80CB128BFD747ED1B61AF6BBD5B5DC07B34C5CA7AF73D1EE973B93E13918801AEFD674DF92A0AD84BFA2A8CEE1AD26140DA1D5FC0C450A1EAEBC88F8EA8E703A0F3A814E1F6975AA5BE732473575D16F137D2CE5F7A546CE4371ECB5E8052295E122A9CF89A026E2D09BDE56B8B04CC4CAE66CD0C5E0DFE30695DD798C50E39C911C887FEBACAAEFD2BFE7D454E051C432D66AD84680DA7C126F1A9C7C540283CCB863B9414BB536BA358259104ECB406B4976F97558FA4E5854888A8D13C96A14025DA0C55F869F6AF954B1E7AA1D317262C52099860E870A7EAF72F9910ACA809FF2DEA37FCA3EFB31FD43A308E4138E40178BEAC0FBB0E79ED7D1DCF8F8A81A4ABBFE6749F4C1B96BD65A14822490BC0A71E854BC8077C7A8F2C6FE308F86DEC97F600A4A0015F086B021F7F0BCAFDE3DA4D7E38A9AA1E992539389E99412FD22988EAF9DAE7 +20170623195226 2 6 100 4095 2 F2D0058FA043FB189699D118DE484B66A10DCE703B27209CFC6D23D9178067C9D560D7D8BA9D4439A22AED66322F25D886C0A5CD41821B49AAE3D7A7B72F9B0E2D823709AF5444C7E9474DF5867E605E638923A2FAD546A86B8014BA460D238A939B445D7489C91977B54AB531D75B0F4264F187218F885129751EC78654F4B21191365FEA1B7FEFC40842BBC07C4F1D1AD153F6A39B582406F6B5895336A1199F7556EE957EAC716AE6678CBE5390730F0EBB3CC5210242A80CB128BFD747ED1B61AF6BBD5B5DC07B34C5CA7AF73D1EE973B93E13918801AEFD674DF92A0AD84BFA2A8CEE1AD26140DA1D5FC0C450A1EAEBC88F8EA8E703A0F3A814E1F6975AA5BE732473575D16F137D2CE5F7A546CE4371ECB5E8052295E122A9CF89A026E2D09BDE56B8B04CC4CAE66CD0C5E0DFE30695DD798C50E39C911C887FEBACAAEFD2BFE7D454E051C432D66AD84680DA7C126F1A9C7C540283CCB863B9414BB536BA358259104ECB406B4976F97558FA4E5854888A8D13C96A14025DA0C55F869F6AF954B1E7AA1D317262C52099860E870A7EAF72F9910ACA809FF2DEA37FCA3EFB31FD43A308E4138E40178BEAC0FBB0E79ED7D1DCF8F8A81A4ABBFE6749F4C1B96BD65A14822490BC0A71E854BC8077C7A8F2C6FE308F86DEC97F600A4A0015F086B021F7F0BCAFDE3DA4D7E38A9AA1E992539389E99412FD22988EFA2202B +20170623195633 2 6 100 4095 5 F2D0058FA043FB189699D118DE484B66A10DCE703B27209CFC6D23D9178067C9D560D7D8BA9D4439A22AED66322F25D886C0A5CD41821B49AAE3D7A7B72F9B0E2D823709AF5444C7E9474DF5867E605E638923A2FAD546A86B8014BA460D238A939B445D7489C91977B54AB531D75B0F4264F187218F885129751EC78654F4B21191365FEA1B7FEFC40842BBC07C4F1D1AD153F6A39B582406F6B5895336A1199F7556EE957EAC716AE6678CBE5390730F0EBB3CC5210242A80CB128BFD747ED1B61AF6BBD5B5DC07B34C5CA7AF73D1EE973B93E13918801AEFD674DF92A0AD84BFA2A8CEE1AD26140DA1D5FC0C450A1EAEBC88F8EA8E703A0F3A814E1F6975AA5BE732473575D16F137D2CE5F7A546CE4371ECB5E8052295E122A9CF89A026E2D09BDE56B8B04CC4CAE66CD0C5E0DFE30695DD798C50E39C911C887FEBACAAEFD2BFE7D454E051C432D66AD84680DA7C126F1A9C7C540283CCB863B9414BB536BA358259104ECB406B4976F97558FA4E5854888A8D13C96A14025DA0C55F869F6AF954B1E7AA1D317262C52099860E870A7EAF72F9910ACA809FF2DEA37FCA3EFB31FD43A308E4138E40178BEAC0FBB0E79ED7D1DCF8F8A81A4ABBFE6749F4C1B96BD65A14822490BC0A71E854BC8077C7A8F2C6FE308F86DEC97F600A4A0015F086B021F7F0BCAFDE3DA4D7E38A9AA1E992539389E99412FD22988EFEED5BF +20170623201051 2 6 100 4095 2 F2D0058FA043FB189699D118DE484B66A10DCE703B27209CFC6D23D9178067C9D560D7D8BA9D4439A22AED66322F25D886C0A5CD41821B49AAE3D7A7B72F9B0E2D823709AF5444C7E9474DF5867E605E638923A2FAD546A86B8014BA460D238A939B445D7489C91977B54AB531D75B0F4264F187218F885129751EC78654F4B21191365FEA1B7FEFC40842BBC07C4F1D1AD153F6A39B582406F6B5895336A1199F7556EE957EAC716AE6678CBE5390730F0EBB3CC5210242A80CB128BFD747ED1B61AF6BBD5B5DC07B34C5CA7AF73D1EE973B93E13918801AEFD674DF92A0AD84BFA2A8CEE1AD26140DA1D5FC0C450A1EAEBC88F8EA8E703A0F3A814E1F6975AA5BE732473575D16F137D2CE5F7A546CE4371ECB5E8052295E122A9CF89A026E2D09BDE56B8B04CC4CAE66CD0C5E0DFE30695DD798C50E39C911C887FEBACAAEFD2BFE7D454E051C432D66AD84680DA7C126F1A9C7C540283CCB863B9414BB536BA358259104ECB406B4976F97558FA4E5854888A8D13C96A14025DA0C55F869F6AF954B1E7AA1D317262C52099860E870A7EAF72F9910ACA809FF2DEA37FCA3EFB31FD43A308E4138E40178BEAC0FBB0E79ED7D1DCF8F8A81A4ABBFE6749F4C1B96BD65A14822490BC0A71E854BC8077C7A8F2C6FE308F86DEC97F600A4A0015F086B021F7F0BCAFDE3DA4D7E38A9AA1E992539389E99412FD22988F10F59CB +20170623202959 2 6 100 4095 5 F2D0058FA043FB189699D118DE484B66A10DCE703B27209CFC6D23D9178067C9D560D7D8BA9D4439A22AED66322F25D886C0A5CD41821B49AAE3D7A7B72F9B0E2D823709AF5444C7E9474DF5867E605E638923A2FAD546A86B8014BA460D238A939B445D7489C91977B54AB531D75B0F4264F187218F885129751EC78654F4B21191365FEA1B7FEFC40842BBC07C4F1D1AD153F6A39B582406F6B5895336A1199F7556EE957EAC716AE6678CBE5390730F0EBB3CC5210242A80CB128BFD747ED1B61AF6BBD5B5DC07B34C5CA7AF73D1EE973B93E13918801AEFD674DF92A0AD84BFA2A8CEE1AD26140DA1D5FC0C450A1EAEBC88F8EA8E703A0F3A814E1F6975AA5BE732473575D16F137D2CE5F7A546CE4371ECB5E8052295E122A9CF89A026E2D09BDE56B8B04CC4CAE66CD0C5E0DFE30695DD798C50E39C911C887FEBACAAEFD2BFE7D454E051C432D66AD84680DA7C126F1A9C7C540283CCB863B9414BB536BA358259104ECB406B4976F97558FA4E5854888A8D13C96A14025DA0C55F869F6AF954B1E7AA1D317262C52099860E870A7EAF72F9910ACA809FF2DEA37FCA3EFB31FD43A308E4138E40178BEAC0FBB0E79ED7D1DCF8F8A81A4ABBFE6749F4C1B96BD65A14822490BC0A71E854BC8077C7A8F2C6FE308F86DEC97F600A4A0015F086B021F7F0BCAFDE3DA4D7E38A9AA1E992539389E99412FD22988F2921927 +20170623203734 2 6 100 4095 2 F2D0058FA043FB189699D118DE484B66A10DCE703B27209CFC6D23D9178067C9D560D7D8BA9D4439A22AED66322F25D886C0A5CD41821B49AAE3D7A7B72F9B0E2D823709AF5444C7E9474DF5867E605E638923A2FAD546A86B8014BA460D238A939B445D7489C91977B54AB531D75B0F4264F187218F885129751EC78654F4B21191365FEA1B7FEFC40842BBC07C4F1D1AD153F6A39B582406F6B5895336A1199F7556EE957EAC716AE6678CBE5390730F0EBB3CC5210242A80CB128BFD747ED1B61AF6BBD5B5DC07B34C5CA7AF73D1EE973B93E13918801AEFD674DF92A0AD84BFA2A8CEE1AD26140DA1D5FC0C450A1EAEBC88F8EA8E703A0F3A814E1F6975AA5BE732473575D16F137D2CE5F7A546CE4371ECB5E8052295E122A9CF89A026E2D09BDE56B8B04CC4CAE66CD0C5E0DFE30695DD798C50E39C911C887FEBACAAEFD2BFE7D454E051C432D66AD84680DA7C126F1A9C7C540283CCB863B9414BB536BA358259104ECB406B4976F97558FA4E5854888A8D13C96A14025DA0C55F869F6AF954B1E7AA1D317262C52099860E870A7EAF72F9910ACA809FF2DEA37FCA3EFB31FD43A308E4138E40178BEAC0FBB0E79ED7D1DCF8F8A81A4ABBFE6749F4C1B96BD65A14822490BC0A71E854BC8077C7A8F2C6FE308F86DEC97F600A4A0015F086B021F7F0BCAFDE3DA4D7E38A9AA1E992539389E99412FD22988F32287EB +20170623204218 2 6 100 4095 2 F2D0058FA043FB189699D118DE484B66A10DCE703B27209CFC6D23D9178067C9D560D7D8BA9D4439A22AED66322F25D886C0A5CD41821B49AAE3D7A7B72F9B0E2D823709AF5444C7E9474DF5867E605E638923A2FAD546A86B8014BA460D238A939B445D7489C91977B54AB531D75B0F4264F187218F885129751EC78654F4B21191365FEA1B7FEFC40842BBC07C4F1D1AD153F6A39B582406F6B5895336A1199F7556EE957EAC716AE6678CBE5390730F0EBB3CC5210242A80CB128BFD747ED1B61AF6BBD5B5DC07B34C5CA7AF73D1EE973B93E13918801AEFD674DF92A0AD84BFA2A8CEE1AD26140DA1D5FC0C450A1EAEBC88F8EA8E703A0F3A814E1F6975AA5BE732473575D16F137D2CE5F7A546CE4371ECB5E8052295E122A9CF89A026E2D09BDE56B8B04CC4CAE66CD0C5E0DFE30695DD798C50E39C911C887FEBACAAEFD2BFE7D454E051C432D66AD84680DA7C126F1A9C7C540283CCB863B9414BB536BA358259104ECB406B4976F97558FA4E5854888A8D13C96A14025DA0C55F869F6AF954B1E7AA1D317262C52099860E870A7EAF72F9910ACA809FF2DEA37FCA3EFB31FD43A308E4138E40178BEAC0FBB0E79ED7D1DCF8F8A81A4ABBFE6749F4C1B96BD65A14822490BC0A71E854BC8077C7A8F2C6FE308F86DEC97F600A4A0015F086B021F7F0BCAFDE3DA4D7E38A9AA1E992539389E99412FD22988F37F8B03 +20170623204329 2 6 100 4095 5 F2D0058FA043FB189699D118DE484B66A10DCE703B27209CFC6D23D9178067C9D560D7D8BA9D4439A22AED66322F25D886C0A5CD41821B49AAE3D7A7B72F9B0E2D823709AF5444C7E9474DF5867E605E638923A2FAD546A86B8014BA460D238A939B445D7489C91977B54AB531D75B0F4264F187218F885129751EC78654F4B21191365FEA1B7FEFC40842BBC07C4F1D1AD153F6A39B582406F6B5895336A1199F7556EE957EAC716AE6678CBE5390730F0EBB3CC5210242A80CB128BFD747ED1B61AF6BBD5B5DC07B34C5CA7AF73D1EE973B93E13918801AEFD674DF92A0AD84BFA2A8CEE1AD26140DA1D5FC0C450A1EAEBC88F8EA8E703A0F3A814E1F6975AA5BE732473575D16F137D2CE5F7A546CE4371ECB5E8052295E122A9CF89A026E2D09BDE56B8B04CC4CAE66CD0C5E0DFE30695DD798C50E39C911C887FEBACAAEFD2BFE7D454E051C432D66AD84680DA7C126F1A9C7C540283CCB863B9414BB536BA358259104ECB406B4976F97558FA4E5854888A8D13C96A14025DA0C55F869F6AF954B1E7AA1D317262C52099860E870A7EAF72F9910ACA809FF2DEA37FCA3EFB31FD43A308E4138E40178BEAC0FBB0E79ED7D1DCF8F8A81A4ABBFE6749F4C1B96BD65A14822490BC0A71E854BC8077C7A8F2C6FE308F86DEC97F600A4A0015F086B021F7F0BCAFDE3DA4D7E38A9AA1E992539389E99412FD22988F38F411F +20170623204840 2 6 100 4095 2 F2D0058FA043FB189699D118DE484B66A10DCE703B27209CFC6D23D9178067C9D560D7D8BA9D4439A22AED66322F25D886C0A5CD41821B49AAE3D7A7B72F9B0E2D823709AF5444C7E9474DF5867E605E638923A2FAD546A86B8014BA460D238A939B445D7489C91977B54AB531D75B0F4264F187218F885129751EC78654F4B21191365FEA1B7FEFC40842BBC07C4F1D1AD153F6A39B582406F6B5895336A1199F7556EE957EAC716AE6678CBE5390730F0EBB3CC5210242A80CB128BFD747ED1B61AF6BBD5B5DC07B34C5CA7AF73D1EE973B93E13918801AEFD674DF92A0AD84BFA2A8CEE1AD26140DA1D5FC0C450A1EAEBC88F8EA8E703A0F3A814E1F6975AA5BE732473575D16F137D2CE5F7A546CE4371ECB5E8052295E122A9CF89A026E2D09BDE56B8B04CC4CAE66CD0C5E0DFE30695DD798C50E39C911C887FEBACAAEFD2BFE7D454E051C432D66AD84680DA7C126F1A9C7C540283CCB863B9414BB536BA358259104ECB406B4976F97558FA4E5854888A8D13C96A14025DA0C55F869F6AF954B1E7AA1D317262C52099860E870A7EAF72F9910ACA809FF2DEA37FCA3EFB31FD43A308E4138E40178BEAC0FBB0E79ED7D1DCF8F8A81A4ABBFE6749F4C1B96BD65A14822490BC0A71E854BC8077C7A8F2C6FE308F86DEC97F600A4A0015F086B021F7F0BCAFDE3DA4D7E38A9AA1E992539389E99412FD22988F3EE7B13 +20170623205709 2 6 100 4095 2 F2D0058FA043FB189699D118DE484B66A10DCE703B27209CFC6D23D9178067C9D560D7D8BA9D4439A22AED66322F25D886C0A5CD41821B49AAE3D7A7B72F9B0E2D823709AF5444C7E9474DF5867E605E638923A2FAD546A86B8014BA460D238A939B445D7489C91977B54AB531D75B0F4264F187218F885129751EC78654F4B21191365FEA1B7FEFC40842BBC07C4F1D1AD153F6A39B582406F6B5895336A1199F7556EE957EAC716AE6678CBE5390730F0EBB3CC5210242A80CB128BFD747ED1B61AF6BBD5B5DC07B34C5CA7AF73D1EE973B93E13918801AEFD674DF92A0AD84BFA2A8CEE1AD26140DA1D5FC0C450A1EAEBC88F8EA8E703A0F3A814E1F6975AA5BE732473575D16F137D2CE5F7A546CE4371ECB5E8052295E122A9CF89A026E2D09BDE56B8B04CC4CAE66CD0C5E0DFE30695DD798C50E39C911C887FEBACAAEFD2BFE7D454E051C432D66AD84680DA7C126F1A9C7C540283CCB863B9414BB536BA358259104ECB406B4976F97558FA4E5854888A8D13C96A14025DA0C55F869F6AF954B1E7AA1D317262C52099860E870A7EAF72F9910ACA809FF2DEA37FCA3EFB31FD43A308E4138E40178BEAC0FBB0E79ED7D1DCF8F8A81A4ABBFE6749F4C1B96BD65A14822490BC0A71E854BC8077C7A8F2C6FE308F86DEC97F600A4A0015F086B021F7F0BCAFDE3DA4D7E38A9AA1E992539389E99412FD22988F493374B +20170623205814 2 6 100 4095 2 F2D0058FA043FB189699D118DE484B66A10DCE703B27209CFC6D23D9178067C9D560D7D8BA9D4439A22AED66322F25D886C0A5CD41821B49AAE3D7A7B72F9B0E2D823709AF5444C7E9474DF5867E605E638923A2FAD546A86B8014BA460D238A939B445D7489C91977B54AB531D75B0F4264F187218F885129751EC78654F4B21191365FEA1B7FEFC40842BBC07C4F1D1AD153F6A39B582406F6B5895336A1199F7556EE957EAC716AE6678CBE5390730F0EBB3CC5210242A80CB128BFD747ED1B61AF6BBD5B5DC07B34C5CA7AF73D1EE973B93E13918801AEFD674DF92A0AD84BFA2A8CEE1AD26140DA1D5FC0C450A1EAEBC88F8EA8E703A0F3A814E1F6975AA5BE732473575D16F137D2CE5F7A546CE4371ECB5E8052295E122A9CF89A026E2D09BDE56B8B04CC4CAE66CD0C5E0DFE30695DD798C50E39C911C887FEBACAAEFD2BFE7D454E051C432D66AD84680DA7C126F1A9C7C540283CCB863B9414BB536BA358259104ECB406B4976F97558FA4E5854888A8D13C96A14025DA0C55F869F6AF954B1E7AA1D317262C52099860E870A7EAF72F9910ACA809FF2DEA37FCA3EFB31FD43A308E4138E40178BEAC0FBB0E79ED7D1DCF8F8A81A4ABBFE6749F4C1B96BD65A14822490BC0A71E854BC8077C7A8F2C6FE308F86DEC97F600A4A0015F086B021F7F0BCAFDE3DA4D7E38A9AA1E992539389E99412FD22988F4A24813 +20170623210627 2 6 100 4095 2 F2D0058FA043FB189699D118DE484B66A10DCE703B27209CFC6D23D9178067C9D560D7D8BA9D4439A22AED66322F25D886C0A5CD41821B49AAE3D7A7B72F9B0E2D823709AF5444C7E9474DF5867E605E638923A2FAD546A86B8014BA460D238A939B445D7489C91977B54AB531D75B0F4264F187218F885129751EC78654F4B21191365FEA1B7FEFC40842BBC07C4F1D1AD153F6A39B582406F6B5895336A1199F7556EE957EAC716AE6678CBE5390730F0EBB3CC5210242A80CB128BFD747ED1B61AF6BBD5B5DC07B34C5CA7AF73D1EE973B93E13918801AEFD674DF92A0AD84BFA2A8CEE1AD26140DA1D5FC0C450A1EAEBC88F8EA8E703A0F3A814E1F6975AA5BE732473575D16F137D2CE5F7A546CE4371ECB5E8052295E122A9CF89A026E2D09BDE56B8B04CC4CAE66CD0C5E0DFE30695DD798C50E39C911C887FEBACAAEFD2BFE7D454E051C432D66AD84680DA7C126F1A9C7C540283CCB863B9414BB536BA358259104ECB406B4976F97558FA4E5854888A8D13C96A14025DA0C55F869F6AF954B1E7AA1D317262C52099860E870A7EAF72F9910ACA809FF2DEA37FCA3EFB31FD43A308E4138E40178BEAC0FBB0E79ED7D1DCF8F8A81A4ABBFE6749F4C1B96BD65A14822490BC0A71E854BC8077C7A8F2C6FE308F86DEC97F600A4A0015F086B021F7F0BCAFDE3DA4D7E38A9AA1E992539389E99412FD22988F53F787B +20170623210958 2 6 100 4095 2 F2D0058FA043FB189699D118DE484B66A10DCE703B27209CFC6D23D9178067C9D560D7D8BA9D4439A22AED66322F25D886C0A5CD41821B49AAE3D7A7B72F9B0E2D823709AF5444C7E9474DF5867E605E638923A2FAD546A86B8014BA460D238A939B445D7489C91977B54AB531D75B0F4264F187218F885129751EC78654F4B21191365FEA1B7FEFC40842BBC07C4F1D1AD153F6A39B582406F6B5895336A1199F7556EE957EAC716AE6678CBE5390730F0EBB3CC5210242A80CB128BFD747ED1B61AF6BBD5B5DC07B34C5CA7AF73D1EE973B93E13918801AEFD674DF92A0AD84BFA2A8CEE1AD26140DA1D5FC0C450A1EAEBC88F8EA8E703A0F3A814E1F6975AA5BE732473575D16F137D2CE5F7A546CE4371ECB5E8052295E122A9CF89A026E2D09BDE56B8B04CC4CAE66CD0C5E0DFE30695DD798C50E39C911C887FEBACAAEFD2BFE7D454E051C432D66AD84680DA7C126F1A9C7C540283CCB863B9414BB536BA358259104ECB406B4976F97558FA4E5854888A8D13C96A14025DA0C55F869F6AF954B1E7AA1D317262C52099860E870A7EAF72F9910ACA809FF2DEA37FCA3EFB31FD43A308E4138E40178BEAC0FBB0E79ED7D1DCF8F8A81A4ABBFE6749F4C1B96BD65A14822490BC0A71E854BC8077C7A8F2C6FE308F86DEC97F600A4A0015F086B021F7F0BCAFDE3DA4D7E38A9AA1E992539389E99412FD22988F57EC8EB +20170623211248 2 6 100 4095 5 F2D0058FA043FB189699D118DE484B66A10DCE703B27209CFC6D23D9178067C9D560D7D8BA9D4439A22AED66322F25D886C0A5CD41821B49AAE3D7A7B72F9B0E2D823709AF5444C7E9474DF5867E605E638923A2FAD546A86B8014BA460D238A939B445D7489C91977B54AB531D75B0F4264F187218F885129751EC78654F4B21191365FEA1B7FEFC40842BBC07C4F1D1AD153F6A39B582406F6B5895336A1199F7556EE957EAC716AE6678CBE5390730F0EBB3CC5210242A80CB128BFD747ED1B61AF6BBD5B5DC07B34C5CA7AF73D1EE973B93E13918801AEFD674DF92A0AD84BFA2A8CEE1AD26140DA1D5FC0C450A1EAEBC88F8EA8E703A0F3A814E1F6975AA5BE732473575D16F137D2CE5F7A546CE4371ECB5E8052295E122A9CF89A026E2D09BDE56B8B04CC4CAE66CD0C5E0DFE30695DD798C50E39C911C887FEBACAAEFD2BFE7D454E051C432D66AD84680DA7C126F1A9C7C540283CCB863B9414BB536BA358259104ECB406B4976F97558FA4E5854888A8D13C96A14025DA0C55F869F6AF954B1E7AA1D317262C52099860E870A7EAF72F9910ACA809FF2DEA37FCA3EFB31FD43A308E4138E40178BEAC0FBB0E79ED7D1DCF8F8A81A4ABBFE6749F4C1B96BD65A14822490BC0A71E854BC8077C7A8F2C6FE308F86DEC97F600A4A0015F086B021F7F0BCAFDE3DA4D7E38A9AA1E992539389E99412FD22988F5B1A9D7 +20170623213826 2 6 100 4095 5 F2D0058FA043FB189699D118DE484B66A10DCE703B27209CFC6D23D9178067C9D560D7D8BA9D4439A22AED66322F25D886C0A5CD41821B49AAE3D7A7B72F9B0E2D823709AF5444C7E9474DF5867E605E638923A2FAD546A86B8014BA460D238A939B445D7489C91977B54AB531D75B0F4264F187218F885129751EC78654F4B21191365FEA1B7FEFC40842BBC07C4F1D1AD153F6A39B582406F6B5895336A1199F7556EE957EAC716AE6678CBE5390730F0EBB3CC5210242A80CB128BFD747ED1B61AF6BBD5B5DC07B34C5CA7AF73D1EE973B93E13918801AEFD674DF92A0AD84BFA2A8CEE1AD26140DA1D5FC0C450A1EAEBC88F8EA8E703A0F3A814E1F6975AA5BE732473575D16F137D2CE5F7A546CE4371ECB5E8052295E122A9CF89A026E2D09BDE56B8B04CC4CAE66CD0C5E0DFE30695DD798C50E39C911C887FEBACAAEFD2BFE7D454E051C432D66AD84680DA7C126F1A9C7C540283CCB863B9414BB536BA358259104ECB406B4976F97558FA4E5854888A8D13C96A14025DA0C55F869F6AF954B1E7AA1D317262C52099860E870A7EAF72F9910ACA809FF2DEA37FCA3EFB31FD43A308E4138E40178BEAC0FBB0E79ED7D1DCF8F8A81A4ABBFE6749F4C1B96BD65A14822490BC0A71E854BC8077C7A8F2C6FE308F86DEC97F600A4A0015F086B021F7F0BCAFDE3DA4D7E38A9AA1E992539389E99412FD22988F7B2A7AF +20170623213924 2 6 100 4095 2 F2D0058FA043FB189699D118DE484B66A10DCE703B27209CFC6D23D9178067C9D560D7D8BA9D4439A22AED66322F25D886C0A5CD41821B49AAE3D7A7B72F9B0E2D823709AF5444C7E9474DF5867E605E638923A2FAD546A86B8014BA460D238A939B445D7489C91977B54AB531D75B0F4264F187218F885129751EC78654F4B21191365FEA1B7FEFC40842BBC07C4F1D1AD153F6A39B582406F6B5895336A1199F7556EE957EAC716AE6678CBE5390730F0EBB3CC5210242A80CB128BFD747ED1B61AF6BBD5B5DC07B34C5CA7AF73D1EE973B93E13918801AEFD674DF92A0AD84BFA2A8CEE1AD26140DA1D5FC0C450A1EAEBC88F8EA8E703A0F3A814E1F6975AA5BE732473575D16F137D2CE5F7A546CE4371ECB5E8052295E122A9CF89A026E2D09BDE56B8B04CC4CAE66CD0C5E0DFE30695DD798C50E39C911C887FEBACAAEFD2BFE7D454E051C432D66AD84680DA7C126F1A9C7C540283CCB863B9414BB536BA358259104ECB406B4976F97558FA4E5854888A8D13C96A14025DA0C55F869F6AF954B1E7AA1D317262C52099860E870A7EAF72F9910ACA809FF2DEA37FCA3EFB31FD43A308E4138E40178BEAC0FBB0E79ED7D1DCF8F8A81A4ABBFE6749F4C1B96BD65A14822490BC0A71E854BC8077C7A8F2C6FE308F86DEC97F600A4A0015F086B021F7F0BCAFDE3DA4D7E38A9AA1E992539389E99412FD22988F7BDBA73 +20170623214723 2 6 100 4095 5 F2D0058FA043FB189699D118DE484B66A10DCE703B27209CFC6D23D9178067C9D560D7D8BA9D4439A22AED66322F25D886C0A5CD41821B49AAE3D7A7B72F9B0E2D823709AF5444C7E9474DF5867E605E638923A2FAD546A86B8014BA460D238A939B445D7489C91977B54AB531D75B0F4264F187218F885129751EC78654F4B21191365FEA1B7FEFC40842BBC07C4F1D1AD153F6A39B582406F6B5895336A1199F7556EE957EAC716AE6678CBE5390730F0EBB3CC5210242A80CB128BFD747ED1B61AF6BBD5B5DC07B34C5CA7AF73D1EE973B93E13918801AEFD674DF92A0AD84BFA2A8CEE1AD26140DA1D5FC0C450A1EAEBC88F8EA8E703A0F3A814E1F6975AA5BE732473575D16F137D2CE5F7A546CE4371ECB5E8052295E122A9CF89A026E2D09BDE56B8B04CC4CAE66CD0C5E0DFE30695DD798C50E39C911C887FEBACAAEFD2BFE7D454E051C432D66AD84680DA7C126F1A9C7C540283CCB863B9414BB536BA358259104ECB406B4976F97558FA4E5854888A8D13C96A14025DA0C55F869F6AF954B1E7AA1D317262C52099860E870A7EAF72F9910ACA809FF2DEA37FCA3EFB31FD43A308E4138E40178BEAC0FBB0E79ED7D1DCF8F8A81A4ABBFE6749F4C1B96BD65A14822490BC0A71E854BC8077C7A8F2C6FE308F86DEC97F600A4A0015F086B021F7F0BCAFDE3DA4D7E38A9AA1E992539389E99412FD22988F8513E37 +20170623233949 2 6 100 6143 2 E30D9BCD65DA0EAEF6A1D4D083834D4724538836AE04DFB6A7DAF235F5D9992B7E42128D43E229BF4906EF0C6A27F60B95A1FC514C2D55A0D616B3B6924F08E9C0BCD8AE1CB624F645785C2AA552C94E125D6602CF63CF52014A1B0A4AE0DE823B03B6ABFA25839ABC3E8E050C295B8B3471EC58EAD9B659294C72EA65229E4E8EB21CA79CBB41BB552118A3CD32108E51D5FCE5C46A6CD03E4246CB57E32BAA09B15503FBFA4F4C943B2378F10EE312C1F12A14010AFD1698B8EBCCFC8D0DF17829A153199154EBF9E40FD81B8E1AF5881D0EC1D3BEDB2D0F1DB9C44C9D8E7047310623D4FAAE28D2C16612CFB9AE9A8FD05B8FE22930346ECF7B21B5800778EA0D5D3B7BDF18B03ABF33C9D0B4648CF687ED229C811CE290CFAF94F9C9AF4EC3E47480955E5C81E85DA9EBCE99652DA07225C7CCEF39E224556E48D6371981C7232E00F3419F7B335FF36FE3989558277654DB356063ABC8F7BD0EF828B40D3BFC06D12FEC51278ACD32C3B67D4E2A0BBA1E20BDDA06DB9AF6AB250179DE3332EAC0A6D381963B51E8E167B8285BA3E6538B1D38B16B32196ABE009ADFDAF5E686E0107F76ED10414B6249D6895188456505CDB897FFCCEB8931802F87C02DFDC62825C6255DF2654712BE230CC86A30229D9E3438DB35CEED8F8447B9209CDECFC1776D2C43B4B98E9EEA3F4C049C1287CDB4540D395A4BC992602150CCC0479597E221E201B778DCA9701C517C89B95004FC19373ED9755C90FF32C44013678876EAD3FE5E637BF2F1959130EAF79E7A93088F52AA0AC993324294536CF3787C3A3F06F2DC201A070967E6F4525803DC83F5160B560465A4CE4BF20315858BE0E62A07C55B3A772CBF93DE99AADFCB304D2B544A9F17A22C2BEB791D98F714CA7CFF701CB7CAEC55C292A25A147935D7BBD1E66F2ED3EBC66E763209169033CE5A2D9884DC0CBAFF37517372544E1EB780A26CC71E5649EDFD5DA2FCFB58093D74D76FC2DAEC54567104701C31E3872C15BAC5F2A96833EEDAB9B7FF731F827DB3273D271BA8F9DE06181C1E38D031896971D801C571954337D915376BC3 +20170624020214 2 6 100 6143 5 E30D9BCD65DA0EAEF6A1D4D083834D4724538836AE04DFB6A7DAF235F5D9992B7E42128D43E229BF4906EF0C6A27F60B95A1FC514C2D55A0D616B3B6924F08E9C0BCD8AE1CB624F645785C2AA552C94E125D6602CF63CF52014A1B0A4AE0DE823B03B6ABFA25839ABC3E8E050C295B8B3471EC58EAD9B659294C72EA65229E4E8EB21CA79CBB41BB552118A3CD32108E51D5FCE5C46A6CD03E4246CB57E32BAA09B15503FBFA4F4C943B2378F10EE312C1F12A14010AFD1698B8EBCCFC8D0DF17829A153199154EBF9E40FD81B8E1AF5881D0EC1D3BEDB2D0F1DB9C44C9D8E7047310623D4FAAE28D2C16612CFB9AE9A8FD05B8FE22930346ECF7B21B5800778EA0D5D3B7BDF18B03ABF33C9D0B4648CF687ED229C811CE290CFAF94F9C9AF4EC3E47480955E5C81E85DA9EBCE99652DA07225C7CCEF39E224556E48D6371981C7232E00F3419F7B335FF36FE3989558277654DB356063ABC8F7BD0EF828B40D3BFC06D12FEC51278ACD32C3B67D4E2A0BBA1E20BDDA06DB9AF6AB250179DE3332EAC0A6D381963B51E8E167B8285BA3E6538B1D38B16B32196ABE009ADFDAF5E686E0107F76ED10414B6249D6895188456505CDB897FFCCEB8931802F87C02DFDC62825C6255DF2654712BE230CC86A30229D9E3438DB35CEED8F8447B9209CDECFC1776D2C43B4B98E9EEA3F4C049C1287CDB4540D395A4BC992602150CCC0479597E221E201B778DCA9701C517C89B95004FC19373ED9755C90FF32C44013678876EAD3FE5E637BF2F1959130EAF79E7A93088F52AA0AC993324294536CF3787C3A3F06F2DC201A070967E6F4525803DC83F5160B560465A4CE4BF20315858BE0E62A07C55B3A772CBF93DE99AADFCB304D2B544A9F17A22C2BEB791D98F714CA7CFF701CB7CAEC55C292A25A147935D7BBD1E66F2ED3EBC66E763209169033CE5A2D9884DC0CBAFF37517372544E1EB780A26CC71E5649EDFD5DA2FCFB58093D74D76FC2DAEC54567104701C31E3872C15BAC5F2A96833EEDAB9B7FF731F827DB3273D271BA8F9DE06181C1E38D031896971D801C571954337D918FF036F +20170624030028 2 6 100 6143 5 E30D9BCD65DA0EAEF6A1D4D083834D4724538836AE04DFB6A7DAF235F5D9992B7E42128D43E229BF4906EF0C6A27F60B95A1FC514C2D55A0D616B3B6924F08E9C0BCD8AE1CB624F645785C2AA552C94E125D6602CF63CF52014A1B0A4AE0DE823B03B6ABFA25839ABC3E8E050C295B8B3471EC58EAD9B659294C72EA65229E4E8EB21CA79CBB41BB552118A3CD32108E51D5FCE5C46A6CD03E4246CB57E32BAA09B15503FBFA4F4C943B2378F10EE312C1F12A14010AFD1698B8EBCCFC8D0DF17829A153199154EBF9E40FD81B8E1AF5881D0EC1D3BEDB2D0F1DB9C44C9D8E7047310623D4FAAE28D2C16612CFB9AE9A8FD05B8FE22930346ECF7B21B5800778EA0D5D3B7BDF18B03ABF33C9D0B4648CF687ED229C811CE290CFAF94F9C9AF4EC3E47480955E5C81E85DA9EBCE99652DA07225C7CCEF39E224556E48D6371981C7232E00F3419F7B335FF36FE3989558277654DB356063ABC8F7BD0EF828B40D3BFC06D12FEC51278ACD32C3B67D4E2A0BBA1E20BDDA06DB9AF6AB250179DE3332EAC0A6D381963B51E8E167B8285BA3E6538B1D38B16B32196ABE009ADFDAF5E686E0107F76ED10414B6249D6895188456505CDB897FFCCEB8931802F87C02DFDC62825C6255DF2654712BE230CC86A30229D9E3438DB35CEED8F8447B9209CDECFC1776D2C43B4B98E9EEA3F4C049C1287CDB4540D395A4BC992602150CCC0479597E221E201B778DCA9701C517C89B95004FC19373ED9755C90FF32C44013678876EAD3FE5E637BF2F1959130EAF79E7A93088F52AA0AC993324294536CF3787C3A3F06F2DC201A070967E6F4525803DC83F5160B560465A4CE4BF20315858BE0E62A07C55B3A772CBF93DE99AADFCB304D2B544A9F17A22C2BEB791D98F714CA7CFF701CB7CAEC55C292A25A147935D7BBD1E66F2ED3EBC66E763209169033CE5A2D9884DC0CBAFF37517372544E1EB780A26CC71E5649EDFD5DA2FCFB58093D74D76FC2DAEC54567104701C31E3872C15BAC5F2A96833EEDAB9B7FF731F827DB3273D271BA8F9DE06181C1E38D031896971D801C571954337D91A80668F +20170624033630 2 6 100 6143 2 E30D9BCD65DA0EAEF6A1D4D083834D4724538836AE04DFB6A7DAF235F5D9992B7E42128D43E229BF4906EF0C6A27F60B95A1FC514C2D55A0D616B3B6924F08E9C0BCD8AE1CB624F645785C2AA552C94E125D6602CF63CF52014A1B0A4AE0DE823B03B6ABFA25839ABC3E8E050C295B8B3471EC58EAD9B659294C72EA65229E4E8EB21CA79CBB41BB552118A3CD32108E51D5FCE5C46A6CD03E4246CB57E32BAA09B15503FBFA4F4C943B2378F10EE312C1F12A14010AFD1698B8EBCCFC8D0DF17829A153199154EBF9E40FD81B8E1AF5881D0EC1D3BEDB2D0F1DB9C44C9D8E7047310623D4FAAE28D2C16612CFB9AE9A8FD05B8FE22930346ECF7B21B5800778EA0D5D3B7BDF18B03ABF33C9D0B4648CF687ED229C811CE290CFAF94F9C9AF4EC3E47480955E5C81E85DA9EBCE99652DA07225C7CCEF39E224556E48D6371981C7232E00F3419F7B335FF36FE3989558277654DB356063ABC8F7BD0EF828B40D3BFC06D12FEC51278ACD32C3B67D4E2A0BBA1E20BDDA06DB9AF6AB250179DE3332EAC0A6D381963B51E8E167B8285BA3E6538B1D38B16B32196ABE009ADFDAF5E686E0107F76ED10414B6249D6895188456505CDB897FFCCEB8931802F87C02DFDC62825C6255DF2654712BE230CC86A30229D9E3438DB35CEED8F8447B9209CDECFC1776D2C43B4B98E9EEA3F4C049C1287CDB4540D395A4BC992602150CCC0479597E221E201B778DCA9701C517C89B95004FC19373ED9755C90FF32C44013678876EAD3FE5E637BF2F1959130EAF79E7A93088F52AA0AC993324294536CF3787C3A3F06F2DC201A070967E6F4525803DC83F5160B560465A4CE4BF20315858BE0E62A07C55B3A772CBF93DE99AADFCB304D2B544A9F17A22C2BEB791D98F714CA7CFF701CB7CAEC55C292A25A147935D7BBD1E66F2ED3EBC66E763209169033CE5A2D9884DC0CBAFF37517372544E1EB780A26CC71E5649EDFD5DA2FCFB58093D74D76FC2DAEC54567104701C31E3872C15BAC5F2A96833EEDAB9B7FF731F827DB3273D271BA8F9DE06181C1E38D031896971D801C571954337D91B697BC3 +20170624052652 2 6 100 6143 2 E30D9BCD65DA0EAEF6A1D4D083834D4724538836AE04DFB6A7DAF235F5D9992B7E42128D43E229BF4906EF0C6A27F60B95A1FC514C2D55A0D616B3B6924F08E9C0BCD8AE1CB624F645785C2AA552C94E125D6602CF63CF52014A1B0A4AE0DE823B03B6ABFA25839ABC3E8E050C295B8B3471EC58EAD9B659294C72EA65229E4E8EB21CA79CBB41BB552118A3CD32108E51D5FCE5C46A6CD03E4246CB57E32BAA09B15503FBFA4F4C943B2378F10EE312C1F12A14010AFD1698B8EBCCFC8D0DF17829A153199154EBF9E40FD81B8E1AF5881D0EC1D3BEDB2D0F1DB9C44C9D8E7047310623D4FAAE28D2C16612CFB9AE9A8FD05B8FE22930346ECF7B21B5800778EA0D5D3B7BDF18B03ABF33C9D0B4648CF687ED229C811CE290CFAF94F9C9AF4EC3E47480955E5C81E85DA9EBCE99652DA07225C7CCEF39E224556E48D6371981C7232E00F3419F7B335FF36FE3989558277654DB356063ABC8F7BD0EF828B40D3BFC06D12FEC51278ACD32C3B67D4E2A0BBA1E20BDDA06DB9AF6AB250179DE3332EAC0A6D381963B51E8E167B8285BA3E6538B1D38B16B32196ABE009ADFDAF5E686E0107F76ED10414B6249D6895188456505CDB897FFCCEB8931802F87C02DFDC62825C6255DF2654712BE230CC86A30229D9E3438DB35CEED8F8447B9209CDECFC1776D2C43B4B98E9EEA3F4C049C1287CDB4540D395A4BC992602150CCC0479597E221E201B778DCA9701C517C89B95004FC19373ED9755C90FF32C44013678876EAD3FE5E637BF2F1959130EAF79E7A93088F52AA0AC993324294536CF3787C3A3F06F2DC201A070967E6F4525803DC83F5160B560465A4CE4BF20315858BE0E62A07C55B3A772CBF93DE99AADFCB304D2B544A9F17A22C2BEB791D98F714CA7CFF701CB7CAEC55C292A25A147935D7BBD1E66F2ED3EBC66E763209169033CE5A2D9884DC0CBAFF37517372544E1EB780A26CC71E5649EDFD5DA2FCFB58093D74D76FC2DAEC54567104701C31E3872C15BAC5F2A96833EEDAB9B7FF731F827DB3273D271BA8F9DE06181C1E38D031896971D801C571954337D91E5556DB +20170624075515 2 6 100 6143 2 E30D9BCD65DA0EAEF6A1D4D083834D4724538836AE04DFB6A7DAF235F5D9992B7E42128D43E229BF4906EF0C6A27F60B95A1FC514C2D55A0D616B3B6924F08E9C0BCD8AE1CB624F645785C2AA552C94E125D6602CF63CF52014A1B0A4AE0DE823B03B6ABFA25839ABC3E8E050C295B8B3471EC58EAD9B659294C72EA65229E4E8EB21CA79CBB41BB552118A3CD32108E51D5FCE5C46A6CD03E4246CB57E32BAA09B15503FBFA4F4C943B2378F10EE312C1F12A14010AFD1698B8EBCCFC8D0DF17829A153199154EBF9E40FD81B8E1AF5881D0EC1D3BEDB2D0F1DB9C44C9D8E7047310623D4FAAE28D2C16612CFB9AE9A8FD05B8FE22930346ECF7B21B5800778EA0D5D3B7BDF18B03ABF33C9D0B4648CF687ED229C811CE290CFAF94F9C9AF4EC3E47480955E5C81E85DA9EBCE99652DA07225C7CCEF39E224556E48D6371981C7232E00F3419F7B335FF36FE3989558277654DB356063ABC8F7BD0EF828B40D3BFC06D12FEC51278ACD32C3B67D4E2A0BBA1E20BDDA06DB9AF6AB250179DE3332EAC0A6D381963B51E8E167B8285BA3E6538B1D38B16B32196ABE009ADFDAF5E686E0107F76ED10414B6249D6895188456505CDB897FFCCEB8931802F87C02DFDC62825C6255DF2654712BE230CC86A30229D9E3438DB35CEED8F8447B9209CDECFC1776D2C43B4B98E9EEA3F4C049C1287CDB4540D395A4BC992602150CCC0479597E221E201B778DCA9701C517C89B95004FC19373ED9755C90FF32C44013678876EAD3FE5E637BF2F1959130EAF79E7A93088F52AA0AC993324294536CF3787C3A3F06F2DC201A070967E6F4525803DC83F5160B560465A4CE4BF20315858BE0E62A07C55B3A772CBF93DE99AADFCB304D2B544A9F17A22C2BEB791D98F714CA7CFF701CB7CAEC55C292A25A147935D7BBD1E66F2ED3EBC66E763209169033CE5A2D9884DC0CBAFF37517372544E1EB780A26CC71E5649EDFD5DA2FCFB58093D74D76FC2DAEC54567104701C31E3872C15BAC5F2A96833EEDAB9B7FF731F827DB3273D271BA8F9DE06181C1E38D031896971D801C571954337D922262F73 +20170624103157 2 6 100 6143 5 E30D9BCD65DA0EAEF6A1D4D083834D4724538836AE04DFB6A7DAF235F5D9992B7E42128D43E229BF4906EF0C6A27F60B95A1FC514C2D55A0D616B3B6924F08E9C0BCD8AE1CB624F645785C2AA552C94E125D6602CF63CF52014A1B0A4AE0DE823B03B6ABFA25839ABC3E8E050C295B8B3471EC58EAD9B659294C72EA65229E4E8EB21CA79CBB41BB552118A3CD32108E51D5FCE5C46A6CD03E4246CB57E32BAA09B15503FBFA4F4C943B2378F10EE312C1F12A14010AFD1698B8EBCCFC8D0DF17829A153199154EBF9E40FD81B8E1AF5881D0EC1D3BEDB2D0F1DB9C44C9D8E7047310623D4FAAE28D2C16612CFB9AE9A8FD05B8FE22930346ECF7B21B5800778EA0D5D3B7BDF18B03ABF33C9D0B4648CF687ED229C811CE290CFAF94F9C9AF4EC3E47480955E5C81E85DA9EBCE99652DA07225C7CCEF39E224556E48D6371981C7232E00F3419F7B335FF36FE3989558277654DB356063ABC8F7BD0EF828B40D3BFC06D12FEC51278ACD32C3B67D4E2A0BBA1E20BDDA06DB9AF6AB250179DE3332EAC0A6D381963B51E8E167B8285BA3E6538B1D38B16B32196ABE009ADFDAF5E686E0107F76ED10414B6249D6895188456505CDB897FFCCEB8931802F87C02DFDC62825C6255DF2654712BE230CC86A30229D9E3438DB35CEED8F8447B9209CDECFC1776D2C43B4B98E9EEA3F4C049C1287CDB4540D395A4BC992602150CCC0479597E221E201B778DCA9701C517C89B95004FC19373ED9755C90FF32C44013678876EAD3FE5E637BF2F1959130EAF79E7A93088F52AA0AC993324294536CF3787C3A3F06F2DC201A070967E6F4525803DC83F5160B560465A4CE4BF20315858BE0E62A07C55B3A772CBF93DE99AADFCB304D2B544A9F17A22C2BEB791D98F714CA7CFF701CB7CAEC55C292A25A147935D7BBD1E66F2ED3EBC66E763209169033CE5A2D9884DC0CBAFF37517372544E1EB780A26CC71E5649EDFD5DA2FCFB58093D74D76FC2DAEC54567104701C31E3872C15BAC5F2A96833EEDAB9B7FF731F827DB3273D271BA8F9DE06181C1E38D031896971D801C571954337D92638CCD7 +20170624120558 2 6 100 6143 2 E30D9BCD65DA0EAEF6A1D4D083834D4724538836AE04DFB6A7DAF235F5D9992B7E42128D43E229BF4906EF0C6A27F60B95A1FC514C2D55A0D616B3B6924F08E9C0BCD8AE1CB624F645785C2AA552C94E125D6602CF63CF52014A1B0A4AE0DE823B03B6ABFA25839ABC3E8E050C295B8B3471EC58EAD9B659294C72EA65229E4E8EB21CA79CBB41BB552118A3CD32108E51D5FCE5C46A6CD03E4246CB57E32BAA09B15503FBFA4F4C943B2378F10EE312C1F12A14010AFD1698B8EBCCFC8D0DF17829A153199154EBF9E40FD81B8E1AF5881D0EC1D3BEDB2D0F1DB9C44C9D8E7047310623D4FAAE28D2C16612CFB9AE9A8FD05B8FE22930346ECF7B21B5800778EA0D5D3B7BDF18B03ABF33C9D0B4648CF687ED229C811CE290CFAF94F9C9AF4EC3E47480955E5C81E85DA9EBCE99652DA07225C7CCEF39E224556E48D6371981C7232E00F3419F7B335FF36FE3989558277654DB356063ABC8F7BD0EF828B40D3BFC06D12FEC51278ACD32C3B67D4E2A0BBA1E20BDDA06DB9AF6AB250179DE3332EAC0A6D381963B51E8E167B8285BA3E6538B1D38B16B32196ABE009ADFDAF5E686E0107F76ED10414B6249D6895188456505CDB897FFCCEB8931802F87C02DFDC62825C6255DF2654712BE230CC86A30229D9E3438DB35CEED8F8447B9209CDECFC1776D2C43B4B98E9EEA3F4C049C1287CDB4540D395A4BC992602150CCC0479597E221E201B778DCA9701C517C89B95004FC19373ED9755C90FF32C44013678876EAD3FE5E637BF2F1959130EAF79E7A93088F52AA0AC993324294536CF3787C3A3F06F2DC201A070967E6F4525803DC83F5160B560465A4CE4BF20315858BE0E62A07C55B3A772CBF93DE99AADFCB304D2B544A9F17A22C2BEB791D98F714CA7CFF701CB7CAEC55C292A25A147935D7BBD1E66F2ED3EBC66E763209169033CE5A2D9884DC0CBAFF37517372544E1EB780A26CC71E5649EDFD5DA2FCFB58093D74D76FC2DAEC54567104701C31E3872C15BAC5F2A96833EEDAB9B7FF731F827DB3273D271BA8F9DE06181C1E38D031896971D801C571954337D92895C273 +20170624130210 2 6 100 6143 5 E30D9BCD65DA0EAEF6A1D4D083834D4724538836AE04DFB6A7DAF235F5D9992B7E42128D43E229BF4906EF0C6A27F60B95A1FC514C2D55A0D616B3B6924F08E9C0BCD8AE1CB624F645785C2AA552C94E125D6602CF63CF52014A1B0A4AE0DE823B03B6ABFA25839ABC3E8E050C295B8B3471EC58EAD9B659294C72EA65229E4E8EB21CA79CBB41BB552118A3CD32108E51D5FCE5C46A6CD03E4246CB57E32BAA09B15503FBFA4F4C943B2378F10EE312C1F12A14010AFD1698B8EBCCFC8D0DF17829A153199154EBF9E40FD81B8E1AF5881D0EC1D3BEDB2D0F1DB9C44C9D8E7047310623D4FAAE28D2C16612CFB9AE9A8FD05B8FE22930346ECF7B21B5800778EA0D5D3B7BDF18B03ABF33C9D0B4648CF687ED229C811CE290CFAF94F9C9AF4EC3E47480955E5C81E85DA9EBCE99652DA07225C7CCEF39E224556E48D6371981C7232E00F3419F7B335FF36FE3989558277654DB356063ABC8F7BD0EF828B40D3BFC06D12FEC51278ACD32C3B67D4E2A0BBA1E20BDDA06DB9AF6AB250179DE3332EAC0A6D381963B51E8E167B8285BA3E6538B1D38B16B32196ABE009ADFDAF5E686E0107F76ED10414B6249D6895188456505CDB897FFCCEB8931802F87C02DFDC62825C6255DF2654712BE230CC86A30229D9E3438DB35CEED8F8447B9209CDECFC1776D2C43B4B98E9EEA3F4C049C1287CDB4540D395A4BC992602150CCC0479597E221E201B778DCA9701C517C89B95004FC19373ED9755C90FF32C44013678876EAD3FE5E637BF2F1959130EAF79E7A93088F52AA0AC993324294536CF3787C3A3F06F2DC201A070967E6F4525803DC83F5160B560465A4CE4BF20315858BE0E62A07C55B3A772CBF93DE99AADFCB304D2B544A9F17A22C2BEB791D98F714CA7CFF701CB7CAEC55C292A25A147935D7BBD1E66F2ED3EBC66E763209169033CE5A2D9884DC0CBAFF37517372544E1EB780A26CC71E5649EDFD5DA2FCFB58093D74D76FC2DAEC54567104701C31E3872C15BAC5F2A96833EEDAB9B7FF731F827DB3273D271BA8F9DE06181C1E38D031896971D801C571954337D92A0429E7 +20170624131317 2 6 100 6143 2 E30D9BCD65DA0EAEF6A1D4D083834D4724538836AE04DFB6A7DAF235F5D9992B7E42128D43E229BF4906EF0C6A27F60B95A1FC514C2D55A0D616B3B6924F08E9C0BCD8AE1CB624F645785C2AA552C94E125D6602CF63CF52014A1B0A4AE0DE823B03B6ABFA25839ABC3E8E050C295B8B3471EC58EAD9B659294C72EA65229E4E8EB21CA79CBB41BB552118A3CD32108E51D5FCE5C46A6CD03E4246CB57E32BAA09B15503FBFA4F4C943B2378F10EE312C1F12A14010AFD1698B8EBCCFC8D0DF17829A153199154EBF9E40FD81B8E1AF5881D0EC1D3BEDB2D0F1DB9C44C9D8E7047310623D4FAAE28D2C16612CFB9AE9A8FD05B8FE22930346ECF7B21B5800778EA0D5D3B7BDF18B03ABF33C9D0B4648CF687ED229C811CE290CFAF94F9C9AF4EC3E47480955E5C81E85DA9EBCE99652DA07225C7CCEF39E224556E48D6371981C7232E00F3419F7B335FF36FE3989558277654DB356063ABC8F7BD0EF828B40D3BFC06D12FEC51278ACD32C3B67D4E2A0BBA1E20BDDA06DB9AF6AB250179DE3332EAC0A6D381963B51E8E167B8285BA3E6538B1D38B16B32196ABE009ADFDAF5E686E0107F76ED10414B6249D6895188456505CDB897FFCCEB8931802F87C02DFDC62825C6255DF2654712BE230CC86A30229D9E3438DB35CEED8F8447B9209CDECFC1776D2C43B4B98E9EEA3F4C049C1287CDB4540D395A4BC992602150CCC0479597E221E201B778DCA9701C517C89B95004FC19373ED9755C90FF32C44013678876EAD3FE5E637BF2F1959130EAF79E7A93088F52AA0AC993324294536CF3787C3A3F06F2DC201A070967E6F4525803DC83F5160B560465A4CE4BF20315858BE0E62A07C55B3A772CBF93DE99AADFCB304D2B544A9F17A22C2BEB791D98F714CA7CFF701CB7CAEC55C292A25A147935D7BBD1E66F2ED3EBC66E763209169033CE5A2D9884DC0CBAFF37517372544E1EB780A26CC71E5649EDFD5DA2FCFB58093D74D76FC2DAEC54567104701C31E3872C15BAC5F2A96833EEDAB9B7FF731F827DB3273D271BA8F9DE06181C1E38D031896971D801C571954337D92A441063 +20170624132538 2 6 100 6143 5 E30D9BCD65DA0EAEF6A1D4D083834D4724538836AE04DFB6A7DAF235F5D9992B7E42128D43E229BF4906EF0C6A27F60B95A1FC514C2D55A0D616B3B6924F08E9C0BCD8AE1CB624F645785C2AA552C94E125D6602CF63CF52014A1B0A4AE0DE823B03B6ABFA25839ABC3E8E050C295B8B3471EC58EAD9B659294C72EA65229E4E8EB21CA79CBB41BB552118A3CD32108E51D5FCE5C46A6CD03E4246CB57E32BAA09B15503FBFA4F4C943B2378F10EE312C1F12A14010AFD1698B8EBCCFC8D0DF17829A153199154EBF9E40FD81B8E1AF5881D0EC1D3BEDB2D0F1DB9C44C9D8E7047310623D4FAAE28D2C16612CFB9AE9A8FD05B8FE22930346ECF7B21B5800778EA0D5D3B7BDF18B03ABF33C9D0B4648CF687ED229C811CE290CFAF94F9C9AF4EC3E47480955E5C81E85DA9EBCE99652DA07225C7CCEF39E224556E48D6371981C7232E00F3419F7B335FF36FE3989558277654DB356063ABC8F7BD0EF828B40D3BFC06D12FEC51278ACD32C3B67D4E2A0BBA1E20BDDA06DB9AF6AB250179DE3332EAC0A6D381963B51E8E167B8285BA3E6538B1D38B16B32196ABE009ADFDAF5E686E0107F76ED10414B6249D6895188456505CDB897FFCCEB8931802F87C02DFDC62825C6255DF2654712BE230CC86A30229D9E3438DB35CEED8F8447B9209CDECFC1776D2C43B4B98E9EEA3F4C049C1287CDB4540D395A4BC992602150CCC0479597E221E201B778DCA9701C517C89B95004FC19373ED9755C90FF32C44013678876EAD3FE5E637BF2F1959130EAF79E7A93088F52AA0AC993324294536CF3787C3A3F06F2DC201A070967E6F4525803DC83F5160B560465A4CE4BF20315858BE0E62A07C55B3A772CBF93DE99AADFCB304D2B544A9F17A22C2BEB791D98F714CA7CFF701CB7CAEC55C292A25A147935D7BBD1E66F2ED3EBC66E763209169033CE5A2D9884DC0CBAFF37517372544E1EB780A26CC71E5649EDFD5DA2FCFB58093D74D76FC2DAEC54567104701C31E3872C15BAC5F2A96833EEDAB9B7FF731F827DB3273D271BA8F9DE06181C1E38D031896971D801C571954337D92A8E794F +20170624133715 2 6 100 6143 5 E30D9BCD65DA0EAEF6A1D4D083834D4724538836AE04DFB6A7DAF235F5D9992B7E42128D43E229BF4906EF0C6A27F60B95A1FC514C2D55A0D616B3B6924F08E9C0BCD8AE1CB624F645785C2AA552C94E125D6602CF63CF52014A1B0A4AE0DE823B03B6ABFA25839ABC3E8E050C295B8B3471EC58EAD9B659294C72EA65229E4E8EB21CA79CBB41BB552118A3CD32108E51D5FCE5C46A6CD03E4246CB57E32BAA09B15503FBFA4F4C943B2378F10EE312C1F12A14010AFD1698B8EBCCFC8D0DF17829A153199154EBF9E40FD81B8E1AF5881D0EC1D3BEDB2D0F1DB9C44C9D8E7047310623D4FAAE28D2C16612CFB9AE9A8FD05B8FE22930346ECF7B21B5800778EA0D5D3B7BDF18B03ABF33C9D0B4648CF687ED229C811CE290CFAF94F9C9AF4EC3E47480955E5C81E85DA9EBCE99652DA07225C7CCEF39E224556E48D6371981C7232E00F3419F7B335FF36FE3989558277654DB356063ABC8F7BD0EF828B40D3BFC06D12FEC51278ACD32C3B67D4E2A0BBA1E20BDDA06DB9AF6AB250179DE3332EAC0A6D381963B51E8E167B8285BA3E6538B1D38B16B32196ABE009ADFDAF5E686E0107F76ED10414B6249D6895188456505CDB897FFCCEB8931802F87C02DFDC62825C6255DF2654712BE230CC86A30229D9E3438DB35CEED8F8447B9209CDECFC1776D2C43B4B98E9EEA3F4C049C1287CDB4540D395A4BC992602150CCC0479597E221E201B778DCA9701C517C89B95004FC19373ED9755C90FF32C44013678876EAD3FE5E637BF2F1959130EAF79E7A93088F52AA0AC993324294536CF3787C3A3F06F2DC201A070967E6F4525803DC83F5160B560465A4CE4BF20315858BE0E62A07C55B3A772CBF93DE99AADFCB304D2B544A9F17A22C2BEB791D98F714CA7CFF701CB7CAEC55C292A25A147935D7BBD1E66F2ED3EBC66E763209169033CE5A2D9884DC0CBAFF37517372544E1EB780A26CC71E5649EDFD5DA2FCFB58093D74D76FC2DAEC54567104701C31E3872C15BAC5F2A96833EEDAB9B7FF731F827DB3273D271BA8F9DE06181C1E38D031896971D801C571954337D92AD26E07 +20170624145051 2 6 100 6143 5 E30D9BCD65DA0EAEF6A1D4D083834D4724538836AE04DFB6A7DAF235F5D9992B7E42128D43E229BF4906EF0C6A27F60B95A1FC514C2D55A0D616B3B6924F08E9C0BCD8AE1CB624F645785C2AA552C94E125D6602CF63CF52014A1B0A4AE0DE823B03B6ABFA25839ABC3E8E050C295B8B3471EC58EAD9B659294C72EA65229E4E8EB21CA79CBB41BB552118A3CD32108E51D5FCE5C46A6CD03E4246CB57E32BAA09B15503FBFA4F4C943B2378F10EE312C1F12A14010AFD1698B8EBCCFC8D0DF17829A153199154EBF9E40FD81B8E1AF5881D0EC1D3BEDB2D0F1DB9C44C9D8E7047310623D4FAAE28D2C16612CFB9AE9A8FD05B8FE22930346ECF7B21B5800778EA0D5D3B7BDF18B03ABF33C9D0B4648CF687ED229C811CE290CFAF94F9C9AF4EC3E47480955E5C81E85DA9EBCE99652DA07225C7CCEF39E224556E48D6371981C7232E00F3419F7B335FF36FE3989558277654DB356063ABC8F7BD0EF828B40D3BFC06D12FEC51278ACD32C3B67D4E2A0BBA1E20BDDA06DB9AF6AB250179DE3332EAC0A6D381963B51E8E167B8285BA3E6538B1D38B16B32196ABE009ADFDAF5E686E0107F76ED10414B6249D6895188456505CDB897FFCCEB8931802F87C02DFDC62825C6255DF2654712BE230CC86A30229D9E3438DB35CEED8F8447B9209CDECFC1776D2C43B4B98E9EEA3F4C049C1287CDB4540D395A4BC992602150CCC0479597E221E201B778DCA9701C517C89B95004FC19373ED9755C90FF32C44013678876EAD3FE5E637BF2F1959130EAF79E7A93088F52AA0AC993324294536CF3787C3A3F06F2DC201A070967E6F4525803DC83F5160B560465A4CE4BF20315858BE0E62A07C55B3A772CBF93DE99AADFCB304D2B544A9F17A22C2BEB791D98F714CA7CFF701CB7CAEC55C292A25A147935D7BBD1E66F2ED3EBC66E763209169033CE5A2D9884DC0CBAFF37517372544E1EB780A26CC71E5649EDFD5DA2FCFB58093D74D76FC2DAEC54567104701C31E3872C15BAC5F2A96833EEDAB9B7FF731F827DB3273D271BA8F9DE06181C1E38D031896971D801C571954337D92CB7412F +20170624163751 2 6 100 6143 2 E30D9BCD65DA0EAEF6A1D4D083834D4724538836AE04DFB6A7DAF235F5D9992B7E42128D43E229BF4906EF0C6A27F60B95A1FC514C2D55A0D616B3B6924F08E9C0BCD8AE1CB624F645785C2AA552C94E125D6602CF63CF52014A1B0A4AE0DE823B03B6ABFA25839ABC3E8E050C295B8B3471EC58EAD9B659294C72EA65229E4E8EB21CA79CBB41BB552118A3CD32108E51D5FCE5C46A6CD03E4246CB57E32BAA09B15503FBFA4F4C943B2378F10EE312C1F12A14010AFD1698B8EBCCFC8D0DF17829A153199154EBF9E40FD81B8E1AF5881D0EC1D3BEDB2D0F1DB9C44C9D8E7047310623D4FAAE28D2C16612CFB9AE9A8FD05B8FE22930346ECF7B21B5800778EA0D5D3B7BDF18B03ABF33C9D0B4648CF687ED229C811CE290CFAF94F9C9AF4EC3E47480955E5C81E85DA9EBCE99652DA07225C7CCEF39E224556E48D6371981C7232E00F3419F7B335FF36FE3989558277654DB356063ABC8F7BD0EF828B40D3BFC06D12FEC51278ACD32C3B67D4E2A0BBA1E20BDDA06DB9AF6AB250179DE3332EAC0A6D381963B51E8E167B8285BA3E6538B1D38B16B32196ABE009ADFDAF5E686E0107F76ED10414B6249D6895188456505CDB897FFCCEB8931802F87C02DFDC62825C6255DF2654712BE230CC86A30229D9E3438DB35CEED8F8447B9209CDECFC1776D2C43B4B98E9EEA3F4C049C1287CDB4540D395A4BC992602150CCC0479597E221E201B778DCA9701C517C89B95004FC19373ED9755C90FF32C44013678876EAD3FE5E637BF2F1959130EAF79E7A93088F52AA0AC993324294536CF3787C3A3F06F2DC201A070967E6F4525803DC83F5160B560465A4CE4BF20315858BE0E62A07C55B3A772CBF93DE99AADFCB304D2B544A9F17A22C2BEB791D98F714CA7CFF701CB7CAEC55C292A25A147935D7BBD1E66F2ED3EBC66E763209169033CE5A2D9884DC0CBAFF37517372544E1EB780A26CC71E5649EDFD5DA2FCFB58093D74D76FC2DAEC54567104701C31E3872C15BAC5F2A96833EEDAB9B7FF731F827DB3273D271BA8F9DE06181C1E38D031896971D801C571954337D92F668E7B +20170624172739 2 6 100 6143 2 E30D9BCD65DA0EAEF6A1D4D083834D4724538836AE04DFB6A7DAF235F5D9992B7E42128D43E229BF4906EF0C6A27F60B95A1FC514C2D55A0D616B3B6924F08E9C0BCD8AE1CB624F645785C2AA552C94E125D6602CF63CF52014A1B0A4AE0DE823B03B6ABFA25839ABC3E8E050C295B8B3471EC58EAD9B659294C72EA65229E4E8EB21CA79CBB41BB552118A3CD32108E51D5FCE5C46A6CD03E4246CB57E32BAA09B15503FBFA4F4C943B2378F10EE312C1F12A14010AFD1698B8EBCCFC8D0DF17829A153199154EBF9E40FD81B8E1AF5881D0EC1D3BEDB2D0F1DB9C44C9D8E7047310623D4FAAE28D2C16612CFB9AE9A8FD05B8FE22930346ECF7B21B5800778EA0D5D3B7BDF18B03ABF33C9D0B4648CF687ED229C811CE290CFAF94F9C9AF4EC3E47480955E5C81E85DA9EBCE99652DA07225C7CCEF39E224556E48D6371981C7232E00F3419F7B335FF36FE3989558277654DB356063ABC8F7BD0EF828B40D3BFC06D12FEC51278ACD32C3B67D4E2A0BBA1E20BDDA06DB9AF6AB250179DE3332EAC0A6D381963B51E8E167B8285BA3E6538B1D38B16B32196ABE009ADFDAF5E686E0107F76ED10414B6249D6895188456505CDB897FFCCEB8931802F87C02DFDC62825C6255DF2654712BE230CC86A30229D9E3438DB35CEED8F8447B9209CDECFC1776D2C43B4B98E9EEA3F4C049C1287CDB4540D395A4BC992602150CCC0479597E221E201B778DCA9701C517C89B95004FC19373ED9755C90FF32C44013678876EAD3FE5E637BF2F1959130EAF79E7A93088F52AA0AC993324294536CF3787C3A3F06F2DC201A070967E6F4525803DC83F5160B560465A4CE4BF20315858BE0E62A07C55B3A772CBF93DE99AADFCB304D2B544A9F17A22C2BEB791D98F714CA7CFF701CB7CAEC55C292A25A147935D7BBD1E66F2ED3EBC66E763209169033CE5A2D9884DC0CBAFF37517372544E1EB780A26CC71E5649EDFD5DA2FCFB58093D74D76FC2DAEC54567104701C31E3872C15BAC5F2A96833EEDAB9B7FF731F827DB3273D271BA8F9DE06181C1E38D031896971D801C571954337D930A8FC4B +20170624174055 2 6 100 6143 2 E30D9BCD65DA0EAEF6A1D4D083834D4724538836AE04DFB6A7DAF235F5D9992B7E42128D43E229BF4906EF0C6A27F60B95A1FC514C2D55A0D616B3B6924F08E9C0BCD8AE1CB624F645785C2AA552C94E125D6602CF63CF52014A1B0A4AE0DE823B03B6ABFA25839ABC3E8E050C295B8B3471EC58EAD9B659294C72EA65229E4E8EB21CA79CBB41BB552118A3CD32108E51D5FCE5C46A6CD03E4246CB57E32BAA09B15503FBFA4F4C943B2378F10EE312C1F12A14010AFD1698B8EBCCFC8D0DF17829A153199154EBF9E40FD81B8E1AF5881D0EC1D3BEDB2D0F1DB9C44C9D8E7047310623D4FAAE28D2C16612CFB9AE9A8FD05B8FE22930346ECF7B21B5800778EA0D5D3B7BDF18B03ABF33C9D0B4648CF687ED229C811CE290CFAF94F9C9AF4EC3E47480955E5C81E85DA9EBCE99652DA07225C7CCEF39E224556E48D6371981C7232E00F3419F7B335FF36FE3989558277654DB356063ABC8F7BD0EF828B40D3BFC06D12FEC51278ACD32C3B67D4E2A0BBA1E20BDDA06DB9AF6AB250179DE3332EAC0A6D381963B51E8E167B8285BA3E6538B1D38B16B32196ABE009ADFDAF5E686E0107F76ED10414B6249D6895188456505CDB897FFCCEB8931802F87C02DFDC62825C6255DF2654712BE230CC86A30229D9E3438DB35CEED8F8447B9209CDECFC1776D2C43B4B98E9EEA3F4C049C1287CDB4540D395A4BC992602150CCC0479597E221E201B778DCA9701C517C89B95004FC19373ED9755C90FF32C44013678876EAD3FE5E637BF2F1959130EAF79E7A93088F52AA0AC993324294536CF3787C3A3F06F2DC201A070967E6F4525803DC83F5160B560465A4CE4BF20315858BE0E62A07C55B3A772CBF93DE99AADFCB304D2B544A9F17A22C2BEB791D98F714CA7CFF701CB7CAEC55C292A25A147935D7BBD1E66F2ED3EBC66E763209169033CE5A2D9884DC0CBAFF37517372544E1EB780A26CC71E5649EDFD5DA2FCFB58093D74D76FC2DAEC54567104701C31E3872C15BAC5F2A96833EEDAB9B7FF731F827DB3273D271BA8F9DE06181C1E38D031896971D801C571954337D930F6B80B +20170624185924 2 6 100 6143 5 E30D9BCD65DA0EAEF6A1D4D083834D4724538836AE04DFB6A7DAF235F5D9992B7E42128D43E229BF4906EF0C6A27F60B95A1FC514C2D55A0D616B3B6924F08E9C0BCD8AE1CB624F645785C2AA552C94E125D6602CF63CF52014A1B0A4AE0DE823B03B6ABFA25839ABC3E8E050C295B8B3471EC58EAD9B659294C72EA65229E4E8EB21CA79CBB41BB552118A3CD32108E51D5FCE5C46A6CD03E4246CB57E32BAA09B15503FBFA4F4C943B2378F10EE312C1F12A14010AFD1698B8EBCCFC8D0DF17829A153199154EBF9E40FD81B8E1AF5881D0EC1D3BEDB2D0F1DB9C44C9D8E7047310623D4FAAE28D2C16612CFB9AE9A8FD05B8FE22930346ECF7B21B5800778EA0D5D3B7BDF18B03ABF33C9D0B4648CF687ED229C811CE290CFAF94F9C9AF4EC3E47480955E5C81E85DA9EBCE99652DA07225C7CCEF39E224556E48D6371981C7232E00F3419F7B335FF36FE3989558277654DB356063ABC8F7BD0EF828B40D3BFC06D12FEC51278ACD32C3B67D4E2A0BBA1E20BDDA06DB9AF6AB250179DE3332EAC0A6D381963B51E8E167B8285BA3E6538B1D38B16B32196ABE009ADFDAF5E686E0107F76ED10414B6249D6895188456505CDB897FFCCEB8931802F87C02DFDC62825C6255DF2654712BE230CC86A30229D9E3438DB35CEED8F8447B9209CDECFC1776D2C43B4B98E9EEA3F4C049C1287CDB4540D395A4BC992602150CCC0479597E221E201B778DCA9701C517C89B95004FC19373ED9755C90FF32C44013678876EAD3FE5E637BF2F1959130EAF79E7A93088F52AA0AC993324294536CF3787C3A3F06F2DC201A070967E6F4525803DC83F5160B560465A4CE4BF20315858BE0E62A07C55B3A772CBF93DE99AADFCB304D2B544A9F17A22C2BEB791D98F714CA7CFF701CB7CAEC55C292A25A147935D7BBD1E66F2ED3EBC66E763209169033CE5A2D9884DC0CBAFF37517372544E1EB780A26CC71E5649EDFD5DA2FCFB58093D74D76FC2DAEC54567104701C31E3872C15BAC5F2A96833EEDAB9B7FF731F827DB3273D271BA8F9DE06181C1E38D031896971D801C571954337D932ED85B7 +20170624220917 2 6 100 6143 2 E30D9BCD65DA0EAEF6A1D4D083834D4724538836AE04DFB6A7DAF235F5D9992B7E42128D43E229BF4906EF0C6A27F60B95A1FC514C2D55A0D616B3B6924F08E9C0BCD8AE1CB624F645785C2AA552C94E125D6602CF63CF52014A1B0A4AE0DE823B03B6ABFA25839ABC3E8E050C295B8B3471EC58EAD9B659294C72EA65229E4E8EB21CA79CBB41BB552118A3CD32108E51D5FCE5C46A6CD03E4246CB57E32BAA09B15503FBFA4F4C943B2378F10EE312C1F12A14010AFD1698B8EBCCFC8D0DF17829A153199154EBF9E40FD81B8E1AF5881D0EC1D3BEDB2D0F1DB9C44C9D8E7047310623D4FAAE28D2C16612CFB9AE9A8FD05B8FE22930346ECF7B21B5800778EA0D5D3B7BDF18B03ABF33C9D0B4648CF687ED229C811CE290CFAF94F9C9AF4EC3E47480955E5C81E85DA9EBCE99652DA07225C7CCEF39E224556E48D6371981C7232E00F3419F7B335FF36FE3989558277654DB356063ABC8F7BD0EF828B40D3BFC06D12FEC51278ACD32C3B67D4E2A0BBA1E20BDDA06DB9AF6AB250179DE3332EAC0A6D381963B51E8E167B8285BA3E6538B1D38B16B32196ABE009ADFDAF5E686E0107F76ED10414B6249D6895188456505CDB897FFCCEB8931802F87C02DFDC62825C6255DF2654712BE230CC86A30229D9E3438DB35CEED8F8447B9209CDECFC1776D2C43B4B98E9EEA3F4C049C1287CDB4540D395A4BC992602150CCC0479597E221E201B778DCA9701C517C89B95004FC19373ED9755C90FF32C44013678876EAD3FE5E637BF2F1959130EAF79E7A93088F52AA0AC993324294536CF3787C3A3F06F2DC201A070967E6F4525803DC83F5160B560465A4CE4BF20315858BE0E62A07C55B3A772CBF93DE99AADFCB304D2B544A9F17A22C2BEB791D98F714CA7CFF701CB7CAEC55C292A25A147935D7BBD1E66F2ED3EBC66E763209169033CE5A2D9884DC0CBAFF37517372544E1EB780A26CC71E5649EDFD5DA2FCFB58093D74D76FC2DAEC54567104701C31E3872C15BAC5F2A96833EEDAB9B7FF731F827DB3273D271BA8F9DE06181C1E38D031896971D801C571954337D937BF2B3B +20170624222456 2 6 100 6143 2 E30D9BCD65DA0EAEF6A1D4D083834D4724538836AE04DFB6A7DAF235F5D9992B7E42128D43E229BF4906EF0C6A27F60B95A1FC514C2D55A0D616B3B6924F08E9C0BCD8AE1CB624F645785C2AA552C94E125D6602CF63CF52014A1B0A4AE0DE823B03B6ABFA25839ABC3E8E050C295B8B3471EC58EAD9B659294C72EA65229E4E8EB21CA79CBB41BB552118A3CD32108E51D5FCE5C46A6CD03E4246CB57E32BAA09B15503FBFA4F4C943B2378F10EE312C1F12A14010AFD1698B8EBCCFC8D0DF17829A153199154EBF9E40FD81B8E1AF5881D0EC1D3BEDB2D0F1DB9C44C9D8E7047310623D4FAAE28D2C16612CFB9AE9A8FD05B8FE22930346ECF7B21B5800778EA0D5D3B7BDF18B03ABF33C9D0B4648CF687ED229C811CE290CFAF94F9C9AF4EC3E47480955E5C81E85DA9EBCE99652DA07225C7CCEF39E224556E48D6371981C7232E00F3419F7B335FF36FE3989558277654DB356063ABC8F7BD0EF828B40D3BFC06D12FEC51278ACD32C3B67D4E2A0BBA1E20BDDA06DB9AF6AB250179DE3332EAC0A6D381963B51E8E167B8285BA3E6538B1D38B16B32196ABE009ADFDAF5E686E0107F76ED10414B6249D6895188456505CDB897FFCCEB8931802F87C02DFDC62825C6255DF2654712BE230CC86A30229D9E3438DB35CEED8F8447B9209CDECFC1776D2C43B4B98E9EEA3F4C049C1287CDB4540D395A4BC992602150CCC0479597E221E201B778DCA9701C517C89B95004FC19373ED9755C90FF32C44013678876EAD3FE5E637BF2F1959130EAF79E7A93088F52AA0AC993324294536CF3787C3A3F06F2DC201A070967E6F4525803DC83F5160B560465A4CE4BF20315858BE0E62A07C55B3A772CBF93DE99AADFCB304D2B544A9F17A22C2BEB791D98F714CA7CFF701CB7CAEC55C292A25A147935D7BBD1E66F2ED3EBC66E763209169033CE5A2D9884DC0CBAFF37517372544E1EB780A26CC71E5649EDFD5DA2FCFB58093D74D76FC2DAEC54567104701C31E3872C15BAC5F2A96833EEDAB9B7FF731F827DB3273D271BA8F9DE06181C1E38D031896971D801C571954337D9381B839B +20170625033902 2 6 100 6143 2 E30D9BCD65DA0EAEF6A1D4D083834D4724538836AE04DFB6A7DAF235F5D9992B7E42128D43E229BF4906EF0C6A27F60B95A1FC514C2D55A0D616B3B6924F08E9C0BCD8AE1CB624F645785C2AA552C94E125D6602CF63CF52014A1B0A4AE0DE823B03B6ABFA25839ABC3E8E050C295B8B3471EC58EAD9B659294C72EA65229E4E8EB21CA79CBB41BB552118A3CD32108E51D5FCE5C46A6CD03E4246CB57E32BAA09B15503FBFA4F4C943B2378F10EE312C1F12A14010AFD1698B8EBCCFC8D0DF17829A153199154EBF9E40FD81B8E1AF5881D0EC1D3BEDB2D0F1DB9C44C9D8E7047310623D4FAAE28D2C16612CFB9AE9A8FD05B8FE22930346ECF7B21B5800778EA0D5D3B7BDF18B03ABF33C9D0B4648CF687ED229C811CE290CFAF94F9C9AF4EC3E47480955E5C81E85DA9EBCE99652DA07225C7CCEF39E224556E48D6371981C7232E00F3419F7B335FF36FE3989558277654DB356063ABC8F7BD0EF828B40D3BFC06D12FEC51278ACD32C3B67D4E2A0BBA1E20BDDA06DB9AF6AB250179DE3332EAC0A6D381963B51E8E167B8285BA3E6538B1D38B16B32196ABE009ADFDAF5E686E0107F76ED10414B6249D6895188456505CDB897FFCCEB8931802F87C02DFDC62825C6255DF2654712BE230CC86A30229D9E3438DB35CEED8F8447B9209CDECFC1776D2C43B4B98E9EEA3F4C049C1287CDB4540D395A4BC992602150CCC0479597E221E201B778DCA9701C517C89B95004FC19373ED9755C90FF32C44013678876EAD3FE5E637BF2F1959130EAF79E7A93088F52AA0AC993324294536CF3787C3A3F06F2DC201A070967E6F4525803DC83F5160B560465A4CE4BF20315858BE0E62A07C55B3A772CBF93DE99AADFCB304D2B544A9F17A22C2BEB791D98F714CA7CFF701CB7CAEC55C292A25A147935D7BBD1E66F2ED3EBC66E763209169033CE5A2D9884DC0CBAFF37517372544E1EB780A26CC71E5649EDFD5DA2FCFB58093D74D76FC2DAEC54567104701C31E3872C15BAC5F2A96833EEDAB9B7FF731F827DB3273D271BA8F9DE06181C1E38D031896971D801C571954337D94007305B +20170625053719 2 6 100 6143 5 E30D9BCD65DA0EAEF6A1D4D083834D4724538836AE04DFB6A7DAF235F5D9992B7E42128D43E229BF4906EF0C6A27F60B95A1FC514C2D55A0D616B3B6924F08E9C0BCD8AE1CB624F645785C2AA552C94E125D6602CF63CF52014A1B0A4AE0DE823B03B6ABFA25839ABC3E8E050C295B8B3471EC58EAD9B659294C72EA65229E4E8EB21CA79CBB41BB552118A3CD32108E51D5FCE5C46A6CD03E4246CB57E32BAA09B15503FBFA4F4C943B2378F10EE312C1F12A14010AFD1698B8EBCCFC8D0DF17829A153199154EBF9E40FD81B8E1AF5881D0EC1D3BEDB2D0F1DB9C44C9D8E7047310623D4FAAE28D2C16612CFB9AE9A8FD05B8FE22930346ECF7B21B5800778EA0D5D3B7BDF18B03ABF33C9D0B4648CF687ED229C811CE290CFAF94F9C9AF4EC3E47480955E5C81E85DA9EBCE99652DA07225C7CCEF39E224556E48D6371981C7232E00F3419F7B335FF36FE3989558277654DB356063ABC8F7BD0EF828B40D3BFC06D12FEC51278ACD32C3B67D4E2A0BBA1E20BDDA06DB9AF6AB250179DE3332EAC0A6D381963B51E8E167B8285BA3E6538B1D38B16B32196ABE009ADFDAF5E686E0107F76ED10414B6249D6895188456505CDB897FFCCEB8931802F87C02DFDC62825C6255DF2654712BE230CC86A30229D9E3438DB35CEED8F8447B9209CDECFC1776D2C43B4B98E9EEA3F4C049C1287CDB4540D395A4BC992602150CCC0479597E221E201B778DCA9701C517C89B95004FC19373ED9755C90FF32C44013678876EAD3FE5E637BF2F1959130EAF79E7A93088F52AA0AC993324294536CF3787C3A3F06F2DC201A070967E6F4525803DC83F5160B560465A4CE4BF20315858BE0E62A07C55B3A772CBF93DE99AADFCB304D2B544A9F17A22C2BEB791D98F714CA7CFF701CB7CAEC55C292A25A147935D7BBD1E66F2ED3EBC66E763209169033CE5A2D9884DC0CBAFF37517372544E1EB780A26CC71E5649EDFD5DA2FCFB58093D74D76FC2DAEC54567104701C31E3872C15BAC5F2A96833EEDAB9B7FF731F827DB3273D271BA8F9DE06181C1E38D031896971D801C571954337D942F8C1E7 +20170625062259 2 6 100 6143 2 E30D9BCD65DA0EAEF6A1D4D083834D4724538836AE04DFB6A7DAF235F5D9992B7E42128D43E229BF4906EF0C6A27F60B95A1FC514C2D55A0D616B3B6924F08E9C0BCD8AE1CB624F645785C2AA552C94E125D6602CF63CF52014A1B0A4AE0DE823B03B6ABFA25839ABC3E8E050C295B8B3471EC58EAD9B659294C72EA65229E4E8EB21CA79CBB41BB552118A3CD32108E51D5FCE5C46A6CD03E4246CB57E32BAA09B15503FBFA4F4C943B2378F10EE312C1F12A14010AFD1698B8EBCCFC8D0DF17829A153199154EBF9E40FD81B8E1AF5881D0EC1D3BEDB2D0F1DB9C44C9D8E7047310623D4FAAE28D2C16612CFB9AE9A8FD05B8FE22930346ECF7B21B5800778EA0D5D3B7BDF18B03ABF33C9D0B4648CF687ED229C811CE290CFAF94F9C9AF4EC3E47480955E5C81E85DA9EBCE99652DA07225C7CCEF39E224556E48D6371981C7232E00F3419F7B335FF36FE3989558277654DB356063ABC8F7BD0EF828B40D3BFC06D12FEC51278ACD32C3B67D4E2A0BBA1E20BDDA06DB9AF6AB250179DE3332EAC0A6D381963B51E8E167B8285BA3E6538B1D38B16B32196ABE009ADFDAF5E686E0107F76ED10414B6249D6895188456505CDB897FFCCEB8931802F87C02DFDC62825C6255DF2654712BE230CC86A30229D9E3438DB35CEED8F8447B9209CDECFC1776D2C43B4B98E9EEA3F4C049C1287CDB4540D395A4BC992602150CCC0479597E221E201B778DCA9701C517C89B95004FC19373ED9755C90FF32C44013678876EAD3FE5E637BF2F1959130EAF79E7A93088F52AA0AC993324294536CF3787C3A3F06F2DC201A070967E6F4525803DC83F5160B560465A4CE4BF20315858BE0E62A07C55B3A772CBF93DE99AADFCB304D2B544A9F17A22C2BEB791D98F714CA7CFF701CB7CAEC55C292A25A147935D7BBD1E66F2ED3EBC66E763209169033CE5A2D9884DC0CBAFF37517372544E1EB780A26CC71E5649EDFD5DA2FCFB58093D74D76FC2DAEC54567104701C31E3872C15BAC5F2A96833EEDAB9B7FF731F827DB3273D271BA8F9DE06181C1E38D031896971D801C571954337D944178FAB +20170625072908 2 6 100 6143 5 E30D9BCD65DA0EAEF6A1D4D083834D4724538836AE04DFB6A7DAF235F5D9992B7E42128D43E229BF4906EF0C6A27F60B95A1FC514C2D55A0D616B3B6924F08E9C0BCD8AE1CB624F645785C2AA552C94E125D6602CF63CF52014A1B0A4AE0DE823B03B6ABFA25839ABC3E8E050C295B8B3471EC58EAD9B659294C72EA65229E4E8EB21CA79CBB41BB552118A3CD32108E51D5FCE5C46A6CD03E4246CB57E32BAA09B15503FBFA4F4C943B2378F10EE312C1F12A14010AFD1698B8EBCCFC8D0DF17829A153199154EBF9E40FD81B8E1AF5881D0EC1D3BEDB2D0F1DB9C44C9D8E7047310623D4FAAE28D2C16612CFB9AE9A8FD05B8FE22930346ECF7B21B5800778EA0D5D3B7BDF18B03ABF33C9D0B4648CF687ED229C811CE290CFAF94F9C9AF4EC3E47480955E5C81E85DA9EBCE99652DA07225C7CCEF39E224556E48D6371981C7232E00F3419F7B335FF36FE3989558277654DB356063ABC8F7BD0EF828B40D3BFC06D12FEC51278ACD32C3B67D4E2A0BBA1E20BDDA06DB9AF6AB250179DE3332EAC0A6D381963B51E8E167B8285BA3E6538B1D38B16B32196ABE009ADFDAF5E686E0107F76ED10414B6249D6895188456505CDB897FFCCEB8931802F87C02DFDC62825C6255DF2654712BE230CC86A30229D9E3438DB35CEED8F8447B9209CDECFC1776D2C43B4B98E9EEA3F4C049C1287CDB4540D395A4BC992602150CCC0479597E221E201B778DCA9701C517C89B95004FC19373ED9755C90FF32C44013678876EAD3FE5E637BF2F1959130EAF79E7A93088F52AA0AC993324294536CF3787C3A3F06F2DC201A070967E6F4525803DC83F5160B560465A4CE4BF20315858BE0E62A07C55B3A772CBF93DE99AADFCB304D2B544A9F17A22C2BEB791D98F714CA7CFF701CB7CAEC55C292A25A147935D7BBD1E66F2ED3EBC66E763209169033CE5A2D9884DC0CBAFF37517372544E1EB780A26CC71E5649EDFD5DA2FCFB58093D74D76FC2DAEC54567104701C31E3872C15BAC5F2A96833EEDAB9B7FF731F827DB3273D271BA8F9DE06181C1E38D031896971D801C571954337D945B1B3DF +20170625075138 2 6 100 6143 2 E30D9BCD65DA0EAEF6A1D4D083834D4724538836AE04DFB6A7DAF235F5D9992B7E42128D43E229BF4906EF0C6A27F60B95A1FC514C2D55A0D616B3B6924F08E9C0BCD8AE1CB624F645785C2AA552C94E125D6602CF63CF52014A1B0A4AE0DE823B03B6ABFA25839ABC3E8E050C295B8B3471EC58EAD9B659294C72EA65229E4E8EB21CA79CBB41BB552118A3CD32108E51D5FCE5C46A6CD03E4246CB57E32BAA09B15503FBFA4F4C943B2378F10EE312C1F12A14010AFD1698B8EBCCFC8D0DF17829A153199154EBF9E40FD81B8E1AF5881D0EC1D3BEDB2D0F1DB9C44C9D8E7047310623D4FAAE28D2C16612CFB9AE9A8FD05B8FE22930346ECF7B21B5800778EA0D5D3B7BDF18B03ABF33C9D0B4648CF687ED229C811CE290CFAF94F9C9AF4EC3E47480955E5C81E85DA9EBCE99652DA07225C7CCEF39E224556E48D6371981C7232E00F3419F7B335FF36FE3989558277654DB356063ABC8F7BD0EF828B40D3BFC06D12FEC51278ACD32C3B67D4E2A0BBA1E20BDDA06DB9AF6AB250179DE3332EAC0A6D381963B51E8E167B8285BA3E6538B1D38B16B32196ABE009ADFDAF5E686E0107F76ED10414B6249D6895188456505CDB897FFCCEB8931802F87C02DFDC62825C6255DF2654712BE230CC86A30229D9E3438DB35CEED8F8447B9209CDECFC1776D2C43B4B98E9EEA3F4C049C1287CDB4540D395A4BC992602150CCC0479597E221E201B778DCA9701C517C89B95004FC19373ED9755C90FF32C44013678876EAD3FE5E637BF2F1959130EAF79E7A93088F52AA0AC993324294536CF3787C3A3F06F2DC201A070967E6F4525803DC83F5160B560465A4CE4BF20315858BE0E62A07C55B3A772CBF93DE99AADFCB304D2B544A9F17A22C2BEB791D98F714CA7CFF701CB7CAEC55C292A25A147935D7BBD1E66F2ED3EBC66E763209169033CE5A2D9884DC0CBAFF37517372544E1EB780A26CC71E5649EDFD5DA2FCFB58093D74D76FC2DAEC54567104701C31E3872C15BAC5F2A96833EEDAB9B7FF731F827DB3273D271BA8F9DE06181C1E38D031896971D801C571954337D9463A10C3 +20170625080610 2 6 100 6143 2 E30D9BCD65DA0EAEF6A1D4D083834D4724538836AE04DFB6A7DAF235F5D9992B7E42128D43E229BF4906EF0C6A27F60B95A1FC514C2D55A0D616B3B6924F08E9C0BCD8AE1CB624F645785C2AA552C94E125D6602CF63CF52014A1B0A4AE0DE823B03B6ABFA25839ABC3E8E050C295B8B3471EC58EAD9B659294C72EA65229E4E8EB21CA79CBB41BB552118A3CD32108E51D5FCE5C46A6CD03E4246CB57E32BAA09B15503FBFA4F4C943B2378F10EE312C1F12A14010AFD1698B8EBCCFC8D0DF17829A153199154EBF9E40FD81B8E1AF5881D0EC1D3BEDB2D0F1DB9C44C9D8E7047310623D4FAAE28D2C16612CFB9AE9A8FD05B8FE22930346ECF7B21B5800778EA0D5D3B7BDF18B03ABF33C9D0B4648CF687ED229C811CE290CFAF94F9C9AF4EC3E47480955E5C81E85DA9EBCE99652DA07225C7CCEF39E224556E48D6371981C7232E00F3419F7B335FF36FE3989558277654DB356063ABC8F7BD0EF828B40D3BFC06D12FEC51278ACD32C3B67D4E2A0BBA1E20BDDA06DB9AF6AB250179DE3332EAC0A6D381963B51E8E167B8285BA3E6538B1D38B16B32196ABE009ADFDAF5E686E0107F76ED10414B6249D6895188456505CDB897FFCCEB8931802F87C02DFDC62825C6255DF2654712BE230CC86A30229D9E3438DB35CEED8F8447B9209CDECFC1776D2C43B4B98E9EEA3F4C049C1287CDB4540D395A4BC992602150CCC0479597E221E201B778DCA9701C517C89B95004FC19373ED9755C90FF32C44013678876EAD3FE5E637BF2F1959130EAF79E7A93088F52AA0AC993324294536CF3787C3A3F06F2DC201A070967E6F4525803DC83F5160B560465A4CE4BF20315858BE0E62A07C55B3A772CBF93DE99AADFCB304D2B544A9F17A22C2BEB791D98F714CA7CFF701CB7CAEC55C292A25A147935D7BBD1E66F2ED3EBC66E763209169033CE5A2D9884DC0CBAFF37517372544E1EB780A26CC71E5649EDFD5DA2FCFB58093D74D76FC2DAEC54567104701C31E3872C15BAC5F2A96833EEDAB9B7FF731F827DB3273D271BA8F9DE06181C1E38D031896971D801C571954337D94691AE5B +20170625112146 2 6 100 6143 2 E30D9BCD65DA0EAEF6A1D4D083834D4724538836AE04DFB6A7DAF235F5D9992B7E42128D43E229BF4906EF0C6A27F60B95A1FC514C2D55A0D616B3B6924F08E9C0BCD8AE1CB624F645785C2AA552C94E125D6602CF63CF52014A1B0A4AE0DE823B03B6ABFA25839ABC3E8E050C295B8B3471EC58EAD9B659294C72EA65229E4E8EB21CA79CBB41BB552118A3CD32108E51D5FCE5C46A6CD03E4246CB57E32BAA09B15503FBFA4F4C943B2378F10EE312C1F12A14010AFD1698B8EBCCFC8D0DF17829A153199154EBF9E40FD81B8E1AF5881D0EC1D3BEDB2D0F1DB9C44C9D8E7047310623D4FAAE28D2C16612CFB9AE9A8FD05B8FE22930346ECF7B21B5800778EA0D5D3B7BDF18B03ABF33C9D0B4648CF687ED229C811CE290CFAF94F9C9AF4EC3E47480955E5C81E85DA9EBCE99652DA07225C7CCEF39E224556E48D6371981C7232E00F3419F7B335FF36FE3989558277654DB356063ABC8F7BD0EF828B40D3BFC06D12FEC51278ACD32C3B67D4E2A0BBA1E20BDDA06DB9AF6AB250179DE3332EAC0A6D381963B51E8E167B8285BA3E6538B1D38B16B32196ABE009ADFDAF5E686E0107F76ED10414B6249D6895188456505CDB897FFCCEB8931802F87C02DFDC62825C6255DF2654712BE230CC86A30229D9E3438DB35CEED8F8447B9209CDECFC1776D2C43B4B98E9EEA3F4C049C1287CDB4540D395A4BC992602150CCC0479597E221E201B778DCA9701C517C89B95004FC19373ED9755C90FF32C44013678876EAD3FE5E637BF2F1959130EAF79E7A93088F52AA0AC993324294536CF3787C3A3F06F2DC201A070967E6F4525803DC83F5160B560465A4CE4BF20315858BE0E62A07C55B3A772CBF93DE99AADFCB304D2B544A9F17A22C2BEB791D98F714CA7CFF701CB7CAEC55C292A25A147935D7BBD1E66F2ED3EBC66E763209169033CE5A2D9884DC0CBAFF37517372544E1EB780A26CC71E5649EDFD5DA2FCFB58093D74D76FC2DAEC54567104701C31E3872C15BAC5F2A96833EEDAB9B7FF731F827DB3273D271BA8F9DE06181C1E38D031896971D801C571954337D94B5B8CDB +20170625113648 2 6 100 6143 5 E30D9BCD65DA0EAEF6A1D4D083834D4724538836AE04DFB6A7DAF235F5D9992B7E42128D43E229BF4906EF0C6A27F60B95A1FC514C2D55A0D616B3B6924F08E9C0BCD8AE1CB624F645785C2AA552C94E125D6602CF63CF52014A1B0A4AE0DE823B03B6ABFA25839ABC3E8E050C295B8B3471EC58EAD9B659294C72EA65229E4E8EB21CA79CBB41BB552118A3CD32108E51D5FCE5C46A6CD03E4246CB57E32BAA09B15503FBFA4F4C943B2378F10EE312C1F12A14010AFD1698B8EBCCFC8D0DF17829A153199154EBF9E40FD81B8E1AF5881D0EC1D3BEDB2D0F1DB9C44C9D8E7047310623D4FAAE28D2C16612CFB9AE9A8FD05B8FE22930346ECF7B21B5800778EA0D5D3B7BDF18B03ABF33C9D0B4648CF687ED229C811CE290CFAF94F9C9AF4EC3E47480955E5C81E85DA9EBCE99652DA07225C7CCEF39E224556E48D6371981C7232E00F3419F7B335FF36FE3989558277654DB356063ABC8F7BD0EF828B40D3BFC06D12FEC51278ACD32C3B67D4E2A0BBA1E20BDDA06DB9AF6AB250179DE3332EAC0A6D381963B51E8E167B8285BA3E6538B1D38B16B32196ABE009ADFDAF5E686E0107F76ED10414B6249D6895188456505CDB897FFCCEB8931802F87C02DFDC62825C6255DF2654712BE230CC86A30229D9E3438DB35CEED8F8447B9209CDECFC1776D2C43B4B98E9EEA3F4C049C1287CDB4540D395A4BC992602150CCC0479597E221E201B778DCA9701C517C89B95004FC19373ED9755C90FF32C44013678876EAD3FE5E637BF2F1959130EAF79E7A93088F52AA0AC993324294536CF3787C3A3F06F2DC201A070967E6F4525803DC83F5160B560465A4CE4BF20315858BE0E62A07C55B3A772CBF93DE99AADFCB304D2B544A9F17A22C2BEB791D98F714CA7CFF701CB7CAEC55C292A25A147935D7BBD1E66F2ED3EBC66E763209169033CE5A2D9884DC0CBAFF37517372544E1EB780A26CC71E5649EDFD5DA2FCFB58093D74D76FC2DAEC54567104701C31E3872C15BAC5F2A96833EEDAB9B7FF731F827DB3273D271BA8F9DE06181C1E38D031896971D801C571954337D94BB43777 +20170625131459 2 6 100 6143 5 E30D9BCD65DA0EAEF6A1D4D083834D4724538836AE04DFB6A7DAF235F5D9992B7E42128D43E229BF4906EF0C6A27F60B95A1FC514C2D55A0D616B3B6924F08E9C0BCD8AE1CB624F645785C2AA552C94E125D6602CF63CF52014A1B0A4AE0DE823B03B6ABFA25839ABC3E8E050C295B8B3471EC58EAD9B659294C72EA65229E4E8EB21CA79CBB41BB552118A3CD32108E51D5FCE5C46A6CD03E4246CB57E32BAA09B15503FBFA4F4C943B2378F10EE312C1F12A14010AFD1698B8EBCCFC8D0DF17829A153199154EBF9E40FD81B8E1AF5881D0EC1D3BEDB2D0F1DB9C44C9D8E7047310623D4FAAE28D2C16612CFB9AE9A8FD05B8FE22930346ECF7B21B5800778EA0D5D3B7BDF18B03ABF33C9D0B4648CF687ED229C811CE290CFAF94F9C9AF4EC3E47480955E5C81E85DA9EBCE99652DA07225C7CCEF39E224556E48D6371981C7232E00F3419F7B335FF36FE3989558277654DB356063ABC8F7BD0EF828B40D3BFC06D12FEC51278ACD32C3B67D4E2A0BBA1E20BDDA06DB9AF6AB250179DE3332EAC0A6D381963B51E8E167B8285BA3E6538B1D38B16B32196ABE009ADFDAF5E686E0107F76ED10414B6249D6895188456505CDB897FFCCEB8931802F87C02DFDC62825C6255DF2654712BE230CC86A30229D9E3438DB35CEED8F8447B9209CDECFC1776D2C43B4B98E9EEA3F4C049C1287CDB4540D395A4BC992602150CCC0479597E221E201B778DCA9701C517C89B95004FC19373ED9755C90FF32C44013678876EAD3FE5E637BF2F1959130EAF79E7A93088F52AA0AC993324294536CF3787C3A3F06F2DC201A070967E6F4525803DC83F5160B560465A4CE4BF20315858BE0E62A07C55B3A772CBF93DE99AADFCB304D2B544A9F17A22C2BEB791D98F714CA7CFF701CB7CAEC55C292A25A147935D7BBD1E66F2ED3EBC66E763209169033CE5A2D9884DC0CBAFF37517372544E1EB780A26CC71E5649EDFD5DA2FCFB58093D74D76FC2DAEC54567104701C31E3872C15BAC5F2A96833EEDAB9B7FF731F827DB3273D271BA8F9DE06181C1E38D031896971D801C571954337D94E2020A7 +20170625141110 2 6 100 6143 5 E30D9BCD65DA0EAEF6A1D4D083834D4724538836AE04DFB6A7DAF235F5D9992B7E42128D43E229BF4906EF0C6A27F60B95A1FC514C2D55A0D616B3B6924F08E9C0BCD8AE1CB624F645785C2AA552C94E125D6602CF63CF52014A1B0A4AE0DE823B03B6ABFA25839ABC3E8E050C295B8B3471EC58EAD9B659294C72EA65229E4E8EB21CA79CBB41BB552118A3CD32108E51D5FCE5C46A6CD03E4246CB57E32BAA09B15503FBFA4F4C943B2378F10EE312C1F12A14010AFD1698B8EBCCFC8D0DF17829A153199154EBF9E40FD81B8E1AF5881D0EC1D3BEDB2D0F1DB9C44C9D8E7047310623D4FAAE28D2C16612CFB9AE9A8FD05B8FE22930346ECF7B21B5800778EA0D5D3B7BDF18B03ABF33C9D0B4648CF687ED229C811CE290CFAF94F9C9AF4EC3E47480955E5C81E85DA9EBCE99652DA07225C7CCEF39E224556E48D6371981C7232E00F3419F7B335FF36FE3989558277654DB356063ABC8F7BD0EF828B40D3BFC06D12FEC51278ACD32C3B67D4E2A0BBA1E20BDDA06DB9AF6AB250179DE3332EAC0A6D381963B51E8E167B8285BA3E6538B1D38B16B32196ABE009ADFDAF5E686E0107F76ED10414B6249D6895188456505CDB897FFCCEB8931802F87C02DFDC62825C6255DF2654712BE230CC86A30229D9E3438DB35CEED8F8447B9209CDECFC1776D2C43B4B98E9EEA3F4C049C1287CDB4540D395A4BC992602150CCC0479597E221E201B778DCA9701C517C89B95004FC19373ED9755C90FF32C44013678876EAD3FE5E637BF2F1959130EAF79E7A93088F52AA0AC993324294536CF3787C3A3F06F2DC201A070967E6F4525803DC83F5160B560465A4CE4BF20315858BE0E62A07C55B3A772CBF93DE99AADFCB304D2B544A9F17A22C2BEB791D98F714CA7CFF701CB7CAEC55C292A25A147935D7BBD1E66F2ED3EBC66E763209169033CE5A2D9884DC0CBAFF37517372544E1EB780A26CC71E5649EDFD5DA2FCFB58093D74D76FC2DAEC54567104701C31E3872C15BAC5F2A96833EEDAB9B7FF731F827DB3273D271BA8F9DE06181C1E38D031896971D801C571954337D94F7F2B87 +20170625144415 2 6 100 6143 2 E30D9BCD65DA0EAEF6A1D4D083834D4724538836AE04DFB6A7DAF235F5D9992B7E42128D43E229BF4906EF0C6A27F60B95A1FC514C2D55A0D616B3B6924F08E9C0BCD8AE1CB624F645785C2AA552C94E125D6602CF63CF52014A1B0A4AE0DE823B03B6ABFA25839ABC3E8E050C295B8B3471EC58EAD9B659294C72EA65229E4E8EB21CA79CBB41BB552118A3CD32108E51D5FCE5C46A6CD03E4246CB57E32BAA09B15503FBFA4F4C943B2378F10EE312C1F12A14010AFD1698B8EBCCFC8D0DF17829A153199154EBF9E40FD81B8E1AF5881D0EC1D3BEDB2D0F1DB9C44C9D8E7047310623D4FAAE28D2C16612CFB9AE9A8FD05B8FE22930346ECF7B21B5800778EA0D5D3B7BDF18B03ABF33C9D0B4648CF687ED229C811CE290CFAF94F9C9AF4EC3E47480955E5C81E85DA9EBCE99652DA07225C7CCEF39E224556E48D6371981C7232E00F3419F7B335FF36FE3989558277654DB356063ABC8F7BD0EF828B40D3BFC06D12FEC51278ACD32C3B67D4E2A0BBA1E20BDDA06DB9AF6AB250179DE3332EAC0A6D381963B51E8E167B8285BA3E6538B1D38B16B32196ABE009ADFDAF5E686E0107F76ED10414B6249D6895188456505CDB897FFCCEB8931802F87C02DFDC62825C6255DF2654712BE230CC86A30229D9E3438DB35CEED8F8447B9209CDECFC1776D2C43B4B98E9EEA3F4C049C1287CDB4540D395A4BC992602150CCC0479597E221E201B778DCA9701C517C89B95004FC19373ED9755C90FF32C44013678876EAD3FE5E637BF2F1959130EAF79E7A93088F52AA0AC993324294536CF3787C3A3F06F2DC201A070967E6F4525803DC83F5160B560465A4CE4BF20315858BE0E62A07C55B3A772CBF93DE99AADFCB304D2B544A9F17A22C2BEB791D98F714CA7CFF701CB7CAEC55C292A25A147935D7BBD1E66F2ED3EBC66E763209169033CE5A2D9884DC0CBAFF37517372544E1EB780A26CC71E5649EDFD5DA2FCFB58093D74D76FC2DAEC54567104701C31E3872C15BAC5F2A96833EEDAB9B7FF731F827DB3273D271BA8F9DE06181C1E38D031896971D801C571954337D9504A46D3 +20170625145639 2 6 100 6143 5 E30D9BCD65DA0EAEF6A1D4D083834D4724538836AE04DFB6A7DAF235F5D9992B7E42128D43E229BF4906EF0C6A27F60B95A1FC514C2D55A0D616B3B6924F08E9C0BCD8AE1CB624F645785C2AA552C94E125D6602CF63CF52014A1B0A4AE0DE823B03B6ABFA25839ABC3E8E050C295B8B3471EC58EAD9B659294C72EA65229E4E8EB21CA79CBB41BB552118A3CD32108E51D5FCE5C46A6CD03E4246CB57E32BAA09B15503FBFA4F4C943B2378F10EE312C1F12A14010AFD1698B8EBCCFC8D0DF17829A153199154EBF9E40FD81B8E1AF5881D0EC1D3BEDB2D0F1DB9C44C9D8E7047310623D4FAAE28D2C16612CFB9AE9A8FD05B8FE22930346ECF7B21B5800778EA0D5D3B7BDF18B03ABF33C9D0B4648CF687ED229C811CE290CFAF94F9C9AF4EC3E47480955E5C81E85DA9EBCE99652DA07225C7CCEF39E224556E48D6371981C7232E00F3419F7B335FF36FE3989558277654DB356063ABC8F7BD0EF828B40D3BFC06D12FEC51278ACD32C3B67D4E2A0BBA1E20BDDA06DB9AF6AB250179DE3332EAC0A6D381963B51E8E167B8285BA3E6538B1D38B16B32196ABE009ADFDAF5E686E0107F76ED10414B6249D6895188456505CDB897FFCCEB8931802F87C02DFDC62825C6255DF2654712BE230CC86A30229D9E3438DB35CEED8F8447B9209CDECFC1776D2C43B4B98E9EEA3F4C049C1287CDB4540D395A4BC992602150CCC0479597E221E201B778DCA9701C517C89B95004FC19373ED9755C90FF32C44013678876EAD3FE5E637BF2F1959130EAF79E7A93088F52AA0AC993324294536CF3787C3A3F06F2DC201A070967E6F4525803DC83F5160B560465A4CE4BF20315858BE0E62A07C55B3A772CBF93DE99AADFCB304D2B544A9F17A22C2BEB791D98F714CA7CFF701CB7CAEC55C292A25A147935D7BBD1E66F2ED3EBC66E763209169033CE5A2D9884DC0CBAFF37517372544E1EB780A26CC71E5649EDFD5DA2FCFB58093D74D76FC2DAEC54567104701C31E3872C15BAC5F2A96833EEDAB9B7FF731F827DB3273D271BA8F9DE06181C1E38D031896971D801C571954337D9508CDF97 +20170625203254 2 6 100 6143 2 E30D9BCD65DA0EAEF6A1D4D083834D4724538836AE04DFB6A7DAF235F5D9992B7E42128D43E229BF4906EF0C6A27F60B95A1FC514C2D55A0D616B3B6924F08E9C0BCD8AE1CB624F645785C2AA552C94E125D6602CF63CF52014A1B0A4AE0DE823B03B6ABFA25839ABC3E8E050C295B8B3471EC58EAD9B659294C72EA65229E4E8EB21CA79CBB41BB552118A3CD32108E51D5FCE5C46A6CD03E4246CB57E32BAA09B15503FBFA4F4C943B2378F10EE312C1F12A14010AFD1698B8EBCCFC8D0DF17829A153199154EBF9E40FD81B8E1AF5881D0EC1D3BEDB2D0F1DB9C44C9D8E7047310623D4FAAE28D2C16612CFB9AE9A8FD05B8FE22930346ECF7B21B5800778EA0D5D3B7BDF18B03ABF33C9D0B4648CF687ED229C811CE290CFAF94F9C9AF4EC3E47480955E5C81E85DA9EBCE99652DA07225C7CCEF39E224556E48D6371981C7232E00F3419F7B335FF36FE3989558277654DB356063ABC8F7BD0EF828B40D3BFC06D12FEC51278ACD32C3B67D4E2A0BBA1E20BDDA06DB9AF6AB250179DE3332EAC0A6D381963B51E8E167B8285BA3E6538B1D38B16B32196ABE009ADFDAF5E686E0107F76ED10414B6249D6895188456505CDB897FFCCEB8931802F87C02DFDC62825C6255DF2654712BE230CC86A30229D9E3438DB35CEED8F8447B9209CDECFC1776D2C43B4B98E9EEA3F4C049C1287CDB4540D395A4BC992602150CCC0479597E221E201B778DCA9701C517C89B95004FC19373ED9755C90FF32C44013678876EAD3FE5E637BF2F1959130EAF79E7A93088F52AA0AC993324294536CF3787C3A3F06F2DC201A070967E6F4525803DC83F5160B560465A4CE4BF20315858BE0E62A07C55B3A772CBF93DE99AADFCB304D2B544A9F17A22C2BEB791D98F714CA7CFF701CB7CAEC55C292A25A147935D7BBD1E66F2ED3EBC66E763209169033CE5A2D9884DC0CBAFF37517372544E1EB780A26CC71E5649EDFD5DA2FCFB58093D74D76FC2DAEC54567104701C31E3872C15BAC5F2A96833EEDAB9B7FF731F827DB3273D271BA8F9DE06181C1E38D031896971D801C571954337D958CDC1DB +20170625215049 2 6 100 6143 2 E30D9BCD65DA0EAEF6A1D4D083834D4724538836AE04DFB6A7DAF235F5D9992B7E42128D43E229BF4906EF0C6A27F60B95A1FC514C2D55A0D616B3B6924F08E9C0BCD8AE1CB624F645785C2AA552C94E125D6602CF63CF52014A1B0A4AE0DE823B03B6ABFA25839ABC3E8E050C295B8B3471EC58EAD9B659294C72EA65229E4E8EB21CA79CBB41BB552118A3CD32108E51D5FCE5C46A6CD03E4246CB57E32BAA09B15503FBFA4F4C943B2378F10EE312C1F12A14010AFD1698B8EBCCFC8D0DF17829A153199154EBF9E40FD81B8E1AF5881D0EC1D3BEDB2D0F1DB9C44C9D8E7047310623D4FAAE28D2C16612CFB9AE9A8FD05B8FE22930346ECF7B21B5800778EA0D5D3B7BDF18B03ABF33C9D0B4648CF687ED229C811CE290CFAF94F9C9AF4EC3E47480955E5C81E85DA9EBCE99652DA07225C7CCEF39E224556E48D6371981C7232E00F3419F7B335FF36FE3989558277654DB356063ABC8F7BD0EF828B40D3BFC06D12FEC51278ACD32C3B67D4E2A0BBA1E20BDDA06DB9AF6AB250179DE3332EAC0A6D381963B51E8E167B8285BA3E6538B1D38B16B32196ABE009ADFDAF5E686E0107F76ED10414B6249D6895188456505CDB897FFCCEB8931802F87C02DFDC62825C6255DF2654712BE230CC86A30229D9E3438DB35CEED8F8447B9209CDECFC1776D2C43B4B98E9EEA3F4C049C1287CDB4540D395A4BC992602150CCC0479597E221E201B778DCA9701C517C89B95004FC19373ED9755C90FF32C44013678876EAD3FE5E637BF2F1959130EAF79E7A93088F52AA0AC993324294536CF3787C3A3F06F2DC201A070967E6F4525803DC83F5160B560465A4CE4BF20315858BE0E62A07C55B3A772CBF93DE99AADFCB304D2B544A9F17A22C2BEB791D98F714CA7CFF701CB7CAEC55C292A25A147935D7BBD1E66F2ED3EBC66E763209169033CE5A2D9884DC0CBAFF37517372544E1EB780A26CC71E5649EDFD5DA2FCFB58093D74D76FC2DAEC54567104701C31E3872C15BAC5F2A96833EEDAB9B7FF731F827DB3273D271BA8F9DE06181C1E38D031896971D801C571954337D95AA6BE13 +20170625220255 2 6 100 6143 5 E30D9BCD65DA0EAEF6A1D4D083834D4724538836AE04DFB6A7DAF235F5D9992B7E42128D43E229BF4906EF0C6A27F60B95A1FC514C2D55A0D616B3B6924F08E9C0BCD8AE1CB624F645785C2AA552C94E125D6602CF63CF52014A1B0A4AE0DE823B03B6ABFA25839ABC3E8E050C295B8B3471EC58EAD9B659294C72EA65229E4E8EB21CA79CBB41BB552118A3CD32108E51D5FCE5C46A6CD03E4246CB57E32BAA09B15503FBFA4F4C943B2378F10EE312C1F12A14010AFD1698B8EBCCFC8D0DF17829A153199154EBF9E40FD81B8E1AF5881D0EC1D3BEDB2D0F1DB9C44C9D8E7047310623D4FAAE28D2C16612CFB9AE9A8FD05B8FE22930346ECF7B21B5800778EA0D5D3B7BDF18B03ABF33C9D0B4648CF687ED229C811CE290CFAF94F9C9AF4EC3E47480955E5C81E85DA9EBCE99652DA07225C7CCEF39E224556E48D6371981C7232E00F3419F7B335FF36FE3989558277654DB356063ABC8F7BD0EF828B40D3BFC06D12FEC51278ACD32C3B67D4E2A0BBA1E20BDDA06DB9AF6AB250179DE3332EAC0A6D381963B51E8E167B8285BA3E6538B1D38B16B32196ABE009ADFDAF5E686E0107F76ED10414B6249D6895188456505CDB897FFCCEB8931802F87C02DFDC62825C6255DF2654712BE230CC86A30229D9E3438DB35CEED8F8447B9209CDECFC1776D2C43B4B98E9EEA3F4C049C1287CDB4540D395A4BC992602150CCC0479597E221E201B778DCA9701C517C89B95004FC19373ED9755C90FF32C44013678876EAD3FE5E637BF2F1959130EAF79E7A93088F52AA0AC993324294536CF3787C3A3F06F2DC201A070967E6F4525803DC83F5160B560465A4CE4BF20315858BE0E62A07C55B3A772CBF93DE99AADFCB304D2B544A9F17A22C2BEB791D98F714CA7CFF701CB7CAEC55C292A25A147935D7BBD1E66F2ED3EBC66E763209169033CE5A2D9884DC0CBAFF37517372544E1EB780A26CC71E5649EDFD5DA2FCFB58093D74D76FC2DAEC54567104701C31E3872C15BAC5F2A96833EEDAB9B7FF731F827DB3273D271BA8F9DE06181C1E38D031896971D801C571954337D95AE8D4FF +20170626000351 2 6 100 6143 2 FE3AFB7EA9CBCB633757EA982ED0DDFF120459E69D35DB36ACC5F69B04A5CCEE59A0312A97687F2B3DBC20917F4BF0B16D97B75EDCA16B58BDEB8BB1A726F6CB8BF5D7FC483777129A1C19CB559943EF201323760672C63859E830C6E99AFE5DD7A4E89BAD41C63B687558DD277F4E06A29D1E14A21CAA6FDD4E6F21EB8B146F2C04F93B1C94234E6295F2F8773B16BA3D51758841EA48ADD1A626E252DB3B78594B4586AC9E9EAF100F294ADC82BEBBF8CAB96B671EE7050B42733EB741107C5D2199D305C84F93C6AEEE6BD607DB7C0EFED773FB1DB73B04EFA72EB36111B99EBE6EEE899307FD288329FB2DB7E81776AEF0F935FFEE77611BDCFEC309F97EEB6E36FE42CA4C8EFAA0B4B93F5D83606B8FA7B49DD1DBB8F828B9C805381CB5DF4AC7FFAE27C62CBCD2FE80BB4157EB7F3267041255AC2F7EA3B450951878166049E5FF1BD3B361082FB184E342DDA1961ACFD90944F37E09A06AFE463AA9AA66EE699D28C4D109F3E8111CF4D625161B2855C11593AE408AE44DC026091119744FF09A4AB3C00717ACA004E26ACA53BF6444D839CF477A56FEAFFBF2E4CB946512815269D8E3C163FC29288A917A4A0ACC6DF54454CE2D54AC79AE05BF816DE1E3E9D3A9CC69DBE674880F98ECB8D8D4C4247AC07BC9B7C40FB89C4B9D4DA4604B37D15047DFB28C5D241CDFA327C3996872A0C05B84342F81A308D7796CA4A4038E47A5D4658F757C3F9645F11DEA92AE4D2E77FDB1A5D12519FF947F39A68152528CB02F915894D728C0E755B8BC4A99FCFC778A4099558A06D5FECC4C22DAA7E23C3B5E8E99B5365D5046C8C65846D949A521C0B25EFE5F5CD0845F09C29C096C4A80755120A299EA652B204775E53B2D521F366F4EF9FA65B1D8CB048295C39BE92667200E2889B1577CBD0AC23B2280B758A3650BE60D55F215DBF166873592253B1254968B5A46A61C792A153342C3ADE408676F4B27B7F22C50B079D0E32AEA134168A53A36F18E2FFA2459EDBA89BEC13D19C342235F6E9CF8F721B608F6297A3486173A7D5CED5E2AF6343775668C1B1FB0B745157973A06777EB +20170626010044 2 6 100 6143 2 FE3AFB7EA9CBCB633757EA982ED0DDFF120459E69D35DB36ACC5F69B04A5CCEE59A0312A97687F2B3DBC20917F4BF0B16D97B75EDCA16B58BDEB8BB1A726F6CB8BF5D7FC483777129A1C19CB559943EF201323760672C63859E830C6E99AFE5DD7A4E89BAD41C63B687558DD277F4E06A29D1E14A21CAA6FDD4E6F21EB8B146F2C04F93B1C94234E6295F2F8773B16BA3D51758841EA48ADD1A626E252DB3B78594B4586AC9E9EAF100F294ADC82BEBBF8CAB96B671EE7050B42733EB741107C5D2199D305C84F93C6AEEE6BD607DB7C0EFED773FB1DB73B04EFA72EB36111B99EBE6EEE899307FD288329FB2DB7E81776AEF0F935FFEE77611BDCFEC309F97EEB6E36FE42CA4C8EFAA0B4B93F5D83606B8FA7B49DD1DBB8F828B9C805381CB5DF4AC7FFAE27C62CBCD2FE80BB4157EB7F3267041255AC2F7EA3B450951878166049E5FF1BD3B361082FB184E342DDA1961ACFD90944F37E09A06AFE463AA9AA66EE699D28C4D109F3E8111CF4D625161B2855C11593AE408AE44DC026091119744FF09A4AB3C00717ACA004E26ACA53BF6444D839CF477A56FEAFFBF2E4CB946512815269D8E3C163FC29288A917A4A0ACC6DF54454CE2D54AC79AE05BF816DE1E3E9D3A9CC69DBE674880F98ECB8D8D4C4247AC07BC9B7C40FB89C4B9D4DA4604B37D15047DFB28C5D241CDFA327C3996872A0C05B84342F81A308D7796CA4A4038E47A5D4658F757C3F9645F11DEA92AE4D2E77FDB1A5D12519FF947F39A68152528CB02F915894D728C0E755B8BC4A99FCFC778A4099558A06D5FECC4C22DAA7E23C3B5E8E99B5365D5046C8C65846D949A521C0B25EFE5F5CD0845F09C29C096C4A80755120A299EA652B204775E53B2D521F366F4EF9FA65B1D8CB048295C39BE92667200E2889B1577CBD0AC23B2280B758A3650BE60D55F215DBF166873592253B1254968B5A46A61C792A153342C3ADE408676F4B27B7F22C50B079D0E32AEA134168A53A36F18E2FFA2459EDBA89BEC13D19C342235F6E9CF8F721B608F6297A3486173A7D5CED5E2AF6343775668C1B1FB0B745157973A1E685DB +20170626011405 2 6 100 6143 2 FE3AFB7EA9CBCB633757EA982ED0DDFF120459E69D35DB36ACC5F69B04A5CCEE59A0312A97687F2B3DBC20917F4BF0B16D97B75EDCA16B58BDEB8BB1A726F6CB8BF5D7FC483777129A1C19CB559943EF201323760672C63859E830C6E99AFE5DD7A4E89BAD41C63B687558DD277F4E06A29D1E14A21CAA6FDD4E6F21EB8B146F2C04F93B1C94234E6295F2F8773B16BA3D51758841EA48ADD1A626E252DB3B78594B4586AC9E9EAF100F294ADC82BEBBF8CAB96B671EE7050B42733EB741107C5D2199D305C84F93C6AEEE6BD607DB7C0EFED773FB1DB73B04EFA72EB36111B99EBE6EEE899307FD288329FB2DB7E81776AEF0F935FFEE77611BDCFEC309F97EEB6E36FE42CA4C8EFAA0B4B93F5D83606B8FA7B49DD1DBB8F828B9C805381CB5DF4AC7FFAE27C62CBCD2FE80BB4157EB7F3267041255AC2F7EA3B450951878166049E5FF1BD3B361082FB184E342DDA1961ACFD90944F37E09A06AFE463AA9AA66EE699D28C4D109F3E8111CF4D625161B2855C11593AE408AE44DC026091119744FF09A4AB3C00717ACA004E26ACA53BF6444D839CF477A56FEAFFBF2E4CB946512815269D8E3C163FC29288A917A4A0ACC6DF54454CE2D54AC79AE05BF816DE1E3E9D3A9CC69DBE674880F98ECB8D8D4C4247AC07BC9B7C40FB89C4B9D4DA4604B37D15047DFB28C5D241CDFA327C3996872A0C05B84342F81A308D7796CA4A4038E47A5D4658F757C3F9645F11DEA92AE4D2E77FDB1A5D12519FF947F39A68152528CB02F915894D728C0E755B8BC4A99FCFC778A4099558A06D5FECC4C22DAA7E23C3B5E8E99B5365D5046C8C65846D949A521C0B25EFE5F5CD0845F09C29C096C4A80755120A299EA652B204775E53B2D521F366F4EF9FA65B1D8CB048295C39BE92667200E2889B1577CBD0AC23B2280B758A3650BE60D55F215DBF166873592253B1254968B5A46A61C792A153342C3ADE408676F4B27B7F22C50B079D0E32AEA134168A53A36F18E2FFA2459EDBA89BEC13D19C342235F6E9CF8F721B608F6297A3486173A7D5CED5E2AF6343775668C1B1FB0B745157973A237A0AB +20170626020723 2 6 100 6143 2 FE3AFB7EA9CBCB633757EA982ED0DDFF120459E69D35DB36ACC5F69B04A5CCEE59A0312A97687F2B3DBC20917F4BF0B16D97B75EDCA16B58BDEB8BB1A726F6CB8BF5D7FC483777129A1C19CB559943EF201323760672C63859E830C6E99AFE5DD7A4E89BAD41C63B687558DD277F4E06A29D1E14A21CAA6FDD4E6F21EB8B146F2C04F93B1C94234E6295F2F8773B16BA3D51758841EA48ADD1A626E252DB3B78594B4586AC9E9EAF100F294ADC82BEBBF8CAB96B671EE7050B42733EB741107C5D2199D305C84F93C6AEEE6BD607DB7C0EFED773FB1DB73B04EFA72EB36111B99EBE6EEE899307FD288329FB2DB7E81776AEF0F935FFEE77611BDCFEC309F97EEB6E36FE42CA4C8EFAA0B4B93F5D83606B8FA7B49DD1DBB8F828B9C805381CB5DF4AC7FFAE27C62CBCD2FE80BB4157EB7F3267041255AC2F7EA3B450951878166049E5FF1BD3B361082FB184E342DDA1961ACFD90944F37E09A06AFE463AA9AA66EE699D28C4D109F3E8111CF4D625161B2855C11593AE408AE44DC026091119744FF09A4AB3C00717ACA004E26ACA53BF6444D839CF477A56FEAFFBF2E4CB946512815269D8E3C163FC29288A917A4A0ACC6DF54454CE2D54AC79AE05BF816DE1E3E9D3A9CC69DBE674880F98ECB8D8D4C4247AC07BC9B7C40FB89C4B9D4DA4604B37D15047DFB28C5D241CDFA327C3996872A0C05B84342F81A308D7796CA4A4038E47A5D4658F757C3F9645F11DEA92AE4D2E77FDB1A5D12519FF947F39A68152528CB02F915894D728C0E755B8BC4A99FCFC778A4099558A06D5FECC4C22DAA7E23C3B5E8E99B5365D5046C8C65846D949A521C0B25EFE5F5CD0845F09C29C096C4A80755120A299EA652B204775E53B2D521F366F4EF9FA65B1D8CB048295C39BE92667200E2889B1577CBD0AC23B2280B758A3650BE60D55F215DBF166873592253B1254968B5A46A61C792A153342C3ADE408676F4B27B7F22C50B079D0E32AEA134168A53A36F18E2FFA2459EDBA89BEC13D19C342235F6E9CF8F721B608F6297A3486173A7D5CED5E2AF6343775668C1B1FB0B745157973A39C76DB +20170626021405 2 6 100 6143 5 FE3AFB7EA9CBCB633757EA982ED0DDFF120459E69D35DB36ACC5F69B04A5CCEE59A0312A97687F2B3DBC20917F4BF0B16D97B75EDCA16B58BDEB8BB1A726F6CB8BF5D7FC483777129A1C19CB559943EF201323760672C63859E830C6E99AFE5DD7A4E89BAD41C63B687558DD277F4E06A29D1E14A21CAA6FDD4E6F21EB8B146F2C04F93B1C94234E6295F2F8773B16BA3D51758841EA48ADD1A626E252DB3B78594B4586AC9E9EAF100F294ADC82BEBBF8CAB96B671EE7050B42733EB741107C5D2199D305C84F93C6AEEE6BD607DB7C0EFED773FB1DB73B04EFA72EB36111B99EBE6EEE899307FD288329FB2DB7E81776AEF0F935FFEE77611BDCFEC309F97EEB6E36FE42CA4C8EFAA0B4B93F5D83606B8FA7B49DD1DBB8F828B9C805381CB5DF4AC7FFAE27C62CBCD2FE80BB4157EB7F3267041255AC2F7EA3B450951878166049E5FF1BD3B361082FB184E342DDA1961ACFD90944F37E09A06AFE463AA9AA66EE699D28C4D109F3E8111CF4D625161B2855C11593AE408AE44DC026091119744FF09A4AB3C00717ACA004E26ACA53BF6444D839CF477A56FEAFFBF2E4CB946512815269D8E3C163FC29288A917A4A0ACC6DF54454CE2D54AC79AE05BF816DE1E3E9D3A9CC69DBE674880F98ECB8D8D4C4247AC07BC9B7C40FB89C4B9D4DA4604B37D15047DFB28C5D241CDFA327C3996872A0C05B84342F81A308D7796CA4A4038E47A5D4658F757C3F9645F11DEA92AE4D2E77FDB1A5D12519FF947F39A68152528CB02F915894D728C0E755B8BC4A99FCFC778A4099558A06D5FECC4C22DAA7E23C3B5E8E99B5365D5046C8C65846D949A521C0B25EFE5F5CD0845F09C29C096C4A80755120A299EA652B204775E53B2D521F366F4EF9FA65B1D8CB048295C39BE92667200E2889B1577CBD0AC23B2280B758A3650BE60D55F215DBF166873592253B1254968B5A46A61C792A153342C3ADE408676F4B27B7F22C50B079D0E32AEA134168A53A36F18E2FFA2459EDBA89BEC13D19C342235F6E9CF8F721B608F6297A3486173A7D5CED5E2AF6343775668C1B1FB0B745157973A3C0D837 +20170626025354 2 6 100 6143 2 FE3AFB7EA9CBCB633757EA982ED0DDFF120459E69D35DB36ACC5F69B04A5CCEE59A0312A97687F2B3DBC20917F4BF0B16D97B75EDCA16B58BDEB8BB1A726F6CB8BF5D7FC483777129A1C19CB559943EF201323760672C63859E830C6E99AFE5DD7A4E89BAD41C63B687558DD277F4E06A29D1E14A21CAA6FDD4E6F21EB8B146F2C04F93B1C94234E6295F2F8773B16BA3D51758841EA48ADD1A626E252DB3B78594B4586AC9E9EAF100F294ADC82BEBBF8CAB96B671EE7050B42733EB741107C5D2199D305C84F93C6AEEE6BD607DB7C0EFED773FB1DB73B04EFA72EB36111B99EBE6EEE899307FD288329FB2DB7E81776AEF0F935FFEE77611BDCFEC309F97EEB6E36FE42CA4C8EFAA0B4B93F5D83606B8FA7B49DD1DBB8F828B9C805381CB5DF4AC7FFAE27C62CBCD2FE80BB4157EB7F3267041255AC2F7EA3B450951878166049E5FF1BD3B361082FB184E342DDA1961ACFD90944F37E09A06AFE463AA9AA66EE699D28C4D109F3E8111CF4D625161B2855C11593AE408AE44DC026091119744FF09A4AB3C00717ACA004E26ACA53BF6444D839CF477A56FEAFFBF2E4CB946512815269D8E3C163FC29288A917A4A0ACC6DF54454CE2D54AC79AE05BF816DE1E3E9D3A9CC69DBE674880F98ECB8D8D4C4247AC07BC9B7C40FB89C4B9D4DA4604B37D15047DFB28C5D241CDFA327C3996872A0C05B84342F81A308D7796CA4A4038E47A5D4658F757C3F9645F11DEA92AE4D2E77FDB1A5D12519FF947F39A68152528CB02F915894D728C0E755B8BC4A99FCFC778A4099558A06D5FECC4C22DAA7E23C3B5E8E99B5365D5046C8C65846D949A521C0B25EFE5F5CD0845F09C29C096C4A80755120A299EA652B204775E53B2D521F366F4EF9FA65B1D8CB048295C39BE92667200E2889B1577CBD0AC23B2280B758A3650BE60D55F215DBF166873592253B1254968B5A46A61C792A153342C3ADE408676F4B27B7F22C50B079D0E32AEA134168A53A36F18E2FFA2459EDBA89BEC13D19C342235F6E9CF8F721B608F6297A3486173A7D5CED5E2AF6343775668C1B1FB0B745157973A4CB1E73 +20170626025848 2 6 100 6143 5 FE3AFB7EA9CBCB633757EA982ED0DDFF120459E69D35DB36ACC5F69B04A5CCEE59A0312A97687F2B3DBC20917F4BF0B16D97B75EDCA16B58BDEB8BB1A726F6CB8BF5D7FC483777129A1C19CB559943EF201323760672C63859E830C6E99AFE5DD7A4E89BAD41C63B687558DD277F4E06A29D1E14A21CAA6FDD4E6F21EB8B146F2C04F93B1C94234E6295F2F8773B16BA3D51758841EA48ADD1A626E252DB3B78594B4586AC9E9EAF100F294ADC82BEBBF8CAB96B671EE7050B42733EB741107C5D2199D305C84F93C6AEEE6BD607DB7C0EFED773FB1DB73B04EFA72EB36111B99EBE6EEE899307FD288329FB2DB7E81776AEF0F935FFEE77611BDCFEC309F97EEB6E36FE42CA4C8EFAA0B4B93F5D83606B8FA7B49DD1DBB8F828B9C805381CB5DF4AC7FFAE27C62CBCD2FE80BB4157EB7F3267041255AC2F7EA3B450951878166049E5FF1BD3B361082FB184E342DDA1961ACFD90944F37E09A06AFE463AA9AA66EE699D28C4D109F3E8111CF4D625161B2855C11593AE408AE44DC026091119744FF09A4AB3C00717ACA004E26ACA53BF6444D839CF477A56FEAFFBF2E4CB946512815269D8E3C163FC29288A917A4A0ACC6DF54454CE2D54AC79AE05BF816DE1E3E9D3A9CC69DBE674880F98ECB8D8D4C4247AC07BC9B7C40FB89C4B9D4DA4604B37D15047DFB28C5D241CDFA327C3996872A0C05B84342F81A308D7796CA4A4038E47A5D4658F757C3F9645F11DEA92AE4D2E77FDB1A5D12519FF947F39A68152528CB02F915894D728C0E755B8BC4A99FCFC778A4099558A06D5FECC4C22DAA7E23C3B5E8E99B5365D5046C8C65846D949A521C0B25EFE5F5CD0845F09C29C096C4A80755120A299EA652B204775E53B2D521F366F4EF9FA65B1D8CB048295C39BE92667200E2889B1577CBD0AC23B2280B758A3650BE60D55F215DBF166873592253B1254968B5A46A61C792A153342C3ADE408676F4B27B7F22C50B079D0E32AEA134168A53A36F18E2FFA2459EDBA89BEC13D19C342235F6E9CF8F721B608F6297A3486173A7D5CED5E2AF6343775668C1B1FB0B745157973A4E33427 +20170626034407 2 6 100 6143 5 FE3AFB7EA9CBCB633757EA982ED0DDFF120459E69D35DB36ACC5F69B04A5CCEE59A0312A97687F2B3DBC20917F4BF0B16D97B75EDCA16B58BDEB8BB1A726F6CB8BF5D7FC483777129A1C19CB559943EF201323760672C63859E830C6E99AFE5DD7A4E89BAD41C63B687558DD277F4E06A29D1E14A21CAA6FDD4E6F21EB8B146F2C04F93B1C94234E6295F2F8773B16BA3D51758841EA48ADD1A626E252DB3B78594B4586AC9E9EAF100F294ADC82BEBBF8CAB96B671EE7050B42733EB741107C5D2199D305C84F93C6AEEE6BD607DB7C0EFED773FB1DB73B04EFA72EB36111B99EBE6EEE899307FD288329FB2DB7E81776AEF0F935FFEE77611BDCFEC309F97EEB6E36FE42CA4C8EFAA0B4B93F5D83606B8FA7B49DD1DBB8F828B9C805381CB5DF4AC7FFAE27C62CBCD2FE80BB4157EB7F3267041255AC2F7EA3B450951878166049E5FF1BD3B361082FB184E342DDA1961ACFD90944F37E09A06AFE463AA9AA66EE699D28C4D109F3E8111CF4D625161B2855C11593AE408AE44DC026091119744FF09A4AB3C00717ACA004E26ACA53BF6444D839CF477A56FEAFFBF2E4CB946512815269D8E3C163FC29288A917A4A0ACC6DF54454CE2D54AC79AE05BF816DE1E3E9D3A9CC69DBE674880F98ECB8D8D4C4247AC07BC9B7C40FB89C4B9D4DA4604B37D15047DFB28C5D241CDFA327C3996872A0C05B84342F81A308D7796CA4A4038E47A5D4658F757C3F9645F11DEA92AE4D2E77FDB1A5D12519FF947F39A68152528CB02F915894D728C0E755B8BC4A99FCFC778A4099558A06D5FECC4C22DAA7E23C3B5E8E99B5365D5046C8C65846D949A521C0B25EFE5F5CD0845F09C29C096C4A80755120A299EA652B204775E53B2D521F366F4EF9FA65B1D8CB048295C39BE92667200E2889B1577CBD0AC23B2280B758A3650BE60D55F215DBF166873592253B1254968B5A46A61C792A153342C3ADE408676F4B27B7F22C50B079D0E32AEA134168A53A36F18E2FFA2459EDBA89BEC13D19C342235F6E9CF8F721B608F6297A3486173A7D5CED5E2AF6343775668C1B1FB0B745157973A60D840F +20170626042648 2 6 100 6143 2 FE3AFB7EA9CBCB633757EA982ED0DDFF120459E69D35DB36ACC5F69B04A5CCEE59A0312A97687F2B3DBC20917F4BF0B16D97B75EDCA16B58BDEB8BB1A726F6CB8BF5D7FC483777129A1C19CB559943EF201323760672C63859E830C6E99AFE5DD7A4E89BAD41C63B687558DD277F4E06A29D1E14A21CAA6FDD4E6F21EB8B146F2C04F93B1C94234E6295F2F8773B16BA3D51758841EA48ADD1A626E252DB3B78594B4586AC9E9EAF100F294ADC82BEBBF8CAB96B671EE7050B42733EB741107C5D2199D305C84F93C6AEEE6BD607DB7C0EFED773FB1DB73B04EFA72EB36111B99EBE6EEE899307FD288329FB2DB7E81776AEF0F935FFEE77611BDCFEC309F97EEB6E36FE42CA4C8EFAA0B4B93F5D83606B8FA7B49DD1DBB8F828B9C805381CB5DF4AC7FFAE27C62CBCD2FE80BB4157EB7F3267041255AC2F7EA3B450951878166049E5FF1BD3B361082FB184E342DDA1961ACFD90944F37E09A06AFE463AA9AA66EE699D28C4D109F3E8111CF4D625161B2855C11593AE408AE44DC026091119744FF09A4AB3C00717ACA004E26ACA53BF6444D839CF477A56FEAFFBF2E4CB946512815269D8E3C163FC29288A917A4A0ACC6DF54454CE2D54AC79AE05BF816DE1E3E9D3A9CC69DBE674880F98ECB8D8D4C4247AC07BC9B7C40FB89C4B9D4DA4604B37D15047DFB28C5D241CDFA327C3996872A0C05B84342F81A308D7796CA4A4038E47A5D4658F757C3F9645F11DEA92AE4D2E77FDB1A5D12519FF947F39A68152528CB02F915894D728C0E755B8BC4A99FCFC778A4099558A06D5FECC4C22DAA7E23C3B5E8E99B5365D5046C8C65846D949A521C0B25EFE5F5CD0845F09C29C096C4A80755120A299EA652B204775E53B2D521F366F4EF9FA65B1D8CB048295C39BE92667200E2889B1577CBD0AC23B2280B758A3650BE60D55F215DBF166873592253B1254968B5A46A61C792A153342C3ADE408676F4B27B7F22C50B079D0E32AEA134168A53A36F18E2FFA2459EDBA89BEC13D19C342235F6E9CF8F721B608F6297A3486173A7D5CED5E2AF6343775668C1B1FB0B745157973A7271AD3 +20170626063327 2 6 100 6143 5 FE3AFB7EA9CBCB633757EA982ED0DDFF120459E69D35DB36ACC5F69B04A5CCEE59A0312A97687F2B3DBC20917F4BF0B16D97B75EDCA16B58BDEB8BB1A726F6CB8BF5D7FC483777129A1C19CB559943EF201323760672C63859E830C6E99AFE5DD7A4E89BAD41C63B687558DD277F4E06A29D1E14A21CAA6FDD4E6F21EB8B146F2C04F93B1C94234E6295F2F8773B16BA3D51758841EA48ADD1A626E252DB3B78594B4586AC9E9EAF100F294ADC82BEBBF8CAB96B671EE7050B42733EB741107C5D2199D305C84F93C6AEEE6BD607DB7C0EFED773FB1DB73B04EFA72EB36111B99EBE6EEE899307FD288329FB2DB7E81776AEF0F935FFEE77611BDCFEC309F97EEB6E36FE42CA4C8EFAA0B4B93F5D83606B8FA7B49DD1DBB8F828B9C805381CB5DF4AC7FFAE27C62CBCD2FE80BB4157EB7F3267041255AC2F7EA3B450951878166049E5FF1BD3B361082FB184E342DDA1961ACFD90944F37E09A06AFE463AA9AA66EE699D28C4D109F3E8111CF4D625161B2855C11593AE408AE44DC026091119744FF09A4AB3C00717ACA004E26ACA53BF6444D839CF477A56FEAFFBF2E4CB946512815269D8E3C163FC29288A917A4A0ACC6DF54454CE2D54AC79AE05BF816DE1E3E9D3A9CC69DBE674880F98ECB8D8D4C4247AC07BC9B7C40FB89C4B9D4DA4604B37D15047DFB28C5D241CDFA327C3996872A0C05B84342F81A308D7796CA4A4038E47A5D4658F757C3F9645F11DEA92AE4D2E77FDB1A5D12519FF947F39A68152528CB02F915894D728C0E755B8BC4A99FCFC778A4099558A06D5FECC4C22DAA7E23C3B5E8E99B5365D5046C8C65846D949A521C0B25EFE5F5CD0845F09C29C096C4A80755120A299EA652B204775E53B2D521F366F4EF9FA65B1D8CB048295C39BE92667200E2889B1577CBD0AC23B2280B758A3650BE60D55F215DBF166873592253B1254968B5A46A61C792A153342C3ADE408676F4B27B7F22C50B079D0E32AEA134168A53A36F18E2FFA2459EDBA89BEC13D19C342235F6E9CF8F721B608F6297A3486173A7D5CED5E2AF6343775668C1B1FB0B745157973AA7A8227 +20170626073301 2 6 100 6143 2 FE3AFB7EA9CBCB633757EA982ED0DDFF120459E69D35DB36ACC5F69B04A5CCEE59A0312A97687F2B3DBC20917F4BF0B16D97B75EDCA16B58BDEB8BB1A726F6CB8BF5D7FC483777129A1C19CB559943EF201323760672C63859E830C6E99AFE5DD7A4E89BAD41C63B687558DD277F4E06A29D1E14A21CAA6FDD4E6F21EB8B146F2C04F93B1C94234E6295F2F8773B16BA3D51758841EA48ADD1A626E252DB3B78594B4586AC9E9EAF100F294ADC82BEBBF8CAB96B671EE7050B42733EB741107C5D2199D305C84F93C6AEEE6BD607DB7C0EFED773FB1DB73B04EFA72EB36111B99EBE6EEE899307FD288329FB2DB7E81776AEF0F935FFEE77611BDCFEC309F97EEB6E36FE42CA4C8EFAA0B4B93F5D83606B8FA7B49DD1DBB8F828B9C805381CB5DF4AC7FFAE27C62CBCD2FE80BB4157EB7F3267041255AC2F7EA3B450951878166049E5FF1BD3B361082FB184E342DDA1961ACFD90944F37E09A06AFE463AA9AA66EE699D28C4D109F3E8111CF4D625161B2855C11593AE408AE44DC026091119744FF09A4AB3C00717ACA004E26ACA53BF6444D839CF477A56FEAFFBF2E4CB946512815269D8E3C163FC29288A917A4A0ACC6DF54454CE2D54AC79AE05BF816DE1E3E9D3A9CC69DBE674880F98ECB8D8D4C4247AC07BC9B7C40FB89C4B9D4DA4604B37D15047DFB28C5D241CDFA327C3996872A0C05B84342F81A308D7796CA4A4038E47A5D4658F757C3F9645F11DEA92AE4D2E77FDB1A5D12519FF947F39A68152528CB02F915894D728C0E755B8BC4A99FCFC778A4099558A06D5FECC4C22DAA7E23C3B5E8E99B5365D5046C8C65846D949A521C0B25EFE5F5CD0845F09C29C096C4A80755120A299EA652B204775E53B2D521F366F4EF9FA65B1D8CB048295C39BE92667200E2889B1577CBD0AC23B2280B758A3650BE60D55F215DBF166873592253B1254968B5A46A61C792A153342C3ADE408676F4B27B7F22C50B079D0E32AEA134168A53A36F18E2FFA2459EDBA89BEC13D19C342235F6E9CF8F721B608F6297A3486173A7D5CED5E2AF6343775668C1B1FB0B745157973AC001F7B +20170626073912 2 6 100 6143 5 FE3AFB7EA9CBCB633757EA982ED0DDFF120459E69D35DB36ACC5F69B04A5CCEE59A0312A97687F2B3DBC20917F4BF0B16D97B75EDCA16B58BDEB8BB1A726F6CB8BF5D7FC483777129A1C19CB559943EF201323760672C63859E830C6E99AFE5DD7A4E89BAD41C63B687558DD277F4E06A29D1E14A21CAA6FDD4E6F21EB8B146F2C04F93B1C94234E6295F2F8773B16BA3D51758841EA48ADD1A626E252DB3B78594B4586AC9E9EAF100F294ADC82BEBBF8CAB96B671EE7050B42733EB741107C5D2199D305C84F93C6AEEE6BD607DB7C0EFED773FB1DB73B04EFA72EB36111B99EBE6EEE899307FD288329FB2DB7E81776AEF0F935FFEE77611BDCFEC309F97EEB6E36FE42CA4C8EFAA0B4B93F5D83606B8FA7B49DD1DBB8F828B9C805381CB5DF4AC7FFAE27C62CBCD2FE80BB4157EB7F3267041255AC2F7EA3B450951878166049E5FF1BD3B361082FB184E342DDA1961ACFD90944F37E09A06AFE463AA9AA66EE699D28C4D109F3E8111CF4D625161B2855C11593AE408AE44DC026091119744FF09A4AB3C00717ACA004E26ACA53BF6444D839CF477A56FEAFFBF2E4CB946512815269D8E3C163FC29288A917A4A0ACC6DF54454CE2D54AC79AE05BF816DE1E3E9D3A9CC69DBE674880F98ECB8D8D4C4247AC07BC9B7C40FB89C4B9D4DA4604B37D15047DFB28C5D241CDFA327C3996872A0C05B84342F81A308D7796CA4A4038E47A5D4658F757C3F9645F11DEA92AE4D2E77FDB1A5D12519FF947F39A68152528CB02F915894D728C0E755B8BC4A99FCFC778A4099558A06D5FECC4C22DAA7E23C3B5E8E99B5365D5046C8C65846D949A521C0B25EFE5F5CD0845F09C29C096C4A80755120A299EA652B204775E53B2D521F366F4EF9FA65B1D8CB048295C39BE92667200E2889B1577CBD0AC23B2280B758A3650BE60D55F215DBF166873592253B1254968B5A46A61C792A153342C3ADE408676F4B27B7F22C50B079D0E32AEA134168A53A36F18E2FFA2459EDBA89BEC13D19C342235F6E9CF8F721B608F6297A3486173A7D5CED5E2AF6343775668C1B1FB0B745157973AC204247 +20170626083935 2 6 100 6143 5 FE3AFB7EA9CBCB633757EA982ED0DDFF120459E69D35DB36ACC5F69B04A5CCEE59A0312A97687F2B3DBC20917F4BF0B16D97B75EDCA16B58BDEB8BB1A726F6CB8BF5D7FC483777129A1C19CB559943EF201323760672C63859E830C6E99AFE5DD7A4E89BAD41C63B687558DD277F4E06A29D1E14A21CAA6FDD4E6F21EB8B146F2C04F93B1C94234E6295F2F8773B16BA3D51758841EA48ADD1A626E252DB3B78594B4586AC9E9EAF100F294ADC82BEBBF8CAB96B671EE7050B42733EB741107C5D2199D305C84F93C6AEEE6BD607DB7C0EFED773FB1DB73B04EFA72EB36111B99EBE6EEE899307FD288329FB2DB7E81776AEF0F935FFEE77611BDCFEC309F97EEB6E36FE42CA4C8EFAA0B4B93F5D83606B8FA7B49DD1DBB8F828B9C805381CB5DF4AC7FFAE27C62CBCD2FE80BB4157EB7F3267041255AC2F7EA3B450951878166049E5FF1BD3B361082FB184E342DDA1961ACFD90944F37E09A06AFE463AA9AA66EE699D28C4D109F3E8111CF4D625161B2855C11593AE408AE44DC026091119744FF09A4AB3C00717ACA004E26ACA53BF6444D839CF477A56FEAFFBF2E4CB946512815269D8E3C163FC29288A917A4A0ACC6DF54454CE2D54AC79AE05BF816DE1E3E9D3A9CC69DBE674880F98ECB8D8D4C4247AC07BC9B7C40FB89C4B9D4DA4604B37D15047DFB28C5D241CDFA327C3996872A0C05B84342F81A308D7796CA4A4038E47A5D4658F757C3F9645F11DEA92AE4D2E77FDB1A5D12519FF947F39A68152528CB02F915894D728C0E755B8BC4A99FCFC778A4099558A06D5FECC4C22DAA7E23C3B5E8E99B5365D5046C8C65846D949A521C0B25EFE5F5CD0845F09C29C096C4A80755120A299EA652B204775E53B2D521F366F4EF9FA65B1D8CB048295C39BE92667200E2889B1577CBD0AC23B2280B758A3650BE60D55F215DBF166873592253B1254968B5A46A61C792A153342C3ADE408676F4B27B7F22C50B079D0E32AEA134168A53A36F18E2FFA2459EDBA89BEC13D19C342235F6E9CF8F721B608F6297A3486173A7D5CED5E2AF6343775668C1B1FB0B745157973ADB29CEF +20170626085130 2 6 100 6143 2 FE3AFB7EA9CBCB633757EA982ED0DDFF120459E69D35DB36ACC5F69B04A5CCEE59A0312A97687F2B3DBC20917F4BF0B16D97B75EDCA16B58BDEB8BB1A726F6CB8BF5D7FC483777129A1C19CB559943EF201323760672C63859E830C6E99AFE5DD7A4E89BAD41C63B687558DD277F4E06A29D1E14A21CAA6FDD4E6F21EB8B146F2C04F93B1C94234E6295F2F8773B16BA3D51758841EA48ADD1A626E252DB3B78594B4586AC9E9EAF100F294ADC82BEBBF8CAB96B671EE7050B42733EB741107C5D2199D305C84F93C6AEEE6BD607DB7C0EFED773FB1DB73B04EFA72EB36111B99EBE6EEE899307FD288329FB2DB7E81776AEF0F935FFEE77611BDCFEC309F97EEB6E36FE42CA4C8EFAA0B4B93F5D83606B8FA7B49DD1DBB8F828B9C805381CB5DF4AC7FFAE27C62CBCD2FE80BB4157EB7F3267041255AC2F7EA3B450951878166049E5FF1BD3B361082FB184E342DDA1961ACFD90944F37E09A06AFE463AA9AA66EE699D28C4D109F3E8111CF4D625161B2855C11593AE408AE44DC026091119744FF09A4AB3C00717ACA004E26ACA53BF6444D839CF477A56FEAFFBF2E4CB946512815269D8E3C163FC29288A917A4A0ACC6DF54454CE2D54AC79AE05BF816DE1E3E9D3A9CC69DBE674880F98ECB8D8D4C4247AC07BC9B7C40FB89C4B9D4DA4604B37D15047DFB28C5D241CDFA327C3996872A0C05B84342F81A308D7796CA4A4038E47A5D4658F757C3F9645F11DEA92AE4D2E77FDB1A5D12519FF947F39A68152528CB02F915894D728C0E755B8BC4A99FCFC778A4099558A06D5FECC4C22DAA7E23C3B5E8E99B5365D5046C8C65846D949A521C0B25EFE5F5CD0845F09C29C096C4A80755120A299EA652B204775E53B2D521F366F4EF9FA65B1D8CB048295C39BE92667200E2889B1577CBD0AC23B2280B758A3650BE60D55F215DBF166873592253B1254968B5A46A61C792A153342C3ADE408676F4B27B7F22C50B079D0E32AEA134168A53A36F18E2FFA2459EDBA89BEC13D19C342235F6E9CF8F721B608F6297A3486173A7D5CED5E2AF6343775668C1B1FB0B745157973ADFA675B +20170626103016 2 6 100 6143 2 FE3AFB7EA9CBCB633757EA982ED0DDFF120459E69D35DB36ACC5F69B04A5CCEE59A0312A97687F2B3DBC20917F4BF0B16D97B75EDCA16B58BDEB8BB1A726F6CB8BF5D7FC483777129A1C19CB559943EF201323760672C63859E830C6E99AFE5DD7A4E89BAD41C63B687558DD277F4E06A29D1E14A21CAA6FDD4E6F21EB8B146F2C04F93B1C94234E6295F2F8773B16BA3D51758841EA48ADD1A626E252DB3B78594B4586AC9E9EAF100F294ADC82BEBBF8CAB96B671EE7050B42733EB741107C5D2199D305C84F93C6AEEE6BD607DB7C0EFED773FB1DB73B04EFA72EB36111B99EBE6EEE899307FD288329FB2DB7E81776AEF0F935FFEE77611BDCFEC309F97EEB6E36FE42CA4C8EFAA0B4B93F5D83606B8FA7B49DD1DBB8F828B9C805381CB5DF4AC7FFAE27C62CBCD2FE80BB4157EB7F3267041255AC2F7EA3B450951878166049E5FF1BD3B361082FB184E342DDA1961ACFD90944F37E09A06AFE463AA9AA66EE699D28C4D109F3E8111CF4D625161B2855C11593AE408AE44DC026091119744FF09A4AB3C00717ACA004E26ACA53BF6444D839CF477A56FEAFFBF2E4CB946512815269D8E3C163FC29288A917A4A0ACC6DF54454CE2D54AC79AE05BF816DE1E3E9D3A9CC69DBE674880F98ECB8D8D4C4247AC07BC9B7C40FB89C4B9D4DA4604B37D15047DFB28C5D241CDFA327C3996872A0C05B84342F81A308D7796CA4A4038E47A5D4658F757C3F9645F11DEA92AE4D2E77FDB1A5D12519FF947F39A68152528CB02F915894D728C0E755B8BC4A99FCFC778A4099558A06D5FECC4C22DAA7E23C3B5E8E99B5365D5046C8C65846D949A521C0B25EFE5F5CD0845F09C29C096C4A80755120A299EA652B204775E53B2D521F366F4EF9FA65B1D8CB048295C39BE92667200E2889B1577CBD0AC23B2280B758A3650BE60D55F215DBF166873592253B1254968B5A46A61C792A153342C3ADE408676F4B27B7F22C50B079D0E32AEA134168A53A36F18E2FFA2459EDBA89BEC13D19C342235F6E9CF8F721B608F6297A3486173A7D5CED5E2AF6343775668C1B1FB0B745157973B0702723 +20170626110918 2 6 100 6143 5 FE3AFB7EA9CBCB633757EA982ED0DDFF120459E69D35DB36ACC5F69B04A5CCEE59A0312A97687F2B3DBC20917F4BF0B16D97B75EDCA16B58BDEB8BB1A726F6CB8BF5D7FC483777129A1C19CB559943EF201323760672C63859E830C6E99AFE5DD7A4E89BAD41C63B687558DD277F4E06A29D1E14A21CAA6FDD4E6F21EB8B146F2C04F93B1C94234E6295F2F8773B16BA3D51758841EA48ADD1A626E252DB3B78594B4586AC9E9EAF100F294ADC82BEBBF8CAB96B671EE7050B42733EB741107C5D2199D305C84F93C6AEEE6BD607DB7C0EFED773FB1DB73B04EFA72EB36111B99EBE6EEE899307FD288329FB2DB7E81776AEF0F935FFEE77611BDCFEC309F97EEB6E36FE42CA4C8EFAA0B4B93F5D83606B8FA7B49DD1DBB8F828B9C805381CB5DF4AC7FFAE27C62CBCD2FE80BB4157EB7F3267041255AC2F7EA3B450951878166049E5FF1BD3B361082FB184E342DDA1961ACFD90944F37E09A06AFE463AA9AA66EE699D28C4D109F3E8111CF4D625161B2855C11593AE408AE44DC026091119744FF09A4AB3C00717ACA004E26ACA53BF6444D839CF477A56FEAFFBF2E4CB946512815269D8E3C163FC29288A917A4A0ACC6DF54454CE2D54AC79AE05BF816DE1E3E9D3A9CC69DBE674880F98ECB8D8D4C4247AC07BC9B7C40FB89C4B9D4DA4604B37D15047DFB28C5D241CDFA327C3996872A0C05B84342F81A308D7796CA4A4038E47A5D4658F757C3F9645F11DEA92AE4D2E77FDB1A5D12519FF947F39A68152528CB02F915894D728C0E755B8BC4A99FCFC778A4099558A06D5FECC4C22DAA7E23C3B5E8E99B5365D5046C8C65846D949A521C0B25EFE5F5CD0845F09C29C096C4A80755120A299EA652B204775E53B2D521F366F4EF9FA65B1D8CB048295C39BE92667200E2889B1577CBD0AC23B2280B758A3650BE60D55F215DBF166873592253B1254968B5A46A61C792A153342C3ADE408676F4B27B7F22C50B079D0E32AEA134168A53A36F18E2FFA2459EDBA89BEC13D19C342235F6E9CF8F721B608F6297A3486173A7D5CED5E2AF6343775668C1B1FB0B745157973B1648BFF +20170626113343 2 6 100 6143 2 FE3AFB7EA9CBCB633757EA982ED0DDFF120459E69D35DB36ACC5F69B04A5CCEE59A0312A97687F2B3DBC20917F4BF0B16D97B75EDCA16B58BDEB8BB1A726F6CB8BF5D7FC483777129A1C19CB559943EF201323760672C63859E830C6E99AFE5DD7A4E89BAD41C63B687558DD277F4E06A29D1E14A21CAA6FDD4E6F21EB8B146F2C04F93B1C94234E6295F2F8773B16BA3D51758841EA48ADD1A626E252DB3B78594B4586AC9E9EAF100F294ADC82BEBBF8CAB96B671EE7050B42733EB741107C5D2199D305C84F93C6AEEE6BD607DB7C0EFED773FB1DB73B04EFA72EB36111B99EBE6EEE899307FD288329FB2DB7E81776AEF0F935FFEE77611BDCFEC309F97EEB6E36FE42CA4C8EFAA0B4B93F5D83606B8FA7B49DD1DBB8F828B9C805381CB5DF4AC7FFAE27C62CBCD2FE80BB4157EB7F3267041255AC2F7EA3B450951878166049E5FF1BD3B361082FB184E342DDA1961ACFD90944F37E09A06AFE463AA9AA66EE699D28C4D109F3E8111CF4D625161B2855C11593AE408AE44DC026091119744FF09A4AB3C00717ACA004E26ACA53BF6444D839CF477A56FEAFFBF2E4CB946512815269D8E3C163FC29288A917A4A0ACC6DF54454CE2D54AC79AE05BF816DE1E3E9D3A9CC69DBE674880F98ECB8D8D4C4247AC07BC9B7C40FB89C4B9D4DA4604B37D15047DFB28C5D241CDFA327C3996872A0C05B84342F81A308D7796CA4A4038E47A5D4658F757C3F9645F11DEA92AE4D2E77FDB1A5D12519FF947F39A68152528CB02F915894D728C0E755B8BC4A99FCFC778A4099558A06D5FECC4C22DAA7E23C3B5E8E99B5365D5046C8C65846D949A521C0B25EFE5F5CD0845F09C29C096C4A80755120A299EA652B204775E53B2D521F366F4EF9FA65B1D8CB048295C39BE92667200E2889B1577CBD0AC23B2280B758A3650BE60D55F215DBF166873592253B1254968B5A46A61C792A153342C3ADE408676F4B27B7F22C50B079D0E32AEA134168A53A36F18E2FFA2459EDBA89BEC13D19C342235F6E9CF8F721B608F6297A3486173A7D5CED5E2AF6343775668C1B1FB0B745157973B1F924B3 +20170626150922 2 6 100 6143 2 FE3AFB7EA9CBCB633757EA982ED0DDFF120459E69D35DB36ACC5F69B04A5CCEE59A0312A97687F2B3DBC20917F4BF0B16D97B75EDCA16B58BDEB8BB1A726F6CB8BF5D7FC483777129A1C19CB559943EF201323760672C63859E830C6E99AFE5DD7A4E89BAD41C63B687558DD277F4E06A29D1E14A21CAA6FDD4E6F21EB8B146F2C04F93B1C94234E6295F2F8773B16BA3D51758841EA48ADD1A626E252DB3B78594B4586AC9E9EAF100F294ADC82BEBBF8CAB96B671EE7050B42733EB741107C5D2199D305C84F93C6AEEE6BD607DB7C0EFED773FB1DB73B04EFA72EB36111B99EBE6EEE899307FD288329FB2DB7E81776AEF0F935FFEE77611BDCFEC309F97EEB6E36FE42CA4C8EFAA0B4B93F5D83606B8FA7B49DD1DBB8F828B9C805381CB5DF4AC7FFAE27C62CBCD2FE80BB4157EB7F3267041255AC2F7EA3B450951878166049E5FF1BD3B361082FB184E342DDA1961ACFD90944F37E09A06AFE463AA9AA66EE699D28C4D109F3E8111CF4D625161B2855C11593AE408AE44DC026091119744FF09A4AB3C00717ACA004E26ACA53BF6444D839CF477A56FEAFFBF2E4CB946512815269D8E3C163FC29288A917A4A0ACC6DF54454CE2D54AC79AE05BF816DE1E3E9D3A9CC69DBE674880F98ECB8D8D4C4247AC07BC9B7C40FB89C4B9D4DA4604B37D15047DFB28C5D241CDFA327C3996872A0C05B84342F81A308D7796CA4A4038E47A5D4658F757C3F9645F11DEA92AE4D2E77FDB1A5D12519FF947F39A68152528CB02F915894D728C0E755B8BC4A99FCFC778A4099558A06D5FECC4C22DAA7E23C3B5E8E99B5365D5046C8C65846D949A521C0B25EFE5F5CD0845F09C29C096C4A80755120A299EA652B204775E53B2D521F366F4EF9FA65B1D8CB048295C39BE92667200E2889B1577CBD0AC23B2280B758A3650BE60D55F215DBF166873592253B1254968B5A46A61C792A153342C3ADE408676F4B27B7F22C50B079D0E32AEA134168A53A36F18E2FFA2459EDBA89BEC13D19C342235F6E9CF8F721B608F6297A3486173A7D5CED5E2AF6343775668C1B1FB0B745157973B78B107B +20170626162428 2 6 100 6143 2 FE3AFB7EA9CBCB633757EA982ED0DDFF120459E69D35DB36ACC5F69B04A5CCEE59A0312A97687F2B3DBC20917F4BF0B16D97B75EDCA16B58BDEB8BB1A726F6CB8BF5D7FC483777129A1C19CB559943EF201323760672C63859E830C6E99AFE5DD7A4E89BAD41C63B687558DD277F4E06A29D1E14A21CAA6FDD4E6F21EB8B146F2C04F93B1C94234E6295F2F8773B16BA3D51758841EA48ADD1A626E252DB3B78594B4586AC9E9EAF100F294ADC82BEBBF8CAB96B671EE7050B42733EB741107C5D2199D305C84F93C6AEEE6BD607DB7C0EFED773FB1DB73B04EFA72EB36111B99EBE6EEE899307FD288329FB2DB7E81776AEF0F935FFEE77611BDCFEC309F97EEB6E36FE42CA4C8EFAA0B4B93F5D83606B8FA7B49DD1DBB8F828B9C805381CB5DF4AC7FFAE27C62CBCD2FE80BB4157EB7F3267041255AC2F7EA3B450951878166049E5FF1BD3B361082FB184E342DDA1961ACFD90944F37E09A06AFE463AA9AA66EE699D28C4D109F3E8111CF4D625161B2855C11593AE408AE44DC026091119744FF09A4AB3C00717ACA004E26ACA53BF6444D839CF477A56FEAFFBF2E4CB946512815269D8E3C163FC29288A917A4A0ACC6DF54454CE2D54AC79AE05BF816DE1E3E9D3A9CC69DBE674880F98ECB8D8D4C4247AC07BC9B7C40FB89C4B9D4DA4604B37D15047DFB28C5D241CDFA327C3996872A0C05B84342F81A308D7796CA4A4038E47A5D4658F757C3F9645F11DEA92AE4D2E77FDB1A5D12519FF947F39A68152528CB02F915894D728C0E755B8BC4A99FCFC778A4099558A06D5FECC4C22DAA7E23C3B5E8E99B5365D5046C8C65846D949A521C0B25EFE5F5CD0845F09C29C096C4A80755120A299EA652B204775E53B2D521F366F4EF9FA65B1D8CB048295C39BE92667200E2889B1577CBD0AC23B2280B758A3650BE60D55F215DBF166873592253B1254968B5A46A61C792A153342C3ADE408676F4B27B7F22C50B079D0E32AEA134168A53A36F18E2FFA2459EDBA89BEC13D19C342235F6E9CF8F721B608F6297A3486173A7D5CED5E2AF6343775668C1B1FB0B745157973B972EB6B +20170626171558 2 6 100 6143 5 FE3AFB7EA9CBCB633757EA982ED0DDFF120459E69D35DB36ACC5F69B04A5CCEE59A0312A97687F2B3DBC20917F4BF0B16D97B75EDCA16B58BDEB8BB1A726F6CB8BF5D7FC483777129A1C19CB559943EF201323760672C63859E830C6E99AFE5DD7A4E89BAD41C63B687558DD277F4E06A29D1E14A21CAA6FDD4E6F21EB8B146F2C04F93B1C94234E6295F2F8773B16BA3D51758841EA48ADD1A626E252DB3B78594B4586AC9E9EAF100F294ADC82BEBBF8CAB96B671EE7050B42733EB741107C5D2199D305C84F93C6AEEE6BD607DB7C0EFED773FB1DB73B04EFA72EB36111B99EBE6EEE899307FD288329FB2DB7E81776AEF0F935FFEE77611BDCFEC309F97EEB6E36FE42CA4C8EFAA0B4B93F5D83606B8FA7B49DD1DBB8F828B9C805381CB5DF4AC7FFAE27C62CBCD2FE80BB4157EB7F3267041255AC2F7EA3B450951878166049E5FF1BD3B361082FB184E342DDA1961ACFD90944F37E09A06AFE463AA9AA66EE699D28C4D109F3E8111CF4D625161B2855C11593AE408AE44DC026091119744FF09A4AB3C00717ACA004E26ACA53BF6444D839CF477A56FEAFFBF2E4CB946512815269D8E3C163FC29288A917A4A0ACC6DF54454CE2D54AC79AE05BF816DE1E3E9D3A9CC69DBE674880F98ECB8D8D4C4247AC07BC9B7C40FB89C4B9D4DA4604B37D15047DFB28C5D241CDFA327C3996872A0C05B84342F81A308D7796CA4A4038E47A5D4658F757C3F9645F11DEA92AE4D2E77FDB1A5D12519FF947F39A68152528CB02F915894D728C0E755B8BC4A99FCFC778A4099558A06D5FECC4C22DAA7E23C3B5E8E99B5365D5046C8C65846D949A521C0B25EFE5F5CD0845F09C29C096C4A80755120A299EA652B204775E53B2D521F366F4EF9FA65B1D8CB048295C39BE92667200E2889B1577CBD0AC23B2280B758A3650BE60D55F215DBF166873592253B1254968B5A46A61C792A153342C3ADE408676F4B27B7F22C50B079D0E32AEA134168A53A36F18E2FFA2459EDBA89BEC13D19C342235F6E9CF8F721B608F6297A3486173A7D5CED5E2AF6343775668C1B1FB0B745157973BAC16547 +20170626231518 2 6 100 6143 2 FE3AFB7EA9CBCB633757EA982ED0DDFF120459E69D35DB36ACC5F69B04A5CCEE59A0312A97687F2B3DBC20917F4BF0B16D97B75EDCA16B58BDEB8BB1A726F6CB8BF5D7FC483777129A1C19CB559943EF201323760672C63859E830C6E99AFE5DD7A4E89BAD41C63B687558DD277F4E06A29D1E14A21CAA6FDD4E6F21EB8B146F2C04F93B1C94234E6295F2F8773B16BA3D51758841EA48ADD1A626E252DB3B78594B4586AC9E9EAF100F294ADC82BEBBF8CAB96B671EE7050B42733EB741107C5D2199D305C84F93C6AEEE6BD607DB7C0EFED773FB1DB73B04EFA72EB36111B99EBE6EEE899307FD288329FB2DB7E81776AEF0F935FFEE77611BDCFEC309F97EEB6E36FE42CA4C8EFAA0B4B93F5D83606B8FA7B49DD1DBB8F828B9C805381CB5DF4AC7FFAE27C62CBCD2FE80BB4157EB7F3267041255AC2F7EA3B450951878166049E5FF1BD3B361082FB184E342DDA1961ACFD90944F37E09A06AFE463AA9AA66EE699D28C4D109F3E8111CF4D625161B2855C11593AE408AE44DC026091119744FF09A4AB3C00717ACA004E26ACA53BF6444D839CF477A56FEAFFBF2E4CB946512815269D8E3C163FC29288A917A4A0ACC6DF54454CE2D54AC79AE05BF816DE1E3E9D3A9CC69DBE674880F98ECB8D8D4C4247AC07BC9B7C40FB89C4B9D4DA4604B37D15047DFB28C5D241CDFA327C3996872A0C05B84342F81A308D7796CA4A4038E47A5D4658F757C3F9645F11DEA92AE4D2E77FDB1A5D12519FF947F39A68152528CB02F915894D728C0E755B8BC4A99FCFC778A4099558A06D5FECC4C22DAA7E23C3B5E8E99B5365D5046C8C65846D949A521C0B25EFE5F5CD0845F09C29C096C4A80755120A299EA652B204775E53B2D521F366F4EF9FA65B1D8CB048295C39BE92667200E2889B1577CBD0AC23B2280B758A3650BE60D55F215DBF166873592253B1254968B5A46A61C792A153342C3ADE408676F4B27B7F22C50B079D0E32AEA134168A53A36F18E2FFA2459EDBA89BEC13D19C342235F6E9CF8F721B608F6297A3486173A7D5CED5E2AF6343775668C1B1FB0B745157973C3C4E533 +20170627001636 2 6 100 6143 5 FE3AFB7EA9CBCB633757EA982ED0DDFF120459E69D35DB36ACC5F69B04A5CCEE59A0312A97687F2B3DBC20917F4BF0B16D97B75EDCA16B58BDEB8BB1A726F6CB8BF5D7FC483777129A1C19CB559943EF201323760672C63859E830C6E99AFE5DD7A4E89BAD41C63B687558DD277F4E06A29D1E14A21CAA6FDD4E6F21EB8B146F2C04F93B1C94234E6295F2F8773B16BA3D51758841EA48ADD1A626E252DB3B78594B4586AC9E9EAF100F294ADC82BEBBF8CAB96B671EE7050B42733EB741107C5D2199D305C84F93C6AEEE6BD607DB7C0EFED773FB1DB73B04EFA72EB36111B99EBE6EEE899307FD288329FB2DB7E81776AEF0F935FFEE77611BDCFEC309F97EEB6E36FE42CA4C8EFAA0B4B93F5D83606B8FA7B49DD1DBB8F828B9C805381CB5DF4AC7FFAE27C62CBCD2FE80BB4157EB7F3267041255AC2F7EA3B450951878166049E5FF1BD3B361082FB184E342DDA1961ACFD90944F37E09A06AFE463AA9AA66EE699D28C4D109F3E8111CF4D625161B2855C11593AE408AE44DC026091119744FF09A4AB3C00717ACA004E26ACA53BF6444D839CF477A56FEAFFBF2E4CB946512815269D8E3C163FC29288A917A4A0ACC6DF54454CE2D54AC79AE05BF816DE1E3E9D3A9CC69DBE674880F98ECB8D8D4C4247AC07BC9B7C40FB89C4B9D4DA4604B37D15047DFB28C5D241CDFA327C3996872A0C05B84342F81A308D7796CA4A4038E47A5D4658F757C3F9645F11DEA92AE4D2E77FDB1A5D12519FF947F39A68152528CB02F915894D728C0E755B8BC4A99FCFC778A4099558A06D5FECC4C22DAA7E23C3B5E8E99B5365D5046C8C65846D949A521C0B25EFE5F5CD0845F09C29C096C4A80755120A299EA652B204775E53B2D521F366F4EF9FA65B1D8CB048295C39BE92667200E2889B1577CBD0AC23B2280B758A3650BE60D55F215DBF166873592253B1254968B5A46A61C792A153342C3ADE408676F4B27B7F22C50B079D0E32AEA134168A53A36F18E2FFA2459EDBA89BEC13D19C342235F6E9CF8F721B608F6297A3486173A7D5CED5E2AF6343775668C1B1FB0B745157973C53DC917 +20170627023229 2 6 100 6143 2 FE3AFB7EA9CBCB633757EA982ED0DDFF120459E69D35DB36ACC5F69B04A5CCEE59A0312A97687F2B3DBC20917F4BF0B16D97B75EDCA16B58BDEB8BB1A726F6CB8BF5D7FC483777129A1C19CB559943EF201323760672C63859E830C6E99AFE5DD7A4E89BAD41C63B687558DD277F4E06A29D1E14A21CAA6FDD4E6F21EB8B146F2C04F93B1C94234E6295F2F8773B16BA3D51758841EA48ADD1A626E252DB3B78594B4586AC9E9EAF100F294ADC82BEBBF8CAB96B671EE7050B42733EB741107C5D2199D305C84F93C6AEEE6BD607DB7C0EFED773FB1DB73B04EFA72EB36111B99EBE6EEE899307FD288329FB2DB7E81776AEF0F935FFEE77611BDCFEC309F97EEB6E36FE42CA4C8EFAA0B4B93F5D83606B8FA7B49DD1DBB8F828B9C805381CB5DF4AC7FFAE27C62CBCD2FE80BB4157EB7F3267041255AC2F7EA3B450951878166049E5FF1BD3B361082FB184E342DDA1961ACFD90944F37E09A06AFE463AA9AA66EE699D28C4D109F3E8111CF4D625161B2855C11593AE408AE44DC026091119744FF09A4AB3C00717ACA004E26ACA53BF6444D839CF477A56FEAFFBF2E4CB946512815269D8E3C163FC29288A917A4A0ACC6DF54454CE2D54AC79AE05BF816DE1E3E9D3A9CC69DBE674880F98ECB8D8D4C4247AC07BC9B7C40FB89C4B9D4DA4604B37D15047DFB28C5D241CDFA327C3996872A0C05B84342F81A308D7796CA4A4038E47A5D4658F757C3F9645F11DEA92AE4D2E77FDB1A5D12519FF947F39A68152528CB02F915894D728C0E755B8BC4A99FCFC778A4099558A06D5FECC4C22DAA7E23C3B5E8E99B5365D5046C8C65846D949A521C0B25EFE5F5CD0845F09C29C096C4A80755120A299EA652B204775E53B2D521F366F4EF9FA65B1D8CB048295C39BE92667200E2889B1577CBD0AC23B2280B758A3650BE60D55F215DBF166873592253B1254968B5A46A61C792A153342C3ADE408676F4B27B7F22C50B079D0E32AEA134168A53A36F18E2FFA2459EDBA89BEC13D19C342235F6E9CF8F721B608F6297A3486173A7D5CED5E2AF6343775668C1B1FB0B745157973C8A24E33 +20170627055348 2 6 100 6143 5 FE3AFB7EA9CBCB633757EA982ED0DDFF120459E69D35DB36ACC5F69B04A5CCEE59A0312A97687F2B3DBC20917F4BF0B16D97B75EDCA16B58BDEB8BB1A726F6CB8BF5D7FC483777129A1C19CB559943EF201323760672C63859E830C6E99AFE5DD7A4E89BAD41C63B687558DD277F4E06A29D1E14A21CAA6FDD4E6F21EB8B146F2C04F93B1C94234E6295F2F8773B16BA3D51758841EA48ADD1A626E252DB3B78594B4586AC9E9EAF100F294ADC82BEBBF8CAB96B671EE7050B42733EB741107C5D2199D305C84F93C6AEEE6BD607DB7C0EFED773FB1DB73B04EFA72EB36111B99EBE6EEE899307FD288329FB2DB7E81776AEF0F935FFEE77611BDCFEC309F97EEB6E36FE42CA4C8EFAA0B4B93F5D83606B8FA7B49DD1DBB8F828B9C805381CB5DF4AC7FFAE27C62CBCD2FE80BB4157EB7F3267041255AC2F7EA3B450951878166049E5FF1BD3B361082FB184E342DDA1961ACFD90944F37E09A06AFE463AA9AA66EE699D28C4D109F3E8111CF4D625161B2855C11593AE408AE44DC026091119744FF09A4AB3C00717ACA004E26ACA53BF6444D839CF477A56FEAFFBF2E4CB946512815269D8E3C163FC29288A917A4A0ACC6DF54454CE2D54AC79AE05BF816DE1E3E9D3A9CC69DBE674880F98ECB8D8D4C4247AC07BC9B7C40FB89C4B9D4DA4604B37D15047DFB28C5D241CDFA327C3996872A0C05B84342F81A308D7796CA4A4038E47A5D4658F757C3F9645F11DEA92AE4D2E77FDB1A5D12519FF947F39A68152528CB02F915894D728C0E755B8BC4A99FCFC778A4099558A06D5FECC4C22DAA7E23C3B5E8E99B5365D5046C8C65846D949A521C0B25EFE5F5CD0845F09C29C096C4A80755120A299EA652B204775E53B2D521F366F4EF9FA65B1D8CB048295C39BE92667200E2889B1577CBD0AC23B2280B758A3650BE60D55F215DBF166873592253B1254968B5A46A61C792A153342C3ADE408676F4B27B7F22C50B079D0E32AEA134168A53A36F18E2FFA2459EDBA89BEC13D19C342235F6E9CF8F721B608F6297A3486173A7D5CED5E2AF6343775668C1B1FB0B745157973CDB0A037 +20170627085558 2 6 100 6143 2 FE3AFB7EA9CBCB633757EA982ED0DDFF120459E69D35DB36ACC5F69B04A5CCEE59A0312A97687F2B3DBC20917F4BF0B16D97B75EDCA16B58BDEB8BB1A726F6CB8BF5D7FC483777129A1C19CB559943EF201323760672C63859E830C6E99AFE5DD7A4E89BAD41C63B687558DD277F4E06A29D1E14A21CAA6FDD4E6F21EB8B146F2C04F93B1C94234E6295F2F8773B16BA3D51758841EA48ADD1A626E252DB3B78594B4586AC9E9EAF100F294ADC82BEBBF8CAB96B671EE7050B42733EB741107C5D2199D305C84F93C6AEEE6BD607DB7C0EFED773FB1DB73B04EFA72EB36111B99EBE6EEE899307FD288329FB2DB7E81776AEF0F935FFEE77611BDCFEC309F97EEB6E36FE42CA4C8EFAA0B4B93F5D83606B8FA7B49DD1DBB8F828B9C805381CB5DF4AC7FFAE27C62CBCD2FE80BB4157EB7F3267041255AC2F7EA3B450951878166049E5FF1BD3B361082FB184E342DDA1961ACFD90944F37E09A06AFE463AA9AA66EE699D28C4D109F3E8111CF4D625161B2855C11593AE408AE44DC026091119744FF09A4AB3C00717ACA004E26ACA53BF6444D839CF477A56FEAFFBF2E4CB946512815269D8E3C163FC29288A917A4A0ACC6DF54454CE2D54AC79AE05BF816DE1E3E9D3A9CC69DBE674880F98ECB8D8D4C4247AC07BC9B7C40FB89C4B9D4DA4604B37D15047DFB28C5D241CDFA327C3996872A0C05B84342F81A308D7796CA4A4038E47A5D4658F757C3F9645F11DEA92AE4D2E77FDB1A5D12519FF947F39A68152528CB02F915894D728C0E755B8BC4A99FCFC778A4099558A06D5FECC4C22DAA7E23C3B5E8E99B5365D5046C8C65846D949A521C0B25EFE5F5CD0845F09C29C096C4A80755120A299EA652B204775E53B2D521F366F4EF9FA65B1D8CB048295C39BE92667200E2889B1577CBD0AC23B2280B758A3650BE60D55F215DBF166873592253B1254968B5A46A61C792A153342C3ADE408676F4B27B7F22C50B079D0E32AEA134168A53A36F18E2FFA2459EDBA89BEC13D19C342235F6E9CF8F721B608F6297A3486173A7D5CED5E2AF6343775668C1B1FB0B745157973D234059B +20170627111046 2 6 100 6143 2 FE3AFB7EA9CBCB633757EA982ED0DDFF120459E69D35DB36ACC5F69B04A5CCEE59A0312A97687F2B3DBC20917F4BF0B16D97B75EDCA16B58BDEB8BB1A726F6CB8BF5D7FC483777129A1C19CB559943EF201323760672C63859E830C6E99AFE5DD7A4E89BAD41C63B687558DD277F4E06A29D1E14A21CAA6FDD4E6F21EB8B146F2C04F93B1C94234E6295F2F8773B16BA3D51758841EA48ADD1A626E252DB3B78594B4586AC9E9EAF100F294ADC82BEBBF8CAB96B671EE7050B42733EB741107C5D2199D305C84F93C6AEEE6BD607DB7C0EFED773FB1DB73B04EFA72EB36111B99EBE6EEE899307FD288329FB2DB7E81776AEF0F935FFEE77611BDCFEC309F97EEB6E36FE42CA4C8EFAA0B4B93F5D83606B8FA7B49DD1DBB8F828B9C805381CB5DF4AC7FFAE27C62CBCD2FE80BB4157EB7F3267041255AC2F7EA3B450951878166049E5FF1BD3B361082FB184E342DDA1961ACFD90944F37E09A06AFE463AA9AA66EE699D28C4D109F3E8111CF4D625161B2855C11593AE408AE44DC026091119744FF09A4AB3C00717ACA004E26ACA53BF6444D839CF477A56FEAFFBF2E4CB946512815269D8E3C163FC29288A917A4A0ACC6DF54454CE2D54AC79AE05BF816DE1E3E9D3A9CC69DBE674880F98ECB8D8D4C4247AC07BC9B7C40FB89C4B9D4DA4604B37D15047DFB28C5D241CDFA327C3996872A0C05B84342F81A308D7796CA4A4038E47A5D4658F757C3F9645F11DEA92AE4D2E77FDB1A5D12519FF947F39A68152528CB02F915894D728C0E755B8BC4A99FCFC778A4099558A06D5FECC4C22DAA7E23C3B5E8E99B5365D5046C8C65846D949A521C0B25EFE5F5CD0845F09C29C096C4A80755120A299EA652B204775E53B2D521F366F4EF9FA65B1D8CB048295C39BE92667200E2889B1577CBD0AC23B2280B758A3650BE60D55F215DBF166873592253B1254968B5A46A61C792A153342C3ADE408676F4B27B7F22C50B079D0E32AEA134168A53A36F18E2FFA2459EDBA89BEC13D19C342235F6E9CF8F721B608F6297A3486173A7D5CED5E2AF6343775668C1B1FB0B745157973D57B1B3B +20170627114331 2 6 100 6143 5 FE3AFB7EA9CBCB633757EA982ED0DDFF120459E69D35DB36ACC5F69B04A5CCEE59A0312A97687F2B3DBC20917F4BF0B16D97B75EDCA16B58BDEB8BB1A726F6CB8BF5D7FC483777129A1C19CB559943EF201323760672C63859E830C6E99AFE5DD7A4E89BAD41C63B687558DD277F4E06A29D1E14A21CAA6FDD4E6F21EB8B146F2C04F93B1C94234E6295F2F8773B16BA3D51758841EA48ADD1A626E252DB3B78594B4586AC9E9EAF100F294ADC82BEBBF8CAB96B671EE7050B42733EB741107C5D2199D305C84F93C6AEEE6BD607DB7C0EFED773FB1DB73B04EFA72EB36111B99EBE6EEE899307FD288329FB2DB7E81776AEF0F935FFEE77611BDCFEC309F97EEB6E36FE42CA4C8EFAA0B4B93F5D83606B8FA7B49DD1DBB8F828B9C805381CB5DF4AC7FFAE27C62CBCD2FE80BB4157EB7F3267041255AC2F7EA3B450951878166049E5FF1BD3B361082FB184E342DDA1961ACFD90944F37E09A06AFE463AA9AA66EE699D28C4D109F3E8111CF4D625161B2855C11593AE408AE44DC026091119744FF09A4AB3C00717ACA004E26ACA53BF6444D839CF477A56FEAFFBF2E4CB946512815269D8E3C163FC29288A917A4A0ACC6DF54454CE2D54AC79AE05BF816DE1E3E9D3A9CC69DBE674880F98ECB8D8D4C4247AC07BC9B7C40FB89C4B9D4DA4604B37D15047DFB28C5D241CDFA327C3996872A0C05B84342F81A308D7796CA4A4038E47A5D4658F757C3F9645F11DEA92AE4D2E77FDB1A5D12519FF947F39A68152528CB02F915894D728C0E755B8BC4A99FCFC778A4099558A06D5FECC4C22DAA7E23C3B5E8E99B5365D5046C8C65846D949A521C0B25EFE5F5CD0845F09C29C096C4A80755120A299EA652B204775E53B2D521F366F4EF9FA65B1D8CB048295C39BE92667200E2889B1577CBD0AC23B2280B758A3650BE60D55F215DBF166873592253B1254968B5A46A61C792A153342C3ADE408676F4B27B7F22C50B079D0E32AEA134168A53A36F18E2FFA2459EDBA89BEC13D19C342235F6E9CF8F721B608F6297A3486173A7D5CED5E2AF6343775668C1B1FB0B745157973D63E6527 +20170627143549 2 6 100 6143 2 FE3AFB7EA9CBCB633757EA982ED0DDFF120459E69D35DB36ACC5F69B04A5CCEE59A0312A97687F2B3DBC20917F4BF0B16D97B75EDCA16B58BDEB8BB1A726F6CB8BF5D7FC483777129A1C19CB559943EF201323760672C63859E830C6E99AFE5DD7A4E89BAD41C63B687558DD277F4E06A29D1E14A21CAA6FDD4E6F21EB8B146F2C04F93B1C94234E6295F2F8773B16BA3D51758841EA48ADD1A626E252DB3B78594B4586AC9E9EAF100F294ADC82BEBBF8CAB96B671EE7050B42733EB741107C5D2199D305C84F93C6AEEE6BD607DB7C0EFED773FB1DB73B04EFA72EB36111B99EBE6EEE899307FD288329FB2DB7E81776AEF0F935FFEE77611BDCFEC309F97EEB6E36FE42CA4C8EFAA0B4B93F5D83606B8FA7B49DD1DBB8F828B9C805381CB5DF4AC7FFAE27C62CBCD2FE80BB4157EB7F3267041255AC2F7EA3B450951878166049E5FF1BD3B361082FB184E342DDA1961ACFD90944F37E09A06AFE463AA9AA66EE699D28C4D109F3E8111CF4D625161B2855C11593AE408AE44DC026091119744FF09A4AB3C00717ACA004E26ACA53BF6444D839CF477A56FEAFFBF2E4CB946512815269D8E3C163FC29288A917A4A0ACC6DF54454CE2D54AC79AE05BF816DE1E3E9D3A9CC69DBE674880F98ECB8D8D4C4247AC07BC9B7C40FB89C4B9D4DA4604B37D15047DFB28C5D241CDFA327C3996872A0C05B84342F81A308D7796CA4A4038E47A5D4658F757C3F9645F11DEA92AE4D2E77FDB1A5D12519FF947F39A68152528CB02F915894D728C0E755B8BC4A99FCFC778A4099558A06D5FECC4C22DAA7E23C3B5E8E99B5365D5046C8C65846D949A521C0B25EFE5F5CD0845F09C29C096C4A80755120A299EA652B204775E53B2D521F366F4EF9FA65B1D8CB048295C39BE92667200E2889B1577CBD0AC23B2280B758A3650BE60D55F215DBF166873592253B1254968B5A46A61C792A153342C3ADE408676F4B27B7F22C50B079D0E32AEA134168A53A36F18E2FFA2459EDBA89BEC13D19C342235F6E9CF8F721B608F6297A3486173A7D5CED5E2AF6343775668C1B1FB0B745157973DA76351B +20170627150713 2 6 100 6143 2 FE3AFB7EA9CBCB633757EA982ED0DDFF120459E69D35DB36ACC5F69B04A5CCEE59A0312A97687F2B3DBC20917F4BF0B16D97B75EDCA16B58BDEB8BB1A726F6CB8BF5D7FC483777129A1C19CB559943EF201323760672C63859E830C6E99AFE5DD7A4E89BAD41C63B687558DD277F4E06A29D1E14A21CAA6FDD4E6F21EB8B146F2C04F93B1C94234E6295F2F8773B16BA3D51758841EA48ADD1A626E252DB3B78594B4586AC9E9EAF100F294ADC82BEBBF8CAB96B671EE7050B42733EB741107C5D2199D305C84F93C6AEEE6BD607DB7C0EFED773FB1DB73B04EFA72EB36111B99EBE6EEE899307FD288329FB2DB7E81776AEF0F935FFEE77611BDCFEC309F97EEB6E36FE42CA4C8EFAA0B4B93F5D83606B8FA7B49DD1DBB8F828B9C805381CB5DF4AC7FFAE27C62CBCD2FE80BB4157EB7F3267041255AC2F7EA3B450951878166049E5FF1BD3B361082FB184E342DDA1961ACFD90944F37E09A06AFE463AA9AA66EE699D28C4D109F3E8111CF4D625161B2855C11593AE408AE44DC026091119744FF09A4AB3C00717ACA004E26ACA53BF6444D839CF477A56FEAFFBF2E4CB946512815269D8E3C163FC29288A917A4A0ACC6DF54454CE2D54AC79AE05BF816DE1E3E9D3A9CC69DBE674880F98ECB8D8D4C4247AC07BC9B7C40FB89C4B9D4DA4604B37D15047DFB28C5D241CDFA327C3996872A0C05B84342F81A308D7796CA4A4038E47A5D4658F757C3F9645F11DEA92AE4D2E77FDB1A5D12519FF947F39A68152528CB02F915894D728C0E755B8BC4A99FCFC778A4099558A06D5FECC4C22DAA7E23C3B5E8E99B5365D5046C8C65846D949A521C0B25EFE5F5CD0845F09C29C096C4A80755120A299EA652B204775E53B2D521F366F4EF9FA65B1D8CB048295C39BE92667200E2889B1577CBD0AC23B2280B758A3650BE60D55F215DBF166873592253B1254968B5A46A61C792A153342C3ADE408676F4B27B7F22C50B079D0E32AEA134168A53A36F18E2FFA2459EDBA89BEC13D19C342235F6E9CF8F721B608F6297A3486173A7D5CED5E2AF6343775668C1B1FB0B745157973DB2FF40B +20170627151417 2 6 100 6143 2 FE3AFB7EA9CBCB633757EA982ED0DDFF120459E69D35DB36ACC5F69B04A5CCEE59A0312A97687F2B3DBC20917F4BF0B16D97B75EDCA16B58BDEB8BB1A726F6CB8BF5D7FC483777129A1C19CB559943EF201323760672C63859E830C6E99AFE5DD7A4E89BAD41C63B687558DD277F4E06A29D1E14A21CAA6FDD4E6F21EB8B146F2C04F93B1C94234E6295F2F8773B16BA3D51758841EA48ADD1A626E252DB3B78594B4586AC9E9EAF100F294ADC82BEBBF8CAB96B671EE7050B42733EB741107C5D2199D305C84F93C6AEEE6BD607DB7C0EFED773FB1DB73B04EFA72EB36111B99EBE6EEE899307FD288329FB2DB7E81776AEF0F935FFEE77611BDCFEC309F97EEB6E36FE42CA4C8EFAA0B4B93F5D83606B8FA7B49DD1DBB8F828B9C805381CB5DF4AC7FFAE27C62CBCD2FE80BB4157EB7F3267041255AC2F7EA3B450951878166049E5FF1BD3B361082FB184E342DDA1961ACFD90944F37E09A06AFE463AA9AA66EE699D28C4D109F3E8111CF4D625161B2855C11593AE408AE44DC026091119744FF09A4AB3C00717ACA004E26ACA53BF6444D839CF477A56FEAFFBF2E4CB946512815269D8E3C163FC29288A917A4A0ACC6DF54454CE2D54AC79AE05BF816DE1E3E9D3A9CC69DBE674880F98ECB8D8D4C4247AC07BC9B7C40FB89C4B9D4DA4604B37D15047DFB28C5D241CDFA327C3996872A0C05B84342F81A308D7796CA4A4038E47A5D4658F757C3F9645F11DEA92AE4D2E77FDB1A5D12519FF947F39A68152528CB02F915894D728C0E755B8BC4A99FCFC778A4099558A06D5FECC4C22DAA7E23C3B5E8E99B5365D5046C8C65846D949A521C0B25EFE5F5CD0845F09C29C096C4A80755120A299EA652B204775E53B2D521F366F4EF9FA65B1D8CB048295C39BE92667200E2889B1577CBD0AC23B2280B758A3650BE60D55F215DBF166873592253B1254968B5A46A61C792A153342C3ADE408676F4B27B7F22C50B079D0E32AEA134168A53A36F18E2FFA2459EDBA89BEC13D19C342235F6E9CF8F721B608F6297A3486173A7D5CED5E2AF6343775668C1B1FB0B745157973DB566CC3 +20170627162358 2 6 100 6143 5 FE3AFB7EA9CBCB633757EA982ED0DDFF120459E69D35DB36ACC5F69B04A5CCEE59A0312A97687F2B3DBC20917F4BF0B16D97B75EDCA16B58BDEB8BB1A726F6CB8BF5D7FC483777129A1C19CB559943EF201323760672C63859E830C6E99AFE5DD7A4E89BAD41C63B687558DD277F4E06A29D1E14A21CAA6FDD4E6F21EB8B146F2C04F93B1C94234E6295F2F8773B16BA3D51758841EA48ADD1A626E252DB3B78594B4586AC9E9EAF100F294ADC82BEBBF8CAB96B671EE7050B42733EB741107C5D2199D305C84F93C6AEEE6BD607DB7C0EFED773FB1DB73B04EFA72EB36111B99EBE6EEE899307FD288329FB2DB7E81776AEF0F935FFEE77611BDCFEC309F97EEB6E36FE42CA4C8EFAA0B4B93F5D83606B8FA7B49DD1DBB8F828B9C805381CB5DF4AC7FFAE27C62CBCD2FE80BB4157EB7F3267041255AC2F7EA3B450951878166049E5FF1BD3B361082FB184E342DDA1961ACFD90944F37E09A06AFE463AA9AA66EE699D28C4D109F3E8111CF4D625161B2855C11593AE408AE44DC026091119744FF09A4AB3C00717ACA004E26ACA53BF6444D839CF477A56FEAFFBF2E4CB946512815269D8E3C163FC29288A917A4A0ACC6DF54454CE2D54AC79AE05BF816DE1E3E9D3A9CC69DBE674880F98ECB8D8D4C4247AC07BC9B7C40FB89C4B9D4DA4604B37D15047DFB28C5D241CDFA327C3996872A0C05B84342F81A308D7796CA4A4038E47A5D4658F757C3F9645F11DEA92AE4D2E77FDB1A5D12519FF947F39A68152528CB02F915894D728C0E755B8BC4A99FCFC778A4099558A06D5FECC4C22DAA7E23C3B5E8E99B5365D5046C8C65846D949A521C0B25EFE5F5CD0845F09C29C096C4A80755120A299EA652B204775E53B2D521F366F4EF9FA65B1D8CB048295C39BE92667200E2889B1577CBD0AC23B2280B758A3650BE60D55F215DBF166873592253B1254968B5A46A61C792A153342C3ADE408676F4B27B7F22C50B079D0E32AEA134168A53A36F18E2FFA2459EDBA89BEC13D19C342235F6E9CF8F721B608F6297A3486173A7D5CED5E2AF6343775668C1B1FB0B745157973DD096627 +20170627175138 2 6 100 6143 5 FE3AFB7EA9CBCB633757EA982ED0DDFF120459E69D35DB36ACC5F69B04A5CCEE59A0312A97687F2B3DBC20917F4BF0B16D97B75EDCA16B58BDEB8BB1A726F6CB8BF5D7FC483777129A1C19CB559943EF201323760672C63859E830C6E99AFE5DD7A4E89BAD41C63B687558DD277F4E06A29D1E14A21CAA6FDD4E6F21EB8B146F2C04F93B1C94234E6295F2F8773B16BA3D51758841EA48ADD1A626E252DB3B78594B4586AC9E9EAF100F294ADC82BEBBF8CAB96B671EE7050B42733EB741107C5D2199D305C84F93C6AEEE6BD607DB7C0EFED773FB1DB73B04EFA72EB36111B99EBE6EEE899307FD288329FB2DB7E81776AEF0F935FFEE77611BDCFEC309F97EEB6E36FE42CA4C8EFAA0B4B93F5D83606B8FA7B49DD1DBB8F828B9C805381CB5DF4AC7FFAE27C62CBCD2FE80BB4157EB7F3267041255AC2F7EA3B450951878166049E5FF1BD3B361082FB184E342DDA1961ACFD90944F37E09A06AFE463AA9AA66EE699D28C4D109F3E8111CF4D625161B2855C11593AE408AE44DC026091119744FF09A4AB3C00717ACA004E26ACA53BF6444D839CF477A56FEAFFBF2E4CB946512815269D8E3C163FC29288A917A4A0ACC6DF54454CE2D54AC79AE05BF816DE1E3E9D3A9CC69DBE674880F98ECB8D8D4C4247AC07BC9B7C40FB89C4B9D4DA4604B37D15047DFB28C5D241CDFA327C3996872A0C05B84342F81A308D7796CA4A4038E47A5D4658F757C3F9645F11DEA92AE4D2E77FDB1A5D12519FF947F39A68152528CB02F915894D728C0E755B8BC4A99FCFC778A4099558A06D5FECC4C22DAA7E23C3B5E8E99B5365D5046C8C65846D949A521C0B25EFE5F5CD0845F09C29C096C4A80755120A299EA652B204775E53B2D521F366F4EF9FA65B1D8CB048295C39BE92667200E2889B1577CBD0AC23B2280B758A3650BE60D55F215DBF166873592253B1254968B5A46A61C792A153342C3ADE408676F4B27B7F22C50B079D0E32AEA134168A53A36F18E2FFA2459EDBA89BEC13D19C342235F6E9CF8F721B608F6297A3486173A7D5CED5E2AF6343775668C1B1FB0B745157973DF2B3477 +20170627180034 2 6 100 6143 2 FE3AFB7EA9CBCB633757EA982ED0DDFF120459E69D35DB36ACC5F69B04A5CCEE59A0312A97687F2B3DBC20917F4BF0B16D97B75EDCA16B58BDEB8BB1A726F6CB8BF5D7FC483777129A1C19CB559943EF201323760672C63859E830C6E99AFE5DD7A4E89BAD41C63B687558DD277F4E06A29D1E14A21CAA6FDD4E6F21EB8B146F2C04F93B1C94234E6295F2F8773B16BA3D51758841EA48ADD1A626E252DB3B78594B4586AC9E9EAF100F294ADC82BEBBF8CAB96B671EE7050B42733EB741107C5D2199D305C84F93C6AEEE6BD607DB7C0EFED773FB1DB73B04EFA72EB36111B99EBE6EEE899307FD288329FB2DB7E81776AEF0F935FFEE77611BDCFEC309F97EEB6E36FE42CA4C8EFAA0B4B93F5D83606B8FA7B49DD1DBB8F828B9C805381CB5DF4AC7FFAE27C62CBCD2FE80BB4157EB7F3267041255AC2F7EA3B450951878166049E5FF1BD3B361082FB184E342DDA1961ACFD90944F37E09A06AFE463AA9AA66EE699D28C4D109F3E8111CF4D625161B2855C11593AE408AE44DC026091119744FF09A4AB3C00717ACA004E26ACA53BF6444D839CF477A56FEAFFBF2E4CB946512815269D8E3C163FC29288A917A4A0ACC6DF54454CE2D54AC79AE05BF816DE1E3E9D3A9CC69DBE674880F98ECB8D8D4C4247AC07BC9B7C40FB89C4B9D4DA4604B37D15047DFB28C5D241CDFA327C3996872A0C05B84342F81A308D7796CA4A4038E47A5D4658F757C3F9645F11DEA92AE4D2E77FDB1A5D12519FF947F39A68152528CB02F915894D728C0E755B8BC4A99FCFC778A4099558A06D5FECC4C22DAA7E23C3B5E8E99B5365D5046C8C65846D949A521C0B25EFE5F5CD0845F09C29C096C4A80755120A299EA652B204775E53B2D521F366F4EF9FA65B1D8CB048295C39BE92667200E2889B1577CBD0AC23B2280B758A3650BE60D55F215DBF166873592253B1254968B5A46A61C792A153342C3ADE408676F4B27B7F22C50B079D0E32AEA134168A53A36F18E2FFA2459EDBA89BEC13D19C342235F6E9CF8F721B608F6297A3486173A7D5CED5E2AF6343775668C1B1FB0B745157973DF5CD463 +20170627192816 2 6 100 6143 2 FE3AFB7EA9CBCB633757EA982ED0DDFF120459E69D35DB36ACC5F69B04A5CCEE59A0312A97687F2B3DBC20917F4BF0B16D97B75EDCA16B58BDEB8BB1A726F6CB8BF5D7FC483777129A1C19CB559943EF201323760672C63859E830C6E99AFE5DD7A4E89BAD41C63B687558DD277F4E06A29D1E14A21CAA6FDD4E6F21EB8B146F2C04F93B1C94234E6295F2F8773B16BA3D51758841EA48ADD1A626E252DB3B78594B4586AC9E9EAF100F294ADC82BEBBF8CAB96B671EE7050B42733EB741107C5D2199D305C84F93C6AEEE6BD607DB7C0EFED773FB1DB73B04EFA72EB36111B99EBE6EEE899307FD288329FB2DB7E81776AEF0F935FFEE77611BDCFEC309F97EEB6E36FE42CA4C8EFAA0B4B93F5D83606B8FA7B49DD1DBB8F828B9C805381CB5DF4AC7FFAE27C62CBCD2FE80BB4157EB7F3267041255AC2F7EA3B450951878166049E5FF1BD3B361082FB184E342DDA1961ACFD90944F37E09A06AFE463AA9AA66EE699D28C4D109F3E8111CF4D625161B2855C11593AE408AE44DC026091119744FF09A4AB3C00717ACA004E26ACA53BF6444D839CF477A56FEAFFBF2E4CB946512815269D8E3C163FC29288A917A4A0ACC6DF54454CE2D54AC79AE05BF816DE1E3E9D3A9CC69DBE674880F98ECB8D8D4C4247AC07BC9B7C40FB89C4B9D4DA4604B37D15047DFB28C5D241CDFA327C3996872A0C05B84342F81A308D7796CA4A4038E47A5D4658F757C3F9645F11DEA92AE4D2E77FDB1A5D12519FF947F39A68152528CB02F915894D728C0E755B8BC4A99FCFC778A4099558A06D5FECC4C22DAA7E23C3B5E8E99B5365D5046C8C65846D949A521C0B25EFE5F5CD0845F09C29C096C4A80755120A299EA652B204775E53B2D521F366F4EF9FA65B1D8CB048295C39BE92667200E2889B1577CBD0AC23B2280B758A3650BE60D55F215DBF166873592253B1254968B5A46A61C792A153342C3ADE408676F4B27B7F22C50B079D0E32AEA134168A53A36F18E2FFA2459EDBA89BEC13D19C342235F6E9CF8F721B608F6297A3486173A7D5CED5E2AF6343775668C1B1FB0B745157973E16B337B +20170627194138 2 6 100 6143 2 FE3AFB7EA9CBCB633757EA982ED0DDFF120459E69D35DB36ACC5F69B04A5CCEE59A0312A97687F2B3DBC20917F4BF0B16D97B75EDCA16B58BDEB8BB1A726F6CB8BF5D7FC483777129A1C19CB559943EF201323760672C63859E830C6E99AFE5DD7A4E89BAD41C63B687558DD277F4E06A29D1E14A21CAA6FDD4E6F21EB8B146F2C04F93B1C94234E6295F2F8773B16BA3D51758841EA48ADD1A626E252DB3B78594B4586AC9E9EAF100F294ADC82BEBBF8CAB96B671EE7050B42733EB741107C5D2199D305C84F93C6AEEE6BD607DB7C0EFED773FB1DB73B04EFA72EB36111B99EBE6EEE899307FD288329FB2DB7E81776AEF0F935FFEE77611BDCFEC309F97EEB6E36FE42CA4C8EFAA0B4B93F5D83606B8FA7B49DD1DBB8F828B9C805381CB5DF4AC7FFAE27C62CBCD2FE80BB4157EB7F3267041255AC2F7EA3B450951878166049E5FF1BD3B361082FB184E342DDA1961ACFD90944F37E09A06AFE463AA9AA66EE699D28C4D109F3E8111CF4D625161B2855C11593AE408AE44DC026091119744FF09A4AB3C00717ACA004E26ACA53BF6444D839CF477A56FEAFFBF2E4CB946512815269D8E3C163FC29288A917A4A0ACC6DF54454CE2D54AC79AE05BF816DE1E3E9D3A9CC69DBE674880F98ECB8D8D4C4247AC07BC9B7C40FB89C4B9D4DA4604B37D15047DFB28C5D241CDFA327C3996872A0C05B84342F81A308D7796CA4A4038E47A5D4658F757C3F9645F11DEA92AE4D2E77FDB1A5D12519FF947F39A68152528CB02F915894D728C0E755B8BC4A99FCFC778A4099558A06D5FECC4C22DAA7E23C3B5E8E99B5365D5046C8C65846D949A521C0B25EFE5F5CD0845F09C29C096C4A80755120A299EA652B204775E53B2D521F366F4EF9FA65B1D8CB048295C39BE92667200E2889B1577CBD0AC23B2280B758A3650BE60D55F215DBF166873592253B1254968B5A46A61C792A153342C3ADE408676F4B27B7F22C50B079D0E32AEA134168A53A36F18E2FFA2459EDBA89BEC13D19C342235F6E9CF8F721B608F6297A3486173A7D5CED5E2AF6343775668C1B1FB0B745157973E1B23A4B +20170627235654 2 6 100 7679 2 E411B879FDA69428A30BDE74B417706E5936E16C5E1F2B64A07EAE1D69C857C23126701460740D93467EB3A3386827E658069CAC4D55CC4929493C193D53A0D91141135B2F0B19E659BB541883E569D38B329761EDF3C409D34A49870356F3723AD2F720383E49B1752B837DF80F48632A469A0A96AC8F02E5B766B590D722B5BD3ED9191BB70C1D4044A3D5CE850489216C3184D73BAE2B655D76B30EC1851951A756E2A45CD1FF82A83BDC1803005034BEB2EAC35FF7362831D8FBE02E07B1CCA351D47AD65B5282151FB2711A880410CED2C1CF205CC2072F6F244189F5BDB3AFDBA7FB02DD21C99D1EF72C1EF8BC6C68A273D16CB2D3CA190C30BDDEEAD7CA2E519F3AF806B5CBD436B971C1F1981EB35CB4007D129F43E660F7E47E807C889A1DC5FEFA7C304DB41B36982FEFB7390DC6C8E9474D3EEB84B3F757C367475EB1B4CB5B86F9507090F2CB37533E2B96BBC6F75B3BF1F4CECF18F67E7492A681845CF5AFA1B70FB3B0A09CDD3375BCF716CBF2A594533D157CB6C4008CF8C4818C9418E44A995028487B0346BD399BFB431CA94B3FC2AF9822520153105ADACEBE719CC24D1D043AC2AC24BD41759AA452000C43CB885D5F0D71DC2451A2C5C04B0B085BD23B5295B7A109DCD729C34479D51EAB4617FDD163128B25F5803B262C3D97E2D63B3E84D85B67ECDFDE6FA377E208BD2EF867072D341AC731338268AD82285DD6D219DE44EB0588E477CBFCD5F5C068D2FA877339424F324012D346C3E2B3C4408E4FD84535C5D4EA02137ABE0426BC4C3AD6EABAA221579CBA22023F8204ECCC98D143652DEBF5869CD73A81C0E4C6FC9A22F9E648B6783AA1D0F0A1F76B1C4E8692339A6A259F3D8419CF7FD22A26023678BFE4F70C79E7F113882E6C7A0606C5AA9094DB161683E43CCEC8C73FEBC7B82617B90541C2BC15EBA18B55E430373CF21DD235BA332EE6D7A6D042BAB4DEF94939AAD2A1F6FD235B09CA6CCFB45A614C79F3C83253B82BB73826DD22127F3F14292A9B682D607D6C9313DF5324712F976C8978AEDC97B40095E66BF850BCB83F477E1F5AB045844EA5CA0652C7C2C284B90FFDCAE2D5F3C165F66FCE871A5D0AFAA158E77099BFA7A969C8F3425E326D24E7E875D588B5E652ED331ABE4A72AFF7D89CFA9D55116B2610AEA4D1D16BCE1FE8D22849827677FEC8EC9864F5A4B874E7AA3228E31DACECA3ED7E1F31675CCA03E599E748BBCA483821DDC5F1C7ED376EDE7A650AD06CE3FC4E76062354B7D89093EBBF9717CED067846349E8BBEEC4CDDE0907F2DD1C31125F1DBB7B9A94E07677C4EBC756A5ED3D8DB30FB5772328272C6CE22848CB +20170628025708 2 6 100 7679 2 E411B879FDA69428A30BDE74B417706E5936E16C5E1F2B64A07EAE1D69C857C23126701460740D93467EB3A3386827E658069CAC4D55CC4929493C193D53A0D91141135B2F0B19E659BB541883E569D38B329761EDF3C409D34A49870356F3723AD2F720383E49B1752B837DF80F48632A469A0A96AC8F02E5B766B590D722B5BD3ED9191BB70C1D4044A3D5CE850489216C3184D73BAE2B655D76B30EC1851951A756E2A45CD1FF82A83BDC1803005034BEB2EAC35FF7362831D8FBE02E07B1CCA351D47AD65B5282151FB2711A880410CED2C1CF205CC2072F6F244189F5BDB3AFDBA7FB02DD21C99D1EF72C1EF8BC6C68A273D16CB2D3CA190C30BDDEEAD7CA2E519F3AF806B5CBD436B971C1F1981EB35CB4007D129F43E660F7E47E807C889A1DC5FEFA7C304DB41B36982FEFB7390DC6C8E9474D3EEB84B3F757C367475EB1B4CB5B86F9507090F2CB37533E2B96BBC6F75B3BF1F4CECF18F67E7492A681845CF5AFA1B70FB3B0A09CDD3375BCF716CBF2A594533D157CB6C4008CF8C4818C9418E44A995028487B0346BD399BFB431CA94B3FC2AF9822520153105ADACEBE719CC24D1D043AC2AC24BD41759AA452000C43CB885D5F0D71DC2451A2C5C04B0B085BD23B5295B7A109DCD729C34479D51EAB4617FDD163128B25F5803B262C3D97E2D63B3E84D85B67ECDFDE6FA377E208BD2EF867072D341AC731338268AD82285DD6D219DE44EB0588E477CBFCD5F5C068D2FA877339424F324012D346C3E2B3C4408E4FD84535C5D4EA02137ABE0426BC4C3AD6EABAA221579CBA22023F8204ECCC98D143652DEBF5869CD73A81C0E4C6FC9A22F9E648B6783AA1D0F0A1F76B1C4E8692339A6A259F3D8419CF7FD22A26023678BFE4F70C79E7F113882E6C7A0606C5AA9094DB161683E43CCEC8C73FEBC7B82617B90541C2BC15EBA18B55E430373CF21DD235BA332EE6D7A6D042BAB4DEF94939AAD2A1F6FD235B09CA6CCFB45A614C79F3C83253B82BB73826DD22127F3F14292A9B682D607D6C9313DF5324712F976C8978AEDC97B40095E66BF850BCB83F477E1F5AB045844EA5CA0652C7C2C284B90FFDCAE2D5F3C165F66FCE871A5D0AFAA158E77099BFA7A969C8F3425E326D24E7E875D588B5E652ED331ABE4A72AFF7D89CFA9D55116B2610AEA4D1D16BCE1FE8D22849827677FEC8EC9864F5A4B874E7AA3228E31DACECA3ED7E1F31675CCA03E599E748BBCA483821DDC5F1C7ED376EDE7A650AD06CE3FC4E76062354B7D89093EBBF9717CED067846349E8BBEEC4CDDE0907F2DD1C31125F1DBB7B9A94E07677C4EBC756A5ED3D8DB30FB5772328272C6CE4C7FC03 +20170628090844 2 6 100 7679 5 E411B879FDA69428A30BDE74B417706E5936E16C5E1F2B64A07EAE1D69C857C23126701460740D93467EB3A3386827E658069CAC4D55CC4929493C193D53A0D91141135B2F0B19E659BB541883E569D38B329761EDF3C409D34A49870356F3723AD2F720383E49B1752B837DF80F48632A469A0A96AC8F02E5B766B590D722B5BD3ED9191BB70C1D4044A3D5CE850489216C3184D73BAE2B655D76B30EC1851951A756E2A45CD1FF82A83BDC1803005034BEB2EAC35FF7362831D8FBE02E07B1CCA351D47AD65B5282151FB2711A880410CED2C1CF205CC2072F6F244189F5BDB3AFDBA7FB02DD21C99D1EF72C1EF8BC6C68A273D16CB2D3CA190C30BDDEEAD7CA2E519F3AF806B5CBD436B971C1F1981EB35CB4007D129F43E660F7E47E807C889A1DC5FEFA7C304DB41B36982FEFB7390DC6C8E9474D3EEB84B3F757C367475EB1B4CB5B86F9507090F2CB37533E2B96BBC6F75B3BF1F4CECF18F67E7492A681845CF5AFA1B70FB3B0A09CDD3375BCF716CBF2A594533D157CB6C4008CF8C4818C9418E44A995028487B0346BD399BFB431CA94B3FC2AF9822520153105ADACEBE719CC24D1D043AC2AC24BD41759AA452000C43CB885D5F0D71DC2451A2C5C04B0B085BD23B5295B7A109DCD729C34479D51EAB4617FDD163128B25F5803B262C3D97E2D63B3E84D85B67ECDFDE6FA377E208BD2EF867072D341AC731338268AD82285DD6D219DE44EB0588E477CBFCD5F5C068D2FA877339424F324012D346C3E2B3C4408E4FD84535C5D4EA02137ABE0426BC4C3AD6EABAA221579CBA22023F8204ECCC98D143652DEBF5869CD73A81C0E4C6FC9A22F9E648B6783AA1D0F0A1F76B1C4E8692339A6A259F3D8419CF7FD22A26023678BFE4F70C79E7F113882E6C7A0606C5AA9094DB161683E43CCEC8C73FEBC7B82617B90541C2BC15EBA18B55E430373CF21DD235BA332EE6D7A6D042BAB4DEF94939AAD2A1F6FD235B09CA6CCFB45A614C79F3C83253B82BB73826DD22127F3F14292A9B682D607D6C9313DF5324712F976C8978AEDC97B40095E66BF850BCB83F477E1F5AB045844EA5CA0652C7C2C284B90FFDCAE2D5F3C165F66FCE871A5D0AFAA158E77099BFA7A969C8F3425E326D24E7E875D588B5E652ED331ABE4A72AFF7D89CFA9D55116B2610AEA4D1D16BCE1FE8D22849827677FEC8EC9864F5A4B874E7AA3228E31DACECA3ED7E1F31675CCA03E599E748BBCA483821DDC5F1C7ED376EDE7A650AD06CE3FC4E76062354B7D89093EBBF9717CED067846349E8BBEEC4CDDE0907F2DD1C31125F1DBB7B9A94E07677C4EBC756A5ED3D8DB30FB5772328272C6CEA316C0F +20170628104935 2 6 100 7679 2 E411B879FDA69428A30BDE74B417706E5936E16C5E1F2B64A07EAE1D69C857C23126701460740D93467EB3A3386827E658069CAC4D55CC4929493C193D53A0D91141135B2F0B19E659BB541883E569D38B329761EDF3C409D34A49870356F3723AD2F720383E49B1752B837DF80F48632A469A0A96AC8F02E5B766B590D722B5BD3ED9191BB70C1D4044A3D5CE850489216C3184D73BAE2B655D76B30EC1851951A756E2A45CD1FF82A83BDC1803005034BEB2EAC35FF7362831D8FBE02E07B1CCA351D47AD65B5282151FB2711A880410CED2C1CF205CC2072F6F244189F5BDB3AFDBA7FB02DD21C99D1EF72C1EF8BC6C68A273D16CB2D3CA190C30BDDEEAD7CA2E519F3AF806B5CBD436B971C1F1981EB35CB4007D129F43E660F7E47E807C889A1DC5FEFA7C304DB41B36982FEFB7390DC6C8E9474D3EEB84B3F757C367475EB1B4CB5B86F9507090F2CB37533E2B96BBC6F75B3BF1F4CECF18F67E7492A681845CF5AFA1B70FB3B0A09CDD3375BCF716CBF2A594533D157CB6C4008CF8C4818C9418E44A995028487B0346BD399BFB431CA94B3FC2AF9822520153105ADACEBE719CC24D1D043AC2AC24BD41759AA452000C43CB885D5F0D71DC2451A2C5C04B0B085BD23B5295B7A109DCD729C34479D51EAB4617FDD163128B25F5803B262C3D97E2D63B3E84D85B67ECDFDE6FA377E208BD2EF867072D341AC731338268AD82285DD6D219DE44EB0588E477CBFCD5F5C068D2FA877339424F324012D346C3E2B3C4408E4FD84535C5D4EA02137ABE0426BC4C3AD6EABAA221579CBA22023F8204ECCC98D143652DEBF5869CD73A81C0E4C6FC9A22F9E648B6783AA1D0F0A1F76B1C4E8692339A6A259F3D8419CF7FD22A26023678BFE4F70C79E7F113882E6C7A0606C5AA9094DB161683E43CCEC8C73FEBC7B82617B90541C2BC15EBA18B55E430373CF21DD235BA332EE6D7A6D042BAB4DEF94939AAD2A1F6FD235B09CA6CCFB45A614C79F3C83253B82BB73826DD22127F3F14292A9B682D607D6C9313DF5324712F976C8978AEDC97B40095E66BF850BCB83F477E1F5AB045844EA5CA0652C7C2C284B90FFDCAE2D5F3C165F66FCE871A5D0AFAA158E77099BFA7A969C8F3425E326D24E7E875D588B5E652ED331ABE4A72AFF7D89CFA9D55116B2610AEA4D1D16BCE1FE8D22849827677FEC8EC9864F5A4B874E7AA3228E31DACECA3ED7E1F31675CCA03E599E748BBCA483821DDC5F1C7ED376EDE7A650AD06CE3FC4E76062354B7D89093EBBF9717CED067846349E8BBEEC4CDDE0907F2DD1C31125F1DBB7B9A94E07677C4EBC756A5ED3D8DB30FB5772328272C6CEB9D111B +20170628114328 2 6 100 7679 2 E411B879FDA69428A30BDE74B417706E5936E16C5E1F2B64A07EAE1D69C857C23126701460740D93467EB3A3386827E658069CAC4D55CC4929493C193D53A0D91141135B2F0B19E659BB541883E569D38B329761EDF3C409D34A49870356F3723AD2F720383E49B1752B837DF80F48632A469A0A96AC8F02E5B766B590D722B5BD3ED9191BB70C1D4044A3D5CE850489216C3184D73BAE2B655D76B30EC1851951A756E2A45CD1FF82A83BDC1803005034BEB2EAC35FF7362831D8FBE02E07B1CCA351D47AD65B5282151FB2711A880410CED2C1CF205CC2072F6F244189F5BDB3AFDBA7FB02DD21C99D1EF72C1EF8BC6C68A273D16CB2D3CA190C30BDDEEAD7CA2E519F3AF806B5CBD436B971C1F1981EB35CB4007D129F43E660F7E47E807C889A1DC5FEFA7C304DB41B36982FEFB7390DC6C8E9474D3EEB84B3F757C367475EB1B4CB5B86F9507090F2CB37533E2B96BBC6F75B3BF1F4CECF18F67E7492A681845CF5AFA1B70FB3B0A09CDD3375BCF716CBF2A594533D157CB6C4008CF8C4818C9418E44A995028487B0346BD399BFB431CA94B3FC2AF9822520153105ADACEBE719CC24D1D043AC2AC24BD41759AA452000C43CB885D5F0D71DC2451A2C5C04B0B085BD23B5295B7A109DCD729C34479D51EAB4617FDD163128B25F5803B262C3D97E2D63B3E84D85B67ECDFDE6FA377E208BD2EF867072D341AC731338268AD82285DD6D219DE44EB0588E477CBFCD5F5C068D2FA877339424F324012D346C3E2B3C4408E4FD84535C5D4EA02137ABE0426BC4C3AD6EABAA221579CBA22023F8204ECCC98D143652DEBF5869CD73A81C0E4C6FC9A22F9E648B6783AA1D0F0A1F76B1C4E8692339A6A259F3D8419CF7FD22A26023678BFE4F70C79E7F113882E6C7A0606C5AA9094DB161683E43CCEC8C73FEBC7B82617B90541C2BC15EBA18B55E430373CF21DD235BA332EE6D7A6D042BAB4DEF94939AAD2A1F6FD235B09CA6CCFB45A614C79F3C83253B82BB73826DD22127F3F14292A9B682D607D6C9313DF5324712F976C8978AEDC97B40095E66BF850BCB83F477E1F5AB045844EA5CA0652C7C2C284B90FFDCAE2D5F3C165F66FCE871A5D0AFAA158E77099BFA7A969C8F3425E326D24E7E875D588B5E652ED331ABE4A72AFF7D89CFA9D55116B2610AEA4D1D16BCE1FE8D22849827677FEC8EC9864F5A4B874E7AA3228E31DACECA3ED7E1F31675CCA03E599E748BBCA483821DDC5F1C7ED376EDE7A650AD06CE3FC4E76062354B7D89093EBBF9717CED067846349E8BBEEC4CDDE0907F2DD1C31125F1DBB7B9A94E07677C4EBC756A5ED3D8DB30FB5772328272C6CEC57837B +20170628155547 2 6 100 7679 5 E411B879FDA69428A30BDE74B417706E5936E16C5E1F2B64A07EAE1D69C857C23126701460740D93467EB3A3386827E658069CAC4D55CC4929493C193D53A0D91141135B2F0B19E659BB541883E569D38B329761EDF3C409D34A49870356F3723AD2F720383E49B1752B837DF80F48632A469A0A96AC8F02E5B766B590D722B5BD3ED9191BB70C1D4044A3D5CE850489216C3184D73BAE2B655D76B30EC1851951A756E2A45CD1FF82A83BDC1803005034BEB2EAC35FF7362831D8FBE02E07B1CCA351D47AD65B5282151FB2711A880410CED2C1CF205CC2072F6F244189F5BDB3AFDBA7FB02DD21C99D1EF72C1EF8BC6C68A273D16CB2D3CA190C30BDDEEAD7CA2E519F3AF806B5CBD436B971C1F1981EB35CB4007D129F43E660F7E47E807C889A1DC5FEFA7C304DB41B36982FEFB7390DC6C8E9474D3EEB84B3F757C367475EB1B4CB5B86F9507090F2CB37533E2B96BBC6F75B3BF1F4CECF18F67E7492A681845CF5AFA1B70FB3B0A09CDD3375BCF716CBF2A594533D157CB6C4008CF8C4818C9418E44A995028487B0346BD399BFB431CA94B3FC2AF9822520153105ADACEBE719CC24D1D043AC2AC24BD41759AA452000C43CB885D5F0D71DC2451A2C5C04B0B085BD23B5295B7A109DCD729C34479D51EAB4617FDD163128B25F5803B262C3D97E2D63B3E84D85B67ECDFDE6FA377E208BD2EF867072D341AC731338268AD82285DD6D219DE44EB0588E477CBFCD5F5C068D2FA877339424F324012D346C3E2B3C4408E4FD84535C5D4EA02137ABE0426BC4C3AD6EABAA221579CBA22023F8204ECCC98D143652DEBF5869CD73A81C0E4C6FC9A22F9E648B6783AA1D0F0A1F76B1C4E8692339A6A259F3D8419CF7FD22A26023678BFE4F70C79E7F113882E6C7A0606C5AA9094DB161683E43CCEC8C73FEBC7B82617B90541C2BC15EBA18B55E430373CF21DD235BA332EE6D7A6D042BAB4DEF94939AAD2A1F6FD235B09CA6CCFB45A614C79F3C83253B82BB73826DD22127F3F14292A9B682D607D6C9313DF5324712F976C8978AEDC97B40095E66BF850BCB83F477E1F5AB045844EA5CA0652C7C2C284B90FFDCAE2D5F3C165F66FCE871A5D0AFAA158E77099BFA7A969C8F3425E326D24E7E875D588B5E652ED331ABE4A72AFF7D89CFA9D55116B2610AEA4D1D16BCE1FE8D22849827677FEC8EC9864F5A4B874E7AA3228E31DACECA3ED7E1F31675CCA03E599E748BBCA483821DDC5F1C7ED376EDE7A650AD06CE3FC4E76062354B7D89093EBBF9717CED067846349E8BBEEC4CDDE0907F2DD1C31125F1DBB7B9A94E07677C4EBC756A5ED3D8DB30FB5772328272C6CEFEB085F +20170628161354 2 6 100 7679 2 E411B879FDA69428A30BDE74B417706E5936E16C5E1F2B64A07EAE1D69C857C23126701460740D93467EB3A3386827E658069CAC4D55CC4929493C193D53A0D91141135B2F0B19E659BB541883E569D38B329761EDF3C409D34A49870356F3723AD2F720383E49B1752B837DF80F48632A469A0A96AC8F02E5B766B590D722B5BD3ED9191BB70C1D4044A3D5CE850489216C3184D73BAE2B655D76B30EC1851951A756E2A45CD1FF82A83BDC1803005034BEB2EAC35FF7362831D8FBE02E07B1CCA351D47AD65B5282151FB2711A880410CED2C1CF205CC2072F6F244189F5BDB3AFDBA7FB02DD21C99D1EF72C1EF8BC6C68A273D16CB2D3CA190C30BDDEEAD7CA2E519F3AF806B5CBD436B971C1F1981EB35CB4007D129F43E660F7E47E807C889A1DC5FEFA7C304DB41B36982FEFB7390DC6C8E9474D3EEB84B3F757C367475EB1B4CB5B86F9507090F2CB37533E2B96BBC6F75B3BF1F4CECF18F67E7492A681845CF5AFA1B70FB3B0A09CDD3375BCF716CBF2A594533D157CB6C4008CF8C4818C9418E44A995028487B0346BD399BFB431CA94B3FC2AF9822520153105ADACEBE719CC24D1D043AC2AC24BD41759AA452000C43CB885D5F0D71DC2451A2C5C04B0B085BD23B5295B7A109DCD729C34479D51EAB4617FDD163128B25F5803B262C3D97E2D63B3E84D85B67ECDFDE6FA377E208BD2EF867072D341AC731338268AD82285DD6D219DE44EB0588E477CBFCD5F5C068D2FA877339424F324012D346C3E2B3C4408E4FD84535C5D4EA02137ABE0426BC4C3AD6EABAA221579CBA22023F8204ECCC98D143652DEBF5869CD73A81C0E4C6FC9A22F9E648B6783AA1D0F0A1F76B1C4E8692339A6A259F3D8419CF7FD22A26023678BFE4F70C79E7F113882E6C7A0606C5AA9094DB161683E43CCEC8C73FEBC7B82617B90541C2BC15EBA18B55E430373CF21DD235BA332EE6D7A6D042BAB4DEF94939AAD2A1F6FD235B09CA6CCFB45A614C79F3C83253B82BB73826DD22127F3F14292A9B682D607D6C9313DF5324712F976C8978AEDC97B40095E66BF850BCB83F477E1F5AB045844EA5CA0652C7C2C284B90FFDCAE2D5F3C165F66FCE871A5D0AFAA158E77099BFA7A969C8F3425E326D24E7E875D588B5E652ED331ABE4A72AFF7D89CFA9D55116B2610AEA4D1D16BCE1FE8D22849827677FEC8EC9864F5A4B874E7AA3228E31DACECA3ED7E1F31675CCA03E599E748BBCA483821DDC5F1C7ED376EDE7A650AD06CE3FC4E76062354B7D89093EBBF9717CED067846349E8BBEEC4CDDE0907F2DD1C31125F1DBB7B9A94E07677C4EBC756A5ED3D8DB30FB5772328272C6CF024A37B +20170629103301 2 6 100 7679 5 E411B879FDA69428A30BDE74B417706E5936E16C5E1F2B64A07EAE1D69C857C23126701460740D93467EB3A3386827E658069CAC4D55CC4929493C193D53A0D91141135B2F0B19E659BB541883E569D38B329761EDF3C409D34A49870356F3723AD2F720383E49B1752B837DF80F48632A469A0A96AC8F02E5B766B590D722B5BD3ED9191BB70C1D4044A3D5CE850489216C3184D73BAE2B655D76B30EC1851951A756E2A45CD1FF82A83BDC1803005034BEB2EAC35FF7362831D8FBE02E07B1CCA351D47AD65B5282151FB2711A880410CED2C1CF205CC2072F6F244189F5BDB3AFDBA7FB02DD21C99D1EF72C1EF8BC6C68A273D16CB2D3CA190C30BDDEEAD7CA2E519F3AF806B5CBD436B971C1F1981EB35CB4007D129F43E660F7E47E807C889A1DC5FEFA7C304DB41B36982FEFB7390DC6C8E9474D3EEB84B3F757C367475EB1B4CB5B86F9507090F2CB37533E2B96BBC6F75B3BF1F4CECF18F67E7492A681845CF5AFA1B70FB3B0A09CDD3375BCF716CBF2A594533D157CB6C4008CF8C4818C9418E44A995028487B0346BD399BFB431CA94B3FC2AF9822520153105ADACEBE719CC24D1D043AC2AC24BD41759AA452000C43CB885D5F0D71DC2451A2C5C04B0B085BD23B5295B7A109DCD729C34479D51EAB4617FDD163128B25F5803B262C3D97E2D63B3E84D85B67ECDFDE6FA377E208BD2EF867072D341AC731338268AD82285DD6D219DE44EB0588E477CBFCD5F5C068D2FA877339424F324012D346C3E2B3C4408E4FD84535C5D4EA02137ABE0426BC4C3AD6EABAA221579CBA22023F8204ECCC98D143652DEBF5869CD73A81C0E4C6FC9A22F9E648B6783AA1D0F0A1F76B1C4E8692339A6A259F3D8419CF7FD22A26023678BFE4F70C79E7F113882E6C7A0606C5AA9094DB161683E43CCEC8C73FEBC7B82617B90541C2BC15EBA18B55E430373CF21DD235BA332EE6D7A6D042BAB4DEF94939AAD2A1F6FD235B09CA6CCFB45A614C79F3C83253B82BB73826DD22127F3F14292A9B682D607D6C9313DF5324712F976C8978AEDC97B40095E66BF850BCB83F477E1F5AB045844EA5CA0652C7C2C284B90FFDCAE2D5F3C165F66FCE871A5D0AFAA158E77099BFA7A969C8F3425E326D24E7E875D588B5E652ED331ABE4A72AFF7D89CFA9D55116B2610AEA4D1D16BCE1FE8D22849827677FEC8EC9864F5A4B874E7AA3228E31DACECA3ED7E1F31675CCA03E599E748BBCA483821DDC5F1C7ED376EDE7A650AD06CE3FC4E76062354B7D89093EBBF9717CED067846349E8BBEEC4CDDE0907F2DD1C31125F1DBB7B9A94E07677C4EBC756A5ED3D8DB30FB5772328272C6CF75BD46F +20170629121023 2 6 100 7679 5 E411B879FDA69428A30BDE74B417706E5936E16C5E1F2B64A07EAE1D69C857C23126701460740D93467EB3A3386827E658069CAC4D55CC4929493C193D53A0D91141135B2F0B19E659BB541883E569D38B329761EDF3C409D34A49870356F3723AD2F720383E49B1752B837DF80F48632A469A0A96AC8F02E5B766B590D722B5BD3ED9191BB70C1D4044A3D5CE850489216C3184D73BAE2B655D76B30EC1851951A756E2A45CD1FF82A83BDC1803005034BEB2EAC35FF7362831D8FBE02E07B1CCA351D47AD65B5282151FB2711A880410CED2C1CF205CC2072F6F244189F5BDB3AFDBA7FB02DD21C99D1EF72C1EF8BC6C68A273D16CB2D3CA190C30BDDEEAD7CA2E519F3AF806B5CBD436B971C1F1981EB35CB4007D129F43E660F7E47E807C889A1DC5FEFA7C304DB41B36982FEFB7390DC6C8E9474D3EEB84B3F757C367475EB1B4CB5B86F9507090F2CB37533E2B96BBC6F75B3BF1F4CECF18F67E7492A681845CF5AFA1B70FB3B0A09CDD3375BCF716CBF2A594533D157CB6C4008CF8C4818C9418E44A995028487B0346BD399BFB431CA94B3FC2AF9822520153105ADACEBE719CC24D1D043AC2AC24BD41759AA452000C43CB885D5F0D71DC2451A2C5C04B0B085BD23B5295B7A109DCD729C34479D51EAB4617FDD163128B25F5803B262C3D97E2D63B3E84D85B67ECDFDE6FA377E208BD2EF867072D341AC731338268AD82285DD6D219DE44EB0588E477CBFCD5F5C068D2FA877339424F324012D346C3E2B3C4408E4FD84535C5D4EA02137ABE0426BC4C3AD6EABAA221579CBA22023F8204ECCC98D143652DEBF5869CD73A81C0E4C6FC9A22F9E648B6783AA1D0F0A1F76B1C4E8692339A6A259F3D8419CF7FD22A26023678BFE4F70C79E7F113882E6C7A0606C5AA9094DB161683E43CCEC8C73FEBC7B82617B90541C2BC15EBA18B55E430373CF21DD235BA332EE6D7A6D042BAB4DEF94939AAD2A1F6FD235B09CA6CCFB45A614C79F3C83253B82BB73826DD22127F3F14292A9B682D607D6C9313DF5324712F976C8978AEDC97B40095E66BF850BCB83F477E1F5AB045844EA5CA0652C7C2C284B90FFDCAE2D5F3C165F66FCE871A5D0AFAA158E77099BFA7A969C8F3425E326D24E7E875D588B5E652ED331ABE4A72AFF7D89CFA9D55116B2610AEA4D1D16BCE1FE8D22849827677FEC8EC9864F5A4B874E7AA3228E31DACECA3ED7E1F31675CCA03E599E748BBCA483821DDC5F1C7ED376EDE7A650AD06CE3FC4E76062354B7D89093EBBF9717CED067846349E8BBEEC4CDDE0907F2DD1C31125F1DBB7B9A94E07677C4EBC756A5ED3D8DB30FB5772328272C6CF8B74F97 +20170630003105 2 6 100 7679 2 E411B879FDA69428A30BDE74B417706E5936E16C5E1F2B64A07EAE1D69C857C23126701460740D93467EB3A3386827E658069CAC4D55CC4929493C193D53A0D91141135B2F0B19E659BB541883E569D38B329761EDF3C409D34A49870356F3723AD2F720383E49B1752B837DF80F48632A469A0A96AC8F02E5B766B590D722B5BD3ED9191BB70C1D4044A3D5CE850489216C3184D73BAE2B655D76B30EC1851951A756E2A45CD1FF82A83BDC1803005034BEB2EAC35FF7362831D8FBE02E07B1CCA351D47AD65B5282151FB2711A880410CED2C1CF205CC2072F6F244189F5BDB3AFDBA7FB02DD21C99D1EF72C1EF8BC6C68A273D16CB2D3CA190C30BDDEEAD7CA2E519F3AF806B5CBD436B971C1F1981EB35CB4007D129F43E660F7E47E807C889A1DC5FEFA7C304DB41B36982FEFB7390DC6C8E9474D3EEB84B3F757C367475EB1B4CB5B86F9507090F2CB37533E2B96BBC6F75B3BF1F4CECF18F67E7492A681845CF5AFA1B70FB3B0A09CDD3375BCF716CBF2A594533D157CB6C4008CF8C4818C9418E44A995028487B0346BD399BFB431CA94B3FC2AF9822520153105ADACEBE719CC24D1D043AC2AC24BD41759AA452000C43CB885D5F0D71DC2451A2C5C04B0B085BD23B5295B7A109DCD729C34479D51EAB4617FDD163128B25F5803B262C3D97E2D63B3E84D85B67ECDFDE6FA377E208BD2EF867072D341AC731338268AD82285DD6D219DE44EB0588E477CBFCD5F5C068D2FA877339424F324012D346C3E2B3C4408E4FD84535C5D4EA02137ABE0426BC4C3AD6EABAA221579CBA22023F8204ECCC98D143652DEBF5869CD73A81C0E4C6FC9A22F9E648B6783AA1D0F0A1F76B1C4E8692339A6A259F3D8419CF7FD22A26023678BFE4F70C79E7F113882E6C7A0606C5AA9094DB161683E43CCEC8C73FEBC7B82617B90541C2BC15EBA18B55E430373CF21DD235BA332EE6D7A6D042BAB4DEF94939AAD2A1F6FD235B09CA6CCFB45A614C79F3C83253B82BB73826DD22127F3F14292A9B682D607D6C9313DF5324712F976C8978AEDC97B40095E66BF850BCB83F477E1F5AB045844EA5CA0652C7C2C284B90FFDCAE2D5F3C165F66FCE871A5D0AFAA158E77099BFA7A969C8F3425E326D24E7E875D588B5E652ED331ABE4A72AFF7D89CFA9D55116B2610AEA4D1D16BCE1FE8D22849827677FEC8EC9864F5A4B874E7AA3228E31DACECA3ED7E1F31675CCA03E599E748BBCA483821DDC5F1C7ED376EDE7A650AD06CE3FC4E76062354B7D89093EBBF9717CED067846349E8BBEEC4CDDE0907F2DD1C31125F1DBB7B9A94E07677C4EBC756A5ED3D8DB30FB5772328272C6D0331EC63 +20170630052003 2 6 100 7679 2 E411B879FDA69428A30BDE74B417706E5936E16C5E1F2B64A07EAE1D69C857C23126701460740D93467EB3A3386827E658069CAC4D55CC4929493C193D53A0D91141135B2F0B19E659BB541883E569D38B329761EDF3C409D34A49870356F3723AD2F720383E49B1752B837DF80F48632A469A0A96AC8F02E5B766B590D722B5BD3ED9191BB70C1D4044A3D5CE850489216C3184D73BAE2B655D76B30EC1851951A756E2A45CD1FF82A83BDC1803005034BEB2EAC35FF7362831D8FBE02E07B1CCA351D47AD65B5282151FB2711A880410CED2C1CF205CC2072F6F244189F5BDB3AFDBA7FB02DD21C99D1EF72C1EF8BC6C68A273D16CB2D3CA190C30BDDEEAD7CA2E519F3AF806B5CBD436B971C1F1981EB35CB4007D129F43E660F7E47E807C889A1DC5FEFA7C304DB41B36982FEFB7390DC6C8E9474D3EEB84B3F757C367475EB1B4CB5B86F9507090F2CB37533E2B96BBC6F75B3BF1F4CECF18F67E7492A681845CF5AFA1B70FB3B0A09CDD3375BCF716CBF2A594533D157CB6C4008CF8C4818C9418E44A995028487B0346BD399BFB431CA94B3FC2AF9822520153105ADACEBE719CC24D1D043AC2AC24BD41759AA452000C43CB885D5F0D71DC2451A2C5C04B0B085BD23B5295B7A109DCD729C34479D51EAB4617FDD163128B25F5803B262C3D97E2D63B3E84D85B67ECDFDE6FA377E208BD2EF867072D341AC731338268AD82285DD6D219DE44EB0588E477CBFCD5F5C068D2FA877339424F324012D346C3E2B3C4408E4FD84535C5D4EA02137ABE0426BC4C3AD6EABAA221579CBA22023F8204ECCC98D143652DEBF5869CD73A81C0E4C6FC9A22F9E648B6783AA1D0F0A1F76B1C4E8692339A6A259F3D8419CF7FD22A26023678BFE4F70C79E7F113882E6C7A0606C5AA9094DB161683E43CCEC8C73FEBC7B82617B90541C2BC15EBA18B55E430373CF21DD235BA332EE6D7A6D042BAB4DEF94939AAD2A1F6FD235B09CA6CCFB45A614C79F3C83253B82BB73826DD22127F3F14292A9B682D607D6C9313DF5324712F976C8978AEDC97B40095E66BF850BCB83F477E1F5AB045844EA5CA0652C7C2C284B90FFDCAE2D5F3C165F66FCE871A5D0AFAA158E77099BFA7A969C8F3425E326D24E7E875D588B5E652ED331ABE4A72AFF7D89CFA9D55116B2610AEA4D1D16BCE1FE8D22849827677FEC8EC9864F5A4B874E7AA3228E31DACECA3ED7E1F31675CCA03E599E748BBCA483821DDC5F1C7ED376EDE7A650AD06CE3FC4E76062354B7D89093EBBF9717CED067846349E8BBEEC4CDDE0907F2DD1C31125F1DBB7B9A94E07677C4EBC756A5ED3D8DB30FB5772328272C6D04F2C61B +20170630145450 2 6 100 7679 2 E411B879FDA69428A30BDE74B417706E5936E16C5E1F2B64A07EAE1D69C857C23126701460740D93467EB3A3386827E658069CAC4D55CC4929493C193D53A0D91141135B2F0B19E659BB541883E569D38B329761EDF3C409D34A49870356F3723AD2F720383E49B1752B837DF80F48632A469A0A96AC8F02E5B766B590D722B5BD3ED9191BB70C1D4044A3D5CE850489216C3184D73BAE2B655D76B30EC1851951A756E2A45CD1FF82A83BDC1803005034BEB2EAC35FF7362831D8FBE02E07B1CCA351D47AD65B5282151FB2711A880410CED2C1CF205CC2072F6F244189F5BDB3AFDBA7FB02DD21C99D1EF72C1EF8BC6C68A273D16CB2D3CA190C30BDDEEAD7CA2E519F3AF806B5CBD436B971C1F1981EB35CB4007D129F43E660F7E47E807C889A1DC5FEFA7C304DB41B36982FEFB7390DC6C8E9474D3EEB84B3F757C367475EB1B4CB5B86F9507090F2CB37533E2B96BBC6F75B3BF1F4CECF18F67E7492A681845CF5AFA1B70FB3B0A09CDD3375BCF716CBF2A594533D157CB6C4008CF8C4818C9418E44A995028487B0346BD399BFB431CA94B3FC2AF9822520153105ADACEBE719CC24D1D043AC2AC24BD41759AA452000C43CB885D5F0D71DC2451A2C5C04B0B085BD23B5295B7A109DCD729C34479D51EAB4617FDD163128B25F5803B262C3D97E2D63B3E84D85B67ECDFDE6FA377E208BD2EF867072D341AC731338268AD82285DD6D219DE44EB0588E477CBFCD5F5C068D2FA877339424F324012D346C3E2B3C4408E4FD84535C5D4EA02137ABE0426BC4C3AD6EABAA221579CBA22023F8204ECCC98D143652DEBF5869CD73A81C0E4C6FC9A22F9E648B6783AA1D0F0A1F76B1C4E8692339A6A259F3D8419CF7FD22A26023678BFE4F70C79E7F113882E6C7A0606C5AA9094DB161683E43CCEC8C73FEBC7B82617B90541C2BC15EBA18B55E430373CF21DD235BA332EE6D7A6D042BAB4DEF94939AAD2A1F6FD235B09CA6CCFB45A614C79F3C83253B82BB73826DD22127F3F14292A9B682D607D6C9313DF5324712F976C8978AEDC97B40095E66BF850BCB83F477E1F5AB045844EA5CA0652C7C2C284B90FFDCAE2D5F3C165F66FCE871A5D0AFAA158E77099BFA7A969C8F3425E326D24E7E875D588B5E652ED331ABE4A72AFF7D89CFA9D55116B2610AEA4D1D16BCE1FE8D22849827677FEC8EC9864F5A4B874E7AA3228E31DACECA3ED7E1F31675CCA03E599E748BBCA483821DDC5F1C7ED376EDE7A650AD06CE3FC4E76062354B7D89093EBBF9717CED067846349E8BBEEC4CDDE0907F2DD1C31125F1DBB7B9A94E07677C4EBC756A5ED3D8DB30FB5772328272C6D0CF7BF93 +20170701010810 2 6 100 7679 5 E411B879FDA69428A30BDE74B417706E5936E16C5E1F2B64A07EAE1D69C857C23126701460740D93467EB3A3386827E658069CAC4D55CC4929493C193D53A0D91141135B2F0B19E659BB541883E569D38B329761EDF3C409D34A49870356F3723AD2F720383E49B1752B837DF80F48632A469A0A96AC8F02E5B766B590D722B5BD3ED9191BB70C1D4044A3D5CE850489216C3184D73BAE2B655D76B30EC1851951A756E2A45CD1FF82A83BDC1803005034BEB2EAC35FF7362831D8FBE02E07B1CCA351D47AD65B5282151FB2711A880410CED2C1CF205CC2072F6F244189F5BDB3AFDBA7FB02DD21C99D1EF72C1EF8BC6C68A273D16CB2D3CA190C30BDDEEAD7CA2E519F3AF806B5CBD436B971C1F1981EB35CB4007D129F43E660F7E47E807C889A1DC5FEFA7C304DB41B36982FEFB7390DC6C8E9474D3EEB84B3F757C367475EB1B4CB5B86F9507090F2CB37533E2B96BBC6F75B3BF1F4CECF18F67E7492A681845CF5AFA1B70FB3B0A09CDD3375BCF716CBF2A594533D157CB6C4008CF8C4818C9418E44A995028487B0346BD399BFB431CA94B3FC2AF9822520153105ADACEBE719CC24D1D043AC2AC24BD41759AA452000C43CB885D5F0D71DC2451A2C5C04B0B085BD23B5295B7A109DCD729C34479D51EAB4617FDD163128B25F5803B262C3D97E2D63B3E84D85B67ECDFDE6FA377E208BD2EF867072D341AC731338268AD82285DD6D219DE44EB0588E477CBFCD5F5C068D2FA877339424F324012D346C3E2B3C4408E4FD84535C5D4EA02137ABE0426BC4C3AD6EABAA221579CBA22023F8204ECCC98D143652DEBF5869CD73A81C0E4C6FC9A22F9E648B6783AA1D0F0A1F76B1C4E8692339A6A259F3D8419CF7FD22A26023678BFE4F70C79E7F113882E6C7A0606C5AA9094DB161683E43CCEC8C73FEBC7B82617B90541C2BC15EBA18B55E430373CF21DD235BA332EE6D7A6D042BAB4DEF94939AAD2A1F6FD235B09CA6CCFB45A614C79F3C83253B82BB73826DD22127F3F14292A9B682D607D6C9313DF5324712F976C8978AEDC97B40095E66BF850BCB83F477E1F5AB045844EA5CA0652C7C2C284B90FFDCAE2D5F3C165F66FCE871A5D0AFAA158E77099BFA7A969C8F3425E326D24E7E875D588B5E652ED331ABE4A72AFF7D89CFA9D55116B2610AEA4D1D16BCE1FE8D22849827677FEC8EC9864F5A4B874E7AA3228E31DACECA3ED7E1F31675CCA03E599E748BBCA483821DDC5F1C7ED376EDE7A650AD06CE3FC4E76062354B7D89093EBBF9717CED067846349E8BBEEC4CDDE0907F2DD1C31125F1DBB7B9A94E07677C4EBC756A5ED3D8DB30FB5772328272C6D1578081F +20170701015400 2 6 100 7679 5 E411B879FDA69428A30BDE74B417706E5936E16C5E1F2B64A07EAE1D69C857C23126701460740D93467EB3A3386827E658069CAC4D55CC4929493C193D53A0D91141135B2F0B19E659BB541883E569D38B329761EDF3C409D34A49870356F3723AD2F720383E49B1752B837DF80F48632A469A0A96AC8F02E5B766B590D722B5BD3ED9191BB70C1D4044A3D5CE850489216C3184D73BAE2B655D76B30EC1851951A756E2A45CD1FF82A83BDC1803005034BEB2EAC35FF7362831D8FBE02E07B1CCA351D47AD65B5282151FB2711A880410CED2C1CF205CC2072F6F244189F5BDB3AFDBA7FB02DD21C99D1EF72C1EF8BC6C68A273D16CB2D3CA190C30BDDEEAD7CA2E519F3AF806B5CBD436B971C1F1981EB35CB4007D129F43E660F7E47E807C889A1DC5FEFA7C304DB41B36982FEFB7390DC6C8E9474D3EEB84B3F757C367475EB1B4CB5B86F9507090F2CB37533E2B96BBC6F75B3BF1F4CECF18F67E7492A681845CF5AFA1B70FB3B0A09CDD3375BCF716CBF2A594533D157CB6C4008CF8C4818C9418E44A995028487B0346BD399BFB431CA94B3FC2AF9822520153105ADACEBE719CC24D1D043AC2AC24BD41759AA452000C43CB885D5F0D71DC2451A2C5C04B0B085BD23B5295B7A109DCD729C34479D51EAB4617FDD163128B25F5803B262C3D97E2D63B3E84D85B67ECDFDE6FA377E208BD2EF867072D341AC731338268AD82285DD6D219DE44EB0588E477CBFCD5F5C068D2FA877339424F324012D346C3E2B3C4408E4FD84535C5D4EA02137ABE0426BC4C3AD6EABAA221579CBA22023F8204ECCC98D143652DEBF5869CD73A81C0E4C6FC9A22F9E648B6783AA1D0F0A1F76B1C4E8692339A6A259F3D8419CF7FD22A26023678BFE4F70C79E7F113882E6C7A0606C5AA9094DB161683E43CCEC8C73FEBC7B82617B90541C2BC15EBA18B55E430373CF21DD235BA332EE6D7A6D042BAB4DEF94939AAD2A1F6FD235B09CA6CCFB45A614C79F3C83253B82BB73826DD22127F3F14292A9B682D607D6C9313DF5324712F976C8978AEDC97B40095E66BF850BCB83F477E1F5AB045844EA5CA0652C7C2C284B90FFDCAE2D5F3C165F66FCE871A5D0AFAA158E77099BFA7A969C8F3425E326D24E7E875D588B5E652ED331ABE4A72AFF7D89CFA9D55116B2610AEA4D1D16BCE1FE8D22849827677FEC8EC9864F5A4B874E7AA3228E31DACECA3ED7E1F31675CCA03E599E748BBCA483821DDC5F1C7ED376EDE7A650AD06CE3FC4E76062354B7D89093EBBF9717CED067846349E8BBEEC4CDDE0907F2DD1C31125F1DBB7B9A94E07677C4EBC756A5ED3D8DB30FB5772328272C6D161119BF +20170701082405 2 6 100 7679 2 E411B879FDA69428A30BDE74B417706E5936E16C5E1F2B64A07EAE1D69C857C23126701460740D93467EB3A3386827E658069CAC4D55CC4929493C193D53A0D91141135B2F0B19E659BB541883E569D38B329761EDF3C409D34A49870356F3723AD2F720383E49B1752B837DF80F48632A469A0A96AC8F02E5B766B590D722B5BD3ED9191BB70C1D4044A3D5CE850489216C3184D73BAE2B655D76B30EC1851951A756E2A45CD1FF82A83BDC1803005034BEB2EAC35FF7362831D8FBE02E07B1CCA351D47AD65B5282151FB2711A880410CED2C1CF205CC2072F6F244189F5BDB3AFDBA7FB02DD21C99D1EF72C1EF8BC6C68A273D16CB2D3CA190C30BDDEEAD7CA2E519F3AF806B5CBD436B971C1F1981EB35CB4007D129F43E660F7E47E807C889A1DC5FEFA7C304DB41B36982FEFB7390DC6C8E9474D3EEB84B3F757C367475EB1B4CB5B86F9507090F2CB37533E2B96BBC6F75B3BF1F4CECF18F67E7492A681845CF5AFA1B70FB3B0A09CDD3375BCF716CBF2A594533D157CB6C4008CF8C4818C9418E44A995028487B0346BD399BFB431CA94B3FC2AF9822520153105ADACEBE719CC24D1D043AC2AC24BD41759AA452000C43CB885D5F0D71DC2451A2C5C04B0B085BD23B5295B7A109DCD729C34479D51EAB4617FDD163128B25F5803B262C3D97E2D63B3E84D85B67ECDFDE6FA377E208BD2EF867072D341AC731338268AD82285DD6D219DE44EB0588E477CBFCD5F5C068D2FA877339424F324012D346C3E2B3C4408E4FD84535C5D4EA02137ABE0426BC4C3AD6EABAA221579CBA22023F8204ECCC98D143652DEBF5869CD73A81C0E4C6FC9A22F9E648B6783AA1D0F0A1F76B1C4E8692339A6A259F3D8419CF7FD22A26023678BFE4F70C79E7F113882E6C7A0606C5AA9094DB161683E43CCEC8C73FEBC7B82617B90541C2BC15EBA18B55E430373CF21DD235BA332EE6D7A6D042BAB4DEF94939AAD2A1F6FD235B09CA6CCFB45A614C79F3C83253B82BB73826DD22127F3F14292A9B682D607D6C9313DF5324712F976C8978AEDC97B40095E66BF850BCB83F477E1F5AB045844EA5CA0652C7C2C284B90FFDCAE2D5F3C165F66FCE871A5D0AFAA158E77099BFA7A969C8F3425E326D24E7E875D588B5E652ED331ABE4A72AFF7D89CFA9D55116B2610AEA4D1D16BCE1FE8D22849827677FEC8EC9864F5A4B874E7AA3228E31DACECA3ED7E1F31675CCA03E599E748BBCA483821DDC5F1C7ED376EDE7A650AD06CE3FC4E76062354B7D89093EBBF9717CED067846349E8BBEEC4CDDE0907F2DD1C31125F1DBB7B9A94E07677C4EBC756A5ED3D8DB30FB5772328272C6D1B5FB48B +20170701092427 2 6 100 7679 5 E411B879FDA69428A30BDE74B417706E5936E16C5E1F2B64A07EAE1D69C857C23126701460740D93467EB3A3386827E658069CAC4D55CC4929493C193D53A0D91141135B2F0B19E659BB541883E569D38B329761EDF3C409D34A49870356F3723AD2F720383E49B1752B837DF80F48632A469A0A96AC8F02E5B766B590D722B5BD3ED9191BB70C1D4044A3D5CE850489216C3184D73BAE2B655D76B30EC1851951A756E2A45CD1FF82A83BDC1803005034BEB2EAC35FF7362831D8FBE02E07B1CCA351D47AD65B5282151FB2711A880410CED2C1CF205CC2072F6F244189F5BDB3AFDBA7FB02DD21C99D1EF72C1EF8BC6C68A273D16CB2D3CA190C30BDDEEAD7CA2E519F3AF806B5CBD436B971C1F1981EB35CB4007D129F43E660F7E47E807C889A1DC5FEFA7C304DB41B36982FEFB7390DC6C8E9474D3EEB84B3F757C367475EB1B4CB5B86F9507090F2CB37533E2B96BBC6F75B3BF1F4CECF18F67E7492A681845CF5AFA1B70FB3B0A09CDD3375BCF716CBF2A594533D157CB6C4008CF8C4818C9418E44A995028487B0346BD399BFB431CA94B3FC2AF9822520153105ADACEBE719CC24D1D043AC2AC24BD41759AA452000C43CB885D5F0D71DC2451A2C5C04B0B085BD23B5295B7A109DCD729C34479D51EAB4617FDD163128B25F5803B262C3D97E2D63B3E84D85B67ECDFDE6FA377E208BD2EF867072D341AC731338268AD82285DD6D219DE44EB0588E477CBFCD5F5C068D2FA877339424F324012D346C3E2B3C4408E4FD84535C5D4EA02137ABE0426BC4C3AD6EABAA221579CBA22023F8204ECCC98D143652DEBF5869CD73A81C0E4C6FC9A22F9E648B6783AA1D0F0A1F76B1C4E8692339A6A259F3D8419CF7FD22A26023678BFE4F70C79E7F113882E6C7A0606C5AA9094DB161683E43CCEC8C73FEBC7B82617B90541C2BC15EBA18B55E430373CF21DD235BA332EE6D7A6D042BAB4DEF94939AAD2A1F6FD235B09CA6CCFB45A614C79F3C83253B82BB73826DD22127F3F14292A9B682D607D6C9313DF5324712F976C8978AEDC97B40095E66BF850BCB83F477E1F5AB045844EA5CA0652C7C2C284B90FFDCAE2D5F3C165F66FCE871A5D0AFAA158E77099BFA7A969C8F3425E326D24E7E875D588B5E652ED331ABE4A72AFF7D89CFA9D55116B2610AEA4D1D16BCE1FE8D22849827677FEC8EC9864F5A4B874E7AA3228E31DACECA3ED7E1F31675CCA03E599E748BBCA483821DDC5F1C7ED376EDE7A650AD06CE3FC4E76062354B7D89093EBBF9717CED067846349E8BBEEC4CDDE0907F2DD1C31125F1DBB7B9A94E07677C4EBC756A5ED3D8DB30FB5772328272C6D1C2B0E47 +20170701161137 2 6 100 7679 2 E411B879FDA69428A30BDE74B417706E5936E16C5E1F2B64A07EAE1D69C857C23126701460740D93467EB3A3386827E658069CAC4D55CC4929493C193D53A0D91141135B2F0B19E659BB541883E569D38B329761EDF3C409D34A49870356F3723AD2F720383E49B1752B837DF80F48632A469A0A96AC8F02E5B766B590D722B5BD3ED9191BB70C1D4044A3D5CE850489216C3184D73BAE2B655D76B30EC1851951A756E2A45CD1FF82A83BDC1803005034BEB2EAC35FF7362831D8FBE02E07B1CCA351D47AD65B5282151FB2711A880410CED2C1CF205CC2072F6F244189F5BDB3AFDBA7FB02DD21C99D1EF72C1EF8BC6C68A273D16CB2D3CA190C30BDDEEAD7CA2E519F3AF806B5CBD436B971C1F1981EB35CB4007D129F43E660F7E47E807C889A1DC5FEFA7C304DB41B36982FEFB7390DC6C8E9474D3EEB84B3F757C367475EB1B4CB5B86F9507090F2CB37533E2B96BBC6F75B3BF1F4CECF18F67E7492A681845CF5AFA1B70FB3B0A09CDD3375BCF716CBF2A594533D157CB6C4008CF8C4818C9418E44A995028487B0346BD399BFB431CA94B3FC2AF9822520153105ADACEBE719CC24D1D043AC2AC24BD41759AA452000C43CB885D5F0D71DC2451A2C5C04B0B085BD23B5295B7A109DCD729C34479D51EAB4617FDD163128B25F5803B262C3D97E2D63B3E84D85B67ECDFDE6FA377E208BD2EF867072D341AC731338268AD82285DD6D219DE44EB0588E477CBFCD5F5C068D2FA877339424F324012D346C3E2B3C4408E4FD84535C5D4EA02137ABE0426BC4C3AD6EABAA221579CBA22023F8204ECCC98D143652DEBF5869CD73A81C0E4C6FC9A22F9E648B6783AA1D0F0A1F76B1C4E8692339A6A259F3D8419CF7FD22A26023678BFE4F70C79E7F113882E6C7A0606C5AA9094DB161683E43CCEC8C73FEBC7B82617B90541C2BC15EBA18B55E430373CF21DD235BA332EE6D7A6D042BAB4DEF94939AAD2A1F6FD235B09CA6CCFB45A614C79F3C83253B82BB73826DD22127F3F14292A9B682D607D6C9313DF5324712F976C8978AEDC97B40095E66BF850BCB83F477E1F5AB045844EA5CA0652C7C2C284B90FFDCAE2D5F3C165F66FCE871A5D0AFAA158E77099BFA7A969C8F3425E326D24E7E875D588B5E652ED331ABE4A72AFF7D89CFA9D55116B2610AEA4D1D16BCE1FE8D22849827677FEC8EC9864F5A4B874E7AA3228E31DACECA3ED7E1F31675CCA03E599E748BBCA483821DDC5F1C7ED376EDE7A650AD06CE3FC4E76062354B7D89093EBBF9717CED067846349E8BBEEC4CDDE0907F2DD1C31125F1DBB7B9A94E07677C4EBC756A5ED3D8DB30FB5772328272C6D21ABD21B +20170702022204 2 6 100 7679 2 E411B879FDA69428A30BDE74B417706E5936E16C5E1F2B64A07EAE1D69C857C23126701460740D93467EB3A3386827E658069CAC4D55CC4929493C193D53A0D91141135B2F0B19E659BB541883E569D38B329761EDF3C409D34A49870356F3723AD2F720383E49B1752B837DF80F48632A469A0A96AC8F02E5B766B590D722B5BD3ED9191BB70C1D4044A3D5CE850489216C3184D73BAE2B655D76B30EC1851951A756E2A45CD1FF82A83BDC1803005034BEB2EAC35FF7362831D8FBE02E07B1CCA351D47AD65B5282151FB2711A880410CED2C1CF205CC2072F6F244189F5BDB3AFDBA7FB02DD21C99D1EF72C1EF8BC6C68A273D16CB2D3CA190C30BDDEEAD7CA2E519F3AF806B5CBD436B971C1F1981EB35CB4007D129F43E660F7E47E807C889A1DC5FEFA7C304DB41B36982FEFB7390DC6C8E9474D3EEB84B3F757C367475EB1B4CB5B86F9507090F2CB37533E2B96BBC6F75B3BF1F4CECF18F67E7492A681845CF5AFA1B70FB3B0A09CDD3375BCF716CBF2A594533D157CB6C4008CF8C4818C9418E44A995028487B0346BD399BFB431CA94B3FC2AF9822520153105ADACEBE719CC24D1D043AC2AC24BD41759AA452000C43CB885D5F0D71DC2451A2C5C04B0B085BD23B5295B7A109DCD729C34479D51EAB4617FDD163128B25F5803B262C3D97E2D63B3E84D85B67ECDFDE6FA377E208BD2EF867072D341AC731338268AD82285DD6D219DE44EB0588E477CBFCD5F5C068D2FA877339424F324012D346C3E2B3C4408E4FD84535C5D4EA02137ABE0426BC4C3AD6EABAA221579CBA22023F8204ECCC98D143652DEBF5869CD73A81C0E4C6FC9A22F9E648B6783AA1D0F0A1F76B1C4E8692339A6A259F3D8419CF7FD22A26023678BFE4F70C79E7F113882E6C7A0606C5AA9094DB161683E43CCEC8C73FEBC7B82617B90541C2BC15EBA18B55E430373CF21DD235BA332EE6D7A6D042BAB4DEF94939AAD2A1F6FD235B09CA6CCFB45A614C79F3C83253B82BB73826DD22127F3F14292A9B682D607D6C9313DF5324712F976C8978AEDC97B40095E66BF850BCB83F477E1F5AB045844EA5CA0652C7C2C284B90FFDCAE2D5F3C165F66FCE871A5D0AFAA158E77099BFA7A969C8F3425E326D24E7E875D588B5E652ED331ABE4A72AFF7D89CFA9D55116B2610AEA4D1D16BCE1FE8D22849827677FEC8EC9864F5A4B874E7AA3228E31DACECA3ED7E1F31675CCA03E599E748BBCA483821DDC5F1C7ED376EDE7A650AD06CE3FC4E76062354B7D89093EBBF9717CED067846349E8BBEEC4CDDE0907F2DD1C31125F1DBB7B9A94E07677C4EBC756A5ED3D8DB30FB5772328272C6D29CF7033 +20170702023811 2 6 100 7679 5 E411B879FDA69428A30BDE74B417706E5936E16C5E1F2B64A07EAE1D69C857C23126701460740D93467EB3A3386827E658069CAC4D55CC4929493C193D53A0D91141135B2F0B19E659BB541883E569D38B329761EDF3C409D34A49870356F3723AD2F720383E49B1752B837DF80F48632A469A0A96AC8F02E5B766B590D722B5BD3ED9191BB70C1D4044A3D5CE850489216C3184D73BAE2B655D76B30EC1851951A756E2A45CD1FF82A83BDC1803005034BEB2EAC35FF7362831D8FBE02E07B1CCA351D47AD65B5282151FB2711A880410CED2C1CF205CC2072F6F244189F5BDB3AFDBA7FB02DD21C99D1EF72C1EF8BC6C68A273D16CB2D3CA190C30BDDEEAD7CA2E519F3AF806B5CBD436B971C1F1981EB35CB4007D129F43E660F7E47E807C889A1DC5FEFA7C304DB41B36982FEFB7390DC6C8E9474D3EEB84B3F757C367475EB1B4CB5B86F9507090F2CB37533E2B96BBC6F75B3BF1F4CECF18F67E7492A681845CF5AFA1B70FB3B0A09CDD3375BCF716CBF2A594533D157CB6C4008CF8C4818C9418E44A995028487B0346BD399BFB431CA94B3FC2AF9822520153105ADACEBE719CC24D1D043AC2AC24BD41759AA452000C43CB885D5F0D71DC2451A2C5C04B0B085BD23B5295B7A109DCD729C34479D51EAB4617FDD163128B25F5803B262C3D97E2D63B3E84D85B67ECDFDE6FA377E208BD2EF867072D341AC731338268AD82285DD6D219DE44EB0588E477CBFCD5F5C068D2FA877339424F324012D346C3E2B3C4408E4FD84535C5D4EA02137ABE0426BC4C3AD6EABAA221579CBA22023F8204ECCC98D143652DEBF5869CD73A81C0E4C6FC9A22F9E648B6783AA1D0F0A1F76B1C4E8692339A6A259F3D8419CF7FD22A26023678BFE4F70C79E7F113882E6C7A0606C5AA9094DB161683E43CCEC8C73FEBC7B82617B90541C2BC15EBA18B55E430373CF21DD235BA332EE6D7A6D042BAB4DEF94939AAD2A1F6FD235B09CA6CCFB45A614C79F3C83253B82BB73826DD22127F3F14292A9B682D607D6C9313DF5324712F976C8978AEDC97B40095E66BF850BCB83F477E1F5AB045844EA5CA0652C7C2C284B90FFDCAE2D5F3C165F66FCE871A5D0AFAA158E77099BFA7A969C8F3425E326D24E7E875D588B5E652ED331ABE4A72AFF7D89CFA9D55116B2610AEA4D1D16BCE1FE8D22849827677FEC8EC9864F5A4B874E7AA3228E31DACECA3ED7E1F31675CCA03E599E748BBCA483821DDC5F1C7ED376EDE7A650AD06CE3FC4E76062354B7D89093EBBF9717CED067846349E8BBEEC4CDDE0907F2DD1C31125F1DBB7B9A94E07677C4EBC756A5ED3D8DB30FB5772328272C6D29FB9AAF +20170702062241 2 6 100 7679 2 E411B879FDA69428A30BDE74B417706E5936E16C5E1F2B64A07EAE1D69C857C23126701460740D93467EB3A3386827E658069CAC4D55CC4929493C193D53A0D91141135B2F0B19E659BB541883E569D38B329761EDF3C409D34A49870356F3723AD2F720383E49B1752B837DF80F48632A469A0A96AC8F02E5B766B590D722B5BD3ED9191BB70C1D4044A3D5CE850489216C3184D73BAE2B655D76B30EC1851951A756E2A45CD1FF82A83BDC1803005034BEB2EAC35FF7362831D8FBE02E07B1CCA351D47AD65B5282151FB2711A880410CED2C1CF205CC2072F6F244189F5BDB3AFDBA7FB02DD21C99D1EF72C1EF8BC6C68A273D16CB2D3CA190C30BDDEEAD7CA2E519F3AF806B5CBD436B971C1F1981EB35CB4007D129F43E660F7E47E807C889A1DC5FEFA7C304DB41B36982FEFB7390DC6C8E9474D3EEB84B3F757C367475EB1B4CB5B86F9507090F2CB37533E2B96BBC6F75B3BF1F4CECF18F67E7492A681845CF5AFA1B70FB3B0A09CDD3375BCF716CBF2A594533D157CB6C4008CF8C4818C9418E44A995028487B0346BD399BFB431CA94B3FC2AF9822520153105ADACEBE719CC24D1D043AC2AC24BD41759AA452000C43CB885D5F0D71DC2451A2C5C04B0B085BD23B5295B7A109DCD729C34479D51EAB4617FDD163128B25F5803B262C3D97E2D63B3E84D85B67ECDFDE6FA377E208BD2EF867072D341AC731338268AD82285DD6D219DE44EB0588E477CBFCD5F5C068D2FA877339424F324012D346C3E2B3C4408E4FD84535C5D4EA02137ABE0426BC4C3AD6EABAA221579CBA22023F8204ECCC98D143652DEBF5869CD73A81C0E4C6FC9A22F9E648B6783AA1D0F0A1F76B1C4E8692339A6A259F3D8419CF7FD22A26023678BFE4F70C79E7F113882E6C7A0606C5AA9094DB161683E43CCEC8C73FEBC7B82617B90541C2BC15EBA18B55E430373CF21DD235BA332EE6D7A6D042BAB4DEF94939AAD2A1F6FD235B09CA6CCFB45A614C79F3C83253B82BB73826DD22127F3F14292A9B682D607D6C9313DF5324712F976C8978AEDC97B40095E66BF850BCB83F477E1F5AB045844EA5CA0652C7C2C284B90FFDCAE2D5F3C165F66FCE871A5D0AFAA158E77099BFA7A969C8F3425E326D24E7E875D588B5E652ED331ABE4A72AFF7D89CFA9D55116B2610AEA4D1D16BCE1FE8D22849827677FEC8EC9864F5A4B874E7AA3228E31DACECA3ED7E1F31675CCA03E599E748BBCA483821DDC5F1C7ED376EDE7A650AD06CE3FC4E76062354B7D89093EBBF9717CED067846349E8BBEEC4CDDE0907F2DD1C31125F1DBB7B9A94E07677C4EBC756A5ED3D8DB30FB5772328272C6D2CED4213 +20170702082528 2 6 100 7679 5 E411B879FDA69428A30BDE74B417706E5936E16C5E1F2B64A07EAE1D69C857C23126701460740D93467EB3A3386827E658069CAC4D55CC4929493C193D53A0D91141135B2F0B19E659BB541883E569D38B329761EDF3C409D34A49870356F3723AD2F720383E49B1752B837DF80F48632A469A0A96AC8F02E5B766B590D722B5BD3ED9191BB70C1D4044A3D5CE850489216C3184D73BAE2B655D76B30EC1851951A756E2A45CD1FF82A83BDC1803005034BEB2EAC35FF7362831D8FBE02E07B1CCA351D47AD65B5282151FB2711A880410CED2C1CF205CC2072F6F244189F5BDB3AFDBA7FB02DD21C99D1EF72C1EF8BC6C68A273D16CB2D3CA190C30BDDEEAD7CA2E519F3AF806B5CBD436B971C1F1981EB35CB4007D129F43E660F7E47E807C889A1DC5FEFA7C304DB41B36982FEFB7390DC6C8E9474D3EEB84B3F757C367475EB1B4CB5B86F9507090F2CB37533E2B96BBC6F75B3BF1F4CECF18F67E7492A681845CF5AFA1B70FB3B0A09CDD3375BCF716CBF2A594533D157CB6C4008CF8C4818C9418E44A995028487B0346BD399BFB431CA94B3FC2AF9822520153105ADACEBE719CC24D1D043AC2AC24BD41759AA452000C43CB885D5F0D71DC2451A2C5C04B0B085BD23B5295B7A109DCD729C34479D51EAB4617FDD163128B25F5803B262C3D97E2D63B3E84D85B67ECDFDE6FA377E208BD2EF867072D341AC731338268AD82285DD6D219DE44EB0588E477CBFCD5F5C068D2FA877339424F324012D346C3E2B3C4408E4FD84535C5D4EA02137ABE0426BC4C3AD6EABAA221579CBA22023F8204ECCC98D143652DEBF5869CD73A81C0E4C6FC9A22F9E648B6783AA1D0F0A1F76B1C4E8692339A6A259F3D8419CF7FD22A26023678BFE4F70C79E7F113882E6C7A0606C5AA9094DB161683E43CCEC8C73FEBC7B82617B90541C2BC15EBA18B55E430373CF21DD235BA332EE6D7A6D042BAB4DEF94939AAD2A1F6FD235B09CA6CCFB45A614C79F3C83253B82BB73826DD22127F3F14292A9B682D607D6C9313DF5324712F976C8978AEDC97B40095E66BF850BCB83F477E1F5AB045844EA5CA0652C7C2C284B90FFDCAE2D5F3C165F66FCE871A5D0AFAA158E77099BFA7A969C8F3425E326D24E7E875D588B5E652ED331ABE4A72AFF7D89CFA9D55116B2610AEA4D1D16BCE1FE8D22849827677FEC8EC9864F5A4B874E7AA3228E31DACECA3ED7E1F31675CCA03E599E748BBCA483821DDC5F1C7ED376EDE7A650AD06CE3FC4E76062354B7D89093EBBF9717CED067846349E8BBEEC4CDDE0907F2DD1C31125F1DBB7B9A94E07677C4EBC756A5ED3D8DB30FB5772328272C6D2E88DA5F +20170702151719 2 6 100 7679 5 E411B879FDA69428A30BDE74B417706E5936E16C5E1F2B64A07EAE1D69C857C23126701460740D93467EB3A3386827E658069CAC4D55CC4929493C193D53A0D91141135B2F0B19E659BB541883E569D38B329761EDF3C409D34A49870356F3723AD2F720383E49B1752B837DF80F48632A469A0A96AC8F02E5B766B590D722B5BD3ED9191BB70C1D4044A3D5CE850489216C3184D73BAE2B655D76B30EC1851951A756E2A45CD1FF82A83BDC1803005034BEB2EAC35FF7362831D8FBE02E07B1CCA351D47AD65B5282151FB2711A880410CED2C1CF205CC2072F6F244189F5BDB3AFDBA7FB02DD21C99D1EF72C1EF8BC6C68A273D16CB2D3CA190C30BDDEEAD7CA2E519F3AF806B5CBD436B971C1F1981EB35CB4007D129F43E660F7E47E807C889A1DC5FEFA7C304DB41B36982FEFB7390DC6C8E9474D3EEB84B3F757C367475EB1B4CB5B86F9507090F2CB37533E2B96BBC6F75B3BF1F4CECF18F67E7492A681845CF5AFA1B70FB3B0A09CDD3375BCF716CBF2A594533D157CB6C4008CF8C4818C9418E44A995028487B0346BD399BFB431CA94B3FC2AF9822520153105ADACEBE719CC24D1D043AC2AC24BD41759AA452000C43CB885D5F0D71DC2451A2C5C04B0B085BD23B5295B7A109DCD729C34479D51EAB4617FDD163128B25F5803B262C3D97E2D63B3E84D85B67ECDFDE6FA377E208BD2EF867072D341AC731338268AD82285DD6D219DE44EB0588E477CBFCD5F5C068D2FA877339424F324012D346C3E2B3C4408E4FD84535C5D4EA02137ABE0426BC4C3AD6EABAA221579CBA22023F8204ECCC98D143652DEBF5869CD73A81C0E4C6FC9A22F9E648B6783AA1D0F0A1F76B1C4E8692339A6A259F3D8419CF7FD22A26023678BFE4F70C79E7F113882E6C7A0606C5AA9094DB161683E43CCEC8C73FEBC7B82617B90541C2BC15EBA18B55E430373CF21DD235BA332EE6D7A6D042BAB4DEF94939AAD2A1F6FD235B09CA6CCFB45A614C79F3C83253B82BB73826DD22127F3F14292A9B682D607D6C9313DF5324712F976C8978AEDC97B40095E66BF850BCB83F477E1F5AB045844EA5CA0652C7C2C284B90FFDCAE2D5F3C165F66FCE871A5D0AFAA158E77099BFA7A969C8F3425E326D24E7E875D588B5E652ED331ABE4A72AFF7D89CFA9D55116B2610AEA4D1D16BCE1FE8D22849827677FEC8EC9864F5A4B874E7AA3228E31DACECA3ED7E1F31675CCA03E599E748BBCA483821DDC5F1C7ED376EDE7A650AD06CE3FC4E76062354B7D89093EBBF9717CED067846349E8BBEEC4CDDE0907F2DD1C31125F1DBB7B9A94E07677C4EBC756A5ED3D8DB30FB5772328272C6D33FAA757 +20170702175101 2 6 100 7679 2 E411B879FDA69428A30BDE74B417706E5936E16C5E1F2B64A07EAE1D69C857C23126701460740D93467EB3A3386827E658069CAC4D55CC4929493C193D53A0D91141135B2F0B19E659BB541883E569D38B329761EDF3C409D34A49870356F3723AD2F720383E49B1752B837DF80F48632A469A0A96AC8F02E5B766B590D722B5BD3ED9191BB70C1D4044A3D5CE850489216C3184D73BAE2B655D76B30EC1851951A756E2A45CD1FF82A83BDC1803005034BEB2EAC35FF7362831D8FBE02E07B1CCA351D47AD65B5282151FB2711A880410CED2C1CF205CC2072F6F244189F5BDB3AFDBA7FB02DD21C99D1EF72C1EF8BC6C68A273D16CB2D3CA190C30BDDEEAD7CA2E519F3AF806B5CBD436B971C1F1981EB35CB4007D129F43E660F7E47E807C889A1DC5FEFA7C304DB41B36982FEFB7390DC6C8E9474D3EEB84B3F757C367475EB1B4CB5B86F9507090F2CB37533E2B96BBC6F75B3BF1F4CECF18F67E7492A681845CF5AFA1B70FB3B0A09CDD3375BCF716CBF2A594533D157CB6C4008CF8C4818C9418E44A995028487B0346BD399BFB431CA94B3FC2AF9822520153105ADACEBE719CC24D1D043AC2AC24BD41759AA452000C43CB885D5F0D71DC2451A2C5C04B0B085BD23B5295B7A109DCD729C34479D51EAB4617FDD163128B25F5803B262C3D97E2D63B3E84D85B67ECDFDE6FA377E208BD2EF867072D341AC731338268AD82285DD6D219DE44EB0588E477CBFCD5F5C068D2FA877339424F324012D346C3E2B3C4408E4FD84535C5D4EA02137ABE0426BC4C3AD6EABAA221579CBA22023F8204ECCC98D143652DEBF5869CD73A81C0E4C6FC9A22F9E648B6783AA1D0F0A1F76B1C4E8692339A6A259F3D8419CF7FD22A26023678BFE4F70C79E7F113882E6C7A0606C5AA9094DB161683E43CCEC8C73FEBC7B82617B90541C2BC15EBA18B55E430373CF21DD235BA332EE6D7A6D042BAB4DEF94939AAD2A1F6FD235B09CA6CCFB45A614C79F3C83253B82BB73826DD22127F3F14292A9B682D607D6C9313DF5324712F976C8978AEDC97B40095E66BF850BCB83F477E1F5AB045844EA5CA0652C7C2C284B90FFDCAE2D5F3C165F66FCE871A5D0AFAA158E77099BFA7A969C8F3425E326D24E7E875D588B5E652ED331ABE4A72AFF7D89CFA9D55116B2610AEA4D1D16BCE1FE8D22849827677FEC8EC9864F5A4B874E7AA3228E31DACECA3ED7E1F31675CCA03E599E748BBCA483821DDC5F1C7ED376EDE7A650AD06CE3FC4E76062354B7D89093EBBF9717CED067846349E8BBEEC4CDDE0907F2DD1C31125F1DBB7B9A94E07677C4EBC756A5ED3D8DB30FB5772328272C6D360021F3 +20170702200102 2 6 100 7679 5 E411B879FDA69428A30BDE74B417706E5936E16C5E1F2B64A07EAE1D69C857C23126701460740D93467EB3A3386827E658069CAC4D55CC4929493C193D53A0D91141135B2F0B19E659BB541883E569D38B329761EDF3C409D34A49870356F3723AD2F720383E49B1752B837DF80F48632A469A0A96AC8F02E5B766B590D722B5BD3ED9191BB70C1D4044A3D5CE850489216C3184D73BAE2B655D76B30EC1851951A756E2A45CD1FF82A83BDC1803005034BEB2EAC35FF7362831D8FBE02E07B1CCA351D47AD65B5282151FB2711A880410CED2C1CF205CC2072F6F244189F5BDB3AFDBA7FB02DD21C99D1EF72C1EF8BC6C68A273D16CB2D3CA190C30BDDEEAD7CA2E519F3AF806B5CBD436B971C1F1981EB35CB4007D129F43E660F7E47E807C889A1DC5FEFA7C304DB41B36982FEFB7390DC6C8E9474D3EEB84B3F757C367475EB1B4CB5B86F9507090F2CB37533E2B96BBC6F75B3BF1F4CECF18F67E7492A681845CF5AFA1B70FB3B0A09CDD3375BCF716CBF2A594533D157CB6C4008CF8C4818C9418E44A995028487B0346BD399BFB431CA94B3FC2AF9822520153105ADACEBE719CC24D1D043AC2AC24BD41759AA452000C43CB885D5F0D71DC2451A2C5C04B0B085BD23B5295B7A109DCD729C34479D51EAB4617FDD163128B25F5803B262C3D97E2D63B3E84D85B67ECDFDE6FA377E208BD2EF867072D341AC731338268AD82285DD6D219DE44EB0588E477CBFCD5F5C068D2FA877339424F324012D346C3E2B3C4408E4FD84535C5D4EA02137ABE0426BC4C3AD6EABAA221579CBA22023F8204ECCC98D143652DEBF5869CD73A81C0E4C6FC9A22F9E648B6783AA1D0F0A1F76B1C4E8692339A6A259F3D8419CF7FD22A26023678BFE4F70C79E7F113882E6C7A0606C5AA9094DB161683E43CCEC8C73FEBC7B82617B90541C2BC15EBA18B55E430373CF21DD235BA332EE6D7A6D042BAB4DEF94939AAD2A1F6FD235B09CA6CCFB45A614C79F3C83253B82BB73826DD22127F3F14292A9B682D607D6C9313DF5324712F976C8978AEDC97B40095E66BF850BCB83F477E1F5AB045844EA5CA0652C7C2C284B90FFDCAE2D5F3C165F66FCE871A5D0AFAA158E77099BFA7A969C8F3425E326D24E7E875D588B5E652ED331ABE4A72AFF7D89CFA9D55116B2610AEA4D1D16BCE1FE8D22849827677FEC8EC9864F5A4B874E7AA3228E31DACECA3ED7E1F31675CCA03E599E748BBCA483821DDC5F1C7ED376EDE7A650AD06CE3FC4E76062354B7D89093EBBF9717CED067846349E8BBEEC4CDDE0907F2DD1C31125F1DBB7B9A94E07677C4EBC756A5ED3D8DB30FB5772328272C6D37A9C6C7 +20170703011731 2 6 100 7679 5 E411B879FDA69428A30BDE74B417706E5936E16C5E1F2B64A07EAE1D69C857C23126701460740D93467EB3A3386827E658069CAC4D55CC4929493C193D53A0D91141135B2F0B19E659BB541883E569D38B329761EDF3C409D34A49870356F3723AD2F720383E49B1752B837DF80F48632A469A0A96AC8F02E5B766B590D722B5BD3ED9191BB70C1D4044A3D5CE850489216C3184D73BAE2B655D76B30EC1851951A756E2A45CD1FF82A83BDC1803005034BEB2EAC35FF7362831D8FBE02E07B1CCA351D47AD65B5282151FB2711A880410CED2C1CF205CC2072F6F244189F5BDB3AFDBA7FB02DD21C99D1EF72C1EF8BC6C68A273D16CB2D3CA190C30BDDEEAD7CA2E519F3AF806B5CBD436B971C1F1981EB35CB4007D129F43E660F7E47E807C889A1DC5FEFA7C304DB41B36982FEFB7390DC6C8E9474D3EEB84B3F757C367475EB1B4CB5B86F9507090F2CB37533E2B96BBC6F75B3BF1F4CECF18F67E7492A681845CF5AFA1B70FB3B0A09CDD3375BCF716CBF2A594533D157CB6C4008CF8C4818C9418E44A995028487B0346BD399BFB431CA94B3FC2AF9822520153105ADACEBE719CC24D1D043AC2AC24BD41759AA452000C43CB885D5F0D71DC2451A2C5C04B0B085BD23B5295B7A109DCD729C34479D51EAB4617FDD163128B25F5803B262C3D97E2D63B3E84D85B67ECDFDE6FA377E208BD2EF867072D341AC731338268AD82285DD6D219DE44EB0588E477CBFCD5F5C068D2FA877339424F324012D346C3E2B3C4408E4FD84535C5D4EA02137ABE0426BC4C3AD6EABAA221579CBA22023F8204ECCC98D143652DEBF5869CD73A81C0E4C6FC9A22F9E648B6783AA1D0F0A1F76B1C4E8692339A6A259F3D8419CF7FD22A26023678BFE4F70C79E7F113882E6C7A0606C5AA9094DB161683E43CCEC8C73FEBC7B82617B90541C2BC15EBA18B55E430373CF21DD235BA332EE6D7A6D042BAB4DEF94939AAD2A1F6FD235B09CA6CCFB45A614C79F3C83253B82BB73826DD22127F3F14292A9B682D607D6C9313DF5324712F976C8978AEDC97B40095E66BF850BCB83F477E1F5AB045844EA5CA0652C7C2C284B90FFDCAE2D5F3C165F66FCE871A5D0AFAA158E77099BFA7A969C8F3425E326D24E7E875D588B5E652ED331ABE4A72AFF7D89CFA9D55116B2610AEA4D1D16BCE1FE8D22849827677FEC8EC9864F5A4B874E7AA3228E31DACECA3ED7E1F31675CCA03E599E748BBCA483821DDC5F1C7ED376EDE7A650AD06CE3FC4E76062354B7D89093EBBF9717CED067846349E8BBEEC4CDDE0907F2DD1C31125F1DBB7B9A94E07677C4EBC756A5ED3D8DB30FB5772328272C6D3BCD4977 +20170703155054 2 6 100 7679 2 E411B879FDA69428A30BDE74B417706E5936E16C5E1F2B64A07EAE1D69C857C23126701460740D93467EB3A3386827E658069CAC4D55CC4929493C193D53A0D91141135B2F0B19E659BB541883E569D38B329761EDF3C409D34A49870356F3723AD2F720383E49B1752B837DF80F48632A469A0A96AC8F02E5B766B590D722B5BD3ED9191BB70C1D4044A3D5CE850489216C3184D73BAE2B655D76B30EC1851951A756E2A45CD1FF82A83BDC1803005034BEB2EAC35FF7362831D8FBE02E07B1CCA351D47AD65B5282151FB2711A880410CED2C1CF205CC2072F6F244189F5BDB3AFDBA7FB02DD21C99D1EF72C1EF8BC6C68A273D16CB2D3CA190C30BDDEEAD7CA2E519F3AF806B5CBD436B971C1F1981EB35CB4007D129F43E660F7E47E807C889A1DC5FEFA7C304DB41B36982FEFB7390DC6C8E9474D3EEB84B3F757C367475EB1B4CB5B86F9507090F2CB37533E2B96BBC6F75B3BF1F4CECF18F67E7492A681845CF5AFA1B70FB3B0A09CDD3375BCF716CBF2A594533D157CB6C4008CF8C4818C9418E44A995028487B0346BD399BFB431CA94B3FC2AF9822520153105ADACEBE719CC24D1D043AC2AC24BD41759AA452000C43CB885D5F0D71DC2451A2C5C04B0B085BD23B5295B7A109DCD729C34479D51EAB4617FDD163128B25F5803B262C3D97E2D63B3E84D85B67ECDFDE6FA377E208BD2EF867072D341AC731338268AD82285DD6D219DE44EB0588E477CBFCD5F5C068D2FA877339424F324012D346C3E2B3C4408E4FD84535C5D4EA02137ABE0426BC4C3AD6EABAA221579CBA22023F8204ECCC98D143652DEBF5869CD73A81C0E4C6FC9A22F9E648B6783AA1D0F0A1F76B1C4E8692339A6A259F3D8419CF7FD22A26023678BFE4F70C79E7F113882E6C7A0606C5AA9094DB161683E43CCEC8C73FEBC7B82617B90541C2BC15EBA18B55E430373CF21DD235BA332EE6D7A6D042BAB4DEF94939AAD2A1F6FD235B09CA6CCFB45A614C79F3C83253B82BB73826DD22127F3F14292A9B682D607D6C9313DF5324712F976C8978AEDC97B40095E66BF850BCB83F477E1F5AB045844EA5CA0652C7C2C284B90FFDCAE2D5F3C165F66FCE871A5D0AFAA158E77099BFA7A969C8F3425E326D24E7E875D588B5E652ED331ABE4A72AFF7D89CFA9D55116B2610AEA4D1D16BCE1FE8D22849827677FEC8EC9864F5A4B874E7AA3228E31DACECA3ED7E1F31675CCA03E599E748BBCA483821DDC5F1C7ED376EDE7A650AD06CE3FC4E76062354B7D89093EBBF9717CED067846349E8BBEEC4CDDE0907F2DD1C31125F1DBB7B9A94E07677C4EBC756A5ED3D8DB30FB5772328272C6D431F42D3 +20170704184253 2 6 100 7679 2 C0388038628CD48D5377C99911D89CEDF70AC54721EE6974975D61C9E25580D2108B48CBCDB8B647B271FA822546C00580DB013D19EE5A49EFD9AAECA2036A83BB3E2F96C3E7CB273AA9ACEFCA5A3E4C7C8FCF3332DE11288D8BD76E17B4C530F5F6EFB0D757F63E3B2B519EE960FA8206DF81E7B9DA463CE389E3164588BF5B66355D481DC620F0B2F352782105DF3AB86076DD7D612CE9839CB251D5C975166859A41B740E08E66B746B710479FAA430E2891E60647E04FE71D8F8BC9A6BCD20CFB42299142DC016E672CC350D497809379F54F6F3D1649ADCE72ADECEAAE1ECA85EEE8006700379DE3687A67AF796E1F317815461CFF6E58615CD453265612315FA8F99DC65D9CC218004671E43CE58C9F54862D86B58FD71212199A2A562B1AB9604BF43676A403E8EA56A69E68F1CF0C60C83B8EB31D9C0A23D8410C3A6898D749CAD8CDA9F17A224536BD08436B25E50BA67BAD09276BB55583CEDF48AEEFFD8FA3DBE4F609760DF1EDED136B38792CD164D2EA3C5443F0D8F9117544A9A6AAC615ADE01440B7948B2B53BC3F7218DEDEB16D23C3B0C2AA4BEB99F9A9225D87B6CCB037D8E9A2918C20FE9F2BFF429FD0F23AE370E820842AEDD823DD5B6DDD7F4AD3A06735A2E4144DBABEA5DD83A6AA98EED5F6F3021C246FBABD280986A1E7A24CCBE11BC3050CC04DB566277CECBA8B5BDC1D15E1F066B25B668C7B87EA54894EC7559B64F1400934DCE1C06A10955988E3B3F4A40566B3989608404859335C53EBD6BEE21614EB7C954D543DBA7EB61555B7CED9D08EF560426DBCE3018FBEF788CF69AEAB433B692A9E28CBAFEFC048BD9AB423678D4DD5807329BCC417CF77EC7FD8E50B6D9A8D6B2017B24F6890557AF327980D086499B7C4ED6518B9C23DAB9571CA9E8E949C039C5CC002CBC9BDD08728D543143AFE577738AD309AB2493A8157272196B73C28A4826B37A8274198A4E8188CDADB1D7BB209C84D03500F79B9DFEC1E4441F34069CC01D6B9A57940914F56217C0F3A5CE0C75DE2815EE396D4AB00EC9695DFBCDD88EA6C8017CC29B1257EED39B50E0D075CCF9564D4B22F59F4B5E6667E4CACAC6B63D8CC1C9AB2CC6309A319E559D2062FB99D15B62F08E4DAD676698813D227FF8967B3B3830970E92277B2446A3C269A74FB437800824A8987DA3636A17A53C7E55C66077BE0FBD63441402F19C6C4E1F1C46185A3F3F5D7D7F553F0066EBFCF2ECD74CFC6DB48F6A458AE66EC12532B691FA3AE9A0C19809B3A1AF06340EFB012A33D484D272CA09D5862DAC5E3A00006F260BDE5CE74E007AB12A8F686373949308E574DCE7EA9D145936A2722BB3 +20170704204537 2 6 100 7679 2 C0388038628CD48D5377C99911D89CEDF70AC54721EE6974975D61C9E25580D2108B48CBCDB8B647B271FA822546C00580DB013D19EE5A49EFD9AAECA2036A83BB3E2F96C3E7CB273AA9ACEFCA5A3E4C7C8FCF3332DE11288D8BD76E17B4C530F5F6EFB0D757F63E3B2B519EE960FA8206DF81E7B9DA463CE389E3164588BF5B66355D481DC620F0B2F352782105DF3AB86076DD7D612CE9839CB251D5C975166859A41B740E08E66B746B710479FAA430E2891E60647E04FE71D8F8BC9A6BCD20CFB42299142DC016E672CC350D497809379F54F6F3D1649ADCE72ADECEAAE1ECA85EEE8006700379DE3687A67AF796E1F317815461CFF6E58615CD453265612315FA8F99DC65D9CC218004671E43CE58C9F54862D86B58FD71212199A2A562B1AB9604BF43676A403E8EA56A69E68F1CF0C60C83B8EB31D9C0A23D8410C3A6898D749CAD8CDA9F17A224536BD08436B25E50BA67BAD09276BB55583CEDF48AEEFFD8FA3DBE4F609760DF1EDED136B38792CD164D2EA3C5443F0D8F9117544A9A6AAC615ADE01440B7948B2B53BC3F7218DEDEB16D23C3B0C2AA4BEB99F9A9225D87B6CCB037D8E9A2918C20FE9F2BFF429FD0F23AE370E820842AEDD823DD5B6DDD7F4AD3A06735A2E4144DBABEA5DD83A6AA98EED5F6F3021C246FBABD280986A1E7A24CCBE11BC3050CC04DB566277CECBA8B5BDC1D15E1F066B25B668C7B87EA54894EC7559B64F1400934DCE1C06A10955988E3B3F4A40566B3989608404859335C53EBD6BEE21614EB7C954D543DBA7EB61555B7CED9D08EF560426DBCE3018FBEF788CF69AEAB433B692A9E28CBAFEFC048BD9AB423678D4DD5807329BCC417CF77EC7FD8E50B6D9A8D6B2017B24F6890557AF327980D086499B7C4ED6518B9C23DAB9571CA9E8E949C039C5CC002CBC9BDD08728D543143AFE577738AD309AB2493A8157272196B73C28A4826B37A8274198A4E8188CDADB1D7BB209C84D03500F79B9DFEC1E4441F34069CC01D6B9A57940914F56217C0F3A5CE0C75DE2815EE396D4AB00EC9695DFBCDD88EA6C8017CC29B1257EED39B50E0D075CCF9564D4B22F59F4B5E6667E4CACAC6B63D8CC1C9AB2CC6309A319E559D2062FB99D15B62F08E4DAD676698813D227FF8967B3B3830970E92277B2446A3C269A74FB437800824A8987DA3636A17A53C7E55C66077BE0FBD63441402F19C6C4E1F1C46185A3F3F5D7D7F553F0066EBFCF2ECD74CFC6DB48F6A458AE66EC12532B691FA3AE9A0C19809B3A1AF06340EFB012A33D484D272CA09D5862DAC5E3A00006F260BDE5CE74E007AB12A8F686373949308E574DCE7EA9D145936A4446CCB +20170705051520 2 6 100 7679 2 C0388038628CD48D5377C99911D89CEDF70AC54721EE6974975D61C9E25580D2108B48CBCDB8B647B271FA822546C00580DB013D19EE5A49EFD9AAECA2036A83BB3E2F96C3E7CB273AA9ACEFCA5A3E4C7C8FCF3332DE11288D8BD76E17B4C530F5F6EFB0D757F63E3B2B519EE960FA8206DF81E7B9DA463CE389E3164588BF5B66355D481DC620F0B2F352782105DF3AB86076DD7D612CE9839CB251D5C975166859A41B740E08E66B746B710479FAA430E2891E60647E04FE71D8F8BC9A6BCD20CFB42299142DC016E672CC350D497809379F54F6F3D1649ADCE72ADECEAAE1ECA85EEE8006700379DE3687A67AF796E1F317815461CFF6E58615CD453265612315FA8F99DC65D9CC218004671E43CE58C9F54862D86B58FD71212199A2A562B1AB9604BF43676A403E8EA56A69E68F1CF0C60C83B8EB31D9C0A23D8410C3A6898D749CAD8CDA9F17A224536BD08436B25E50BA67BAD09276BB55583CEDF48AEEFFD8FA3DBE4F609760DF1EDED136B38792CD164D2EA3C5443F0D8F9117544A9A6AAC615ADE01440B7948B2B53BC3F7218DEDEB16D23C3B0C2AA4BEB99F9A9225D87B6CCB037D8E9A2918C20FE9F2BFF429FD0F23AE370E820842AEDD823DD5B6DDD7F4AD3A06735A2E4144DBABEA5DD83A6AA98EED5F6F3021C246FBABD280986A1E7A24CCBE11BC3050CC04DB566277CECBA8B5BDC1D15E1F066B25B668C7B87EA54894EC7559B64F1400934DCE1C06A10955988E3B3F4A40566B3989608404859335C53EBD6BEE21614EB7C954D543DBA7EB61555B7CED9D08EF560426DBCE3018FBEF788CF69AEAB433B692A9E28CBAFEFC048BD9AB423678D4DD5807329BCC417CF77EC7FD8E50B6D9A8D6B2017B24F6890557AF327980D086499B7C4ED6518B9C23DAB9571CA9E8E949C039C5CC002CBC9BDD08728D543143AFE577738AD309AB2493A8157272196B73C28A4826B37A8274198A4E8188CDADB1D7BB209C84D03500F79B9DFEC1E4441F34069CC01D6B9A57940914F56217C0F3A5CE0C75DE2815EE396D4AB00EC9695DFBCDD88EA6C8017CC29B1257EED39B50E0D075CCF9564D4B22F59F4B5E6667E4CACAC6B63D8CC1C9AB2CC6309A319E559D2062FB99D15B62F08E4DAD676698813D227FF8967B3B3830970E92277B2446A3C269A74FB437800824A8987DA3636A17A53C7E55C66077BE0FBD63441402F19C6C4E1F1C46185A3F3F5D7D7F553F0066EBFCF2ECD74CFC6DB48F6A458AE66EC12532B691FA3AE9A0C19809B3A1AF06340EFB012A33D484D272CA09D5862DAC5E3A00006F260BDE5CE74E007AB12A8F686373949308E574DCE7EA9D145936ABC7F083 +20170705084652 2 6 100 7679 2 C0388038628CD48D5377C99911D89CEDF70AC54721EE6974975D61C9E25580D2108B48CBCDB8B647B271FA822546C00580DB013D19EE5A49EFD9AAECA2036A83BB3E2F96C3E7CB273AA9ACEFCA5A3E4C7C8FCF3332DE11288D8BD76E17B4C530F5F6EFB0D757F63E3B2B519EE960FA8206DF81E7B9DA463CE389E3164588BF5B66355D481DC620F0B2F352782105DF3AB86076DD7D612CE9839CB251D5C975166859A41B740E08E66B746B710479FAA430E2891E60647E04FE71D8F8BC9A6BCD20CFB42299142DC016E672CC350D497809379F54F6F3D1649ADCE72ADECEAAE1ECA85EEE8006700379DE3687A67AF796E1F317815461CFF6E58615CD453265612315FA8F99DC65D9CC218004671E43CE58C9F54862D86B58FD71212199A2A562B1AB9604BF43676A403E8EA56A69E68F1CF0C60C83B8EB31D9C0A23D8410C3A6898D749CAD8CDA9F17A224536BD08436B25E50BA67BAD09276BB55583CEDF48AEEFFD8FA3DBE4F609760DF1EDED136B38792CD164D2EA3C5443F0D8F9117544A9A6AAC615ADE01440B7948B2B53BC3F7218DEDEB16D23C3B0C2AA4BEB99F9A9225D87B6CCB037D8E9A2918C20FE9F2BFF429FD0F23AE370E820842AEDD823DD5B6DDD7F4AD3A06735A2E4144DBABEA5DD83A6AA98EED5F6F3021C246FBABD280986A1E7A24CCBE11BC3050CC04DB566277CECBA8B5BDC1D15E1F066B25B668C7B87EA54894EC7559B64F1400934DCE1C06A10955988E3B3F4A40566B3989608404859335C53EBD6BEE21614EB7C954D543DBA7EB61555B7CED9D08EF560426DBCE3018FBEF788CF69AEAB433B692A9E28CBAFEFC048BD9AB423678D4DD5807329BCC417CF77EC7FD8E50B6D9A8D6B2017B24F6890557AF327980D086499B7C4ED6518B9C23DAB9571CA9E8E949C039C5CC002CBC9BDD08728D543143AFE577738AD309AB2493A8157272196B73C28A4826B37A8274198A4E8188CDADB1D7BB209C84D03500F79B9DFEC1E4441F34069CC01D6B9A57940914F56217C0F3A5CE0C75DE2815EE396D4AB00EC9695DFBCDD88EA6C8017CC29B1257EED39B50E0D075CCF9564D4B22F59F4B5E6667E4CACAC6B63D8CC1C9AB2CC6309A319E559D2062FB99D15B62F08E4DAD676698813D227FF8967B3B3830970E92277B2446A3C269A74FB437800824A8987DA3636A17A53C7E55C66077BE0FBD63441402F19C6C4E1F1C46185A3F3F5D7D7F553F0066EBFCF2ECD74CFC6DB48F6A458AE66EC12532B691FA3AE9A0C19809B3A1AF06340EFB012A33D484D272CA09D5862DAC5E3A00006F260BDE5CE74E007AB12A8F686373949308E574DCE7EA9D145936AED1CC73 +20170705094007 2 6 100 7679 5 C0388038628CD48D5377C99911D89CEDF70AC54721EE6974975D61C9E25580D2108B48CBCDB8B647B271FA822546C00580DB013D19EE5A49EFD9AAECA2036A83BB3E2F96C3E7CB273AA9ACEFCA5A3E4C7C8FCF3332DE11288D8BD76E17B4C530F5F6EFB0D757F63E3B2B519EE960FA8206DF81E7B9DA463CE389E3164588BF5B66355D481DC620F0B2F352782105DF3AB86076DD7D612CE9839CB251D5C975166859A41B740E08E66B746B710479FAA430E2891E60647E04FE71D8F8BC9A6BCD20CFB42299142DC016E672CC350D497809379F54F6F3D1649ADCE72ADECEAAE1ECA85EEE8006700379DE3687A67AF796E1F317815461CFF6E58615CD453265612315FA8F99DC65D9CC218004671E43CE58C9F54862D86B58FD71212199A2A562B1AB9604BF43676A403E8EA56A69E68F1CF0C60C83B8EB31D9C0A23D8410C3A6898D749CAD8CDA9F17A224536BD08436B25E50BA67BAD09276BB55583CEDF48AEEFFD8FA3DBE4F609760DF1EDED136B38792CD164D2EA3C5443F0D8F9117544A9A6AAC615ADE01440B7948B2B53BC3F7218DEDEB16D23C3B0C2AA4BEB99F9A9225D87B6CCB037D8E9A2918C20FE9F2BFF429FD0F23AE370E820842AEDD823DD5B6DDD7F4AD3A06735A2E4144DBABEA5DD83A6AA98EED5F6F3021C246FBABD280986A1E7A24CCBE11BC3050CC04DB566277CECBA8B5BDC1D15E1F066B25B668C7B87EA54894EC7559B64F1400934DCE1C06A10955988E3B3F4A40566B3989608404859335C53EBD6BEE21614EB7C954D543DBA7EB61555B7CED9D08EF560426DBCE3018FBEF788CF69AEAB433B692A9E28CBAFEFC048BD9AB423678D4DD5807329BCC417CF77EC7FD8E50B6D9A8D6B2017B24F6890557AF327980D086499B7C4ED6518B9C23DAB9571CA9E8E949C039C5CC002CBC9BDD08728D543143AFE577738AD309AB2493A8157272196B73C28A4826B37A8274198A4E8188CDADB1D7BB209C84D03500F79B9DFEC1E4441F34069CC01D6B9A57940914F56217C0F3A5CE0C75DE2815EE396D4AB00EC9695DFBCDD88EA6C8017CC29B1257EED39B50E0D075CCF9564D4B22F59F4B5E6667E4CACAC6B63D8CC1C9AB2CC6309A319E559D2062FB99D15B62F08E4DAD676698813D227FF8967B3B3830970E92277B2446A3C269A74FB437800824A8987DA3636A17A53C7E55C66077BE0FBD63441402F19C6C4E1F1C46185A3F3F5D7D7F553F0066EBFCF2ECD74CFC6DB48F6A458AE66EC12532B691FA3AE9A0C19809B3A1AF06340EFB012A33D484D272CA09D5862DAC5E3A00006F260BDE5CE74E007AB12A8F686373949308E574DCE7EA9D145936AF8A26FF +20170705115139 2 6 100 7679 5 C0388038628CD48D5377C99911D89CEDF70AC54721EE6974975D61C9E25580D2108B48CBCDB8B647B271FA822546C00580DB013D19EE5A49EFD9AAECA2036A83BB3E2F96C3E7CB273AA9ACEFCA5A3E4C7C8FCF3332DE11288D8BD76E17B4C530F5F6EFB0D757F63E3B2B519EE960FA8206DF81E7B9DA463CE389E3164588BF5B66355D481DC620F0B2F352782105DF3AB86076DD7D612CE9839CB251D5C975166859A41B740E08E66B746B710479FAA430E2891E60647E04FE71D8F8BC9A6BCD20CFB42299142DC016E672CC350D497809379F54F6F3D1649ADCE72ADECEAAE1ECA85EEE8006700379DE3687A67AF796E1F317815461CFF6E58615CD453265612315FA8F99DC65D9CC218004671E43CE58C9F54862D86B58FD71212199A2A562B1AB9604BF43676A403E8EA56A69E68F1CF0C60C83B8EB31D9C0A23D8410C3A6898D749CAD8CDA9F17A224536BD08436B25E50BA67BAD09276BB55583CEDF48AEEFFD8FA3DBE4F609760DF1EDED136B38792CD164D2EA3C5443F0D8F9117544A9A6AAC615ADE01440B7948B2B53BC3F7218DEDEB16D23C3B0C2AA4BEB99F9A9225D87B6CCB037D8E9A2918C20FE9F2BFF429FD0F23AE370E820842AEDD823DD5B6DDD7F4AD3A06735A2E4144DBABEA5DD83A6AA98EED5F6F3021C246FBABD280986A1E7A24CCBE11BC3050CC04DB566277CECBA8B5BDC1D15E1F066B25B668C7B87EA54894EC7559B64F1400934DCE1C06A10955988E3B3F4A40566B3989608404859335C53EBD6BEE21614EB7C954D543DBA7EB61555B7CED9D08EF560426DBCE3018FBEF788CF69AEAB433B692A9E28CBAFEFC048BD9AB423678D4DD5807329BCC417CF77EC7FD8E50B6D9A8D6B2017B24F6890557AF327980D086499B7C4ED6518B9C23DAB9571CA9E8E949C039C5CC002CBC9BDD08728D543143AFE577738AD309AB2493A8157272196B73C28A4826B37A8274198A4E8188CDADB1D7BB209C84D03500F79B9DFEC1E4441F34069CC01D6B9A57940914F56217C0F3A5CE0C75DE2815EE396D4AB00EC9695DFBCDD88EA6C8017CC29B1257EED39B50E0D075CCF9564D4B22F59F4B5E6667E4CACAC6B63D8CC1C9AB2CC6309A319E559D2062FB99D15B62F08E4DAD676698813D227FF8967B3B3830970E92277B2446A3C269A74FB437800824A8987DA3636A17A53C7E55C66077BE0FBD63441402F19C6C4E1F1C46185A3F3F5D7D7F553F0066EBFCF2ECD74CFC6DB48F6A458AE66EC12532B691FA3AE9A0C19809B3A1AF06340EFB012A33D484D272CA09D5862DAC5E3A00006F260BDE5CE74E007AB12A8F686373949308E574DCE7EA9D145936B15913CF +20170705123819 2 6 100 7679 2 C0388038628CD48D5377C99911D89CEDF70AC54721EE6974975D61C9E25580D2108B48CBCDB8B647B271FA822546C00580DB013D19EE5A49EFD9AAECA2036A83BB3E2F96C3E7CB273AA9ACEFCA5A3E4C7C8FCF3332DE11288D8BD76E17B4C530F5F6EFB0D757F63E3B2B519EE960FA8206DF81E7B9DA463CE389E3164588BF5B66355D481DC620F0B2F352782105DF3AB86076DD7D612CE9839CB251D5C975166859A41B740E08E66B746B710479FAA430E2891E60647E04FE71D8F8BC9A6BCD20CFB42299142DC016E672CC350D497809379F54F6F3D1649ADCE72ADECEAAE1ECA85EEE8006700379DE3687A67AF796E1F317815461CFF6E58615CD453265612315FA8F99DC65D9CC218004671E43CE58C9F54862D86B58FD71212199A2A562B1AB9604BF43676A403E8EA56A69E68F1CF0C60C83B8EB31D9C0A23D8410C3A6898D749CAD8CDA9F17A224536BD08436B25E50BA67BAD09276BB55583CEDF48AEEFFD8FA3DBE4F609760DF1EDED136B38792CD164D2EA3C5443F0D8F9117544A9A6AAC615ADE01440B7948B2B53BC3F7218DEDEB16D23C3B0C2AA4BEB99F9A9225D87B6CCB037D8E9A2918C20FE9F2BFF429FD0F23AE370E820842AEDD823DD5B6DDD7F4AD3A06735A2E4144DBABEA5DD83A6AA98EED5F6F3021C246FBABD280986A1E7A24CCBE11BC3050CC04DB566277CECBA8B5BDC1D15E1F066B25B668C7B87EA54894EC7559B64F1400934DCE1C06A10955988E3B3F4A40566B3989608404859335C53EBD6BEE21614EB7C954D543DBA7EB61555B7CED9D08EF560426DBCE3018FBEF788CF69AEAB433B692A9E28CBAFEFC048BD9AB423678D4DD5807329BCC417CF77EC7FD8E50B6D9A8D6B2017B24F6890557AF327980D086499B7C4ED6518B9C23DAB9571CA9E8E949C039C5CC002CBC9BDD08728D543143AFE577738AD309AB2493A8157272196B73C28A4826B37A8274198A4E8188CDADB1D7BB209C84D03500F79B9DFEC1E4441F34069CC01D6B9A57940914F56217C0F3A5CE0C75DE2815EE396D4AB00EC9695DFBCDD88EA6C8017CC29B1257EED39B50E0D075CCF9564D4B22F59F4B5E6667E4CACAC6B63D8CC1C9AB2CC6309A319E559D2062FB99D15B62F08E4DAD676698813D227FF8967B3B3830970E92277B2446A3C269A74FB437800824A8987DA3636A17A53C7E55C66077BE0FBD63441402F19C6C4E1F1C46185A3F3F5D7D7F553F0066EBFCF2ECD74CFC6DB48F6A458AE66EC12532B691FA3AE9A0C19809B3A1AF06340EFB012A33D484D272CA09D5862DAC5E3A00006F260BDE5CE74E007AB12A8F686373949308E574DCE7EA9D145936B1FD105B +20170705150548 2 6 100 7679 2 C0388038628CD48D5377C99911D89CEDF70AC54721EE6974975D61C9E25580D2108B48CBCDB8B647B271FA822546C00580DB013D19EE5A49EFD9AAECA2036A83BB3E2F96C3E7CB273AA9ACEFCA5A3E4C7C8FCF3332DE11288D8BD76E17B4C530F5F6EFB0D757F63E3B2B519EE960FA8206DF81E7B9DA463CE389E3164588BF5B66355D481DC620F0B2F352782105DF3AB86076DD7D612CE9839CB251D5C975166859A41B740E08E66B746B710479FAA430E2891E60647E04FE71D8F8BC9A6BCD20CFB42299142DC016E672CC350D497809379F54F6F3D1649ADCE72ADECEAAE1ECA85EEE8006700379DE3687A67AF796E1F317815461CFF6E58615CD453265612315FA8F99DC65D9CC218004671E43CE58C9F54862D86B58FD71212199A2A562B1AB9604BF43676A403E8EA56A69E68F1CF0C60C83B8EB31D9C0A23D8410C3A6898D749CAD8CDA9F17A224536BD08436B25E50BA67BAD09276BB55583CEDF48AEEFFD8FA3DBE4F609760DF1EDED136B38792CD164D2EA3C5443F0D8F9117544A9A6AAC615ADE01440B7948B2B53BC3F7218DEDEB16D23C3B0C2AA4BEB99F9A9225D87B6CCB037D8E9A2918C20FE9F2BFF429FD0F23AE370E820842AEDD823DD5B6DDD7F4AD3A06735A2E4144DBABEA5DD83A6AA98EED5F6F3021C246FBABD280986A1E7A24CCBE11BC3050CC04DB566277CECBA8B5BDC1D15E1F066B25B668C7B87EA54894EC7559B64F1400934DCE1C06A10955988E3B3F4A40566B3989608404859335C53EBD6BEE21614EB7C954D543DBA7EB61555B7CED9D08EF560426DBCE3018FBEF788CF69AEAB433B692A9E28CBAFEFC048BD9AB423678D4DD5807329BCC417CF77EC7FD8E50B6D9A8D6B2017B24F6890557AF327980D086499B7C4ED6518B9C23DAB9571CA9E8E949C039C5CC002CBC9BDD08728D543143AFE577738AD309AB2493A8157272196B73C28A4826B37A8274198A4E8188CDADB1D7BB209C84D03500F79B9DFEC1E4441F34069CC01D6B9A57940914F56217C0F3A5CE0C75DE2815EE396D4AB00EC9695DFBCDD88EA6C8017CC29B1257EED39B50E0D075CCF9564D4B22F59F4B5E6667E4CACAC6B63D8CC1C9AB2CC6309A319E559D2062FB99D15B62F08E4DAD676698813D227FF8967B3B3830970E92277B2446A3C269A74FB437800824A8987DA3636A17A53C7E55C66077BE0FBD63441402F19C6C4E1F1C46185A3F3F5D7D7F553F0066EBFCF2ECD74CFC6DB48F6A458AE66EC12532B691FA3AE9A0C19809B3A1AF06340EFB012A33D484D272CA09D5862DAC5E3A00006F260BDE5CE74E007AB12A8F686373949308E574DCE7EA9D145936B411305B +20170705152103 2 6 100 7679 2 C0388038628CD48D5377C99911D89CEDF70AC54721EE6974975D61C9E25580D2108B48CBCDB8B647B271FA822546C00580DB013D19EE5A49EFD9AAECA2036A83BB3E2F96C3E7CB273AA9ACEFCA5A3E4C7C8FCF3332DE11288D8BD76E17B4C530F5F6EFB0D757F63E3B2B519EE960FA8206DF81E7B9DA463CE389E3164588BF5B66355D481DC620F0B2F352782105DF3AB86076DD7D612CE9839CB251D5C975166859A41B740E08E66B746B710479FAA430E2891E60647E04FE71D8F8BC9A6BCD20CFB42299142DC016E672CC350D497809379F54F6F3D1649ADCE72ADECEAAE1ECA85EEE8006700379DE3687A67AF796E1F317815461CFF6E58615CD453265612315FA8F99DC65D9CC218004671E43CE58C9F54862D86B58FD71212199A2A562B1AB9604BF43676A403E8EA56A69E68F1CF0C60C83B8EB31D9C0A23D8410C3A6898D749CAD8CDA9F17A224536BD08436B25E50BA67BAD09276BB55583CEDF48AEEFFD8FA3DBE4F609760DF1EDED136B38792CD164D2EA3C5443F0D8F9117544A9A6AAC615ADE01440B7948B2B53BC3F7218DEDEB16D23C3B0C2AA4BEB99F9A9225D87B6CCB037D8E9A2918C20FE9F2BFF429FD0F23AE370E820842AEDD823DD5B6DDD7F4AD3A06735A2E4144DBABEA5DD83A6AA98EED5F6F3021C246FBABD280986A1E7A24CCBE11BC3050CC04DB566277CECBA8B5BDC1D15E1F066B25B668C7B87EA54894EC7559B64F1400934DCE1C06A10955988E3B3F4A40566B3989608404859335C53EBD6BEE21614EB7C954D543DBA7EB61555B7CED9D08EF560426DBCE3018FBEF788CF69AEAB433B692A9E28CBAFEFC048BD9AB423678D4DD5807329BCC417CF77EC7FD8E50B6D9A8D6B2017B24F6890557AF327980D086499B7C4ED6518B9C23DAB9571CA9E8E949C039C5CC002CBC9BDD08728D543143AFE577738AD309AB2493A8157272196B73C28A4826B37A8274198A4E8188CDADB1D7BB209C84D03500F79B9DFEC1E4441F34069CC01D6B9A57940914F56217C0F3A5CE0C75DE2815EE396D4AB00EC9695DFBCDD88EA6C8017CC29B1257EED39B50E0D075CCF9564D4B22F59F4B5E6667E4CACAC6B63D8CC1C9AB2CC6309A319E559D2062FB99D15B62F08E4DAD676698813D227FF8967B3B3830970E92277B2446A3C269A74FB437800824A8987DA3636A17A53C7E55C66077BE0FBD63441402F19C6C4E1F1C46185A3F3F5D7D7F553F0066EBFCF2ECD74CFC6DB48F6A458AE66EC12532B691FA3AE9A0C19809B3A1AF06340EFB012A33D484D272CA09D5862DAC5E3A00006F260BDE5CE74E007AB12A8F686373949308E574DCE7EA9D145936B43D87FB +20170705174143 2 6 100 7679 5 C0388038628CD48D5377C99911D89CEDF70AC54721EE6974975D61C9E25580D2108B48CBCDB8B647B271FA822546C00580DB013D19EE5A49EFD9AAECA2036A83BB3E2F96C3E7CB273AA9ACEFCA5A3E4C7C8FCF3332DE11288D8BD76E17B4C530F5F6EFB0D757F63E3B2B519EE960FA8206DF81E7B9DA463CE389E3164588BF5B66355D481DC620F0B2F352782105DF3AB86076DD7D612CE9839CB251D5C975166859A41B740E08E66B746B710479FAA430E2891E60647E04FE71D8F8BC9A6BCD20CFB42299142DC016E672CC350D497809379F54F6F3D1649ADCE72ADECEAAE1ECA85EEE8006700379DE3687A67AF796E1F317815461CFF6E58615CD453265612315FA8F99DC65D9CC218004671E43CE58C9F54862D86B58FD71212199A2A562B1AB9604BF43676A403E8EA56A69E68F1CF0C60C83B8EB31D9C0A23D8410C3A6898D749CAD8CDA9F17A224536BD08436B25E50BA67BAD09276BB55583CEDF48AEEFFD8FA3DBE4F609760DF1EDED136B38792CD164D2EA3C5443F0D8F9117544A9A6AAC615ADE01440B7948B2B53BC3F7218DEDEB16D23C3B0C2AA4BEB99F9A9225D87B6CCB037D8E9A2918C20FE9F2BFF429FD0F23AE370E820842AEDD823DD5B6DDD7F4AD3A06735A2E4144DBABEA5DD83A6AA98EED5F6F3021C246FBABD280986A1E7A24CCBE11BC3050CC04DB566277CECBA8B5BDC1D15E1F066B25B668C7B87EA54894EC7559B64F1400934DCE1C06A10955988E3B3F4A40566B3989608404859335C53EBD6BEE21614EB7C954D543DBA7EB61555B7CED9D08EF560426DBCE3018FBEF788CF69AEAB433B692A9E28CBAFEFC048BD9AB423678D4DD5807329BCC417CF77EC7FD8E50B6D9A8D6B2017B24F6890557AF327980D086499B7C4ED6518B9C23DAB9571CA9E8E949C039C5CC002CBC9BDD08728D543143AFE577738AD309AB2493A8157272196B73C28A4826B37A8274198A4E8188CDADB1D7BB209C84D03500F79B9DFEC1E4441F34069CC01D6B9A57940914F56217C0F3A5CE0C75DE2815EE396D4AB00EC9695DFBCDD88EA6C8017CC29B1257EED39B50E0D075CCF9564D4B22F59F4B5E6667E4CACAC6B63D8CC1C9AB2CC6309A319E559D2062FB99D15B62F08E4DAD676698813D227FF8967B3B3830970E92277B2446A3C269A74FB437800824A8987DA3636A17A53C7E55C66077BE0FBD63441402F19C6C4E1F1C46185A3F3F5D7D7F553F0066EBFCF2ECD74CFC6DB48F6A458AE66EC12532B691FA3AE9A0C19809B3A1AF06340EFB012A33D484D272CA09D5862DAC5E3A00006F260BDE5CE74E007AB12A8F686373949308E574DCE7EA9D145936B637D557 +20170706120313 2 6 100 7679 2 C0388038628CD48D5377C99911D89CEDF70AC54721EE6974975D61C9E25580D2108B48CBCDB8B647B271FA822546C00580DB013D19EE5A49EFD9AAECA2036A83BB3E2F96C3E7CB273AA9ACEFCA5A3E4C7C8FCF3332DE11288D8BD76E17B4C530F5F6EFB0D757F63E3B2B519EE960FA8206DF81E7B9DA463CE389E3164588BF5B66355D481DC620F0B2F352782105DF3AB86076DD7D612CE9839CB251D5C975166859A41B740E08E66B746B710479FAA430E2891E60647E04FE71D8F8BC9A6BCD20CFB42299142DC016E672CC350D497809379F54F6F3D1649ADCE72ADECEAAE1ECA85EEE8006700379DE3687A67AF796E1F317815461CFF6E58615CD453265612315FA8F99DC65D9CC218004671E43CE58C9F54862D86B58FD71212199A2A562B1AB9604BF43676A403E8EA56A69E68F1CF0C60C83B8EB31D9C0A23D8410C3A6898D749CAD8CDA9F17A224536BD08436B25E50BA67BAD09276BB55583CEDF48AEEFFD8FA3DBE4F609760DF1EDED136B38792CD164D2EA3C5443F0D8F9117544A9A6AAC615ADE01440B7948B2B53BC3F7218DEDEB16D23C3B0C2AA4BEB99F9A9225D87B6CCB037D8E9A2918C20FE9F2BFF429FD0F23AE370E820842AEDD823DD5B6DDD7F4AD3A06735A2E4144DBABEA5DD83A6AA98EED5F6F3021C246FBABD280986A1E7A24CCBE11BC3050CC04DB566277CECBA8B5BDC1D15E1F066B25B668C7B87EA54894EC7559B64F1400934DCE1C06A10955988E3B3F4A40566B3989608404859335C53EBD6BEE21614EB7C954D543DBA7EB61555B7CED9D08EF560426DBCE3018FBEF788CF69AEAB433B692A9E28CBAFEFC048BD9AB423678D4DD5807329BCC417CF77EC7FD8E50B6D9A8D6B2017B24F6890557AF327980D086499B7C4ED6518B9C23DAB9571CA9E8E949C039C5CC002CBC9BDD08728D543143AFE577738AD309AB2493A8157272196B73C28A4826B37A8274198A4E8188CDADB1D7BB209C84D03500F79B9DFEC1E4441F34069CC01D6B9A57940914F56217C0F3A5CE0C75DE2815EE396D4AB00EC9695DFBCDD88EA6C8017CC29B1257EED39B50E0D075CCF9564D4B22F59F4B5E6667E4CACAC6B63D8CC1C9AB2CC6309A319E559D2062FB99D15B62F08E4DAD676698813D227FF8967B3B3830970E92277B2446A3C269A74FB437800824A8987DA3636A17A53C7E55C66077BE0FBD63441402F19C6C4E1F1C46185A3F3F5D7D7F553F0066EBFCF2ECD74CFC6DB48F6A458AE66EC12532B691FA3AE9A0C19809B3A1AF06340EFB012A33D484D272CA09D5862DAC5E3A00006F260BDE5CE74E007AB12A8F686373949308E574DCE7EA9D145936C5C0BE63 +20170706131942 2 6 100 7679 5 C0388038628CD48D5377C99911D89CEDF70AC54721EE6974975D61C9E25580D2108B48CBCDB8B647B271FA822546C00580DB013D19EE5A49EFD9AAECA2036A83BB3E2F96C3E7CB273AA9ACEFCA5A3E4C7C8FCF3332DE11288D8BD76E17B4C530F5F6EFB0D757F63E3B2B519EE960FA8206DF81E7B9DA463CE389E3164588BF5B66355D481DC620F0B2F352782105DF3AB86076DD7D612CE9839CB251D5C975166859A41B740E08E66B746B710479FAA430E2891E60647E04FE71D8F8BC9A6BCD20CFB42299142DC016E672CC350D497809379F54F6F3D1649ADCE72ADECEAAE1ECA85EEE8006700379DE3687A67AF796E1F317815461CFF6E58615CD453265612315FA8F99DC65D9CC218004671E43CE58C9F54862D86B58FD71212199A2A562B1AB9604BF43676A403E8EA56A69E68F1CF0C60C83B8EB31D9C0A23D8410C3A6898D749CAD8CDA9F17A224536BD08436B25E50BA67BAD09276BB55583CEDF48AEEFFD8FA3DBE4F609760DF1EDED136B38792CD164D2EA3C5443F0D8F9117544A9A6AAC615ADE01440B7948B2B53BC3F7218DEDEB16D23C3B0C2AA4BEB99F9A9225D87B6CCB037D8E9A2918C20FE9F2BFF429FD0F23AE370E820842AEDD823DD5B6DDD7F4AD3A06735A2E4144DBABEA5DD83A6AA98EED5F6F3021C246FBABD280986A1E7A24CCBE11BC3050CC04DB566277CECBA8B5BDC1D15E1F066B25B668C7B87EA54894EC7559B64F1400934DCE1C06A10955988E3B3F4A40566B3989608404859335C53EBD6BEE21614EB7C954D543DBA7EB61555B7CED9D08EF560426DBCE3018FBEF788CF69AEAB433B692A9E28CBAFEFC048BD9AB423678D4DD5807329BCC417CF77EC7FD8E50B6D9A8D6B2017B24F6890557AF327980D086499B7C4ED6518B9C23DAB9571CA9E8E949C039C5CC002CBC9BDD08728D543143AFE577738AD309AB2493A8157272196B73C28A4826B37A8274198A4E8188CDADB1D7BB209C84D03500F79B9DFEC1E4441F34069CC01D6B9A57940914F56217C0F3A5CE0C75DE2815EE396D4AB00EC9695DFBCDD88EA6C8017CC29B1257EED39B50E0D075CCF9564D4B22F59F4B5E6667E4CACAC6B63D8CC1C9AB2CC6309A319E559D2062FB99D15B62F08E4DAD676698813D227FF8967B3B3830970E92277B2446A3C269A74FB437800824A8987DA3636A17A53C7E55C66077BE0FBD63441402F19C6C4E1F1C46185A3F3F5D7D7F553F0066EBFCF2ECD74CFC6DB48F6A458AE66EC12532B691FA3AE9A0C19809B3A1AF06340EFB012A33D484D272CA09D5862DAC5E3A00006F260BDE5CE74E007AB12A8F686373949308E574DCE7EA9D145936C6CA2F0F +20170706141404 2 6 100 7679 2 C0388038628CD48D5377C99911D89CEDF70AC54721EE6974975D61C9E25580D2108B48CBCDB8B647B271FA822546C00580DB013D19EE5A49EFD9AAECA2036A83BB3E2F96C3E7CB273AA9ACEFCA5A3E4C7C8FCF3332DE11288D8BD76E17B4C530F5F6EFB0D757F63E3B2B519EE960FA8206DF81E7B9DA463CE389E3164588BF5B66355D481DC620F0B2F352782105DF3AB86076DD7D612CE9839CB251D5C975166859A41B740E08E66B746B710479FAA430E2891E60647E04FE71D8F8BC9A6BCD20CFB42299142DC016E672CC350D497809379F54F6F3D1649ADCE72ADECEAAE1ECA85EEE8006700379DE3687A67AF796E1F317815461CFF6E58615CD453265612315FA8F99DC65D9CC218004671E43CE58C9F54862D86B58FD71212199A2A562B1AB9604BF43676A403E8EA56A69E68F1CF0C60C83B8EB31D9C0A23D8410C3A6898D749CAD8CDA9F17A224536BD08436B25E50BA67BAD09276BB55583CEDF48AEEFFD8FA3DBE4F609760DF1EDED136B38792CD164D2EA3C5443F0D8F9117544A9A6AAC615ADE01440B7948B2B53BC3F7218DEDEB16D23C3B0C2AA4BEB99F9A9225D87B6CCB037D8E9A2918C20FE9F2BFF429FD0F23AE370E820842AEDD823DD5B6DDD7F4AD3A06735A2E4144DBABEA5DD83A6AA98EED5F6F3021C246FBABD280986A1E7A24CCBE11BC3050CC04DB566277CECBA8B5BDC1D15E1F066B25B668C7B87EA54894EC7559B64F1400934DCE1C06A10955988E3B3F4A40566B3989608404859335C53EBD6BEE21614EB7C954D543DBA7EB61555B7CED9D08EF560426DBCE3018FBEF788CF69AEAB433B692A9E28CBAFEFC048BD9AB423678D4DD5807329BCC417CF77EC7FD8E50B6D9A8D6B2017B24F6890557AF327980D086499B7C4ED6518B9C23DAB9571CA9E8E949C039C5CC002CBC9BDD08728D543143AFE577738AD309AB2493A8157272196B73C28A4826B37A8274198A4E8188CDADB1D7BB209C84D03500F79B9DFEC1E4441F34069CC01D6B9A57940914F56217C0F3A5CE0C75DE2815EE396D4AB00EC9695DFBCDD88EA6C8017CC29B1257EED39B50E0D075CCF9564D4B22F59F4B5E6667E4CACAC6B63D8CC1C9AB2CC6309A319E559D2062FB99D15B62F08E4DAD676698813D227FF8967B3B3830970E92277B2446A3C269A74FB437800824A8987DA3636A17A53C7E55C66077BE0FBD63441402F19C6C4E1F1C46185A3F3F5D7D7F553F0066EBFCF2ECD74CFC6DB48F6A458AE66EC12532B691FA3AE9A0C19809B3A1AF06340EFB012A33D484D272CA09D5862DAC5E3A00006F260BDE5CE74E007AB12A8F686373949308E574DCE7EA9D145936C781A68B +20170706153843 2 6 100 7679 2 C0388038628CD48D5377C99911D89CEDF70AC54721EE6974975D61C9E25580D2108B48CBCDB8B647B271FA822546C00580DB013D19EE5A49EFD9AAECA2036A83BB3E2F96C3E7CB273AA9ACEFCA5A3E4C7C8FCF3332DE11288D8BD76E17B4C530F5F6EFB0D757F63E3B2B519EE960FA8206DF81E7B9DA463CE389E3164588BF5B66355D481DC620F0B2F352782105DF3AB86076DD7D612CE9839CB251D5C975166859A41B740E08E66B746B710479FAA430E2891E60647E04FE71D8F8BC9A6BCD20CFB42299142DC016E672CC350D497809379F54F6F3D1649ADCE72ADECEAAE1ECA85EEE8006700379DE3687A67AF796E1F317815461CFF6E58615CD453265612315FA8F99DC65D9CC218004671E43CE58C9F54862D86B58FD71212199A2A562B1AB9604BF43676A403E8EA56A69E68F1CF0C60C83B8EB31D9C0A23D8410C3A6898D749CAD8CDA9F17A224536BD08436B25E50BA67BAD09276BB55583CEDF48AEEFFD8FA3DBE4F609760DF1EDED136B38792CD164D2EA3C5443F0D8F9117544A9A6AAC615ADE01440B7948B2B53BC3F7218DEDEB16D23C3B0C2AA4BEB99F9A9225D87B6CCB037D8E9A2918C20FE9F2BFF429FD0F23AE370E820842AEDD823DD5B6DDD7F4AD3A06735A2E4144DBABEA5DD83A6AA98EED5F6F3021C246FBABD280986A1E7A24CCBE11BC3050CC04DB566277CECBA8B5BDC1D15E1F066B25B668C7B87EA54894EC7559B64F1400934DCE1C06A10955988E3B3F4A40566B3989608404859335C53EBD6BEE21614EB7C954D543DBA7EB61555B7CED9D08EF560426DBCE3018FBEF788CF69AEAB433B692A9E28CBAFEFC048BD9AB423678D4DD5807329BCC417CF77EC7FD8E50B6D9A8D6B2017B24F6890557AF327980D086499B7C4ED6518B9C23DAB9571CA9E8E949C039C5CC002CBC9BDD08728D543143AFE577738AD309AB2493A8157272196B73C28A4826B37A8274198A4E8188CDADB1D7BB209C84D03500F79B9DFEC1E4441F34069CC01D6B9A57940914F56217C0F3A5CE0C75DE2815EE396D4AB00EC9695DFBCDD88EA6C8017CC29B1257EED39B50E0D075CCF9564D4B22F59F4B5E6667E4CACAC6B63D8CC1C9AB2CC6309A319E559D2062FB99D15B62F08E4DAD676698813D227FF8967B3B3830970E92277B2446A3C269A74FB437800824A8987DA3636A17A53C7E55C66077BE0FBD63441402F19C6C4E1F1C46185A3F3F5D7D7F553F0066EBFCF2ECD74CFC6DB48F6A458AE66EC12532B691FA3AE9A0C19809B3A1AF06340EFB012A33D484D272CA09D5862DAC5E3A00006F260BDE5CE74E007AB12A8F686373949308E574DCE7EA9D145936C8A1C2AB +20170706173242 2 6 100 7679 5 C0388038628CD48D5377C99911D89CEDF70AC54721EE6974975D61C9E25580D2108B48CBCDB8B647B271FA822546C00580DB013D19EE5A49EFD9AAECA2036A83BB3E2F96C3E7CB273AA9ACEFCA5A3E4C7C8FCF3332DE11288D8BD76E17B4C530F5F6EFB0D757F63E3B2B519EE960FA8206DF81E7B9DA463CE389E3164588BF5B66355D481DC620F0B2F352782105DF3AB86076DD7D612CE9839CB251D5C975166859A41B740E08E66B746B710479FAA430E2891E60647E04FE71D8F8BC9A6BCD20CFB42299142DC016E672CC350D497809379F54F6F3D1649ADCE72ADECEAAE1ECA85EEE8006700379DE3687A67AF796E1F317815461CFF6E58615CD453265612315FA8F99DC65D9CC218004671E43CE58C9F54862D86B58FD71212199A2A562B1AB9604BF43676A403E8EA56A69E68F1CF0C60C83B8EB31D9C0A23D8410C3A6898D749CAD8CDA9F17A224536BD08436B25E50BA67BAD09276BB55583CEDF48AEEFFD8FA3DBE4F609760DF1EDED136B38792CD164D2EA3C5443F0D8F9117544A9A6AAC615ADE01440B7948B2B53BC3F7218DEDEB16D23C3B0C2AA4BEB99F9A9225D87B6CCB037D8E9A2918C20FE9F2BFF429FD0F23AE370E820842AEDD823DD5B6DDD7F4AD3A06735A2E4144DBABEA5DD83A6AA98EED5F6F3021C246FBABD280986A1E7A24CCBE11BC3050CC04DB566277CECBA8B5BDC1D15E1F066B25B668C7B87EA54894EC7559B64F1400934DCE1C06A10955988E3B3F4A40566B3989608404859335C53EBD6BEE21614EB7C954D543DBA7EB61555B7CED9D08EF560426DBCE3018FBEF788CF69AEAB433B692A9E28CBAFEFC048BD9AB423678D4DD5807329BCC417CF77EC7FD8E50B6D9A8D6B2017B24F6890557AF327980D086499B7C4ED6518B9C23DAB9571CA9E8E949C039C5CC002CBC9BDD08728D543143AFE577738AD309AB2493A8157272196B73C28A4826B37A8274198A4E8188CDADB1D7BB209C84D03500F79B9DFEC1E4441F34069CC01D6B9A57940914F56217C0F3A5CE0C75DE2815EE396D4AB00EC9695DFBCDD88EA6C8017CC29B1257EED39B50E0D075CCF9564D4B22F59F4B5E6667E4CACAC6B63D8CC1C9AB2CC6309A319E559D2062FB99D15B62F08E4DAD676698813D227FF8967B3B3830970E92277B2446A3C269A74FB437800824A8987DA3636A17A53C7E55C66077BE0FBD63441402F19C6C4E1F1C46185A3F3F5D7D7F553F0066EBFCF2ECD74CFC6DB48F6A458AE66EC12532B691FA3AE9A0C19809B3A1AF06340EFB012A33D484D272CA09D5862DAC5E3A00006F260BDE5CE74E007AB12A8F686373949308E574DCE7EA9D145936CA322EEF +20170706183451 2 6 100 7679 2 C0388038628CD48D5377C99911D89CEDF70AC54721EE6974975D61C9E25580D2108B48CBCDB8B647B271FA822546C00580DB013D19EE5A49EFD9AAECA2036A83BB3E2F96C3E7CB273AA9ACEFCA5A3E4C7C8FCF3332DE11288D8BD76E17B4C530F5F6EFB0D757F63E3B2B519EE960FA8206DF81E7B9DA463CE389E3164588BF5B66355D481DC620F0B2F352782105DF3AB86076DD7D612CE9839CB251D5C975166859A41B740E08E66B746B710479FAA430E2891E60647E04FE71D8F8BC9A6BCD20CFB42299142DC016E672CC350D497809379F54F6F3D1649ADCE72ADECEAAE1ECA85EEE8006700379DE3687A67AF796E1F317815461CFF6E58615CD453265612315FA8F99DC65D9CC218004671E43CE58C9F54862D86B58FD71212199A2A562B1AB9604BF43676A403E8EA56A69E68F1CF0C60C83B8EB31D9C0A23D8410C3A6898D749CAD8CDA9F17A224536BD08436B25E50BA67BAD09276BB55583CEDF48AEEFFD8FA3DBE4F609760DF1EDED136B38792CD164D2EA3C5443F0D8F9117544A9A6AAC615ADE01440B7948B2B53BC3F7218DEDEB16D23C3B0C2AA4BEB99F9A9225D87B6CCB037D8E9A2918C20FE9F2BFF429FD0F23AE370E820842AEDD823DD5B6DDD7F4AD3A06735A2E4144DBABEA5DD83A6AA98EED5F6F3021C246FBABD280986A1E7A24CCBE11BC3050CC04DB566277CECBA8B5BDC1D15E1F066B25B668C7B87EA54894EC7559B64F1400934DCE1C06A10955988E3B3F4A40566B3989608404859335C53EBD6BEE21614EB7C954D543DBA7EB61555B7CED9D08EF560426DBCE3018FBEF788CF69AEAB433B692A9E28CBAFEFC048BD9AB423678D4DD5807329BCC417CF77EC7FD8E50B6D9A8D6B2017B24F6890557AF327980D086499B7C4ED6518B9C23DAB9571CA9E8E949C039C5CC002CBC9BDD08728D543143AFE577738AD309AB2493A8157272196B73C28A4826B37A8274198A4E8188CDADB1D7BB209C84D03500F79B9DFEC1E4441F34069CC01D6B9A57940914F56217C0F3A5CE0C75DE2815EE396D4AB00EC9695DFBCDD88EA6C8017CC29B1257EED39B50E0D075CCF9564D4B22F59F4B5E6667E4CACAC6B63D8CC1C9AB2CC6309A319E559D2062FB99D15B62F08E4DAD676698813D227FF8967B3B3830970E92277B2446A3C269A74FB437800824A8987DA3636A17A53C7E55C66077BE0FBD63441402F19C6C4E1F1C46185A3F3F5D7D7F553F0066EBFCF2ECD74CFC6DB48F6A458AE66EC12532B691FA3AE9A0C19809B3A1AF06340EFB012A33D484D272CA09D5862DAC5E3A00006F260BDE5CE74E007AB12A8F686373949308E574DCE7EA9D145936CB02939B +20170706184330 2 6 100 7679 2 C0388038628CD48D5377C99911D89CEDF70AC54721EE6974975D61C9E25580D2108B48CBCDB8B647B271FA822546C00580DB013D19EE5A49EFD9AAECA2036A83BB3E2F96C3E7CB273AA9ACEFCA5A3E4C7C8FCF3332DE11288D8BD76E17B4C530F5F6EFB0D757F63E3B2B519EE960FA8206DF81E7B9DA463CE389E3164588BF5B66355D481DC620F0B2F352782105DF3AB86076DD7D612CE9839CB251D5C975166859A41B740E08E66B746B710479FAA430E2891E60647E04FE71D8F8BC9A6BCD20CFB42299142DC016E672CC350D497809379F54F6F3D1649ADCE72ADECEAAE1ECA85EEE8006700379DE3687A67AF796E1F317815461CFF6E58615CD453265612315FA8F99DC65D9CC218004671E43CE58C9F54862D86B58FD71212199A2A562B1AB9604BF43676A403E8EA56A69E68F1CF0C60C83B8EB31D9C0A23D8410C3A6898D749CAD8CDA9F17A224536BD08436B25E50BA67BAD09276BB55583CEDF48AEEFFD8FA3DBE4F609760DF1EDED136B38792CD164D2EA3C5443F0D8F9117544A9A6AAC615ADE01440B7948B2B53BC3F7218DEDEB16D23C3B0C2AA4BEB99F9A9225D87B6CCB037D8E9A2918C20FE9F2BFF429FD0F23AE370E820842AEDD823DD5B6DDD7F4AD3A06735A2E4144DBABEA5DD83A6AA98EED5F6F3021C246FBABD280986A1E7A24CCBE11BC3050CC04DB566277CECBA8B5BDC1D15E1F066B25B668C7B87EA54894EC7559B64F1400934DCE1C06A10955988E3B3F4A40566B3989608404859335C53EBD6BEE21614EB7C954D543DBA7EB61555B7CED9D08EF560426DBCE3018FBEF788CF69AEAB433B692A9E28CBAFEFC048BD9AB423678D4DD5807329BCC417CF77EC7FD8E50B6D9A8D6B2017B24F6890557AF327980D086499B7C4ED6518B9C23DAB9571CA9E8E949C039C5CC002CBC9BDD08728D543143AFE577738AD309AB2493A8157272196B73C28A4826B37A8274198A4E8188CDADB1D7BB209C84D03500F79B9DFEC1E4441F34069CC01D6B9A57940914F56217C0F3A5CE0C75DE2815EE396D4AB00EC9695DFBCDD88EA6C8017CC29B1257EED39B50E0D075CCF9564D4B22F59F4B5E6667E4CACAC6B63D8CC1C9AB2CC6309A319E559D2062FB99D15B62F08E4DAD676698813D227FF8967B3B3830970E92277B2446A3C269A74FB437800824A8987DA3636A17A53C7E55C66077BE0FBD63441402F19C6C4E1F1C46185A3F3F5D7D7F553F0066EBFCF2ECD74CFC6DB48F6A458AE66EC12532B691FA3AE9A0C19809B3A1AF06340EFB012A33D484D272CA09D5862DAC5E3A00006F260BDE5CE74E007AB12A8F686373949308E574DCE7EA9D145936CB163C7B +20170706195815 2 6 100 7679 2 C0388038628CD48D5377C99911D89CEDF70AC54721EE6974975D61C9E25580D2108B48CBCDB8B647B271FA822546C00580DB013D19EE5A49EFD9AAECA2036A83BB3E2F96C3E7CB273AA9ACEFCA5A3E4C7C8FCF3332DE11288D8BD76E17B4C530F5F6EFB0D757F63E3B2B519EE960FA8206DF81E7B9DA463CE389E3164588BF5B66355D481DC620F0B2F352782105DF3AB86076DD7D612CE9839CB251D5C975166859A41B740E08E66B746B710479FAA430E2891E60647E04FE71D8F8BC9A6BCD20CFB42299142DC016E672CC350D497809379F54F6F3D1649ADCE72ADECEAAE1ECA85EEE8006700379DE3687A67AF796E1F317815461CFF6E58615CD453265612315FA8F99DC65D9CC218004671E43CE58C9F54862D86B58FD71212199A2A562B1AB9604BF43676A403E8EA56A69E68F1CF0C60C83B8EB31D9C0A23D8410C3A6898D749CAD8CDA9F17A224536BD08436B25E50BA67BAD09276BB55583CEDF48AEEFFD8FA3DBE4F609760DF1EDED136B38792CD164D2EA3C5443F0D8F9117544A9A6AAC615ADE01440B7948B2B53BC3F7218DEDEB16D23C3B0C2AA4BEB99F9A9225D87B6CCB037D8E9A2918C20FE9F2BFF429FD0F23AE370E820842AEDD823DD5B6DDD7F4AD3A06735A2E4144DBABEA5DD83A6AA98EED5F6F3021C246FBABD280986A1E7A24CCBE11BC3050CC04DB566277CECBA8B5BDC1D15E1F066B25B668C7B87EA54894EC7559B64F1400934DCE1C06A10955988E3B3F4A40566B3989608404859335C53EBD6BEE21614EB7C954D543DBA7EB61555B7CED9D08EF560426DBCE3018FBEF788CF69AEAB433B692A9E28CBAFEFC048BD9AB423678D4DD5807329BCC417CF77EC7FD8E50B6D9A8D6B2017B24F6890557AF327980D086499B7C4ED6518B9C23DAB9571CA9E8E949C039C5CC002CBC9BDD08728D543143AFE577738AD309AB2493A8157272196B73C28A4826B37A8274198A4E8188CDADB1D7BB209C84D03500F79B9DFEC1E4441F34069CC01D6B9A57940914F56217C0F3A5CE0C75DE2815EE396D4AB00EC9695DFBCDD88EA6C8017CC29B1257EED39B50E0D075CCF9564D4B22F59F4B5E6667E4CACAC6B63D8CC1C9AB2CC6309A319E559D2062FB99D15B62F08E4DAD676698813D227FF8967B3B3830970E92277B2446A3C269A74FB437800824A8987DA3636A17A53C7E55C66077BE0FBD63441402F19C6C4E1F1C46185A3F3F5D7D7F553F0066EBFCF2ECD74CFC6DB48F6A458AE66EC12532B691FA3AE9A0C19809B3A1AF06340EFB012A33D484D272CA09D5862DAC5E3A00006F260BDE5CE74E007AB12A8F686373949308E574DCE7EA9D145936CC15613B +20170707002909 2 6 100 7679 2 C0388038628CD48D5377C99911D89CEDF70AC54721EE6974975D61C9E25580D2108B48CBCDB8B647B271FA822546C00580DB013D19EE5A49EFD9AAECA2036A83BB3E2F96C3E7CB273AA9ACEFCA5A3E4C7C8FCF3332DE11288D8BD76E17B4C530F5F6EFB0D757F63E3B2B519EE960FA8206DF81E7B9DA463CE389E3164588BF5B66355D481DC620F0B2F352782105DF3AB86076DD7D612CE9839CB251D5C975166859A41B740E08E66B746B710479FAA430E2891E60647E04FE71D8F8BC9A6BCD20CFB42299142DC016E672CC350D497809379F54F6F3D1649ADCE72ADECEAAE1ECA85EEE8006700379DE3687A67AF796E1F317815461CFF6E58615CD453265612315FA8F99DC65D9CC218004671E43CE58C9F54862D86B58FD71212199A2A562B1AB9604BF43676A403E8EA56A69E68F1CF0C60C83B8EB31D9C0A23D8410C3A6898D749CAD8CDA9F17A224536BD08436B25E50BA67BAD09276BB55583CEDF48AEEFFD8FA3DBE4F609760DF1EDED136B38792CD164D2EA3C5443F0D8F9117544A9A6AAC615ADE01440B7948B2B53BC3F7218DEDEB16D23C3B0C2AA4BEB99F9A9225D87B6CCB037D8E9A2918C20FE9F2BFF429FD0F23AE370E820842AEDD823DD5B6DDD7F4AD3A06735A2E4144DBABEA5DD83A6AA98EED5F6F3021C246FBABD280986A1E7A24CCBE11BC3050CC04DB566277CECBA8B5BDC1D15E1F066B25B668C7B87EA54894EC7559B64F1400934DCE1C06A10955988E3B3F4A40566B3989608404859335C53EBD6BEE21614EB7C954D543DBA7EB61555B7CED9D08EF560426DBCE3018FBEF788CF69AEAB433B692A9E28CBAFEFC048BD9AB423678D4DD5807329BCC417CF77EC7FD8E50B6D9A8D6B2017B24F6890557AF327980D086499B7C4ED6518B9C23DAB9571CA9E8E949C039C5CC002CBC9BDD08728D543143AFE577738AD309AB2493A8157272196B73C28A4826B37A8274198A4E8188CDADB1D7BB209C84D03500F79B9DFEC1E4441F34069CC01D6B9A57940914F56217C0F3A5CE0C75DE2815EE396D4AB00EC9695DFBCDD88EA6C8017CC29B1257EED39B50E0D075CCF9564D4B22F59F4B5E6667E4CACAC6B63D8CC1C9AB2CC6309A319E559D2062FB99D15B62F08E4DAD676698813D227FF8967B3B3830970E92277B2446A3C269A74FB437800824A8987DA3636A17A53C7E55C66077BE0FBD63441402F19C6C4E1F1C46185A3F3F5D7D7F553F0066EBFCF2ECD74CFC6DB48F6A458AE66EC12532B691FA3AE9A0C19809B3A1AF06340EFB012A33D484D272CA09D5862DAC5E3A00006F260BDE5CE74E007AB12A8F686373949308E574DCE7EA9D145936CFBE39B3 +20170707012259 2 6 100 7679 5 C0388038628CD48D5377C99911D89CEDF70AC54721EE6974975D61C9E25580D2108B48CBCDB8B647B271FA822546C00580DB013D19EE5A49EFD9AAECA2036A83BB3E2F96C3E7CB273AA9ACEFCA5A3E4C7C8FCF3332DE11288D8BD76E17B4C530F5F6EFB0D757F63E3B2B519EE960FA8206DF81E7B9DA463CE389E3164588BF5B66355D481DC620F0B2F352782105DF3AB86076DD7D612CE9839CB251D5C975166859A41B740E08E66B746B710479FAA430E2891E60647E04FE71D8F8BC9A6BCD20CFB42299142DC016E672CC350D497809379F54F6F3D1649ADCE72ADECEAAE1ECA85EEE8006700379DE3687A67AF796E1F317815461CFF6E58615CD453265612315FA8F99DC65D9CC218004671E43CE58C9F54862D86B58FD71212199A2A562B1AB9604BF43676A403E8EA56A69E68F1CF0C60C83B8EB31D9C0A23D8410C3A6898D749CAD8CDA9F17A224536BD08436B25E50BA67BAD09276BB55583CEDF48AEEFFD8FA3DBE4F609760DF1EDED136B38792CD164D2EA3C5443F0D8F9117544A9A6AAC615ADE01440B7948B2B53BC3F7218DEDEB16D23C3B0C2AA4BEB99F9A9225D87B6CCB037D8E9A2918C20FE9F2BFF429FD0F23AE370E820842AEDD823DD5B6DDD7F4AD3A06735A2E4144DBABEA5DD83A6AA98EED5F6F3021C246FBABD280986A1E7A24CCBE11BC3050CC04DB566277CECBA8B5BDC1D15E1F066B25B668C7B87EA54894EC7559B64F1400934DCE1C06A10955988E3B3F4A40566B3989608404859335C53EBD6BEE21614EB7C954D543DBA7EB61555B7CED9D08EF560426DBCE3018FBEF788CF69AEAB433B692A9E28CBAFEFC048BD9AB423678D4DD5807329BCC417CF77EC7FD8E50B6D9A8D6B2017B24F6890557AF327980D086499B7C4ED6518B9C23DAB9571CA9E8E949C039C5CC002CBC9BDD08728D543143AFE577738AD309AB2493A8157272196B73C28A4826B37A8274198A4E8188CDADB1D7BB209C84D03500F79B9DFEC1E4441F34069CC01D6B9A57940914F56217C0F3A5CE0C75DE2815EE396D4AB00EC9695DFBCDD88EA6C8017CC29B1257EED39B50E0D075CCF9564D4B22F59F4B5E6667E4CACAC6B63D8CC1C9AB2CC6309A319E559D2062FB99D15B62F08E4DAD676698813D227FF8967B3B3830970E92277B2446A3C269A74FB437800824A8987DA3636A17A53C7E55C66077BE0FBD63441402F19C6C4E1F1C46185A3F3F5D7D7F553F0066EBFCF2ECD74CFC6DB48F6A458AE66EC12532B691FA3AE9A0C19809B3A1AF06340EFB012A33D484D272CA09D5862DAC5E3A00006F260BDE5CE74E007AB12A8F686373949308E574DCE7EA9D145936D06F0ADF +20170707064939 2 6 100 7679 2 C0388038628CD48D5377C99911D89CEDF70AC54721EE6974975D61C9E25580D2108B48CBCDB8B647B271FA822546C00580DB013D19EE5A49EFD9AAECA2036A83BB3E2F96C3E7CB273AA9ACEFCA5A3E4C7C8FCF3332DE11288D8BD76E17B4C530F5F6EFB0D757F63E3B2B519EE960FA8206DF81E7B9DA463CE389E3164588BF5B66355D481DC620F0B2F352782105DF3AB86076DD7D612CE9839CB251D5C975166859A41B740E08E66B746B710479FAA430E2891E60647E04FE71D8F8BC9A6BCD20CFB42299142DC016E672CC350D497809379F54F6F3D1649ADCE72ADECEAAE1ECA85EEE8006700379DE3687A67AF796E1F317815461CFF6E58615CD453265612315FA8F99DC65D9CC218004671E43CE58C9F54862D86B58FD71212199A2A562B1AB9604BF43676A403E8EA56A69E68F1CF0C60C83B8EB31D9C0A23D8410C3A6898D749CAD8CDA9F17A224536BD08436B25E50BA67BAD09276BB55583CEDF48AEEFFD8FA3DBE4F609760DF1EDED136B38792CD164D2EA3C5443F0D8F9117544A9A6AAC615ADE01440B7948B2B53BC3F7218DEDEB16D23C3B0C2AA4BEB99F9A9225D87B6CCB037D8E9A2918C20FE9F2BFF429FD0F23AE370E820842AEDD823DD5B6DDD7F4AD3A06735A2E4144DBABEA5DD83A6AA98EED5F6F3021C246FBABD280986A1E7A24CCBE11BC3050CC04DB566277CECBA8B5BDC1D15E1F066B25B668C7B87EA54894EC7559B64F1400934DCE1C06A10955988E3B3F4A40566B3989608404859335C53EBD6BEE21614EB7C954D543DBA7EB61555B7CED9D08EF560426DBCE3018FBEF788CF69AEAB433B692A9E28CBAFEFC048BD9AB423678D4DD5807329BCC417CF77EC7FD8E50B6D9A8D6B2017B24F6890557AF327980D086499B7C4ED6518B9C23DAB9571CA9E8E949C039C5CC002CBC9BDD08728D543143AFE577738AD309AB2493A8157272196B73C28A4826B37A8274198A4E8188CDADB1D7BB209C84D03500F79B9DFEC1E4441F34069CC01D6B9A57940914F56217C0F3A5CE0C75DE2815EE396D4AB00EC9695DFBCDD88EA6C8017CC29B1257EED39B50E0D075CCF9564D4B22F59F4B5E6667E4CACAC6B63D8CC1C9AB2CC6309A319E559D2062FB99D15B62F08E4DAD676698813D227FF8967B3B3830970E92277B2446A3C269A74FB437800824A8987DA3636A17A53C7E55C66077BE0FBD63441402F19C6C4E1F1C46185A3F3F5D7D7F553F0066EBFCF2ECD74CFC6DB48F6A458AE66EC12532B691FA3AE9A0C19809B3A1AF06340EFB012A33D484D272CA09D5862DAC5E3A00006F260BDE5CE74E007AB12A8F686373949308E574DCE7EA9D145936D4E0A703 +20170707065604 2 6 100 7679 5 C0388038628CD48D5377C99911D89CEDF70AC54721EE6974975D61C9E25580D2108B48CBCDB8B647B271FA822546C00580DB013D19EE5A49EFD9AAECA2036A83BB3E2F96C3E7CB273AA9ACEFCA5A3E4C7C8FCF3332DE11288D8BD76E17B4C530F5F6EFB0D757F63E3B2B519EE960FA8206DF81E7B9DA463CE389E3164588BF5B66355D481DC620F0B2F352782105DF3AB86076DD7D612CE9839CB251D5C975166859A41B740E08E66B746B710479FAA430E2891E60647E04FE71D8F8BC9A6BCD20CFB42299142DC016E672CC350D497809379F54F6F3D1649ADCE72ADECEAAE1ECA85EEE8006700379DE3687A67AF796E1F317815461CFF6E58615CD453265612315FA8F99DC65D9CC218004671E43CE58C9F54862D86B58FD71212199A2A562B1AB9604BF43676A403E8EA56A69E68F1CF0C60C83B8EB31D9C0A23D8410C3A6898D749CAD8CDA9F17A224536BD08436B25E50BA67BAD09276BB55583CEDF48AEEFFD8FA3DBE4F609760DF1EDED136B38792CD164D2EA3C5443F0D8F9117544A9A6AAC615ADE01440B7948B2B53BC3F7218DEDEB16D23C3B0C2AA4BEB99F9A9225D87B6CCB037D8E9A2918C20FE9F2BFF429FD0F23AE370E820842AEDD823DD5B6DDD7F4AD3A06735A2E4144DBABEA5DD83A6AA98EED5F6F3021C246FBABD280986A1E7A24CCBE11BC3050CC04DB566277CECBA8B5BDC1D15E1F066B25B668C7B87EA54894EC7559B64F1400934DCE1C06A10955988E3B3F4A40566B3989608404859335C53EBD6BEE21614EB7C954D543DBA7EB61555B7CED9D08EF560426DBCE3018FBEF788CF69AEAB433B692A9E28CBAFEFC048BD9AB423678D4DD5807329BCC417CF77EC7FD8E50B6D9A8D6B2017B24F6890557AF327980D086499B7C4ED6518B9C23DAB9571CA9E8E949C039C5CC002CBC9BDD08728D543143AFE577738AD309AB2493A8157272196B73C28A4826B37A8274198A4E8188CDADB1D7BB209C84D03500F79B9DFEC1E4441F34069CC01D6B9A57940914F56217C0F3A5CE0C75DE2815EE396D4AB00EC9695DFBCDD88EA6C8017CC29B1257EED39B50E0D075CCF9564D4B22F59F4B5E6667E4CACAC6B63D8CC1C9AB2CC6309A319E559D2062FB99D15B62F08E4DAD676698813D227FF8967B3B3830970E92277B2446A3C269A74FB437800824A8987DA3636A17A53C7E55C66077BE0FBD63441402F19C6C4E1F1C46185A3F3F5D7D7F553F0066EBFCF2ECD74CFC6DB48F6A458AE66EC12532B691FA3AE9A0C19809B3A1AF06340EFB012A33D484D272CA09D5862DAC5E3A00006F260BDE5CE74E007AB12A8F686373949308E574DCE7EA9D145936D4EE0BAF +20170707120623 2 6 100 7679 2 C0388038628CD48D5377C99911D89CEDF70AC54721EE6974975D61C9E25580D2108B48CBCDB8B647B271FA822546C00580DB013D19EE5A49EFD9AAECA2036A83BB3E2F96C3E7CB273AA9ACEFCA5A3E4C7C8FCF3332DE11288D8BD76E17B4C530F5F6EFB0D757F63E3B2B519EE960FA8206DF81E7B9DA463CE389E3164588BF5B66355D481DC620F0B2F352782105DF3AB86076DD7D612CE9839CB251D5C975166859A41B740E08E66B746B710479FAA430E2891E60647E04FE71D8F8BC9A6BCD20CFB42299142DC016E672CC350D497809379F54F6F3D1649ADCE72ADECEAAE1ECA85EEE8006700379DE3687A67AF796E1F317815461CFF6E58615CD453265612315FA8F99DC65D9CC218004671E43CE58C9F54862D86B58FD71212199A2A562B1AB9604BF43676A403E8EA56A69E68F1CF0C60C83B8EB31D9C0A23D8410C3A6898D749CAD8CDA9F17A224536BD08436B25E50BA67BAD09276BB55583CEDF48AEEFFD8FA3DBE4F609760DF1EDED136B38792CD164D2EA3C5443F0D8F9117544A9A6AAC615ADE01440B7948B2B53BC3F7218DEDEB16D23C3B0C2AA4BEB99F9A9225D87B6CCB037D8E9A2918C20FE9F2BFF429FD0F23AE370E820842AEDD823DD5B6DDD7F4AD3A06735A2E4144DBABEA5DD83A6AA98EED5F6F3021C246FBABD280986A1E7A24CCBE11BC3050CC04DB566277CECBA8B5BDC1D15E1F066B25B668C7B87EA54894EC7559B64F1400934DCE1C06A10955988E3B3F4A40566B3989608404859335C53EBD6BEE21614EB7C954D543DBA7EB61555B7CED9D08EF560426DBCE3018FBEF788CF69AEAB433B692A9E28CBAFEFC048BD9AB423678D4DD5807329BCC417CF77EC7FD8E50B6D9A8D6B2017B24F6890557AF327980D086499B7C4ED6518B9C23DAB9571CA9E8E949C039C5CC002CBC9BDD08728D543143AFE577738AD309AB2493A8157272196B73C28A4826B37A8274198A4E8188CDADB1D7BB209C84D03500F79B9DFEC1E4441F34069CC01D6B9A57940914F56217C0F3A5CE0C75DE2815EE396D4AB00EC9695DFBCDD88EA6C8017CC29B1257EED39B50E0D075CCF9564D4B22F59F4B5E6667E4CACAC6B63D8CC1C9AB2CC6309A319E559D2062FB99D15B62F08E4DAD676698813D227FF8967B3B3830970E92277B2446A3C269A74FB437800824A8987DA3636A17A53C7E55C66077BE0FBD63441402F19C6C4E1F1C46185A3F3F5D7D7F553F0066EBFCF2ECD74CFC6DB48F6A458AE66EC12532B691FA3AE9A0C19809B3A1AF06340EFB012A33D484D272CA09D5862DAC5E3A00006F260BDE5CE74E007AB12A8F686373949308E574DCE7EA9D145936D9082CA3 +20170707121752 2 6 100 7679 5 C0388038628CD48D5377C99911D89CEDF70AC54721EE6974975D61C9E25580D2108B48CBCDB8B647B271FA822546C00580DB013D19EE5A49EFD9AAECA2036A83BB3E2F96C3E7CB273AA9ACEFCA5A3E4C7C8FCF3332DE11288D8BD76E17B4C530F5F6EFB0D757F63E3B2B519EE960FA8206DF81E7B9DA463CE389E3164588BF5B66355D481DC620F0B2F352782105DF3AB86076DD7D612CE9839CB251D5C975166859A41B740E08E66B746B710479FAA430E2891E60647E04FE71D8F8BC9A6BCD20CFB42299142DC016E672CC350D497809379F54F6F3D1649ADCE72ADECEAAE1ECA85EEE8006700379DE3687A67AF796E1F317815461CFF6E58615CD453265612315FA8F99DC65D9CC218004671E43CE58C9F54862D86B58FD71212199A2A562B1AB9604BF43676A403E8EA56A69E68F1CF0C60C83B8EB31D9C0A23D8410C3A6898D749CAD8CDA9F17A224536BD08436B25E50BA67BAD09276BB55583CEDF48AEEFFD8FA3DBE4F609760DF1EDED136B38792CD164D2EA3C5443F0D8F9117544A9A6AAC615ADE01440B7948B2B53BC3F7218DEDEB16D23C3B0C2AA4BEB99F9A9225D87B6CCB037D8E9A2918C20FE9F2BFF429FD0F23AE370E820842AEDD823DD5B6DDD7F4AD3A06735A2E4144DBABEA5DD83A6AA98EED5F6F3021C246FBABD280986A1E7A24CCBE11BC3050CC04DB566277CECBA8B5BDC1D15E1F066B25B668C7B87EA54894EC7559B64F1400934DCE1C06A10955988E3B3F4A40566B3989608404859335C53EBD6BEE21614EB7C954D543DBA7EB61555B7CED9D08EF560426DBCE3018FBEF788CF69AEAB433B692A9E28CBAFEFC048BD9AB423678D4DD5807329BCC417CF77EC7FD8E50B6D9A8D6B2017B24F6890557AF327980D086499B7C4ED6518B9C23DAB9571CA9E8E949C039C5CC002CBC9BDD08728D543143AFE577738AD309AB2493A8157272196B73C28A4826B37A8274198A4E8188CDADB1D7BB209C84D03500F79B9DFEC1E4441F34069CC01D6B9A57940914F56217C0F3A5CE0C75DE2815EE396D4AB00EC9695DFBCDD88EA6C8017CC29B1257EED39B50E0D075CCF9564D4B22F59F4B5E6667E4CACAC6B63D8CC1C9AB2CC6309A319E559D2062FB99D15B62F08E4DAD676698813D227FF8967B3B3830970E92277B2446A3C269A74FB437800824A8987DA3636A17A53C7E55C66077BE0FBD63441402F19C6C4E1F1C46185A3F3F5D7D7F553F0066EBFCF2ECD74CFC6DB48F6A458AE66EC12532B691FA3AE9A0C19809B3A1AF06340EFB012A33D484D272CA09D5862DAC5E3A00006F260BDE5CE74E007AB12A8F686373949308E574DCE7EA9D145936D928FC67 +20170707164931 2 6 100 7679 2 C0388038628CD48D5377C99911D89CEDF70AC54721EE6974975D61C9E25580D2108B48CBCDB8B647B271FA822546C00580DB013D19EE5A49EFD9AAECA2036A83BB3E2F96C3E7CB273AA9ACEFCA5A3E4C7C8FCF3332DE11288D8BD76E17B4C530F5F6EFB0D757F63E3B2B519EE960FA8206DF81E7B9DA463CE389E3164588BF5B66355D481DC620F0B2F352782105DF3AB86076DD7D612CE9839CB251D5C975166859A41B740E08E66B746B710479FAA430E2891E60647E04FE71D8F8BC9A6BCD20CFB42299142DC016E672CC350D497809379F54F6F3D1649ADCE72ADECEAAE1ECA85EEE8006700379DE3687A67AF796E1F317815461CFF6E58615CD453265612315FA8F99DC65D9CC218004671E43CE58C9F54862D86B58FD71212199A2A562B1AB9604BF43676A403E8EA56A69E68F1CF0C60C83B8EB31D9C0A23D8410C3A6898D749CAD8CDA9F17A224536BD08436B25E50BA67BAD09276BB55583CEDF48AEEFFD8FA3DBE4F609760DF1EDED136B38792CD164D2EA3C5443F0D8F9117544A9A6AAC615ADE01440B7948B2B53BC3F7218DEDEB16D23C3B0C2AA4BEB99F9A9225D87B6CCB037D8E9A2918C20FE9F2BFF429FD0F23AE370E820842AEDD823DD5B6DDD7F4AD3A06735A2E4144DBABEA5DD83A6AA98EED5F6F3021C246FBABD280986A1E7A24CCBE11BC3050CC04DB566277CECBA8B5BDC1D15E1F066B25B668C7B87EA54894EC7559B64F1400934DCE1C06A10955988E3B3F4A40566B3989608404859335C53EBD6BEE21614EB7C954D543DBA7EB61555B7CED9D08EF560426DBCE3018FBEF788CF69AEAB433B692A9E28CBAFEFC048BD9AB423678D4DD5807329BCC417CF77EC7FD8E50B6D9A8D6B2017B24F6890557AF327980D086499B7C4ED6518B9C23DAB9571CA9E8E949C039C5CC002CBC9BDD08728D543143AFE577738AD309AB2493A8157272196B73C28A4826B37A8274198A4E8188CDADB1D7BB209C84D03500F79B9DFEC1E4441F34069CC01D6B9A57940914F56217C0F3A5CE0C75DE2815EE396D4AB00EC9695DFBCDD88EA6C8017CC29B1257EED39B50E0D075CCF9564D4B22F59F4B5E6667E4CACAC6B63D8CC1C9AB2CC6309A319E559D2062FB99D15B62F08E4DAD676698813D227FF8967B3B3830970E92277B2446A3C269A74FB437800824A8987DA3636A17A53C7E55C66077BE0FBD63441402F19C6C4E1F1C46185A3F3F5D7D7F553F0066EBFCF2ECD74CFC6DB48F6A458AE66EC12532B691FA3AE9A0C19809B3A1AF06340EFB012A33D484D272CA09D5862DAC5E3A00006F260BDE5CE74E007AB12A8F686373949308E574DCE7EA9D145936DCD75823 +20170707220455 2 6 100 7679 2 C0388038628CD48D5377C99911D89CEDF70AC54721EE6974975D61C9E25580D2108B48CBCDB8B647B271FA822546C00580DB013D19EE5A49EFD9AAECA2036A83BB3E2F96C3E7CB273AA9ACEFCA5A3E4C7C8FCF3332DE11288D8BD76E17B4C530F5F6EFB0D757F63E3B2B519EE960FA8206DF81E7B9DA463CE389E3164588BF5B66355D481DC620F0B2F352782105DF3AB86076DD7D612CE9839CB251D5C975166859A41B740E08E66B746B710479FAA430E2891E60647E04FE71D8F8BC9A6BCD20CFB42299142DC016E672CC350D497809379F54F6F3D1649ADCE72ADECEAAE1ECA85EEE8006700379DE3687A67AF796E1F317815461CFF6E58615CD453265612315FA8F99DC65D9CC218004671E43CE58C9F54862D86B58FD71212199A2A562B1AB9604BF43676A403E8EA56A69E68F1CF0C60C83B8EB31D9C0A23D8410C3A6898D749CAD8CDA9F17A224536BD08436B25E50BA67BAD09276BB55583CEDF48AEEFFD8FA3DBE4F609760DF1EDED136B38792CD164D2EA3C5443F0D8F9117544A9A6AAC615ADE01440B7948B2B53BC3F7218DEDEB16D23C3B0C2AA4BEB99F9A9225D87B6CCB037D8E9A2918C20FE9F2BFF429FD0F23AE370E820842AEDD823DD5B6DDD7F4AD3A06735A2E4144DBABEA5DD83A6AA98EED5F6F3021C246FBABD280986A1E7A24CCBE11BC3050CC04DB566277CECBA8B5BDC1D15E1F066B25B668C7B87EA54894EC7559B64F1400934DCE1C06A10955988E3B3F4A40566B3989608404859335C53EBD6BEE21614EB7C954D543DBA7EB61555B7CED9D08EF560426DBCE3018FBEF788CF69AEAB433B692A9E28CBAFEFC048BD9AB423678D4DD5807329BCC417CF77EC7FD8E50B6D9A8D6B2017B24F6890557AF327980D086499B7C4ED6518B9C23DAB9571CA9E8E949C039C5CC002CBC9BDD08728D543143AFE577738AD309AB2493A8157272196B73C28A4826B37A8274198A4E8188CDADB1D7BB209C84D03500F79B9DFEC1E4441F34069CC01D6B9A57940914F56217C0F3A5CE0C75DE2815EE396D4AB00EC9695DFBCDD88EA6C8017CC29B1257EED39B50E0D075CCF9564D4B22F59F4B5E6667E4CACAC6B63D8CC1C9AB2CC6309A319E559D2062FB99D15B62F08E4DAD676698813D227FF8967B3B3830970E92277B2446A3C269A74FB437800824A8987DA3636A17A53C7E55C66077BE0FBD63441402F19C6C4E1F1C46185A3F3F5D7D7F553F0066EBFCF2ECD74CFC6DB48F6A458AE66EC12532B691FA3AE9A0C19809B3A1AF06340EFB012A33D484D272CA09D5862DAC5E3A00006F260BDE5CE74E007AB12A8F686373949308E574DCE7EA9D145936E0F28243 +20170707233018 2 6 100 7679 2 C0388038628CD48D5377C99911D89CEDF70AC54721EE6974975D61C9E25580D2108B48CBCDB8B647B271FA822546C00580DB013D19EE5A49EFD9AAECA2036A83BB3E2F96C3E7CB273AA9ACEFCA5A3E4C7C8FCF3332DE11288D8BD76E17B4C530F5F6EFB0D757F63E3B2B519EE960FA8206DF81E7B9DA463CE389E3164588BF5B66355D481DC620F0B2F352782105DF3AB86076DD7D612CE9839CB251D5C975166859A41B740E08E66B746B710479FAA430E2891E60647E04FE71D8F8BC9A6BCD20CFB42299142DC016E672CC350D497809379F54F6F3D1649ADCE72ADECEAAE1ECA85EEE8006700379DE3687A67AF796E1F317815461CFF6E58615CD453265612315FA8F99DC65D9CC218004671E43CE58C9F54862D86B58FD71212199A2A562B1AB9604BF43676A403E8EA56A69E68F1CF0C60C83B8EB31D9C0A23D8410C3A6898D749CAD8CDA9F17A224536BD08436B25E50BA67BAD09276BB55583CEDF48AEEFFD8FA3DBE4F609760DF1EDED136B38792CD164D2EA3C5443F0D8F9117544A9A6AAC615ADE01440B7948B2B53BC3F7218DEDEB16D23C3B0C2AA4BEB99F9A9225D87B6CCB037D8E9A2918C20FE9F2BFF429FD0F23AE370E820842AEDD823DD5B6DDD7F4AD3A06735A2E4144DBABEA5DD83A6AA98EED5F6F3021C246FBABD280986A1E7A24CCBE11BC3050CC04DB566277CECBA8B5BDC1D15E1F066B25B668C7B87EA54894EC7559B64F1400934DCE1C06A10955988E3B3F4A40566B3989608404859335C53EBD6BEE21614EB7C954D543DBA7EB61555B7CED9D08EF560426DBCE3018FBEF788CF69AEAB433B692A9E28CBAFEFC048BD9AB423678D4DD5807329BCC417CF77EC7FD8E50B6D9A8D6B2017B24F6890557AF327980D086499B7C4ED6518B9C23DAB9571CA9E8E949C039C5CC002CBC9BDD08728D543143AFE577738AD309AB2493A8157272196B73C28A4826B37A8274198A4E8188CDADB1D7BB209C84D03500F79B9DFEC1E4441F34069CC01D6B9A57940914F56217C0F3A5CE0C75DE2815EE396D4AB00EC9695DFBCDD88EA6C8017CC29B1257EED39B50E0D075CCF9564D4B22F59F4B5E6667E4CACAC6B63D8CC1C9AB2CC6309A319E559D2062FB99D15B62F08E4DAD676698813D227FF8967B3B3830970E92277B2446A3C269A74FB437800824A8987DA3636A17A53C7E55C66077BE0FBD63441402F19C6C4E1F1C46185A3F3F5D7D7F553F0066EBFCF2ECD74CFC6DB48F6A458AE66EC12532B691FA3AE9A0C19809B3A1AF06340EFB012A33D484D272CA09D5862DAC5E3A00006F260BDE5CE74E007AB12A8F686373949308E574DCE7EA9D145936E20BF7B3 +20170708014205 2 6 100 7679 5 C0388038628CD48D5377C99911D89CEDF70AC54721EE6974975D61C9E25580D2108B48CBCDB8B647B271FA822546C00580DB013D19EE5A49EFD9AAECA2036A83BB3E2F96C3E7CB273AA9ACEFCA5A3E4C7C8FCF3332DE11288D8BD76E17B4C530F5F6EFB0D757F63E3B2B519EE960FA8206DF81E7B9DA463CE389E3164588BF5B66355D481DC620F0B2F352782105DF3AB86076DD7D612CE9839CB251D5C975166859A41B740E08E66B746B710479FAA430E2891E60647E04FE71D8F8BC9A6BCD20CFB42299142DC016E672CC350D497809379F54F6F3D1649ADCE72ADECEAAE1ECA85EEE8006700379DE3687A67AF796E1F317815461CFF6E58615CD453265612315FA8F99DC65D9CC218004671E43CE58C9F54862D86B58FD71212199A2A562B1AB9604BF43676A403E8EA56A69E68F1CF0C60C83B8EB31D9C0A23D8410C3A6898D749CAD8CDA9F17A224536BD08436B25E50BA67BAD09276BB55583CEDF48AEEFFD8FA3DBE4F609760DF1EDED136B38792CD164D2EA3C5443F0D8F9117544A9A6AAC615ADE01440B7948B2B53BC3F7218DEDEB16D23C3B0C2AA4BEB99F9A9225D87B6CCB037D8E9A2918C20FE9F2BFF429FD0F23AE370E820842AEDD823DD5B6DDD7F4AD3A06735A2E4144DBABEA5DD83A6AA98EED5F6F3021C246FBABD280986A1E7A24CCBE11BC3050CC04DB566277CECBA8B5BDC1D15E1F066B25B668C7B87EA54894EC7559B64F1400934DCE1C06A10955988E3B3F4A40566B3989608404859335C53EBD6BEE21614EB7C954D543DBA7EB61555B7CED9D08EF560426DBCE3018FBEF788CF69AEAB433B692A9E28CBAFEFC048BD9AB423678D4DD5807329BCC417CF77EC7FD8E50B6D9A8D6B2017B24F6890557AF327980D086499B7C4ED6518B9C23DAB9571CA9E8E949C039C5CC002CBC9BDD08728D543143AFE577738AD309AB2493A8157272196B73C28A4826B37A8274198A4E8188CDADB1D7BB209C84D03500F79B9DFEC1E4441F34069CC01D6B9A57940914F56217C0F3A5CE0C75DE2815EE396D4AB00EC9695DFBCDD88EA6C8017CC29B1257EED39B50E0D075CCF9564D4B22F59F4B5E6667E4CACAC6B63D8CC1C9AB2CC6309A319E559D2062FB99D15B62F08E4DAD676698813D227FF8967B3B3830970E92277B2446A3C269A74FB437800824A8987DA3636A17A53C7E55C66077BE0FBD63441402F19C6C4E1F1C46185A3F3F5D7D7F553F0066EBFCF2ECD74CFC6DB48F6A458AE66EC12532B691FA3AE9A0C19809B3A1AF06340EFB012A33D484D272CA09D5862DAC5E3A00006F260BDE5CE74E007AB12A8F686373949308E574DCE7EA9D145936E3C89587 +20170708023140 2 6 100 7679 2 C0388038628CD48D5377C99911D89CEDF70AC54721EE6974975D61C9E25580D2108B48CBCDB8B647B271FA822546C00580DB013D19EE5A49EFD9AAECA2036A83BB3E2F96C3E7CB273AA9ACEFCA5A3E4C7C8FCF3332DE11288D8BD76E17B4C530F5F6EFB0D757F63E3B2B519EE960FA8206DF81E7B9DA463CE389E3164588BF5B66355D481DC620F0B2F352782105DF3AB86076DD7D612CE9839CB251D5C975166859A41B740E08E66B746B710479FAA430E2891E60647E04FE71D8F8BC9A6BCD20CFB42299142DC016E672CC350D497809379F54F6F3D1649ADCE72ADECEAAE1ECA85EEE8006700379DE3687A67AF796E1F317815461CFF6E58615CD453265612315FA8F99DC65D9CC218004671E43CE58C9F54862D86B58FD71212199A2A562B1AB9604BF43676A403E8EA56A69E68F1CF0C60C83B8EB31D9C0A23D8410C3A6898D749CAD8CDA9F17A224536BD08436B25E50BA67BAD09276BB55583CEDF48AEEFFD8FA3DBE4F609760DF1EDED136B38792CD164D2EA3C5443F0D8F9117544A9A6AAC615ADE01440B7948B2B53BC3F7218DEDEB16D23C3B0C2AA4BEB99F9A9225D87B6CCB037D8E9A2918C20FE9F2BFF429FD0F23AE370E820842AEDD823DD5B6DDD7F4AD3A06735A2E4144DBABEA5DD83A6AA98EED5F6F3021C246FBABD280986A1E7A24CCBE11BC3050CC04DB566277CECBA8B5BDC1D15E1F066B25B668C7B87EA54894EC7559B64F1400934DCE1C06A10955988E3B3F4A40566B3989608404859335C53EBD6BEE21614EB7C954D543DBA7EB61555B7CED9D08EF560426DBCE3018FBEF788CF69AEAB433B692A9E28CBAFEFC048BD9AB423678D4DD5807329BCC417CF77EC7FD8E50B6D9A8D6B2017B24F6890557AF327980D086499B7C4ED6518B9C23DAB9571CA9E8E949C039C5CC002CBC9BDD08728D543143AFE577738AD309AB2493A8157272196B73C28A4826B37A8274198A4E8188CDADB1D7BB209C84D03500F79B9DFEC1E4441F34069CC01D6B9A57940914F56217C0F3A5CE0C75DE2815EE396D4AB00EC9695DFBCDD88EA6C8017CC29B1257EED39B50E0D075CCF9564D4B22F59F4B5E6667E4CACAC6B63D8CC1C9AB2CC6309A319E559D2062FB99D15B62F08E4DAD676698813D227FF8967B3B3830970E92277B2446A3C269A74FB437800824A8987DA3636A17A53C7E55C66077BE0FBD63441402F19C6C4E1F1C46185A3F3F5D7D7F553F0066EBFCF2ECD74CFC6DB48F6A458AE66EC12532B691FA3AE9A0C19809B3A1AF06340EFB012A33D484D272CA09D5862DAC5E3A00006F260BDE5CE74E007AB12A8F686373949308E574DCE7EA9D145936E469C123 +20170708053646 2 6 100 7679 5 C0388038628CD48D5377C99911D89CEDF70AC54721EE6974975D61C9E25580D2108B48CBCDB8B647B271FA822546C00580DB013D19EE5A49EFD9AAECA2036A83BB3E2F96C3E7CB273AA9ACEFCA5A3E4C7C8FCF3332DE11288D8BD76E17B4C530F5F6EFB0D757F63E3B2B519EE960FA8206DF81E7B9DA463CE389E3164588BF5B66355D481DC620F0B2F352782105DF3AB86076DD7D612CE9839CB251D5C975166859A41B740E08E66B746B710479FAA430E2891E60647E04FE71D8F8BC9A6BCD20CFB42299142DC016E672CC350D497809379F54F6F3D1649ADCE72ADECEAAE1ECA85EEE8006700379DE3687A67AF796E1F317815461CFF6E58615CD453265612315FA8F99DC65D9CC218004671E43CE58C9F54862D86B58FD71212199A2A562B1AB9604BF43676A403E8EA56A69E68F1CF0C60C83B8EB31D9C0A23D8410C3A6898D749CAD8CDA9F17A224536BD08436B25E50BA67BAD09276BB55583CEDF48AEEFFD8FA3DBE4F609760DF1EDED136B38792CD164D2EA3C5443F0D8F9117544A9A6AAC615ADE01440B7948B2B53BC3F7218DEDEB16D23C3B0C2AA4BEB99F9A9225D87B6CCB037D8E9A2918C20FE9F2BFF429FD0F23AE370E820842AEDD823DD5B6DDD7F4AD3A06735A2E4144DBABEA5DD83A6AA98EED5F6F3021C246FBABD280986A1E7A24CCBE11BC3050CC04DB566277CECBA8B5BDC1D15E1F066B25B668C7B87EA54894EC7559B64F1400934DCE1C06A10955988E3B3F4A40566B3989608404859335C53EBD6BEE21614EB7C954D543DBA7EB61555B7CED9D08EF560426DBCE3018FBEF788CF69AEAB433B692A9E28CBAFEFC048BD9AB423678D4DD5807329BCC417CF77EC7FD8E50B6D9A8D6B2017B24F6890557AF327980D086499B7C4ED6518B9C23DAB9571CA9E8E949C039C5CC002CBC9BDD08728D543143AFE577738AD309AB2493A8157272196B73C28A4826B37A8274198A4E8188CDADB1D7BB209C84D03500F79B9DFEC1E4441F34069CC01D6B9A57940914F56217C0F3A5CE0C75DE2815EE396D4AB00EC9695DFBCDD88EA6C8017CC29B1257EED39B50E0D075CCF9564D4B22F59F4B5E6667E4CACAC6B63D8CC1C9AB2CC6309A319E559D2062FB99D15B62F08E4DAD676698813D227FF8967B3B3830970E92277B2446A3C269A74FB437800824A8987DA3636A17A53C7E55C66077BE0FBD63441402F19C6C4E1F1C46185A3F3F5D7D7F553F0066EBFCF2ECD74CFC6DB48F6A458AE66EC12532B691FA3AE9A0C19809B3A1AF06340EFB012A33D484D272CA09D5862DAC5E3A00006F260BDE5CE74E007AB12A8F686373949308E574DCE7EA9D145936E6DBCAE7 +20170708071735 2 6 100 7679 5 C0388038628CD48D5377C99911D89CEDF70AC54721EE6974975D61C9E25580D2108B48CBCDB8B647B271FA822546C00580DB013D19EE5A49EFD9AAECA2036A83BB3E2F96C3E7CB273AA9ACEFCA5A3E4C7C8FCF3332DE11288D8BD76E17B4C530F5F6EFB0D757F63E3B2B519EE960FA8206DF81E7B9DA463CE389E3164588BF5B66355D481DC620F0B2F352782105DF3AB86076DD7D612CE9839CB251D5C975166859A41B740E08E66B746B710479FAA430E2891E60647E04FE71D8F8BC9A6BCD20CFB42299142DC016E672CC350D497809379F54F6F3D1649ADCE72ADECEAAE1ECA85EEE8006700379DE3687A67AF796E1F317815461CFF6E58615CD453265612315FA8F99DC65D9CC218004671E43CE58C9F54862D86B58FD71212199A2A562B1AB9604BF43676A403E8EA56A69E68F1CF0C60C83B8EB31D9C0A23D8410C3A6898D749CAD8CDA9F17A224536BD08436B25E50BA67BAD09276BB55583CEDF48AEEFFD8FA3DBE4F609760DF1EDED136B38792CD164D2EA3C5443F0D8F9117544A9A6AAC615ADE01440B7948B2B53BC3F7218DEDEB16D23C3B0C2AA4BEB99F9A9225D87B6CCB037D8E9A2918C20FE9F2BFF429FD0F23AE370E820842AEDD823DD5B6DDD7F4AD3A06735A2E4144DBABEA5DD83A6AA98EED5F6F3021C246FBABD280986A1E7A24CCBE11BC3050CC04DB566277CECBA8B5BDC1D15E1F066B25B668C7B87EA54894EC7559B64F1400934DCE1C06A10955988E3B3F4A40566B3989608404859335C53EBD6BEE21614EB7C954D543DBA7EB61555B7CED9D08EF560426DBCE3018FBEF788CF69AEAB433B692A9E28CBAFEFC048BD9AB423678D4DD5807329BCC417CF77EC7FD8E50B6D9A8D6B2017B24F6890557AF327980D086499B7C4ED6518B9C23DAB9571CA9E8E949C039C5CC002CBC9BDD08728D543143AFE577738AD309AB2493A8157272196B73C28A4826B37A8274198A4E8188CDADB1D7BB209C84D03500F79B9DFEC1E4441F34069CC01D6B9A57940914F56217C0F3A5CE0C75DE2815EE396D4AB00EC9695DFBCDD88EA6C8017CC29B1257EED39B50E0D075CCF9564D4B22F59F4B5E6667E4CACAC6B63D8CC1C9AB2CC6309A319E559D2062FB99D15B62F08E4DAD676698813D227FF8967B3B3830970E92277B2446A3C269A74FB437800824A8987DA3636A17A53C7E55C66077BE0FBD63441402F19C6C4E1F1C46185A3F3F5D7D7F553F0066EBFCF2ECD74CFC6DB48F6A458AE66EC12532B691FA3AE9A0C19809B3A1AF06340EFB012A33D484D272CA09D5862DAC5E3A00006F260BDE5CE74E007AB12A8F686373949308E574DCE7EA9D145936E8297A7F +20170708072409 2 6 100 7679 5 C0388038628CD48D5377C99911D89CEDF70AC54721EE6974975D61C9E25580D2108B48CBCDB8B647B271FA822546C00580DB013D19EE5A49EFD9AAECA2036A83BB3E2F96C3E7CB273AA9ACEFCA5A3E4C7C8FCF3332DE11288D8BD76E17B4C530F5F6EFB0D757F63E3B2B519EE960FA8206DF81E7B9DA463CE389E3164588BF5B66355D481DC620F0B2F352782105DF3AB86076DD7D612CE9839CB251D5C975166859A41B740E08E66B746B710479FAA430E2891E60647E04FE71D8F8BC9A6BCD20CFB42299142DC016E672CC350D497809379F54F6F3D1649ADCE72ADECEAAE1ECA85EEE8006700379DE3687A67AF796E1F317815461CFF6E58615CD453265612315FA8F99DC65D9CC218004671E43CE58C9F54862D86B58FD71212199A2A562B1AB9604BF43676A403E8EA56A69E68F1CF0C60C83B8EB31D9C0A23D8410C3A6898D749CAD8CDA9F17A224536BD08436B25E50BA67BAD09276BB55583CEDF48AEEFFD8FA3DBE4F609760DF1EDED136B38792CD164D2EA3C5443F0D8F9117544A9A6AAC615ADE01440B7948B2B53BC3F7218DEDEB16D23C3B0C2AA4BEB99F9A9225D87B6CCB037D8E9A2918C20FE9F2BFF429FD0F23AE370E820842AEDD823DD5B6DDD7F4AD3A06735A2E4144DBABEA5DD83A6AA98EED5F6F3021C246FBABD280986A1E7A24CCBE11BC3050CC04DB566277CECBA8B5BDC1D15E1F066B25B668C7B87EA54894EC7559B64F1400934DCE1C06A10955988E3B3F4A40566B3989608404859335C53EBD6BEE21614EB7C954D543DBA7EB61555B7CED9D08EF560426DBCE3018FBEF788CF69AEAB433B692A9E28CBAFEFC048BD9AB423678D4DD5807329BCC417CF77EC7FD8E50B6D9A8D6B2017B24F6890557AF327980D086499B7C4ED6518B9C23DAB9571CA9E8E949C039C5CC002CBC9BDD08728D543143AFE577738AD309AB2493A8157272196B73C28A4826B37A8274198A4E8188CDADB1D7BB209C84D03500F79B9DFEC1E4441F34069CC01D6B9A57940914F56217C0F3A5CE0C75DE2815EE396D4AB00EC9695DFBCDD88EA6C8017CC29B1257EED39B50E0D075CCF9564D4B22F59F4B5E6667E4CACAC6B63D8CC1C9AB2CC6309A319E559D2062FB99D15B62F08E4DAD676698813D227FF8967B3B3830970E92277B2446A3C269A74FB437800824A8987DA3636A17A53C7E55C66077BE0FBD63441402F19C6C4E1F1C46185A3F3F5D7D7F553F0066EBFCF2ECD74CFC6DB48F6A458AE66EC12532B691FA3AE9A0C19809B3A1AF06340EFB012A33D484D272CA09D5862DAC5E3A00006F260BDE5CE74E007AB12A8F686373949308E574DCE7EA9D145936E836D247 +20170708102649 2 6 100 7679 5 C0388038628CD48D5377C99911D89CEDF70AC54721EE6974975D61C9E25580D2108B48CBCDB8B647B271FA822546C00580DB013D19EE5A49EFD9AAECA2036A83BB3E2F96C3E7CB273AA9ACEFCA5A3E4C7C8FCF3332DE11288D8BD76E17B4C530F5F6EFB0D757F63E3B2B519EE960FA8206DF81E7B9DA463CE389E3164588BF5B66355D481DC620F0B2F352782105DF3AB86076DD7D612CE9839CB251D5C975166859A41B740E08E66B746B710479FAA430E2891E60647E04FE71D8F8BC9A6BCD20CFB42299142DC016E672CC350D497809379F54F6F3D1649ADCE72ADECEAAE1ECA85EEE8006700379DE3687A67AF796E1F317815461CFF6E58615CD453265612315FA8F99DC65D9CC218004671E43CE58C9F54862D86B58FD71212199A2A562B1AB9604BF43676A403E8EA56A69E68F1CF0C60C83B8EB31D9C0A23D8410C3A6898D749CAD8CDA9F17A224536BD08436B25E50BA67BAD09276BB55583CEDF48AEEFFD8FA3DBE4F609760DF1EDED136B38792CD164D2EA3C5443F0D8F9117544A9A6AAC615ADE01440B7948B2B53BC3F7218DEDEB16D23C3B0C2AA4BEB99F9A9225D87B6CCB037D8E9A2918C20FE9F2BFF429FD0F23AE370E820842AEDD823DD5B6DDD7F4AD3A06735A2E4144DBABEA5DD83A6AA98EED5F6F3021C246FBABD280986A1E7A24CCBE11BC3050CC04DB566277CECBA8B5BDC1D15E1F066B25B668C7B87EA54894EC7559B64F1400934DCE1C06A10955988E3B3F4A40566B3989608404859335C53EBD6BEE21614EB7C954D543DBA7EB61555B7CED9D08EF560426DBCE3018FBEF788CF69AEAB433B692A9E28CBAFEFC048BD9AB423678D4DD5807329BCC417CF77EC7FD8E50B6D9A8D6B2017B24F6890557AF327980D086499B7C4ED6518B9C23DAB9571CA9E8E949C039C5CC002CBC9BDD08728D543143AFE577738AD309AB2493A8157272196B73C28A4826B37A8274198A4E8188CDADB1D7BB209C84D03500F79B9DFEC1E4441F34069CC01D6B9A57940914F56217C0F3A5CE0C75DE2815EE396D4AB00EC9695DFBCDD88EA6C8017CC29B1257EED39B50E0D075CCF9564D4B22F59F4B5E6667E4CACAC6B63D8CC1C9AB2CC6309A319E559D2062FB99D15B62F08E4DAD676698813D227FF8967B3B3830970E92277B2446A3C269A74FB437800824A8987DA3636A17A53C7E55C66077BE0FBD63441402F19C6C4E1F1C46185A3F3F5D7D7F553F0066EBFCF2ECD74CFC6DB48F6A458AE66EC12532B691FA3AE9A0C19809B3A1AF06340EFB012A33D484D272CA09D5862DAC5E3A00006F260BDE5CE74E007AB12A8F686373949308E574DCE7EA9D145936EA984FCF +20170708144918 2 6 100 7679 2 C0388038628CD48D5377C99911D89CEDF70AC54721EE6974975D61C9E25580D2108B48CBCDB8B647B271FA822546C00580DB013D19EE5A49EFD9AAECA2036A83BB3E2F96C3E7CB273AA9ACEFCA5A3E4C7C8FCF3332DE11288D8BD76E17B4C530F5F6EFB0D757F63E3B2B519EE960FA8206DF81E7B9DA463CE389E3164588BF5B66355D481DC620F0B2F352782105DF3AB86076DD7D612CE9839CB251D5C975166859A41B740E08E66B746B710479FAA430E2891E60647E04FE71D8F8BC9A6BCD20CFB42299142DC016E672CC350D497809379F54F6F3D1649ADCE72ADECEAAE1ECA85EEE8006700379DE3687A67AF796E1F317815461CFF6E58615CD453265612315FA8F99DC65D9CC218004671E43CE58C9F54862D86B58FD71212199A2A562B1AB9604BF43676A403E8EA56A69E68F1CF0C60C83B8EB31D9C0A23D8410C3A6898D749CAD8CDA9F17A224536BD08436B25E50BA67BAD09276BB55583CEDF48AEEFFD8FA3DBE4F609760DF1EDED136B38792CD164D2EA3C5443F0D8F9117544A9A6AAC615ADE01440B7948B2B53BC3F7218DEDEB16D23C3B0C2AA4BEB99F9A9225D87B6CCB037D8E9A2918C20FE9F2BFF429FD0F23AE370E820842AEDD823DD5B6DDD7F4AD3A06735A2E4144DBABEA5DD83A6AA98EED5F6F3021C246FBABD280986A1E7A24CCBE11BC3050CC04DB566277CECBA8B5BDC1D15E1F066B25B668C7B87EA54894EC7559B64F1400934DCE1C06A10955988E3B3F4A40566B3989608404859335C53EBD6BEE21614EB7C954D543DBA7EB61555B7CED9D08EF560426DBCE3018FBEF788CF69AEAB433B692A9E28CBAFEFC048BD9AB423678D4DD5807329BCC417CF77EC7FD8E50B6D9A8D6B2017B24F6890557AF327980D086499B7C4ED6518B9C23DAB9571CA9E8E949C039C5CC002CBC9BDD08728D543143AFE577738AD309AB2493A8157272196B73C28A4826B37A8274198A4E8188CDADB1D7BB209C84D03500F79B9DFEC1E4441F34069CC01D6B9A57940914F56217C0F3A5CE0C75DE2815EE396D4AB00EC9695DFBCDD88EA6C8017CC29B1257EED39B50E0D075CCF9564D4B22F59F4B5E6667E4CACAC6B63D8CC1C9AB2CC6309A319E559D2062FB99D15B62F08E4DAD676698813D227FF8967B3B3830970E92277B2446A3C269A74FB437800824A8987DA3636A17A53C7E55C66077BE0FBD63441402F19C6C4E1F1C46185A3F3F5D7D7F553F0066EBFCF2ECD74CFC6DB48F6A458AE66EC12532B691FA3AE9A0C19809B3A1AF06340EFB012A33D484D272CA09D5862DAC5E3A00006F260BDE5CE74E007AB12A8F686373949308E574DCE7EA9D145936EE06AB6B +20170708163647 2 6 100 7679 2 C0388038628CD48D5377C99911D89CEDF70AC54721EE6974975D61C9E25580D2108B48CBCDB8B647B271FA822546C00580DB013D19EE5A49EFD9AAECA2036A83BB3E2F96C3E7CB273AA9ACEFCA5A3E4C7C8FCF3332DE11288D8BD76E17B4C530F5F6EFB0D757F63E3B2B519EE960FA8206DF81E7B9DA463CE389E3164588BF5B66355D481DC620F0B2F352782105DF3AB86076DD7D612CE9839CB251D5C975166859A41B740E08E66B746B710479FAA430E2891E60647E04FE71D8F8BC9A6BCD20CFB42299142DC016E672CC350D497809379F54F6F3D1649ADCE72ADECEAAE1ECA85EEE8006700379DE3687A67AF796E1F317815461CFF6E58615CD453265612315FA8F99DC65D9CC218004671E43CE58C9F54862D86B58FD71212199A2A562B1AB9604BF43676A403E8EA56A69E68F1CF0C60C83B8EB31D9C0A23D8410C3A6898D749CAD8CDA9F17A224536BD08436B25E50BA67BAD09276BB55583CEDF48AEEFFD8FA3DBE4F609760DF1EDED136B38792CD164D2EA3C5443F0D8F9117544A9A6AAC615ADE01440B7948B2B53BC3F7218DEDEB16D23C3B0C2AA4BEB99F9A9225D87B6CCB037D8E9A2918C20FE9F2BFF429FD0F23AE370E820842AEDD823DD5B6DDD7F4AD3A06735A2E4144DBABEA5DD83A6AA98EED5F6F3021C246FBABD280986A1E7A24CCBE11BC3050CC04DB566277CECBA8B5BDC1D15E1F066B25B668C7B87EA54894EC7559B64F1400934DCE1C06A10955988E3B3F4A40566B3989608404859335C53EBD6BEE21614EB7C954D543DBA7EB61555B7CED9D08EF560426DBCE3018FBEF788CF69AEAB433B692A9E28CBAFEFC048BD9AB423678D4DD5807329BCC417CF77EC7FD8E50B6D9A8D6B2017B24F6890557AF327980D086499B7C4ED6518B9C23DAB9571CA9E8E949C039C5CC002CBC9BDD08728D543143AFE577738AD309AB2493A8157272196B73C28A4826B37A8274198A4E8188CDADB1D7BB209C84D03500F79B9DFEC1E4441F34069CC01D6B9A57940914F56217C0F3A5CE0C75DE2815EE396D4AB00EC9695DFBCDD88EA6C8017CC29B1257EED39B50E0D075CCF9564D4B22F59F4B5E6667E4CACAC6B63D8CC1C9AB2CC6309A319E559D2062FB99D15B62F08E4DAD676698813D227FF8967B3B3830970E92277B2446A3C269A74FB437800824A8987DA3636A17A53C7E55C66077BE0FBD63441402F19C6C4E1F1C46185A3F3F5D7D7F553F0066EBFCF2ECD74CFC6DB48F6A458AE66EC12532B691FA3AE9A0C19809B3A1AF06340EFB012A33D484D272CA09D5862DAC5E3A00006F260BDE5CE74E007AB12A8F686373949308E574DCE7EA9D145936EF6DD803 +20170708181531 2 6 100 7679 2 C0388038628CD48D5377C99911D89CEDF70AC54721EE6974975D61C9E25580D2108B48CBCDB8B647B271FA822546C00580DB013D19EE5A49EFD9AAECA2036A83BB3E2F96C3E7CB273AA9ACEFCA5A3E4C7C8FCF3332DE11288D8BD76E17B4C530F5F6EFB0D757F63E3B2B519EE960FA8206DF81E7B9DA463CE389E3164588BF5B66355D481DC620F0B2F352782105DF3AB86076DD7D612CE9839CB251D5C975166859A41B740E08E66B746B710479FAA430E2891E60647E04FE71D8F8BC9A6BCD20CFB42299142DC016E672CC350D497809379F54F6F3D1649ADCE72ADECEAAE1ECA85EEE8006700379DE3687A67AF796E1F317815461CFF6E58615CD453265612315FA8F99DC65D9CC218004671E43CE58C9F54862D86B58FD71212199A2A562B1AB9604BF43676A403E8EA56A69E68F1CF0C60C83B8EB31D9C0A23D8410C3A6898D749CAD8CDA9F17A224536BD08436B25E50BA67BAD09276BB55583CEDF48AEEFFD8FA3DBE4F609760DF1EDED136B38792CD164D2EA3C5443F0D8F9117544A9A6AAC615ADE01440B7948B2B53BC3F7218DEDEB16D23C3B0C2AA4BEB99F9A9225D87B6CCB037D8E9A2918C20FE9F2BFF429FD0F23AE370E820842AEDD823DD5B6DDD7F4AD3A06735A2E4144DBABEA5DD83A6AA98EED5F6F3021C246FBABD280986A1E7A24CCBE11BC3050CC04DB566277CECBA8B5BDC1D15E1F066B25B668C7B87EA54894EC7559B64F1400934DCE1C06A10955988E3B3F4A40566B3989608404859335C53EBD6BEE21614EB7C954D543DBA7EB61555B7CED9D08EF560426DBCE3018FBEF788CF69AEAB433B692A9E28CBAFEFC048BD9AB423678D4DD5807329BCC417CF77EC7FD8E50B6D9A8D6B2017B24F6890557AF327980D086499B7C4ED6518B9C23DAB9571CA9E8E949C039C5CC002CBC9BDD08728D543143AFE577738AD309AB2493A8157272196B73C28A4826B37A8274198A4E8188CDADB1D7BB209C84D03500F79B9DFEC1E4441F34069CC01D6B9A57940914F56217C0F3A5CE0C75DE2815EE396D4AB00EC9695DFBCDD88EA6C8017CC29B1257EED39B50E0D075CCF9564D4B22F59F4B5E6667E4CACAC6B63D8CC1C9AB2CC6309A319E559D2062FB99D15B62F08E4DAD676698813D227FF8967B3B3830970E92277B2446A3C269A74FB437800824A8987DA3636A17A53C7E55C66077BE0FBD63441402F19C6C4E1F1C46185A3F3F5D7D7F553F0066EBFCF2ECD74CFC6DB48F6A458AE66EC12532B691FA3AE9A0C19809B3A1AF06340EFB012A33D484D272CA09D5862DAC5E3A00006F260BDE5CE74E007AB12A8F686373949308E574DCE7EA9D145936F0B07D83 +20170708234000 2 6 100 7679 5 C0388038628CD48D5377C99911D89CEDF70AC54721EE6974975D61C9E25580D2108B48CBCDB8B647B271FA822546C00580DB013D19EE5A49EFD9AAECA2036A83BB3E2F96C3E7CB273AA9ACEFCA5A3E4C7C8FCF3332DE11288D8BD76E17B4C530F5F6EFB0D757F63E3B2B519EE960FA8206DF81E7B9DA463CE389E3164588BF5B66355D481DC620F0B2F352782105DF3AB86076DD7D612CE9839CB251D5C975166859A41B740E08E66B746B710479FAA430E2891E60647E04FE71D8F8BC9A6BCD20CFB42299142DC016E672CC350D497809379F54F6F3D1649ADCE72ADECEAAE1ECA85EEE8006700379DE3687A67AF796E1F317815461CFF6E58615CD453265612315FA8F99DC65D9CC218004671E43CE58C9F54862D86B58FD71212199A2A562B1AB9604BF43676A403E8EA56A69E68F1CF0C60C83B8EB31D9C0A23D8410C3A6898D749CAD8CDA9F17A224536BD08436B25E50BA67BAD09276BB55583CEDF48AEEFFD8FA3DBE4F609760DF1EDED136B38792CD164D2EA3C5443F0D8F9117544A9A6AAC615ADE01440B7948B2B53BC3F7218DEDEB16D23C3B0C2AA4BEB99F9A9225D87B6CCB037D8E9A2918C20FE9F2BFF429FD0F23AE370E820842AEDD823DD5B6DDD7F4AD3A06735A2E4144DBABEA5DD83A6AA98EED5F6F3021C246FBABD280986A1E7A24CCBE11BC3050CC04DB566277CECBA8B5BDC1D15E1F066B25B668C7B87EA54894EC7559B64F1400934DCE1C06A10955988E3B3F4A40566B3989608404859335C53EBD6BEE21614EB7C954D543DBA7EB61555B7CED9D08EF560426DBCE3018FBEF788CF69AEAB433B692A9E28CBAFEFC048BD9AB423678D4DD5807329BCC417CF77EC7FD8E50B6D9A8D6B2017B24F6890557AF327980D086499B7C4ED6518B9C23DAB9571CA9E8E949C039C5CC002CBC9BDD08728D543143AFE577738AD309AB2493A8157272196B73C28A4826B37A8274198A4E8188CDADB1D7BB209C84D03500F79B9DFEC1E4441F34069CC01D6B9A57940914F56217C0F3A5CE0C75DE2815EE396D4AB00EC9695DFBCDD88EA6C8017CC29B1257EED39B50E0D075CCF9564D4B22F59F4B5E6667E4CACAC6B63D8CC1C9AB2CC6309A319E559D2062FB99D15B62F08E4DAD676698813D227FF8967B3B3830970E92277B2446A3C269A74FB437800824A8987DA3636A17A53C7E55C66077BE0FBD63441402F19C6C4E1F1C46185A3F3F5D7D7F553F0066EBFCF2ECD74CFC6DB48F6A458AE66EC12532B691FA3AE9A0C19809B3A1AF06340EFB012A33D484D272CA09D5862DAC5E3A00006F260BDE5CE74E007AB12A8F686373949308E574DCE7EA9D145936F4E4D5BF +20170709023719 2 6 100 7679 2 C0388038628CD48D5377C99911D89CEDF70AC54721EE6974975D61C9E25580D2108B48CBCDB8B647B271FA822546C00580DB013D19EE5A49EFD9AAECA2036A83BB3E2F96C3E7CB273AA9ACEFCA5A3E4C7C8FCF3332DE11288D8BD76E17B4C530F5F6EFB0D757F63E3B2B519EE960FA8206DF81E7B9DA463CE389E3164588BF5B66355D481DC620F0B2F352782105DF3AB86076DD7D612CE9839CB251D5C975166859A41B740E08E66B746B710479FAA430E2891E60647E04FE71D8F8BC9A6BCD20CFB42299142DC016E672CC350D497809379F54F6F3D1649ADCE72ADECEAAE1ECA85EEE8006700379DE3687A67AF796E1F317815461CFF6E58615CD453265612315FA8F99DC65D9CC218004671E43CE58C9F54862D86B58FD71212199A2A562B1AB9604BF43676A403E8EA56A69E68F1CF0C60C83B8EB31D9C0A23D8410C3A6898D749CAD8CDA9F17A224536BD08436B25E50BA67BAD09276BB55583CEDF48AEEFFD8FA3DBE4F609760DF1EDED136B38792CD164D2EA3C5443F0D8F9117544A9A6AAC615ADE01440B7948B2B53BC3F7218DEDEB16D23C3B0C2AA4BEB99F9A9225D87B6CCB037D8E9A2918C20FE9F2BFF429FD0F23AE370E820842AEDD823DD5B6DDD7F4AD3A06735A2E4144DBABEA5DD83A6AA98EED5F6F3021C246FBABD280986A1E7A24CCBE11BC3050CC04DB566277CECBA8B5BDC1D15E1F066B25B668C7B87EA54894EC7559B64F1400934DCE1C06A10955988E3B3F4A40566B3989608404859335C53EBD6BEE21614EB7C954D543DBA7EB61555B7CED9D08EF560426DBCE3018FBEF788CF69AEAB433B692A9E28CBAFEFC048BD9AB423678D4DD5807329BCC417CF77EC7FD8E50B6D9A8D6B2017B24F6890557AF327980D086499B7C4ED6518B9C23DAB9571CA9E8E949C039C5CC002CBC9BDD08728D543143AFE577738AD309AB2493A8157272196B73C28A4826B37A8274198A4E8188CDADB1D7BB209C84D03500F79B9DFEC1E4441F34069CC01D6B9A57940914F56217C0F3A5CE0C75DE2815EE396D4AB00EC9695DFBCDD88EA6C8017CC29B1257EED39B50E0D075CCF9564D4B22F59F4B5E6667E4CACAC6B63D8CC1C9AB2CC6309A319E559D2062FB99D15B62F08E4DAD676698813D227FF8967B3B3830970E92277B2446A3C269A74FB437800824A8987DA3636A17A53C7E55C66077BE0FBD63441402F19C6C4E1F1C46185A3F3F5D7D7F553F0066EBFCF2ECD74CFC6DB48F6A458AE66EC12532B691FA3AE9A0C19809B3A1AF06340EFB012A33D484D272CA09D5862DAC5E3A00006F260BDE5CE74E007AB12A8F686373949308E574DCE7EA9D145936F727B0C3 +20170709063946 2 6 100 7679 2 C0388038628CD48D5377C99911D89CEDF70AC54721EE6974975D61C9E25580D2108B48CBCDB8B647B271FA822546C00580DB013D19EE5A49EFD9AAECA2036A83BB3E2F96C3E7CB273AA9ACEFCA5A3E4C7C8FCF3332DE11288D8BD76E17B4C530F5F6EFB0D757F63E3B2B519EE960FA8206DF81E7B9DA463CE389E3164588BF5B66355D481DC620F0B2F352782105DF3AB86076DD7D612CE9839CB251D5C975166859A41B740E08E66B746B710479FAA430E2891E60647E04FE71D8F8BC9A6BCD20CFB42299142DC016E672CC350D497809379F54F6F3D1649ADCE72ADECEAAE1ECA85EEE8006700379DE3687A67AF796E1F317815461CFF6E58615CD453265612315FA8F99DC65D9CC218004671E43CE58C9F54862D86B58FD71212199A2A562B1AB9604BF43676A403E8EA56A69E68F1CF0C60C83B8EB31D9C0A23D8410C3A6898D749CAD8CDA9F17A224536BD08436B25E50BA67BAD09276BB55583CEDF48AEEFFD8FA3DBE4F609760DF1EDED136B38792CD164D2EA3C5443F0D8F9117544A9A6AAC615ADE01440B7948B2B53BC3F7218DEDEB16D23C3B0C2AA4BEB99F9A9225D87B6CCB037D8E9A2918C20FE9F2BFF429FD0F23AE370E820842AEDD823DD5B6DDD7F4AD3A06735A2E4144DBABEA5DD83A6AA98EED5F6F3021C246FBABD280986A1E7A24CCBE11BC3050CC04DB566277CECBA8B5BDC1D15E1F066B25B668C7B87EA54894EC7559B64F1400934DCE1C06A10955988E3B3F4A40566B3989608404859335C53EBD6BEE21614EB7C954D543DBA7EB61555B7CED9D08EF560426DBCE3018FBEF788CF69AEAB433B692A9E28CBAFEFC048BD9AB423678D4DD5807329BCC417CF77EC7FD8E50B6D9A8D6B2017B24F6890557AF327980D086499B7C4ED6518B9C23DAB9571CA9E8E949C039C5CC002CBC9BDD08728D543143AFE577738AD309AB2493A8157272196B73C28A4826B37A8274198A4E8188CDADB1D7BB209C84D03500F79B9DFEC1E4441F34069CC01D6B9A57940914F56217C0F3A5CE0C75DE2815EE396D4AB00EC9695DFBCDD88EA6C8017CC29B1257EED39B50E0D075CCF9564D4B22F59F4B5E6667E4CACAC6B63D8CC1C9AB2CC6309A319E559D2062FB99D15B62F08E4DAD676698813D227FF8967B3B3830970E92277B2446A3C269A74FB437800824A8987DA3636A17A53C7E55C66077BE0FBD63441402F19C6C4E1F1C46185A3F3F5D7D7F553F0066EBFCF2ECD74CFC6DB48F6A458AE66EC12532B691FA3AE9A0C19809B3A1AF06340EFB012A33D484D272CA09D5862DAC5E3A00006F260BDE5CE74E007AB12A8F686373949308E574DCE7EA9D145936FA3DA1B3 +20170709093311 2 6 100 7679 5 C0388038628CD48D5377C99911D89CEDF70AC54721EE6974975D61C9E25580D2108B48CBCDB8B647B271FA822546C00580DB013D19EE5A49EFD9AAECA2036A83BB3E2F96C3E7CB273AA9ACEFCA5A3E4C7C8FCF3332DE11288D8BD76E17B4C530F5F6EFB0D757F63E3B2B519EE960FA8206DF81E7B9DA463CE389E3164588BF5B66355D481DC620F0B2F352782105DF3AB86076DD7D612CE9839CB251D5C975166859A41B740E08E66B746B710479FAA430E2891E60647E04FE71D8F8BC9A6BCD20CFB42299142DC016E672CC350D497809379F54F6F3D1649ADCE72ADECEAAE1ECA85EEE8006700379DE3687A67AF796E1F317815461CFF6E58615CD453265612315FA8F99DC65D9CC218004671E43CE58C9F54862D86B58FD71212199A2A562B1AB9604BF43676A403E8EA56A69E68F1CF0C60C83B8EB31D9C0A23D8410C3A6898D749CAD8CDA9F17A224536BD08436B25E50BA67BAD09276BB55583CEDF48AEEFFD8FA3DBE4F609760DF1EDED136B38792CD164D2EA3C5443F0D8F9117544A9A6AAC615ADE01440B7948B2B53BC3F7218DEDEB16D23C3B0C2AA4BEB99F9A9225D87B6CCB037D8E9A2918C20FE9F2BFF429FD0F23AE370E820842AEDD823DD5B6DDD7F4AD3A06735A2E4144DBABEA5DD83A6AA98EED5F6F3021C246FBABD280986A1E7A24CCBE11BC3050CC04DB566277CECBA8B5BDC1D15E1F066B25B668C7B87EA54894EC7559B64F1400934DCE1C06A10955988E3B3F4A40566B3989608404859335C53EBD6BEE21614EB7C954D543DBA7EB61555B7CED9D08EF560426DBCE3018FBEF788CF69AEAB433B692A9E28CBAFEFC048BD9AB423678D4DD5807329BCC417CF77EC7FD8E50B6D9A8D6B2017B24F6890557AF327980D086499B7C4ED6518B9C23DAB9571CA9E8E949C039C5CC002CBC9BDD08728D543143AFE577738AD309AB2493A8157272196B73C28A4826B37A8274198A4E8188CDADB1D7BB209C84D03500F79B9DFEC1E4441F34069CC01D6B9A57940914F56217C0F3A5CE0C75DE2815EE396D4AB00EC9695DFBCDD88EA6C8017CC29B1257EED39B50E0D075CCF9564D4B22F59F4B5E6667E4CACAC6B63D8CC1C9AB2CC6309A319E559D2062FB99D15B62F08E4DAD676698813D227FF8967B3B3830970E92277B2446A3C269A74FB437800824A8987DA3636A17A53C7E55C66077BE0FBD63441402F19C6C4E1F1C46185A3F3F5D7D7F553F0066EBFCF2ECD74CFC6DB48F6A458AE66EC12532B691FA3AE9A0C19809B3A1AF06340EFB012A33D484D272CA09D5862DAC5E3A00006F260BDE5CE74E007AB12A8F686373949308E574DCE7EA9D145936FC71EB57 +20170709151341 2 6 100 7679 5 C0388038628CD48D5377C99911D89CEDF70AC54721EE6974975D61C9E25580D2108B48CBCDB8B647B271FA822546C00580DB013D19EE5A49EFD9AAECA2036A83BB3E2F96C3E7CB273AA9ACEFCA5A3E4C7C8FCF3332DE11288D8BD76E17B4C530F5F6EFB0D757F63E3B2B519EE960FA8206DF81E7B9DA463CE389E3164588BF5B66355D481DC620F0B2F352782105DF3AB86076DD7D612CE9839CB251D5C975166859A41B740E08E66B746B710479FAA430E2891E60647E04FE71D8F8BC9A6BCD20CFB42299142DC016E672CC350D497809379F54F6F3D1649ADCE72ADECEAAE1ECA85EEE8006700379DE3687A67AF796E1F317815461CFF6E58615CD453265612315FA8F99DC65D9CC218004671E43CE58C9F54862D86B58FD71212199A2A562B1AB9604BF43676A403E8EA56A69E68F1CF0C60C83B8EB31D9C0A23D8410C3A6898D749CAD8CDA9F17A224536BD08436B25E50BA67BAD09276BB55583CEDF48AEEFFD8FA3DBE4F609760DF1EDED136B38792CD164D2EA3C5443F0D8F9117544A9A6AAC615ADE01440B7948B2B53BC3F7218DEDEB16D23C3B0C2AA4BEB99F9A9225D87B6CCB037D8E9A2918C20FE9F2BFF429FD0F23AE370E820842AEDD823DD5B6DDD7F4AD3A06735A2E4144DBABEA5DD83A6AA98EED5F6F3021C246FBABD280986A1E7A24CCBE11BC3050CC04DB566277CECBA8B5BDC1D15E1F066B25B668C7B87EA54894EC7559B64F1400934DCE1C06A10955988E3B3F4A40566B3989608404859335C53EBD6BEE21614EB7C954D543DBA7EB61555B7CED9D08EF560426DBCE3018FBEF788CF69AEAB433B692A9E28CBAFEFC048BD9AB423678D4DD5807329BCC417CF77EC7FD8E50B6D9A8D6B2017B24F6890557AF327980D086499B7C4ED6518B9C23DAB9571CA9E8E949C039C5CC002CBC9BDD08728D543143AFE577738AD309AB2493A8157272196B73C28A4826B37A8274198A4E8188CDADB1D7BB209C84D03500F79B9DFEC1E4441F34069CC01D6B9A57940914F56217C0F3A5CE0C75DE2815EE396D4AB00EC9695DFBCDD88EA6C8017CC29B1257EED39B50E0D075CCF9564D4B22F59F4B5E6667E4CACAC6B63D8CC1C9AB2CC6309A319E559D2062FB99D15B62F08E4DAD676698813D227FF8967B3B3830970E92277B2446A3C269A74FB437800824A8987DA3636A17A53C7E55C66077BE0FBD63441402F19C6C4E1F1C46185A3F3F5D7D7F553F0066EBFCF2ECD74CFC6DB48F6A458AE66EC12532B691FA3AE9A0C19809B3A1AF06340EFB012A33D484D272CA09D5862DAC5E3A00006F260BDE5CE74E007AB12A8F686373949308E574DCE7EA9D14593700D34957 +20170709162318 2 6 100 7679 5 C0388038628CD48D5377C99911D89CEDF70AC54721EE6974975D61C9E25580D2108B48CBCDB8B647B271FA822546C00580DB013D19EE5A49EFD9AAECA2036A83BB3E2F96C3E7CB273AA9ACEFCA5A3E4C7C8FCF3332DE11288D8BD76E17B4C530F5F6EFB0D757F63E3B2B519EE960FA8206DF81E7B9DA463CE389E3164588BF5B66355D481DC620F0B2F352782105DF3AB86076DD7D612CE9839CB251D5C975166859A41B740E08E66B746B710479FAA430E2891E60647E04FE71D8F8BC9A6BCD20CFB42299142DC016E672CC350D497809379F54F6F3D1649ADCE72ADECEAAE1ECA85EEE8006700379DE3687A67AF796E1F317815461CFF6E58615CD453265612315FA8F99DC65D9CC218004671E43CE58C9F54862D86B58FD71212199A2A562B1AB9604BF43676A403E8EA56A69E68F1CF0C60C83B8EB31D9C0A23D8410C3A6898D749CAD8CDA9F17A224536BD08436B25E50BA67BAD09276BB55583CEDF48AEEFFD8FA3DBE4F609760DF1EDED136B38792CD164D2EA3C5443F0D8F9117544A9A6AAC615ADE01440B7948B2B53BC3F7218DEDEB16D23C3B0C2AA4BEB99F9A9225D87B6CCB037D8E9A2918C20FE9F2BFF429FD0F23AE370E820842AEDD823DD5B6DDD7F4AD3A06735A2E4144DBABEA5DD83A6AA98EED5F6F3021C246FBABD280986A1E7A24CCBE11BC3050CC04DB566277CECBA8B5BDC1D15E1F066B25B668C7B87EA54894EC7559B64F1400934DCE1C06A10955988E3B3F4A40566B3989608404859335C53EBD6BEE21614EB7C954D543DBA7EB61555B7CED9D08EF560426DBCE3018FBEF788CF69AEAB433B692A9E28CBAFEFC048BD9AB423678D4DD5807329BCC417CF77EC7FD8E50B6D9A8D6B2017B24F6890557AF327980D086499B7C4ED6518B9C23DAB9571CA9E8E949C039C5CC002CBC9BDD08728D543143AFE577738AD309AB2493A8157272196B73C28A4826B37A8274198A4E8188CDADB1D7BB209C84D03500F79B9DFEC1E4441F34069CC01D6B9A57940914F56217C0F3A5CE0C75DE2815EE396D4AB00EC9695DFBCDD88EA6C8017CC29B1257EED39B50E0D075CCF9564D4B22F59F4B5E6667E4CACAC6B63D8CC1C9AB2CC6309A319E559D2062FB99D15B62F08E4DAD676698813D227FF8967B3B3830970E92277B2446A3C269A74FB437800824A8987DA3636A17A53C7E55C66077BE0FBD63441402F19C6C4E1F1C46185A3F3F5D7D7F553F0066EBFCF2ECD74CFC6DB48F6A458AE66EC12532B691FA3AE9A0C19809B3A1AF06340EFB012A33D484D272CA09D5862DAC5E3A00006F260BDE5CE74E007AB12A8F686373949308E574DCE7EA9D14593701B3041F +20170709184215 2 6 100 7679 2 C0388038628CD48D5377C99911D89CEDF70AC54721EE6974975D61C9E25580D2108B48CBCDB8B647B271FA822546C00580DB013D19EE5A49EFD9AAECA2036A83BB3E2F96C3E7CB273AA9ACEFCA5A3E4C7C8FCF3332DE11288D8BD76E17B4C530F5F6EFB0D757F63E3B2B519EE960FA8206DF81E7B9DA463CE389E3164588BF5B66355D481DC620F0B2F352782105DF3AB86076DD7D612CE9839CB251D5C975166859A41B740E08E66B746B710479FAA430E2891E60647E04FE71D8F8BC9A6BCD20CFB42299142DC016E672CC350D497809379F54F6F3D1649ADCE72ADECEAAE1ECA85EEE8006700379DE3687A67AF796E1F317815461CFF6E58615CD453265612315FA8F99DC65D9CC218004671E43CE58C9F54862D86B58FD71212199A2A562B1AB9604BF43676A403E8EA56A69E68F1CF0C60C83B8EB31D9C0A23D8410C3A6898D749CAD8CDA9F17A224536BD08436B25E50BA67BAD09276BB55583CEDF48AEEFFD8FA3DBE4F609760DF1EDED136B38792CD164D2EA3C5443F0D8F9117544A9A6AAC615ADE01440B7948B2B53BC3F7218DEDEB16D23C3B0C2AA4BEB99F9A9225D87B6CCB037D8E9A2918C20FE9F2BFF429FD0F23AE370E820842AEDD823DD5B6DDD7F4AD3A06735A2E4144DBABEA5DD83A6AA98EED5F6F3021C246FBABD280986A1E7A24CCBE11BC3050CC04DB566277CECBA8B5BDC1D15E1F066B25B668C7B87EA54894EC7559B64F1400934DCE1C06A10955988E3B3F4A40566B3989608404859335C53EBD6BEE21614EB7C954D543DBA7EB61555B7CED9D08EF560426DBCE3018FBEF788CF69AEAB433B692A9E28CBAFEFC048BD9AB423678D4DD5807329BCC417CF77EC7FD8E50B6D9A8D6B2017B24F6890557AF327980D086499B7C4ED6518B9C23DAB9571CA9E8E949C039C5CC002CBC9BDD08728D543143AFE577738AD309AB2493A8157272196B73C28A4826B37A8274198A4E8188CDADB1D7BB209C84D03500F79B9DFEC1E4441F34069CC01D6B9A57940914F56217C0F3A5CE0C75DE2815EE396D4AB00EC9695DFBCDD88EA6C8017CC29B1257EED39B50E0D075CCF9564D4B22F59F4B5E6667E4CACAC6B63D8CC1C9AB2CC6309A319E559D2062FB99D15B62F08E4DAD676698813D227FF8967B3B3830970E92277B2446A3C269A74FB437800824A8987DA3636A17A53C7E55C66077BE0FBD63441402F19C6C4E1F1C46185A3F3F5D7D7F553F0066EBFCF2ECD74CFC6DB48F6A458AE66EC12532B691FA3AE9A0C19809B3A1AF06340EFB012A33D484D272CA09D5862DAC5E3A00006F260BDE5CE74E007AB12A8F686373949308E574DCE7EA9D1459370374B3A3 +20170709215933 2 6 100 7679 5 C0388038628CD48D5377C99911D89CEDF70AC54721EE6974975D61C9E25580D2108B48CBCDB8B647B271FA822546C00580DB013D19EE5A49EFD9AAECA2036A83BB3E2F96C3E7CB273AA9ACEFCA5A3E4C7C8FCF3332DE11288D8BD76E17B4C530F5F6EFB0D757F63E3B2B519EE960FA8206DF81E7B9DA463CE389E3164588BF5B66355D481DC620F0B2F352782105DF3AB86076DD7D612CE9839CB251D5C975166859A41B740E08E66B746B710479FAA430E2891E60647E04FE71D8F8BC9A6BCD20CFB42299142DC016E672CC350D497809379F54F6F3D1649ADCE72ADECEAAE1ECA85EEE8006700379DE3687A67AF796E1F317815461CFF6E58615CD453265612315FA8F99DC65D9CC218004671E43CE58C9F54862D86B58FD71212199A2A562B1AB9604BF43676A403E8EA56A69E68F1CF0C60C83B8EB31D9C0A23D8410C3A6898D749CAD8CDA9F17A224536BD08436B25E50BA67BAD09276BB55583CEDF48AEEFFD8FA3DBE4F609760DF1EDED136B38792CD164D2EA3C5443F0D8F9117544A9A6AAC615ADE01440B7948B2B53BC3F7218DEDEB16D23C3B0C2AA4BEB99F9A9225D87B6CCB037D8E9A2918C20FE9F2BFF429FD0F23AE370E820842AEDD823DD5B6DDD7F4AD3A06735A2E4144DBABEA5DD83A6AA98EED5F6F3021C246FBABD280986A1E7A24CCBE11BC3050CC04DB566277CECBA8B5BDC1D15E1F066B25B668C7B87EA54894EC7559B64F1400934DCE1C06A10955988E3B3F4A40566B3989608404859335C53EBD6BEE21614EB7C954D543DBA7EB61555B7CED9D08EF560426DBCE3018FBEF788CF69AEAB433B692A9E28CBAFEFC048BD9AB423678D4DD5807329BCC417CF77EC7FD8E50B6D9A8D6B2017B24F6890557AF327980D086499B7C4ED6518B9C23DAB9571CA9E8E949C039C5CC002CBC9BDD08728D543143AFE577738AD309AB2493A8157272196B73C28A4826B37A8274198A4E8188CDADB1D7BB209C84D03500F79B9DFEC1E4441F34069CC01D6B9A57940914F56217C0F3A5CE0C75DE2815EE396D4AB00EC9695DFBCDD88EA6C8017CC29B1257EED39B50E0D075CCF9564D4B22F59F4B5E6667E4CACAC6B63D8CC1C9AB2CC6309A319E559D2062FB99D15B62F08E4DAD676698813D227FF8967B3B3830970E92277B2446A3C269A74FB437800824A8987DA3636A17A53C7E55C66077BE0FBD63441402F19C6C4E1F1C46185A3F3F5D7D7F553F0066EBFCF2ECD74CFC6DB48F6A458AE66EC12532B691FA3AE9A0C19809B3A1AF06340EFB012A33D484D272CA09D5862DAC5E3A00006F260BDE5CE74E007AB12A8F686373949308E574DCE7EA9D14593705ED75E7 +20170710000252 2 6 100 7679 2 C0388038628CD48D5377C99911D89CEDF70AC54721EE6974975D61C9E25580D2108B48CBCDB8B647B271FA822546C00580DB013D19EE5A49EFD9AAECA2036A83BB3E2F96C3E7CB273AA9ACEFCA5A3E4C7C8FCF3332DE11288D8BD76E17B4C530F5F6EFB0D757F63E3B2B519EE960FA8206DF81E7B9DA463CE389E3164588BF5B66355D481DC620F0B2F352782105DF3AB86076DD7D612CE9839CB251D5C975166859A41B740E08E66B746B710479FAA430E2891E60647E04FE71D8F8BC9A6BCD20CFB42299142DC016E672CC350D497809379F54F6F3D1649ADCE72ADECEAAE1ECA85EEE8006700379DE3687A67AF796E1F317815461CFF6E58615CD453265612315FA8F99DC65D9CC218004671E43CE58C9F54862D86B58FD71212199A2A562B1AB9604BF43676A403E8EA56A69E68F1CF0C60C83B8EB31D9C0A23D8410C3A6898D749CAD8CDA9F17A224536BD08436B25E50BA67BAD09276BB55583CEDF48AEEFFD8FA3DBE4F609760DF1EDED136B38792CD164D2EA3C5443F0D8F9117544A9A6AAC615ADE01440B7948B2B53BC3F7218DEDEB16D23C3B0C2AA4BEB99F9A9225D87B6CCB037D8E9A2918C20FE9F2BFF429FD0F23AE370E820842AEDD823DD5B6DDD7F4AD3A06735A2E4144DBABEA5DD83A6AA98EED5F6F3021C246FBABD280986A1E7A24CCBE11BC3050CC04DB566277CECBA8B5BDC1D15E1F066B25B668C7B87EA54894EC7559B64F1400934DCE1C06A10955988E3B3F4A40566B3989608404859335C53EBD6BEE21614EB7C954D543DBA7EB61555B7CED9D08EF560426DBCE3018FBEF788CF69AEAB433B692A9E28CBAFEFC048BD9AB423678D4DD5807329BCC417CF77EC7FD8E50B6D9A8D6B2017B24F6890557AF327980D086499B7C4ED6518B9C23DAB9571CA9E8E949C039C5CC002CBC9BDD08728D543143AFE577738AD309AB2493A8157272196B73C28A4826B37A8274198A4E8188CDADB1D7BB209C84D03500F79B9DFEC1E4441F34069CC01D6B9A57940914F56217C0F3A5CE0C75DE2815EE396D4AB00EC9695DFBCDD88EA6C8017CC29B1257EED39B50E0D075CCF9564D4B22F59F4B5E6667E4CACAC6B63D8CC1C9AB2CC6309A319E559D2062FB99D15B62F08E4DAD676698813D227FF8967B3B3830970E92277B2446A3C269A74FB437800824A8987DA3636A17A53C7E55C66077BE0FBD63441402F19C6C4E1F1C46185A3F3F5D7D7F553F0066EBFCF2ECD74CFC6DB48F6A458AE66EC12532B691FA3AE9A0C19809B3A1AF06340EFB012A33D484D272CA09D5862DAC5E3A00006F260BDE5CE74E007AB12A8F686373949308E574DCE7EA9D145937077174C3 +20170710052851 2 6 100 7679 2 C0388038628CD48D5377C99911D89CEDF70AC54721EE6974975D61C9E25580D2108B48CBCDB8B647B271FA822546C00580DB013D19EE5A49EFD9AAECA2036A83BB3E2F96C3E7CB273AA9ACEFCA5A3E4C7C8FCF3332DE11288D8BD76E17B4C530F5F6EFB0D757F63E3B2B519EE960FA8206DF81E7B9DA463CE389E3164588BF5B66355D481DC620F0B2F352782105DF3AB86076DD7D612CE9839CB251D5C975166859A41B740E08E66B746B710479FAA430E2891E60647E04FE71D8F8BC9A6BCD20CFB42299142DC016E672CC350D497809379F54F6F3D1649ADCE72ADECEAAE1ECA85EEE8006700379DE3687A67AF796E1F317815461CFF6E58615CD453265612315FA8F99DC65D9CC218004671E43CE58C9F54862D86B58FD71212199A2A562B1AB9604BF43676A403E8EA56A69E68F1CF0C60C83B8EB31D9C0A23D8410C3A6898D749CAD8CDA9F17A224536BD08436B25E50BA67BAD09276BB55583CEDF48AEEFFD8FA3DBE4F609760DF1EDED136B38792CD164D2EA3C5443F0D8F9117544A9A6AAC615ADE01440B7948B2B53BC3F7218DEDEB16D23C3B0C2AA4BEB99F9A9225D87B6CCB037D8E9A2918C20FE9F2BFF429FD0F23AE370E820842AEDD823DD5B6DDD7F4AD3A06735A2E4144DBABEA5DD83A6AA98EED5F6F3021C246FBABD280986A1E7A24CCBE11BC3050CC04DB566277CECBA8B5BDC1D15E1F066B25B668C7B87EA54894EC7559B64F1400934DCE1C06A10955988E3B3F4A40566B3989608404859335C53EBD6BEE21614EB7C954D543DBA7EB61555B7CED9D08EF560426DBCE3018FBEF788CF69AEAB433B692A9E28CBAFEFC048BD9AB423678D4DD5807329BCC417CF77EC7FD8E50B6D9A8D6B2017B24F6890557AF327980D086499B7C4ED6518B9C23DAB9571CA9E8E949C039C5CC002CBC9BDD08728D543143AFE577738AD309AB2493A8157272196B73C28A4826B37A8274198A4E8188CDADB1D7BB209C84D03500F79B9DFEC1E4441F34069CC01D6B9A57940914F56217C0F3A5CE0C75DE2815EE396D4AB00EC9695DFBCDD88EA6C8017CC29B1257EED39B50E0D075CCF9564D4B22F59F4B5E6667E4CACAC6B63D8CC1C9AB2CC6309A319E559D2062FB99D15B62F08E4DAD676698813D227FF8967B3B3830970E92277B2446A3C269A74FB437800824A8987DA3636A17A53C7E55C66077BE0FBD63441402F19C6C4E1F1C46185A3F3F5D7D7F553F0066EBFCF2ECD74CFC6DB48F6A458AE66EC12532B691FA3AE9A0C19809B3A1AF06340EFB012A33D484D272CA09D5862DAC5E3A00006F260BDE5CE74E007AB12A8F686373949308E574DCE7EA9D1459370B975DE3 +20170710074510 2 6 100 8191 2 DDFBC1CD4FB7E30639422038F1FFBA2CD3EC3915F3C923282C6588F6EB218FF7B24870C0FE4B48213AB0948E101686FB7B0093ED467B6CA413EDD4B0BFE2155AEBC4DA3D2DD0C78DA9AD989A0E989010D6D5E86A123C169E126F97826EE5F602FF641FDF642A107E7538CB61740CBAF69F6C7DC5DD4DF28998AB61B8672F0B74A3A8DD7D165828D69DCC1BAE4D45F707C3894E040BCC0AF7AA810A6D5CB89276217EB7AFAFE4966D68C10318E8C8CB23CA593E8057F29FF9154908B11D6530E6352F9406C81D9DAC5C298979320B4E0DD89203A1F680C8084154D0439DB6C53EDAF6FCC0E8682EC99D345180120AEC810CBB0C2F1B6D1B660ACEAAD5996A5D184659B6A1F11456BA6A5E94D223959D8171C030499A9DB458702CB35CA7E7CD75D26FF5E94640AB8740ECE82559784BB6D5CB4D041D053629BD3F4178077F3F7E280296C46A3F0FBC37813A1AA221FBA2612F0CFE56450E9B1F2C2AE278EC7A7AAB66D61FA9749FE997EDC31131091620897014D33B2386B490CFD80656B7D2EB08C9DA9928798986996D60F74D766EB8988E2FF676E38C587E7A6651AA28BEB8BB56EBBD6E641E92309AEAA671A5F2EC72629442D2C3A4C2B8E4304DC71B342CD116527832078E6B53C1E0A72909615B408E17625F7259ACA98E46359448FC141F57B51A069B8A402AE3A87E10AE7E910F3916BAC6CE716C539E825A06626673DE7EBD899A3982FCC599791E7CA964C0D37BB076708C03DC7C022980974025C0EA9B72CC3D0A03E4626E030E9C857ECF6B3807AC9E8E0F72098C7E80DAA05BFF60394A8374096878F015597DD5B22E65646A7DDC87B5F6AE68594DF39B0BDB2675A32369AD81FD62033146B8DA6A801E918572CBC70DEBA9F70D088D69425733ACE0084E60E7FCB459A5B71F74F711184B1AEA240834D28D049474BB2E7ED1B17AA2B5EB7D274341456834320BE8FB245B1C2B84A096E7E40573FEB7C2997ED16C8C2C62409B8064398ED220FA82C59E53AD7E864C24473FCC7F017B897D5855F092A9428957467EFD93F67D3FA302C578328A9484CD0496CC83BEAC96504F9601DA2048D25BF43B5A69E46234A164D854B89DF1DEDC36F0304BA5FC035B27E782087C3EC0A81840A3EC042204C63F9698CC74A818428039B23664C409529C4EDD822DF77819805023795EE625D524F12824C1F1FE99546DF75107AFFF7D424C4C3FB3D0BDA2E9BC0D93603457FFE44FABEAB1E6B62223B201D42784731BEE11E0FF0BF29C930DAF913F974739800522E2B9C4094475A5F35AA92E2939E5719EB4EE19446ADC9ECC7EE6BAB5D264C9E74AB6DE856D541146048341EB51734A34E33EF8D929F645E23FD902CB5676DA9C84C9F46490710DC8CF2AA922252C3885CBD8D0CB1D176CAFEB46A625C56BE949F487C6E35E2CE481F024C8898200FD23 +20170710114649 2 6 100 8191 2 DDFBC1CD4FB7E30639422038F1FFBA2CD3EC3915F3C923282C6588F6EB218FF7B24870C0FE4B48213AB0948E101686FB7B0093ED467B6CA413EDD4B0BFE2155AEBC4DA3D2DD0C78DA9AD989A0E989010D6D5E86A123C169E126F97826EE5F602FF641FDF642A107E7538CB61740CBAF69F6C7DC5DD4DF28998AB61B8672F0B74A3A8DD7D165828D69DCC1BAE4D45F707C3894E040BCC0AF7AA810A6D5CB89276217EB7AFAFE4966D68C10318E8C8CB23CA593E8057F29FF9154908B11D6530E6352F9406C81D9DAC5C298979320B4E0DD89203A1F680C8084154D0439DB6C53EDAF6FCC0E8682EC99D345180120AEC810CBB0C2F1B6D1B660ACEAAD5996A5D184659B6A1F11456BA6A5E94D223959D8171C030499A9DB458702CB35CA7E7CD75D26FF5E94640AB8740ECE82559784BB6D5CB4D041D053629BD3F4178077F3F7E280296C46A3F0FBC37813A1AA221FBA2612F0CFE56450E9B1F2C2AE278EC7A7AAB66D61FA9749FE997EDC31131091620897014D33B2386B490CFD80656B7D2EB08C9DA9928798986996D60F74D766EB8988E2FF676E38C587E7A6651AA28BEB8BB56EBBD6E641E92309AEAA671A5F2EC72629442D2C3A4C2B8E4304DC71B342CD116527832078E6B53C1E0A72909615B408E17625F7259ACA98E46359448FC141F57B51A069B8A402AE3A87E10AE7E910F3916BAC6CE716C539E825A06626673DE7EBD899A3982FCC599791E7CA964C0D37BB076708C03DC7C022980974025C0EA9B72CC3D0A03E4626E030E9C857ECF6B3807AC9E8E0F72098C7E80DAA05BFF60394A8374096878F015597DD5B22E65646A7DDC87B5F6AE68594DF39B0BDB2675A32369AD81FD62033146B8DA6A801E918572CBC70DEBA9F70D088D69425733ACE0084E60E7FCB459A5B71F74F711184B1AEA240834D28D049474BB2E7ED1B17AA2B5EB7D274341456834320BE8FB245B1C2B84A096E7E40573FEB7C2997ED16C8C2C62409B8064398ED220FA82C59E53AD7E864C24473FCC7F017B897D5855F092A9428957467EFD93F67D3FA302C578328A9484CD0496CC83BEAC96504F9601DA2048D25BF43B5A69E46234A164D854B89DF1DEDC36F0304BA5FC035B27E782087C3EC0A81840A3EC042204C63F9698CC74A818428039B23664C409529C4EDD822DF77819805023795EE625D524F12824C1F1FE99546DF75107AFFF7D424C4C3FB3D0BDA2E9BC0D93603457FFE44FABEAB1E6B62223B201D42784731BEE11E0FF0BF29C930DAF913F974739800522E2B9C4094475A5F35AA92E2939E5719EB4EE19446ADC9ECC7EE6BAB5D264C9E74AB6DE856D541146048341EB51734A34E33EF8D929F645E23FD902CB5676DA9C84C9F46490710DC8CF2AA922252C3885CBD8D0CB1D176CAFEB46A625C56BE949F487C6E35E2CE481F024C88984F315BB +20170711033842 2 6 100 8191 5 DDFBC1CD4FB7E30639422038F1FFBA2CD3EC3915F3C923282C6588F6EB218FF7B24870C0FE4B48213AB0948E101686FB7B0093ED467B6CA413EDD4B0BFE2155AEBC4DA3D2DD0C78DA9AD989A0E989010D6D5E86A123C169E126F97826EE5F602FF641FDF642A107E7538CB61740CBAF69F6C7DC5DD4DF28998AB61B8672F0B74A3A8DD7D165828D69DCC1BAE4D45F707C3894E040BCC0AF7AA810A6D5CB89276217EB7AFAFE4966D68C10318E8C8CB23CA593E8057F29FF9154908B11D6530E6352F9406C81D9DAC5C298979320B4E0DD89203A1F680C8084154D0439DB6C53EDAF6FCC0E8682EC99D345180120AEC810CBB0C2F1B6D1B660ACEAAD5996A5D184659B6A1F11456BA6A5E94D223959D8171C030499A9DB458702CB35CA7E7CD75D26FF5E94640AB8740ECE82559784BB6D5CB4D041D053629BD3F4178077F3F7E280296C46A3F0FBC37813A1AA221FBA2612F0CFE56450E9B1F2C2AE278EC7A7AAB66D61FA9749FE997EDC31131091620897014D33B2386B490CFD80656B7D2EB08C9DA9928798986996D60F74D766EB8988E2FF676E38C587E7A6651AA28BEB8BB56EBBD6E641E92309AEAA671A5F2EC72629442D2C3A4C2B8E4304DC71B342CD116527832078E6B53C1E0A72909615B408E17625F7259ACA98E46359448FC141F57B51A069B8A402AE3A87E10AE7E910F3916BAC6CE716C539E825A06626673DE7EBD899A3982FCC599791E7CA964C0D37BB076708C03DC7C022980974025C0EA9B72CC3D0A03E4626E030E9C857ECF6B3807AC9E8E0F72098C7E80DAA05BFF60394A8374096878F015597DD5B22E65646A7DDC87B5F6AE68594DF39B0BDB2675A32369AD81FD62033146B8DA6A801E918572CBC70DEBA9F70D088D69425733ACE0084E60E7FCB459A5B71F74F711184B1AEA240834D28D049474BB2E7ED1B17AA2B5EB7D274341456834320BE8FB245B1C2B84A096E7E40573FEB7C2997ED16C8C2C62409B8064398ED220FA82C59E53AD7E864C24473FCC7F017B897D5855F092A9428957467EFD93F67D3FA302C578328A9484CD0496CC83BEAC96504F9601DA2048D25BF43B5A69E46234A164D854B89DF1DEDC36F0304BA5FC035B27E782087C3EC0A81840A3EC042204C63F9698CC74A818428039B23664C409529C4EDD822DF77819805023795EE625D524F12824C1F1FE99546DF75107AFFF7D424C4C3FB3D0BDA2E9BC0D93603457FFE44FABEAB1E6B62223B201D42784731BEE11E0FF0BF29C930DAF913F974739800522E2B9C4094475A5F35AA92E2939E5719EB4EE19446ADC9ECC7EE6BAB5D264C9E74AB6DE856D541146048341EB51734A34E33EF8D929F645E23FD902CB5676DA9C84C9F46490710DC8CF2AA922252C3885CBD8D0CB1D176CAFEB46A625C56BE949F487C6E35E2CE481F024C88990A1C3A7 +20170711064933 2 6 100 8191 2 DDFBC1CD4FB7E30639422038F1FFBA2CD3EC3915F3C923282C6588F6EB218FF7B24870C0FE4B48213AB0948E101686FB7B0093ED467B6CA413EDD4B0BFE2155AEBC4DA3D2DD0C78DA9AD989A0E989010D6D5E86A123C169E126F97826EE5F602FF641FDF642A107E7538CB61740CBAF69F6C7DC5DD4DF28998AB61B8672F0B74A3A8DD7D165828D69DCC1BAE4D45F707C3894E040BCC0AF7AA810A6D5CB89276217EB7AFAFE4966D68C10318E8C8CB23CA593E8057F29FF9154908B11D6530E6352F9406C81D9DAC5C298979320B4E0DD89203A1F680C8084154D0439DB6C53EDAF6FCC0E8682EC99D345180120AEC810CBB0C2F1B6D1B660ACEAAD5996A5D184659B6A1F11456BA6A5E94D223959D8171C030499A9DB458702CB35CA7E7CD75D26FF5E94640AB8740ECE82559784BB6D5CB4D041D053629BD3F4178077F3F7E280296C46A3F0FBC37813A1AA221FBA2612F0CFE56450E9B1F2C2AE278EC7A7AAB66D61FA9749FE997EDC31131091620897014D33B2386B490CFD80656B7D2EB08C9DA9928798986996D60F74D766EB8988E2FF676E38C587E7A6651AA28BEB8BB56EBBD6E641E92309AEAA671A5F2EC72629442D2C3A4C2B8E4304DC71B342CD116527832078E6B53C1E0A72909615B408E17625F7259ACA98E46359448FC141F57B51A069B8A402AE3A87E10AE7E910F3916BAC6CE716C539E825A06626673DE7EBD899A3982FCC599791E7CA964C0D37BB076708C03DC7C022980974025C0EA9B72CC3D0A03E4626E030E9C857ECF6B3807AC9E8E0F72098C7E80DAA05BFF60394A8374096878F015597DD5B22E65646A7DDC87B5F6AE68594DF39B0BDB2675A32369AD81FD62033146B8DA6A801E918572CBC70DEBA9F70D088D69425733ACE0084E60E7FCB459A5B71F74F711184B1AEA240834D28D049474BB2E7ED1B17AA2B5EB7D274341456834320BE8FB245B1C2B84A096E7E40573FEB7C2997ED16C8C2C62409B8064398ED220FA82C59E53AD7E864C24473FCC7F017B897D5855F092A9428957467EFD93F67D3FA302C578328A9484CD0496CC83BEAC96504F9601DA2048D25BF43B5A69E46234A164D854B89DF1DEDC36F0304BA5FC035B27E782087C3EC0A81840A3EC042204C63F9698CC74A818428039B23664C409529C4EDD822DF77819805023795EE625D524F12824C1F1FE99546DF75107AFFF7D424C4C3FB3D0BDA2E9BC0D93603457FFE44FABEAB1E6B62223B201D42784731BEE11E0FF0BF29C930DAF913F974739800522E2B9C4094475A5F35AA92E2939E5719EB4EE19446ADC9ECC7EE6BAB5D264C9E74AB6DE856D541146048341EB51734A34E33EF8D929F645E23FD902CB5676DA9C84C9F46490710DC8CF2AA922252C3885CBD8D0CB1D176CAFEB46A625C56BE949F487C6E35E2CE481F024C88992F18383 +20170711070835 2 6 100 8191 2 DDFBC1CD4FB7E30639422038F1FFBA2CD3EC3915F3C923282C6588F6EB218FF7B24870C0FE4B48213AB0948E101686FB7B0093ED467B6CA413EDD4B0BFE2155AEBC4DA3D2DD0C78DA9AD989A0E989010D6D5E86A123C169E126F97826EE5F602FF641FDF642A107E7538CB61740CBAF69F6C7DC5DD4DF28998AB61B8672F0B74A3A8DD7D165828D69DCC1BAE4D45F707C3894E040BCC0AF7AA810A6D5CB89276217EB7AFAFE4966D68C10318E8C8CB23CA593E8057F29FF9154908B11D6530E6352F9406C81D9DAC5C298979320B4E0DD89203A1F680C8084154D0439DB6C53EDAF6FCC0E8682EC99D345180120AEC810CBB0C2F1B6D1B660ACEAAD5996A5D184659B6A1F11456BA6A5E94D223959D8171C030499A9DB458702CB35CA7E7CD75D26FF5E94640AB8740ECE82559784BB6D5CB4D041D053629BD3F4178077F3F7E280296C46A3F0FBC37813A1AA221FBA2612F0CFE56450E9B1F2C2AE278EC7A7AAB66D61FA9749FE997EDC31131091620897014D33B2386B490CFD80656B7D2EB08C9DA9928798986996D60F74D766EB8988E2FF676E38C587E7A6651AA28BEB8BB56EBBD6E641E92309AEAA671A5F2EC72629442D2C3A4C2B8E4304DC71B342CD116527832078E6B53C1E0A72909615B408E17625F7259ACA98E46359448FC141F57B51A069B8A402AE3A87E10AE7E910F3916BAC6CE716C539E825A06626673DE7EBD899A3982FCC599791E7CA964C0D37BB076708C03DC7C022980974025C0EA9B72CC3D0A03E4626E030E9C857ECF6B3807AC9E8E0F72098C7E80DAA05BFF60394A8374096878F015597DD5B22E65646A7DDC87B5F6AE68594DF39B0BDB2675A32369AD81FD62033146B8DA6A801E918572CBC70DEBA9F70D088D69425733ACE0084E60E7FCB459A5B71F74F711184B1AEA240834D28D049474BB2E7ED1B17AA2B5EB7D274341456834320BE8FB245B1C2B84A096E7E40573FEB7C2997ED16C8C2C62409B8064398ED220FA82C59E53AD7E864C24473FCC7F017B897D5855F092A9428957467EFD93F67D3FA302C578328A9484CD0496CC83BEAC96504F9601DA2048D25BF43B5A69E46234A164D854B89DF1DEDC36F0304BA5FC035B27E782087C3EC0A81840A3EC042204C63F9698CC74A818428039B23664C409529C4EDD822DF77819805023795EE625D524F12824C1F1FE99546DF75107AFFF7D424C4C3FB3D0BDA2E9BC0D93603457FFE44FABEAB1E6B62223B201D42784731BEE11E0FF0BF29C930DAF913F974739800522E2B9C4094475A5F35AA92E2939E5719EB4EE19446ADC9ECC7EE6BAB5D264C9E74AB6DE856D541146048341EB51734A34E33EF8D929F645E23FD902CB5676DA9C84C9F46490710DC8CF2AA922252C3885CBD8D0CB1D176CAFEB46A625C56BE949F487C6E35E2CE481F024C8899321BE1B +20170712081942 2 6 100 8191 2 DDFBC1CD4FB7E30639422038F1FFBA2CD3EC3915F3C923282C6588F6EB218FF7B24870C0FE4B48213AB0948E101686FB7B0093ED467B6CA413EDD4B0BFE2155AEBC4DA3D2DD0C78DA9AD989A0E989010D6D5E86A123C169E126F97826EE5F602FF641FDF642A107E7538CB61740CBAF69F6C7DC5DD4DF28998AB61B8672F0B74A3A8DD7D165828D69DCC1BAE4D45F707C3894E040BCC0AF7AA810A6D5CB89276217EB7AFAFE4966D68C10318E8C8CB23CA593E8057F29FF9154908B11D6530E6352F9406C81D9DAC5C298979320B4E0DD89203A1F680C8084154D0439DB6C53EDAF6FCC0E8682EC99D345180120AEC810CBB0C2F1B6D1B660ACEAAD5996A5D184659B6A1F11456BA6A5E94D223959D8171C030499A9DB458702CB35CA7E7CD75D26FF5E94640AB8740ECE82559784BB6D5CB4D041D053629BD3F4178077F3F7E280296C46A3F0FBC37813A1AA221FBA2612F0CFE56450E9B1F2C2AE278EC7A7AAB66D61FA9749FE997EDC31131091620897014D33B2386B490CFD80656B7D2EB08C9DA9928798986996D60F74D766EB8988E2FF676E38C587E7A6651AA28BEB8BB56EBBD6E641E92309AEAA671A5F2EC72629442D2C3A4C2B8E4304DC71B342CD116527832078E6B53C1E0A72909615B408E17625F7259ACA98E46359448FC141F57B51A069B8A402AE3A87E10AE7E910F3916BAC6CE716C539E825A06626673DE7EBD899A3982FCC599791E7CA964C0D37BB076708C03DC7C022980974025C0EA9B72CC3D0A03E4626E030E9C857ECF6B3807AC9E8E0F72098C7E80DAA05BFF60394A8374096878F015597DD5B22E65646A7DDC87B5F6AE68594DF39B0BDB2675A32369AD81FD62033146B8DA6A801E918572CBC70DEBA9F70D088D69425733ACE0084E60E7FCB459A5B71F74F711184B1AEA240834D28D049474BB2E7ED1B17AA2B5EB7D274341456834320BE8FB245B1C2B84A096E7E40573FEB7C2997ED16C8C2C62409B8064398ED220FA82C59E53AD7E864C24473FCC7F017B897D5855F092A9428957467EFD93F67D3FA302C578328A9484CD0496CC83BEAC96504F9601DA2048D25BF43B5A69E46234A164D854B89DF1DEDC36F0304BA5FC035B27E782087C3EC0A81840A3EC042204C63F9698CC74A818428039B23664C409529C4EDD822DF77819805023795EE625D524F12824C1F1FE99546DF75107AFFF7D424C4C3FB3D0BDA2E9BC0D93603457FFE44FABEAB1E6B62223B201D42784731BEE11E0FF0BF29C930DAF913F974739800522E2B9C4094475A5F35AA92E2939E5719EB4EE19446ADC9ECC7EE6BAB5D264C9E74AB6DE856D541146048341EB51734A34E33EF8D929F645E23FD902CB5676DA9C84C9F46490710DC8CF2AA922252C3885CBD8D0CB1D176CAFEB46A625C56BE949F487C6E35E2CE481F024C889A5694573 +20170712175235 2 6 100 8191 2 DDFBC1CD4FB7E30639422038F1FFBA2CD3EC3915F3C923282C6588F6EB218FF7B24870C0FE4B48213AB0948E101686FB7B0093ED467B6CA413EDD4B0BFE2155AEBC4DA3D2DD0C78DA9AD989A0E989010D6D5E86A123C169E126F97826EE5F602FF641FDF642A107E7538CB61740CBAF69F6C7DC5DD4DF28998AB61B8672F0B74A3A8DD7D165828D69DCC1BAE4D45F707C3894E040BCC0AF7AA810A6D5CB89276217EB7AFAFE4966D68C10318E8C8CB23CA593E8057F29FF9154908B11D6530E6352F9406C81D9DAC5C298979320B4E0DD89203A1F680C8084154D0439DB6C53EDAF6FCC0E8682EC99D345180120AEC810CBB0C2F1B6D1B660ACEAAD5996A5D184659B6A1F11456BA6A5E94D223959D8171C030499A9DB458702CB35CA7E7CD75D26FF5E94640AB8740ECE82559784BB6D5CB4D041D053629BD3F4178077F3F7E280296C46A3F0FBC37813A1AA221FBA2612F0CFE56450E9B1F2C2AE278EC7A7AAB66D61FA9749FE997EDC31131091620897014D33B2386B490CFD80656B7D2EB08C9DA9928798986996D60F74D766EB8988E2FF676E38C587E7A6651AA28BEB8BB56EBBD6E641E92309AEAA671A5F2EC72629442D2C3A4C2B8E4304DC71B342CD116527832078E6B53C1E0A72909615B408E17625F7259ACA98E46359448FC141F57B51A069B8A402AE3A87E10AE7E910F3916BAC6CE716C539E825A06626673DE7EBD899A3982FCC599791E7CA964C0D37BB076708C03DC7C022980974025C0EA9B72CC3D0A03E4626E030E9C857ECF6B3807AC9E8E0F72098C7E80DAA05BFF60394A8374096878F015597DD5B22E65646A7DDC87B5F6AE68594DF39B0BDB2675A32369AD81FD62033146B8DA6A801E918572CBC70DEBA9F70D088D69425733ACE0084E60E7FCB459A5B71F74F711184B1AEA240834D28D049474BB2E7ED1B17AA2B5EB7D274341456834320BE8FB245B1C2B84A096E7E40573FEB7C2997ED16C8C2C62409B8064398ED220FA82C59E53AD7E864C24473FCC7F017B897D5855F092A9428957467EFD93F67D3FA302C578328A9484CD0496CC83BEAC96504F9601DA2048D25BF43B5A69E46234A164D854B89DF1DEDC36F0304BA5FC035B27E782087C3EC0A81840A3EC042204C63F9698CC74A818428039B23664C409529C4EDD822DF77819805023795EE625D524F12824C1F1FE99546DF75107AFFF7D424C4C3FB3D0BDA2E9BC0D93603457FFE44FABEAB1E6B62223B201D42784731BEE11E0FF0BF29C930DAF913F974739800522E2B9C4094475A5F35AA92E2939E5719EB4EE19446ADC9ECC7EE6BAB5D264C9E74AB6DE856D541146048341EB51734A34E33EF8D929F645E23FD902CB5676DA9C84C9F46490710DC8CF2AA922252C3885CBD8D0CB1D176CAFEB46A625C56BE949F487C6E35E2CE481F024C889AC1C9503 +20170712184856 2 6 100 8191 2 DDFBC1CD4FB7E30639422038F1FFBA2CD3EC3915F3C923282C6588F6EB218FF7B24870C0FE4B48213AB0948E101686FB7B0093ED467B6CA413EDD4B0BFE2155AEBC4DA3D2DD0C78DA9AD989A0E989010D6D5E86A123C169E126F97826EE5F602FF641FDF642A107E7538CB61740CBAF69F6C7DC5DD4DF28998AB61B8672F0B74A3A8DD7D165828D69DCC1BAE4D45F707C3894E040BCC0AF7AA810A6D5CB89276217EB7AFAFE4966D68C10318E8C8CB23CA593E8057F29FF9154908B11D6530E6352F9406C81D9DAC5C298979320B4E0DD89203A1F680C8084154D0439DB6C53EDAF6FCC0E8682EC99D345180120AEC810CBB0C2F1B6D1B660ACEAAD5996A5D184659B6A1F11456BA6A5E94D223959D8171C030499A9DB458702CB35CA7E7CD75D26FF5E94640AB8740ECE82559784BB6D5CB4D041D053629BD3F4178077F3F7E280296C46A3F0FBC37813A1AA221FBA2612F0CFE56450E9B1F2C2AE278EC7A7AAB66D61FA9749FE997EDC31131091620897014D33B2386B490CFD80656B7D2EB08C9DA9928798986996D60F74D766EB8988E2FF676E38C587E7A6651AA28BEB8BB56EBBD6E641E92309AEAA671A5F2EC72629442D2C3A4C2B8E4304DC71B342CD116527832078E6B53C1E0A72909615B408E17625F7259ACA98E46359448FC141F57B51A069B8A402AE3A87E10AE7E910F3916BAC6CE716C539E825A06626673DE7EBD899A3982FCC599791E7CA964C0D37BB076708C03DC7C022980974025C0EA9B72CC3D0A03E4626E030E9C857ECF6B3807AC9E8E0F72098C7E80DAA05BFF60394A8374096878F015597DD5B22E65646A7DDC87B5F6AE68594DF39B0BDB2675A32369AD81FD62033146B8DA6A801E918572CBC70DEBA9F70D088D69425733ACE0084E60E7FCB459A5B71F74F711184B1AEA240834D28D049474BB2E7ED1B17AA2B5EB7D274341456834320BE8FB245B1C2B84A096E7E40573FEB7C2997ED16C8C2C62409B8064398ED220FA82C59E53AD7E864C24473FCC7F017B897D5855F092A9428957467EFD93F67D3FA302C578328A9484CD0496CC83BEAC96504F9601DA2048D25BF43B5A69E46234A164D854B89DF1DEDC36F0304BA5FC035B27E782087C3EC0A81840A3EC042204C63F9698CC74A818428039B23664C409529C4EDD822DF77819805023795EE625D524F12824C1F1FE99546DF75107AFFF7D424C4C3FB3D0BDA2E9BC0D93603457FFE44FABEAB1E6B62223B201D42784731BEE11E0FF0BF29C930DAF913F974739800522E2B9C4094475A5F35AA92E2939E5719EB4EE19446ADC9ECC7EE6BAB5D264C9E74AB6DE856D541146048341EB51734A34E33EF8D929F645E23FD902CB5676DA9C84C9F46490710DC8CF2AA922252C3885CBD8D0CB1D176CAFEB46A625C56BE949F487C6E35E2CE481F024C889ACBA643B +20170712224446 2 6 100 8191 2 DDFBC1CD4FB7E30639422038F1FFBA2CD3EC3915F3C923282C6588F6EB218FF7B24870C0FE4B48213AB0948E101686FB7B0093ED467B6CA413EDD4B0BFE2155AEBC4DA3D2DD0C78DA9AD989A0E989010D6D5E86A123C169E126F97826EE5F602FF641FDF642A107E7538CB61740CBAF69F6C7DC5DD4DF28998AB61B8672F0B74A3A8DD7D165828D69DCC1BAE4D45F707C3894E040BCC0AF7AA810A6D5CB89276217EB7AFAFE4966D68C10318E8C8CB23CA593E8057F29FF9154908B11D6530E6352F9406C81D9DAC5C298979320B4E0DD89203A1F680C8084154D0439DB6C53EDAF6FCC0E8682EC99D345180120AEC810CBB0C2F1B6D1B660ACEAAD5996A5D184659B6A1F11456BA6A5E94D223959D8171C030499A9DB458702CB35CA7E7CD75D26FF5E94640AB8740ECE82559784BB6D5CB4D041D053629BD3F4178077F3F7E280296C46A3F0FBC37813A1AA221FBA2612F0CFE56450E9B1F2C2AE278EC7A7AAB66D61FA9749FE997EDC31131091620897014D33B2386B490CFD80656B7D2EB08C9DA9928798986996D60F74D766EB8988E2FF676E38C587E7A6651AA28BEB8BB56EBBD6E641E92309AEAA671A5F2EC72629442D2C3A4C2B8E4304DC71B342CD116527832078E6B53C1E0A72909615B408E17625F7259ACA98E46359448FC141F57B51A069B8A402AE3A87E10AE7E910F3916BAC6CE716C539E825A06626673DE7EBD899A3982FCC599791E7CA964C0D37BB076708C03DC7C022980974025C0EA9B72CC3D0A03E4626E030E9C857ECF6B3807AC9E8E0F72098C7E80DAA05BFF60394A8374096878F015597DD5B22E65646A7DDC87B5F6AE68594DF39B0BDB2675A32369AD81FD62033146B8DA6A801E918572CBC70DEBA9F70D088D69425733ACE0084E60E7FCB459A5B71F74F711184B1AEA240834D28D049474BB2E7ED1B17AA2B5EB7D274341456834320BE8FB245B1C2B84A096E7E40573FEB7C2997ED16C8C2C62409B8064398ED220FA82C59E53AD7E864C24473FCC7F017B897D5855F092A9428957467EFD93F67D3FA302C578328A9484CD0496CC83BEAC96504F9601DA2048D25BF43B5A69E46234A164D854B89DF1DEDC36F0304BA5FC035B27E782087C3EC0A81840A3EC042204C63F9698CC74A818428039B23664C409529C4EDD822DF77819805023795EE625D524F12824C1F1FE99546DF75107AFFF7D424C4C3FB3D0BDA2E9BC0D93603457FFE44FABEAB1E6B62223B201D42784731BEE11E0FF0BF29C930DAF913F974739800522E2B9C4094475A5F35AA92E2939E5719EB4EE19446ADC9ECC7EE6BAB5D264C9E74AB6DE856D541146048341EB51734A34E33EF8D929F645E23FD902CB5676DA9C84C9F46490710DC8CF2AA922252C3885CBD8D0CB1D176CAFEB46A625C56BE949F487C6E35E2CE481F024C889AF76B1E3 +20170713034208 2 6 100 8191 5 DDFBC1CD4FB7E30639422038F1FFBA2CD3EC3915F3C923282C6588F6EB218FF7B24870C0FE4B48213AB0948E101686FB7B0093ED467B6CA413EDD4B0BFE2155AEBC4DA3D2DD0C78DA9AD989A0E989010D6D5E86A123C169E126F97826EE5F602FF641FDF642A107E7538CB61740CBAF69F6C7DC5DD4DF28998AB61B8672F0B74A3A8DD7D165828D69DCC1BAE4D45F707C3894E040BCC0AF7AA810A6D5CB89276217EB7AFAFE4966D68C10318E8C8CB23CA593E8057F29FF9154908B11D6530E6352F9406C81D9DAC5C298979320B4E0DD89203A1F680C8084154D0439DB6C53EDAF6FCC0E8682EC99D345180120AEC810CBB0C2F1B6D1B660ACEAAD5996A5D184659B6A1F11456BA6A5E94D223959D8171C030499A9DB458702CB35CA7E7CD75D26FF5E94640AB8740ECE82559784BB6D5CB4D041D053629BD3F4178077F3F7E280296C46A3F0FBC37813A1AA221FBA2612F0CFE56450E9B1F2C2AE278EC7A7AAB66D61FA9749FE997EDC31131091620897014D33B2386B490CFD80656B7D2EB08C9DA9928798986996D60F74D766EB8988E2FF676E38C587E7A6651AA28BEB8BB56EBBD6E641E92309AEAA671A5F2EC72629442D2C3A4C2B8E4304DC71B342CD116527832078E6B53C1E0A72909615B408E17625F7259ACA98E46359448FC141F57B51A069B8A402AE3A87E10AE7E910F3916BAC6CE716C539E825A06626673DE7EBD899A3982FCC599791E7CA964C0D37BB076708C03DC7C022980974025C0EA9B72CC3D0A03E4626E030E9C857ECF6B3807AC9E8E0F72098C7E80DAA05BFF60394A8374096878F015597DD5B22E65646A7DDC87B5F6AE68594DF39B0BDB2675A32369AD81FD62033146B8DA6A801E918572CBC70DEBA9F70D088D69425733ACE0084E60E7FCB459A5B71F74F711184B1AEA240834D28D049474BB2E7ED1B17AA2B5EB7D274341456834320BE8FB245B1C2B84A096E7E40573FEB7C2997ED16C8C2C62409B8064398ED220FA82C59E53AD7E864C24473FCC7F017B897D5855F092A9428957467EFD93F67D3FA302C578328A9484CD0496CC83BEAC96504F9601DA2048D25BF43B5A69E46234A164D854B89DF1DEDC36F0304BA5FC035B27E782087C3EC0A81840A3EC042204C63F9698CC74A818428039B23664C409529C4EDD822DF77819805023795EE625D524F12824C1F1FE99546DF75107AFFF7D424C4C3FB3D0BDA2E9BC0D93603457FFE44FABEAB1E6B62223B201D42784731BEE11E0FF0BF29C930DAF913F974739800522E2B9C4094475A5F35AA92E2939E5719EB4EE19446ADC9ECC7EE6BAB5D264C9E74AB6DE856D541146048341EB51734A34E33EF8D929F645E23FD902CB5676DA9C84C9F46490710DC8CF2AA922252C3885CBD8D0CB1D176CAFEB46A625C56BE949F487C6E35E2CE481F024C889B2F38EEF +20170713034622 2 6 100 8191 5 DDFBC1CD4FB7E30639422038F1FFBA2CD3EC3915F3C923282C6588F6EB218FF7B24870C0FE4B48213AB0948E101686FB7B0093ED467B6CA413EDD4B0BFE2155AEBC4DA3D2DD0C78DA9AD989A0E989010D6D5E86A123C169E126F97826EE5F602FF641FDF642A107E7538CB61740CBAF69F6C7DC5DD4DF28998AB61B8672F0B74A3A8DD7D165828D69DCC1BAE4D45F707C3894E040BCC0AF7AA810A6D5CB89276217EB7AFAFE4966D68C10318E8C8CB23CA593E8057F29FF9154908B11D6530E6352F9406C81D9DAC5C298979320B4E0DD89203A1F680C8084154D0439DB6C53EDAF6FCC0E8682EC99D345180120AEC810CBB0C2F1B6D1B660ACEAAD5996A5D184659B6A1F11456BA6A5E94D223959D8171C030499A9DB458702CB35CA7E7CD75D26FF5E94640AB8740ECE82559784BB6D5CB4D041D053629BD3F4178077F3F7E280296C46A3F0FBC37813A1AA221FBA2612F0CFE56450E9B1F2C2AE278EC7A7AAB66D61FA9749FE997EDC31131091620897014D33B2386B490CFD80656B7D2EB08C9DA9928798986996D60F74D766EB8988E2FF676E38C587E7A6651AA28BEB8BB56EBBD6E641E92309AEAA671A5F2EC72629442D2C3A4C2B8E4304DC71B342CD116527832078E6B53C1E0A72909615B408E17625F7259ACA98E46359448FC141F57B51A069B8A402AE3A87E10AE7E910F3916BAC6CE716C539E825A06626673DE7EBD899A3982FCC599791E7CA964C0D37BB076708C03DC7C022980974025C0EA9B72CC3D0A03E4626E030E9C857ECF6B3807AC9E8E0F72098C7E80DAA05BFF60394A8374096878F015597DD5B22E65646A7DDC87B5F6AE68594DF39B0BDB2675A32369AD81FD62033146B8DA6A801E918572CBC70DEBA9F70D088D69425733ACE0084E60E7FCB459A5B71F74F711184B1AEA240834D28D049474BB2E7ED1B17AA2B5EB7D274341456834320BE8FB245B1C2B84A096E7E40573FEB7C2997ED16C8C2C62409B8064398ED220FA82C59E53AD7E864C24473FCC7F017B897D5855F092A9428957467EFD93F67D3FA302C578328A9484CD0496CC83BEAC96504F9601DA2048D25BF43B5A69E46234A164D854B89DF1DEDC36F0304BA5FC035B27E782087C3EC0A81840A3EC042204C63F9698CC74A818428039B23664C409529C4EDD822DF77819805023795EE625D524F12824C1F1FE99546DF75107AFFF7D424C4C3FB3D0BDA2E9BC0D93603457FFE44FABEAB1E6B62223B201D42784731BEE11E0FF0BF29C930DAF913F974739800522E2B9C4094475A5F35AA92E2939E5719EB4EE19446ADC9ECC7EE6BAB5D264C9E74AB6DE856D541146048341EB51734A34E33EF8D929F645E23FD902CB5676DA9C84C9F46490710DC8CF2AA922252C3885CBD8D0CB1D176CAFEB46A625C56BE949F487C6E35E2CE481F024C889B2F6567F +20170713071216 2 6 100 8191 2 DDFBC1CD4FB7E30639422038F1FFBA2CD3EC3915F3C923282C6588F6EB218FF7B24870C0FE4B48213AB0948E101686FB7B0093ED467B6CA413EDD4B0BFE2155AEBC4DA3D2DD0C78DA9AD989A0E989010D6D5E86A123C169E126F97826EE5F602FF641FDF642A107E7538CB61740CBAF69F6C7DC5DD4DF28998AB61B8672F0B74A3A8DD7D165828D69DCC1BAE4D45F707C3894E040BCC0AF7AA810A6D5CB89276217EB7AFAFE4966D68C10318E8C8CB23CA593E8057F29FF9154908B11D6530E6352F9406C81D9DAC5C298979320B4E0DD89203A1F680C8084154D0439DB6C53EDAF6FCC0E8682EC99D345180120AEC810CBB0C2F1B6D1B660ACEAAD5996A5D184659B6A1F11456BA6A5E94D223959D8171C030499A9DB458702CB35CA7E7CD75D26FF5E94640AB8740ECE82559784BB6D5CB4D041D053629BD3F4178077F3F7E280296C46A3F0FBC37813A1AA221FBA2612F0CFE56450E9B1F2C2AE278EC7A7AAB66D61FA9749FE997EDC31131091620897014D33B2386B490CFD80656B7D2EB08C9DA9928798986996D60F74D766EB8988E2FF676E38C587E7A6651AA28BEB8BB56EBBD6E641E92309AEAA671A5F2EC72629442D2C3A4C2B8E4304DC71B342CD116527832078E6B53C1E0A72909615B408E17625F7259ACA98E46359448FC141F57B51A069B8A402AE3A87E10AE7E910F3916BAC6CE716C539E825A06626673DE7EBD899A3982FCC599791E7CA964C0D37BB076708C03DC7C022980974025C0EA9B72CC3D0A03E4626E030E9C857ECF6B3807AC9E8E0F72098C7E80DAA05BFF60394A8374096878F015597DD5B22E65646A7DDC87B5F6AE68594DF39B0BDB2675A32369AD81FD62033146B8DA6A801E918572CBC70DEBA9F70D088D69425733ACE0084E60E7FCB459A5B71F74F711184B1AEA240834D28D049474BB2E7ED1B17AA2B5EB7D274341456834320BE8FB245B1C2B84A096E7E40573FEB7C2997ED16C8C2C62409B8064398ED220FA82C59E53AD7E864C24473FCC7F017B897D5855F092A9428957467EFD93F67D3FA302C578328A9484CD0496CC83BEAC96504F9601DA2048D25BF43B5A69E46234A164D854B89DF1DEDC36F0304BA5FC035B27E782087C3EC0A81840A3EC042204C63F9698CC74A818428039B23664C409529C4EDD822DF77819805023795EE625D524F12824C1F1FE99546DF75107AFFF7D424C4C3FB3D0BDA2E9BC0D93603457FFE44FABEAB1E6B62223B201D42784731BEE11E0FF0BF29C930DAF913F974739800522E2B9C4094475A5F35AA92E2939E5719EB4EE19446ADC9ECC7EE6BAB5D264C9E74AB6DE856D541146048341EB51734A34E33EF8D929F645E23FD902CB5676DA9C84C9F46490710DC8CF2AA922252C3885CBD8D0CB1D176CAFEB46A625C56BE949F487C6E35E2CE481F024C889B55B411B +20170713222010 2 6 100 8191 2 DDFBC1CD4FB7E30639422038F1FFBA2CD3EC3915F3C923282C6588F6EB218FF7B24870C0FE4B48213AB0948E101686FB7B0093ED467B6CA413EDD4B0BFE2155AEBC4DA3D2DD0C78DA9AD989A0E989010D6D5E86A123C169E126F97826EE5F602FF641FDF642A107E7538CB61740CBAF69F6C7DC5DD4DF28998AB61B8672F0B74A3A8DD7D165828D69DCC1BAE4D45F707C3894E040BCC0AF7AA810A6D5CB89276217EB7AFAFE4966D68C10318E8C8CB23CA593E8057F29FF9154908B11D6530E6352F9406C81D9DAC5C298979320B4E0DD89203A1F680C8084154D0439DB6C53EDAF6FCC0E8682EC99D345180120AEC810CBB0C2F1B6D1B660ACEAAD5996A5D184659B6A1F11456BA6A5E94D223959D8171C030499A9DB458702CB35CA7E7CD75D26FF5E94640AB8740ECE82559784BB6D5CB4D041D053629BD3F4178077F3F7E280296C46A3F0FBC37813A1AA221FBA2612F0CFE56450E9B1F2C2AE278EC7A7AAB66D61FA9749FE997EDC31131091620897014D33B2386B490CFD80656B7D2EB08C9DA9928798986996D60F74D766EB8988E2FF676E38C587E7A6651AA28BEB8BB56EBBD6E641E92309AEAA671A5F2EC72629442D2C3A4C2B8E4304DC71B342CD116527832078E6B53C1E0A72909615B408E17625F7259ACA98E46359448FC141F57B51A069B8A402AE3A87E10AE7E910F3916BAC6CE716C539E825A06626673DE7EBD899A3982FCC599791E7CA964C0D37BB076708C03DC7C022980974025C0EA9B72CC3D0A03E4626E030E9C857ECF6B3807AC9E8E0F72098C7E80DAA05BFF60394A8374096878F015597DD5B22E65646A7DDC87B5F6AE68594DF39B0BDB2675A32369AD81FD62033146B8DA6A801E918572CBC70DEBA9F70D088D69425733ACE0084E60E7FCB459A5B71F74F711184B1AEA240834D28D049474BB2E7ED1B17AA2B5EB7D274341456834320BE8FB245B1C2B84A096E7E40573FEB7C2997ED16C8C2C62409B8064398ED220FA82C59E53AD7E864C24473FCC7F017B897D5855F092A9428957467EFD93F67D3FA302C578328A9484CD0496CC83BEAC96504F9601DA2048D25BF43B5A69E46234A164D854B89DF1DEDC36F0304BA5FC035B27E782087C3EC0A81840A3EC042204C63F9698CC74A818428039B23664C409529C4EDD822DF77819805023795EE625D524F12824C1F1FE99546DF75107AFFF7D424C4C3FB3D0BDA2E9BC0D93603457FFE44FABEAB1E6B62223B201D42784731BEE11E0FF0BF29C930DAF913F974739800522E2B9C4094475A5F35AA92E2939E5719EB4EE19446ADC9ECC7EE6BAB5D264C9E74AB6DE856D541146048341EB51734A34E33EF8D929F645E23FD902CB5676DA9C84C9F46490710DC8CF2AA922252C3885CBD8D0CB1D176CAFEB46A625C56BE949F487C6E35E2CE481F024C889BFD2C803 +20170714013005 2 6 100 8191 5 DDFBC1CD4FB7E30639422038F1FFBA2CD3EC3915F3C923282C6588F6EB218FF7B24870C0FE4B48213AB0948E101686FB7B0093ED467B6CA413EDD4B0BFE2155AEBC4DA3D2DD0C78DA9AD989A0E989010D6D5E86A123C169E126F97826EE5F602FF641FDF642A107E7538CB61740CBAF69F6C7DC5DD4DF28998AB61B8672F0B74A3A8DD7D165828D69DCC1BAE4D45F707C3894E040BCC0AF7AA810A6D5CB89276217EB7AFAFE4966D68C10318E8C8CB23CA593E8057F29FF9154908B11D6530E6352F9406C81D9DAC5C298979320B4E0DD89203A1F680C8084154D0439DB6C53EDAF6FCC0E8682EC99D345180120AEC810CBB0C2F1B6D1B660ACEAAD5996A5D184659B6A1F11456BA6A5E94D223959D8171C030499A9DB458702CB35CA7E7CD75D26FF5E94640AB8740ECE82559784BB6D5CB4D041D053629BD3F4178077F3F7E280296C46A3F0FBC37813A1AA221FBA2612F0CFE56450E9B1F2C2AE278EC7A7AAB66D61FA9749FE997EDC31131091620897014D33B2386B490CFD80656B7D2EB08C9DA9928798986996D60F74D766EB8988E2FF676E38C587E7A6651AA28BEB8BB56EBBD6E641E92309AEAA671A5F2EC72629442D2C3A4C2B8E4304DC71B342CD116527832078E6B53C1E0A72909615B408E17625F7259ACA98E46359448FC141F57B51A069B8A402AE3A87E10AE7E910F3916BAC6CE716C539E825A06626673DE7EBD899A3982FCC599791E7CA964C0D37BB076708C03DC7C022980974025C0EA9B72CC3D0A03E4626E030E9C857ECF6B3807AC9E8E0F72098C7E80DAA05BFF60394A8374096878F015597DD5B22E65646A7DDC87B5F6AE68594DF39B0BDB2675A32369AD81FD62033146B8DA6A801E918572CBC70DEBA9F70D088D69425733ACE0084E60E7FCB459A5B71F74F711184B1AEA240834D28D049474BB2E7ED1B17AA2B5EB7D274341456834320BE8FB245B1C2B84A096E7E40573FEB7C2997ED16C8C2C62409B8064398ED220FA82C59E53AD7E864C24473FCC7F017B897D5855F092A9428957467EFD93F67D3FA302C578328A9484CD0496CC83BEAC96504F9601DA2048D25BF43B5A69E46234A164D854B89DF1DEDC36F0304BA5FC035B27E782087C3EC0A81840A3EC042204C63F9698CC74A818428039B23664C409529C4EDD822DF77819805023795EE625D524F12824C1F1FE99546DF75107AFFF7D424C4C3FB3D0BDA2E9BC0D93603457FFE44FABEAB1E6B62223B201D42784731BEE11E0FF0BF29C930DAF913F974739800522E2B9C4094475A5F35AA92E2939E5719EB4EE19446ADC9ECC7EE6BAB5D264C9E74AB6DE856D541146048341EB51734A34E33EF8D929F645E23FD902CB5676DA9C84C9F46490710DC8CF2AA922252C3885CBD8D0CB1D176CAFEB46A625C56BE949F487C6E35E2CE481F024C889C1EF6397 +20170714094721 2 6 100 8191 2 DDFBC1CD4FB7E30639422038F1FFBA2CD3EC3915F3C923282C6588F6EB218FF7B24870C0FE4B48213AB0948E101686FB7B0093ED467B6CA413EDD4B0BFE2155AEBC4DA3D2DD0C78DA9AD989A0E989010D6D5E86A123C169E126F97826EE5F602FF641FDF642A107E7538CB61740CBAF69F6C7DC5DD4DF28998AB61B8672F0B74A3A8DD7D165828D69DCC1BAE4D45F707C3894E040BCC0AF7AA810A6D5CB89276217EB7AFAFE4966D68C10318E8C8CB23CA593E8057F29FF9154908B11D6530E6352F9406C81D9DAC5C298979320B4E0DD89203A1F680C8084154D0439DB6C53EDAF6FCC0E8682EC99D345180120AEC810CBB0C2F1B6D1B660ACEAAD5996A5D184659B6A1F11456BA6A5E94D223959D8171C030499A9DB458702CB35CA7E7CD75D26FF5E94640AB8740ECE82559784BB6D5CB4D041D053629BD3F4178077F3F7E280296C46A3F0FBC37813A1AA221FBA2612F0CFE56450E9B1F2C2AE278EC7A7AAB66D61FA9749FE997EDC31131091620897014D33B2386B490CFD80656B7D2EB08C9DA9928798986996D60F74D766EB8988E2FF676E38C587E7A6651AA28BEB8BB56EBBD6E641E92309AEAA671A5F2EC72629442D2C3A4C2B8E4304DC71B342CD116527832078E6B53C1E0A72909615B408E17625F7259ACA98E46359448FC141F57B51A069B8A402AE3A87E10AE7E910F3916BAC6CE716C539E825A06626673DE7EBD899A3982FCC599791E7CA964C0D37BB076708C03DC7C022980974025C0EA9B72CC3D0A03E4626E030E9C857ECF6B3807AC9E8E0F72098C7E80DAA05BFF60394A8374096878F015597DD5B22E65646A7DDC87B5F6AE68594DF39B0BDB2675A32369AD81FD62033146B8DA6A801E918572CBC70DEBA9F70D088D69425733ACE0084E60E7FCB459A5B71F74F711184B1AEA240834D28D049474BB2E7ED1B17AA2B5EB7D274341456834320BE8FB245B1C2B84A096E7E40573FEB7C2997ED16C8C2C62409B8064398ED220FA82C59E53AD7E864C24473FCC7F017B897D5855F092A9428957467EFD93F67D3FA302C578328A9484CD0496CC83BEAC96504F9601DA2048D25BF43B5A69E46234A164D854B89DF1DEDC36F0304BA5FC035B27E782087C3EC0A81840A3EC042204C63F9698CC74A818428039B23664C409529C4EDD822DF77819805023795EE625D524F12824C1F1FE99546DF75107AFFF7D424C4C3FB3D0BDA2E9BC0D93603457FFE44FABEAB1E6B62223B201D42784731BEE11E0FF0BF29C930DAF913F974739800522E2B9C4094475A5F35AA92E2939E5719EB4EE19446ADC9ECC7EE6BAB5D264C9E74AB6DE856D541146048341EB51734A34E33EF8D929F645E23FD902CB5676DA9C84C9F46490710DC8CF2AA922252C3885CBD8D0CB1D176CAFEB46A625C56BE949F487C6E35E2CE481F024C889C7A27293 +20170714141853 2 6 100 8191 5 DDFBC1CD4FB7E30639422038F1FFBA2CD3EC3915F3C923282C6588F6EB218FF7B24870C0FE4B48213AB0948E101686FB7B0093ED467B6CA413EDD4B0BFE2155AEBC4DA3D2DD0C78DA9AD989A0E989010D6D5E86A123C169E126F97826EE5F602FF641FDF642A107E7538CB61740CBAF69F6C7DC5DD4DF28998AB61B8672F0B74A3A8DD7D165828D69DCC1BAE4D45F707C3894E040BCC0AF7AA810A6D5CB89276217EB7AFAFE4966D68C10318E8C8CB23CA593E8057F29FF9154908B11D6530E6352F9406C81D9DAC5C298979320B4E0DD89203A1F680C8084154D0439DB6C53EDAF6FCC0E8682EC99D345180120AEC810CBB0C2F1B6D1B660ACEAAD5996A5D184659B6A1F11456BA6A5E94D223959D8171C030499A9DB458702CB35CA7E7CD75D26FF5E94640AB8740ECE82559784BB6D5CB4D041D053629BD3F4178077F3F7E280296C46A3F0FBC37813A1AA221FBA2612F0CFE56450E9B1F2C2AE278EC7A7AAB66D61FA9749FE997EDC31131091620897014D33B2386B490CFD80656B7D2EB08C9DA9928798986996D60F74D766EB8988E2FF676E38C587E7A6651AA28BEB8BB56EBBD6E641E92309AEAA671A5F2EC72629442D2C3A4C2B8E4304DC71B342CD116527832078E6B53C1E0A72909615B408E17625F7259ACA98E46359448FC141F57B51A069B8A402AE3A87E10AE7E910F3916BAC6CE716C539E825A06626673DE7EBD899A3982FCC599791E7CA964C0D37BB076708C03DC7C022980974025C0EA9B72CC3D0A03E4626E030E9C857ECF6B3807AC9E8E0F72098C7E80DAA05BFF60394A8374096878F015597DD5B22E65646A7DDC87B5F6AE68594DF39B0BDB2675A32369AD81FD62033146B8DA6A801E918572CBC70DEBA9F70D088D69425733ACE0084E60E7FCB459A5B71F74F711184B1AEA240834D28D049474BB2E7ED1B17AA2B5EB7D274341456834320BE8FB245B1C2B84A096E7E40573FEB7C2997ED16C8C2C62409B8064398ED220FA82C59E53AD7E864C24473FCC7F017B897D5855F092A9428957467EFD93F67D3FA302C578328A9484CD0496CC83BEAC96504F9601DA2048D25BF43B5A69E46234A164D854B89DF1DEDC36F0304BA5FC035B27E782087C3EC0A81840A3EC042204C63F9698CC74A818428039B23664C409529C4EDD822DF77819805023795EE625D524F12824C1F1FE99546DF75107AFFF7D424C4C3FB3D0BDA2E9BC0D93603457FFE44FABEAB1E6B62223B201D42784731BEE11E0FF0BF29C930DAF913F974739800522E2B9C4094475A5F35AA92E2939E5719EB4EE19446ADC9ECC7EE6BAB5D264C9E74AB6DE856D541146048341EB51734A34E33EF8D929F645E23FD902CB5676DA9C84C9F46490710DC8CF2AA922252C3885CBD8D0CB1D176CAFEB46A625C56BE949F487C6E35E2CE481F024C889CAA42B27 +20170714204505 2 6 100 8191 5 DDFBC1CD4FB7E30639422038F1FFBA2CD3EC3915F3C923282C6588F6EB218FF7B24870C0FE4B48213AB0948E101686FB7B0093ED467B6CA413EDD4B0BFE2155AEBC4DA3D2DD0C78DA9AD989A0E989010D6D5E86A123C169E126F97826EE5F602FF641FDF642A107E7538CB61740CBAF69F6C7DC5DD4DF28998AB61B8672F0B74A3A8DD7D165828D69DCC1BAE4D45F707C3894E040BCC0AF7AA810A6D5CB89276217EB7AFAFE4966D68C10318E8C8CB23CA593E8057F29FF9154908B11D6530E6352F9406C81D9DAC5C298979320B4E0DD89203A1F680C8084154D0439DB6C53EDAF6FCC0E8682EC99D345180120AEC810CBB0C2F1B6D1B660ACEAAD5996A5D184659B6A1F11456BA6A5E94D223959D8171C030499A9DB458702CB35CA7E7CD75D26FF5E94640AB8740ECE82559784BB6D5CB4D041D053629BD3F4178077F3F7E280296C46A3F0FBC37813A1AA221FBA2612F0CFE56450E9B1F2C2AE278EC7A7AAB66D61FA9749FE997EDC31131091620897014D33B2386B490CFD80656B7D2EB08C9DA9928798986996D60F74D766EB8988E2FF676E38C587E7A6651AA28BEB8BB56EBBD6E641E92309AEAA671A5F2EC72629442D2C3A4C2B8E4304DC71B342CD116527832078E6B53C1E0A72909615B408E17625F7259ACA98E46359448FC141F57B51A069B8A402AE3A87E10AE7E910F3916BAC6CE716C539E825A06626673DE7EBD899A3982FCC599791E7CA964C0D37BB076708C03DC7C022980974025C0EA9B72CC3D0A03E4626E030E9C857ECF6B3807AC9E8E0F72098C7E80DAA05BFF60394A8374096878F015597DD5B22E65646A7DDC87B5F6AE68594DF39B0BDB2675A32369AD81FD62033146B8DA6A801E918572CBC70DEBA9F70D088D69425733ACE0084E60E7FCB459A5B71F74F711184B1AEA240834D28D049474BB2E7ED1B17AA2B5EB7D274341456834320BE8FB245B1C2B84A096E7E40573FEB7C2997ED16C8C2C62409B8064398ED220FA82C59E53AD7E864C24473FCC7F017B897D5855F092A9428957467EFD93F67D3FA302C578328A9484CD0496CC83BEAC96504F9601DA2048D25BF43B5A69E46234A164D854B89DF1DEDC36F0304BA5FC035B27E782087C3EC0A81840A3EC042204C63F9698CC74A818428039B23664C409529C4EDD822DF77819805023795EE625D524F12824C1F1FE99546DF75107AFFF7D424C4C3FB3D0BDA2E9BC0D93603457FFE44FABEAB1E6B62223B201D42784731BEE11E0FF0BF29C930DAF913F974739800522E2B9C4094475A5F35AA92E2939E5719EB4EE19446ADC9ECC7EE6BAB5D264C9E74AB6DE856D541146048341EB51734A34E33EF8D929F645E23FD902CB5676DA9C84C9F46490710DC8CF2AA922252C3885CBD8D0CB1D176CAFEB46A625C56BE949F487C6E35E2CE481F024C889CEF31E77 +20170714205139 2 6 100 8191 2 DDFBC1CD4FB7E30639422038F1FFBA2CD3EC3915F3C923282C6588F6EB218FF7B24870C0FE4B48213AB0948E101686FB7B0093ED467B6CA413EDD4B0BFE2155AEBC4DA3D2DD0C78DA9AD989A0E989010D6D5E86A123C169E126F97826EE5F602FF641FDF642A107E7538CB61740CBAF69F6C7DC5DD4DF28998AB61B8672F0B74A3A8DD7D165828D69DCC1BAE4D45F707C3894E040BCC0AF7AA810A6D5CB89276217EB7AFAFE4966D68C10318E8C8CB23CA593E8057F29FF9154908B11D6530E6352F9406C81D9DAC5C298979320B4E0DD89203A1F680C8084154D0439DB6C53EDAF6FCC0E8682EC99D345180120AEC810CBB0C2F1B6D1B660ACEAAD5996A5D184659B6A1F11456BA6A5E94D223959D8171C030499A9DB458702CB35CA7E7CD75D26FF5E94640AB8740ECE82559784BB6D5CB4D041D053629BD3F4178077F3F7E280296C46A3F0FBC37813A1AA221FBA2612F0CFE56450E9B1F2C2AE278EC7A7AAB66D61FA9749FE997EDC31131091620897014D33B2386B490CFD80656B7D2EB08C9DA9928798986996D60F74D766EB8988E2FF676E38C587E7A6651AA28BEB8BB56EBBD6E641E92309AEAA671A5F2EC72629442D2C3A4C2B8E4304DC71B342CD116527832078E6B53C1E0A72909615B408E17625F7259ACA98E46359448FC141F57B51A069B8A402AE3A87E10AE7E910F3916BAC6CE716C539E825A06626673DE7EBD899A3982FCC599791E7CA964C0D37BB076708C03DC7C022980974025C0EA9B72CC3D0A03E4626E030E9C857ECF6B3807AC9E8E0F72098C7E80DAA05BFF60394A8374096878F015597DD5B22E65646A7DDC87B5F6AE68594DF39B0BDB2675A32369AD81FD62033146B8DA6A801E918572CBC70DEBA9F70D088D69425733ACE0084E60E7FCB459A5B71F74F711184B1AEA240834D28D049474BB2E7ED1B17AA2B5EB7D274341456834320BE8FB245B1C2B84A096E7E40573FEB7C2997ED16C8C2C62409B8064398ED220FA82C59E53AD7E864C24473FCC7F017B897D5855F092A9428957467EFD93F67D3FA302C578328A9484CD0496CC83BEAC96504F9601DA2048D25BF43B5A69E46234A164D854B89DF1DEDC36F0304BA5FC035B27E782087C3EC0A81840A3EC042204C63F9698CC74A818428039B23664C409529C4EDD822DF77819805023795EE625D524F12824C1F1FE99546DF75107AFFF7D424C4C3FB3D0BDA2E9BC0D93603457FFE44FABEAB1E6B62223B201D42784731BEE11E0FF0BF29C930DAF913F974739800522E2B9C4094475A5F35AA92E2939E5719EB4EE19446ADC9ECC7EE6BAB5D264C9E74AB6DE856D541146048341EB51734A34E33EF8D929F645E23FD902CB5676DA9C84C9F46490710DC8CF2AA922252C3885CBD8D0CB1D176CAFEB46A625C56BE949F487C6E35E2CE481F024C889CEFD860B +20170714214942 2 6 100 8191 2 DDFBC1CD4FB7E30639422038F1FFBA2CD3EC3915F3C923282C6588F6EB218FF7B24870C0FE4B48213AB0948E101686FB7B0093ED467B6CA413EDD4B0BFE2155AEBC4DA3D2DD0C78DA9AD989A0E989010D6D5E86A123C169E126F97826EE5F602FF641FDF642A107E7538CB61740CBAF69F6C7DC5DD4DF28998AB61B8672F0B74A3A8DD7D165828D69DCC1BAE4D45F707C3894E040BCC0AF7AA810A6D5CB89276217EB7AFAFE4966D68C10318E8C8CB23CA593E8057F29FF9154908B11D6530E6352F9406C81D9DAC5C298979320B4E0DD89203A1F680C8084154D0439DB6C53EDAF6FCC0E8682EC99D345180120AEC810CBB0C2F1B6D1B660ACEAAD5996A5D184659B6A1F11456BA6A5E94D223959D8171C030499A9DB458702CB35CA7E7CD75D26FF5E94640AB8740ECE82559784BB6D5CB4D041D053629BD3F4178077F3F7E280296C46A3F0FBC37813A1AA221FBA2612F0CFE56450E9B1F2C2AE278EC7A7AAB66D61FA9749FE997EDC31131091620897014D33B2386B490CFD80656B7D2EB08C9DA9928798986996D60F74D766EB8988E2FF676E38C587E7A6651AA28BEB8BB56EBBD6E641E92309AEAA671A5F2EC72629442D2C3A4C2B8E4304DC71B342CD116527832078E6B53C1E0A72909615B408E17625F7259ACA98E46359448FC141F57B51A069B8A402AE3A87E10AE7E910F3916BAC6CE716C539E825A06626673DE7EBD899A3982FCC599791E7CA964C0D37BB076708C03DC7C022980974025C0EA9B72CC3D0A03E4626E030E9C857ECF6B3807AC9E8E0F72098C7E80DAA05BFF60394A8374096878F015597DD5B22E65646A7DDC87B5F6AE68594DF39B0BDB2675A32369AD81FD62033146B8DA6A801E918572CBC70DEBA9F70D088D69425733ACE0084E60E7FCB459A5B71F74F711184B1AEA240834D28D049474BB2E7ED1B17AA2B5EB7D274341456834320BE8FB245B1C2B84A096E7E40573FEB7C2997ED16C8C2C62409B8064398ED220FA82C59E53AD7E864C24473FCC7F017B897D5855F092A9428957467EFD93F67D3FA302C578328A9484CD0496CC83BEAC96504F9601DA2048D25BF43B5A69E46234A164D854B89DF1DEDC36F0304BA5FC035B27E782087C3EC0A81840A3EC042204C63F9698CC74A818428039B23664C409529C4EDD822DF77819805023795EE625D524F12824C1F1FE99546DF75107AFFF7D424C4C3FB3D0BDA2E9BC0D93603457FFE44FABEAB1E6B62223B201D42784731BEE11E0FF0BF29C930DAF913F974739800522E2B9C4094475A5F35AA92E2939E5719EB4EE19446ADC9ECC7EE6BAB5D264C9E74AB6DE856D541146048341EB51734A34E33EF8D929F645E23FD902CB5676DA9C84C9F46490710DC8CF2AA922252C3885CBD8D0CB1D176CAFEB46A625C56BE949F487C6E35E2CE481F024C889CF9B7253 +20170714230801 2 6 100 8191 2 DDFBC1CD4FB7E30639422038F1FFBA2CD3EC3915F3C923282C6588F6EB218FF7B24870C0FE4B48213AB0948E101686FB7B0093ED467B6CA413EDD4B0BFE2155AEBC4DA3D2DD0C78DA9AD989A0E989010D6D5E86A123C169E126F97826EE5F602FF641FDF642A107E7538CB61740CBAF69F6C7DC5DD4DF28998AB61B8672F0B74A3A8DD7D165828D69DCC1BAE4D45F707C3894E040BCC0AF7AA810A6D5CB89276217EB7AFAFE4966D68C10318E8C8CB23CA593E8057F29FF9154908B11D6530E6352F9406C81D9DAC5C298979320B4E0DD89203A1F680C8084154D0439DB6C53EDAF6FCC0E8682EC99D345180120AEC810CBB0C2F1B6D1B660ACEAAD5996A5D184659B6A1F11456BA6A5E94D223959D8171C030499A9DB458702CB35CA7E7CD75D26FF5E94640AB8740ECE82559784BB6D5CB4D041D053629BD3F4178077F3F7E280296C46A3F0FBC37813A1AA221FBA2612F0CFE56450E9B1F2C2AE278EC7A7AAB66D61FA9749FE997EDC31131091620897014D33B2386B490CFD80656B7D2EB08C9DA9928798986996D60F74D766EB8988E2FF676E38C587E7A6651AA28BEB8BB56EBBD6E641E92309AEAA671A5F2EC72629442D2C3A4C2B8E4304DC71B342CD116527832078E6B53C1E0A72909615B408E17625F7259ACA98E46359448FC141F57B51A069B8A402AE3A87E10AE7E910F3916BAC6CE716C539E825A06626673DE7EBD899A3982FCC599791E7CA964C0D37BB076708C03DC7C022980974025C0EA9B72CC3D0A03E4626E030E9C857ECF6B3807AC9E8E0F72098C7E80DAA05BFF60394A8374096878F015597DD5B22E65646A7DDC87B5F6AE68594DF39B0BDB2675A32369AD81FD62033146B8DA6A801E918572CBC70DEBA9F70D088D69425733ACE0084E60E7FCB459A5B71F74F711184B1AEA240834D28D049474BB2E7ED1B17AA2B5EB7D274341456834320BE8FB245B1C2B84A096E7E40573FEB7C2997ED16C8C2C62409B8064398ED220FA82C59E53AD7E864C24473FCC7F017B897D5855F092A9428957467EFD93F67D3FA302C578328A9484CD0496CC83BEAC96504F9601DA2048D25BF43B5A69E46234A164D854B89DF1DEDC36F0304BA5FC035B27E782087C3EC0A81840A3EC042204C63F9698CC74A818428039B23664C409529C4EDD822DF77819805023795EE625D524F12824C1F1FE99546DF75107AFFF7D424C4C3FB3D0BDA2E9BC0D93603457FFE44FABEAB1E6B62223B201D42784731BEE11E0FF0BF29C930DAF913F974739800522E2B9C4094475A5F35AA92E2939E5719EB4EE19446ADC9ECC7EE6BAB5D264C9E74AB6DE856D541146048341EB51734A34E33EF8D929F645E23FD902CB5676DA9C84C9F46490710DC8CF2AA922252C3885CBD8D0CB1D176CAFEB46A625C56BE949F487C6E35E2CE481F024C889D071D153 +20170715054028 2 6 100 8191 5 DDFBC1CD4FB7E30639422038F1FFBA2CD3EC3915F3C923282C6588F6EB218FF7B24870C0FE4B48213AB0948E101686FB7B0093ED467B6CA413EDD4B0BFE2155AEBC4DA3D2DD0C78DA9AD989A0E989010D6D5E86A123C169E126F97826EE5F602FF641FDF642A107E7538CB61740CBAF69F6C7DC5DD4DF28998AB61B8672F0B74A3A8DD7D165828D69DCC1BAE4D45F707C3894E040BCC0AF7AA810A6D5CB89276217EB7AFAFE4966D68C10318E8C8CB23CA593E8057F29FF9154908B11D6530E6352F9406C81D9DAC5C298979320B4E0DD89203A1F680C8084154D0439DB6C53EDAF6FCC0E8682EC99D345180120AEC810CBB0C2F1B6D1B660ACEAAD5996A5D184659B6A1F11456BA6A5E94D223959D8171C030499A9DB458702CB35CA7E7CD75D26FF5E94640AB8740ECE82559784BB6D5CB4D041D053629BD3F4178077F3F7E280296C46A3F0FBC37813A1AA221FBA2612F0CFE56450E9B1F2C2AE278EC7A7AAB66D61FA9749FE997EDC31131091620897014D33B2386B490CFD80656B7D2EB08C9DA9928798986996D60F74D766EB8988E2FF676E38C587E7A6651AA28BEB8BB56EBBD6E641E92309AEAA671A5F2EC72629442D2C3A4C2B8E4304DC71B342CD116527832078E6B53C1E0A72909615B408E17625F7259ACA98E46359448FC141F57B51A069B8A402AE3A87E10AE7E910F3916BAC6CE716C539E825A06626673DE7EBD899A3982FCC599791E7CA964C0D37BB076708C03DC7C022980974025C0EA9B72CC3D0A03E4626E030E9C857ECF6B3807AC9E8E0F72098C7E80DAA05BFF60394A8374096878F015597DD5B22E65646A7DDC87B5F6AE68594DF39B0BDB2675A32369AD81FD62033146B8DA6A801E918572CBC70DEBA9F70D088D69425733ACE0084E60E7FCB459A5B71F74F711184B1AEA240834D28D049474BB2E7ED1B17AA2B5EB7D274341456834320BE8FB245B1C2B84A096E7E40573FEB7C2997ED16C8C2C62409B8064398ED220FA82C59E53AD7E864C24473FCC7F017B897D5855F092A9428957467EFD93F67D3FA302C578328A9484CD0496CC83BEAC96504F9601DA2048D25BF43B5A69E46234A164D854B89DF1DEDC36F0304BA5FC035B27E782087C3EC0A81840A3EC042204C63F9698CC74A818428039B23664C409529C4EDD822DF77819805023795EE625D524F12824C1F1FE99546DF75107AFFF7D424C4C3FB3D0BDA2E9BC0D93603457FFE44FABEAB1E6B62223B201D42784731BEE11E0FF0BF29C930DAF913F974739800522E2B9C4094475A5F35AA92E2939E5719EB4EE19446ADC9ECC7EE6BAB5D264C9E74AB6DE856D541146048341EB51734A34E33EF8D929F645E23FD902CB5676DA9C84C9F46490710DC8CF2AA922252C3885CBD8D0CB1D176CAFEB46A625C56BE949F487C6E35E2CE481F024C889D4C6B33F +20170715152910 2 6 100 8191 2 DDFBC1CD4FB7E30639422038F1FFBA2CD3EC3915F3C923282C6588F6EB218FF7B24870C0FE4B48213AB0948E101686FB7B0093ED467B6CA413EDD4B0BFE2155AEBC4DA3D2DD0C78DA9AD989A0E989010D6D5E86A123C169E126F97826EE5F602FF641FDF642A107E7538CB61740CBAF69F6C7DC5DD4DF28998AB61B8672F0B74A3A8DD7D165828D69DCC1BAE4D45F707C3894E040BCC0AF7AA810A6D5CB89276217EB7AFAFE4966D68C10318E8C8CB23CA593E8057F29FF9154908B11D6530E6352F9406C81D9DAC5C298979320B4E0DD89203A1F680C8084154D0439DB6C53EDAF6FCC0E8682EC99D345180120AEC810CBB0C2F1B6D1B660ACEAAD5996A5D184659B6A1F11456BA6A5E94D223959D8171C030499A9DB458702CB35CA7E7CD75D26FF5E94640AB8740ECE82559784BB6D5CB4D041D053629BD3F4178077F3F7E280296C46A3F0FBC37813A1AA221FBA2612F0CFE56450E9B1F2C2AE278EC7A7AAB66D61FA9749FE997EDC31131091620897014D33B2386B490CFD80656B7D2EB08C9DA9928798986996D60F74D766EB8988E2FF676E38C587E7A6651AA28BEB8BB56EBBD6E641E92309AEAA671A5F2EC72629442D2C3A4C2B8E4304DC71B342CD116527832078E6B53C1E0A72909615B408E17625F7259ACA98E46359448FC141F57B51A069B8A402AE3A87E10AE7E910F3916BAC6CE716C539E825A06626673DE7EBD899A3982FCC599791E7CA964C0D37BB076708C03DC7C022980974025C0EA9B72CC3D0A03E4626E030E9C857ECF6B3807AC9E8E0F72098C7E80DAA05BFF60394A8374096878F015597DD5B22E65646A7DDC87B5F6AE68594DF39B0BDB2675A32369AD81FD62033146B8DA6A801E918572CBC70DEBA9F70D088D69425733ACE0084E60E7FCB459A5B71F74F711184B1AEA240834D28D049474BB2E7ED1B17AA2B5EB7D274341456834320BE8FB245B1C2B84A096E7E40573FEB7C2997ED16C8C2C62409B8064398ED220FA82C59E53AD7E864C24473FCC7F017B897D5855F092A9428957467EFD93F67D3FA302C578328A9484CD0496CC83BEAC96504F9601DA2048D25BF43B5A69E46234A164D854B89DF1DEDC36F0304BA5FC035B27E782087C3EC0A81840A3EC042204C63F9698CC74A818428039B23664C409529C4EDD822DF77819805023795EE625D524F12824C1F1FE99546DF75107AFFF7D424C4C3FB3D0BDA2E9BC0D93603457FFE44FABEAB1E6B62223B201D42784731BEE11E0FF0BF29C930DAF913F974739800522E2B9C4094475A5F35AA92E2939E5719EB4EE19446ADC9ECC7EE6BAB5D264C9E74AB6DE856D541146048341EB51734A34E33EF8D929F645E23FD902CB5676DA9C84C9F46490710DC8CF2AA922252C3885CBD8D0CB1D176CAFEB46A625C56BE949F487C6E35E2CE481F024C889DB4248D3 +20170715213011 2 6 100 8191 2 DDFBC1CD4FB7E30639422038F1FFBA2CD3EC3915F3C923282C6588F6EB218FF7B24870C0FE4B48213AB0948E101686FB7B0093ED467B6CA413EDD4B0BFE2155AEBC4DA3D2DD0C78DA9AD989A0E989010D6D5E86A123C169E126F97826EE5F602FF641FDF642A107E7538CB61740CBAF69F6C7DC5DD4DF28998AB61B8672F0B74A3A8DD7D165828D69DCC1BAE4D45F707C3894E040BCC0AF7AA810A6D5CB89276217EB7AFAFE4966D68C10318E8C8CB23CA593E8057F29FF9154908B11D6530E6352F9406C81D9DAC5C298979320B4E0DD89203A1F680C8084154D0439DB6C53EDAF6FCC0E8682EC99D345180120AEC810CBB0C2F1B6D1B660ACEAAD5996A5D184659B6A1F11456BA6A5E94D223959D8171C030499A9DB458702CB35CA7E7CD75D26FF5E94640AB8740ECE82559784BB6D5CB4D041D053629BD3F4178077F3F7E280296C46A3F0FBC37813A1AA221FBA2612F0CFE56450E9B1F2C2AE278EC7A7AAB66D61FA9749FE997EDC31131091620897014D33B2386B490CFD80656B7D2EB08C9DA9928798986996D60F74D766EB8988E2FF676E38C587E7A6651AA28BEB8BB56EBBD6E641E92309AEAA671A5F2EC72629442D2C3A4C2B8E4304DC71B342CD116527832078E6B53C1E0A72909615B408E17625F7259ACA98E46359448FC141F57B51A069B8A402AE3A87E10AE7E910F3916BAC6CE716C539E825A06626673DE7EBD899A3982FCC599791E7CA964C0D37BB076708C03DC7C022980974025C0EA9B72CC3D0A03E4626E030E9C857ECF6B3807AC9E8E0F72098C7E80DAA05BFF60394A8374096878F015597DD5B22E65646A7DDC87B5F6AE68594DF39B0BDB2675A32369AD81FD62033146B8DA6A801E918572CBC70DEBA9F70D088D69425733ACE0084E60E7FCB459A5B71F74F711184B1AEA240834D28D049474BB2E7ED1B17AA2B5EB7D274341456834320BE8FB245B1C2B84A096E7E40573FEB7C2997ED16C8C2C62409B8064398ED220FA82C59E53AD7E864C24473FCC7F017B897D5855F092A9428957467EFD93F67D3FA302C578328A9484CD0496CC83BEAC96504F9601DA2048D25BF43B5A69E46234A164D854B89DF1DEDC36F0304BA5FC035B27E782087C3EC0A81840A3EC042204C63F9698CC74A818428039B23664C409529C4EDD822DF77819805023795EE625D524F12824C1F1FE99546DF75107AFFF7D424C4C3FB3D0BDA2E9BC0D93603457FFE44FABEAB1E6B62223B201D42784731BEE11E0FF0BF29C930DAF913F974739800522E2B9C4094475A5F35AA92E2939E5719EB4EE19446ADC9ECC7EE6BAB5D264C9E74AB6DE856D541146048341EB51734A34E33EF8D929F645E23FD902CB5676DA9C84C9F46490710DC8CF2AA922252C3885CBD8D0CB1D176CAFEB46A625C56BE949F487C6E35E2CE481F024C889DF38680B +20170716095854 2 6 100 8191 5 DDFBC1CD4FB7E30639422038F1FFBA2CD3EC3915F3C923282C6588F6EB218FF7B24870C0FE4B48213AB0948E101686FB7B0093ED467B6CA413EDD4B0BFE2155AEBC4DA3D2DD0C78DA9AD989A0E989010D6D5E86A123C169E126F97826EE5F602FF641FDF642A107E7538CB61740CBAF69F6C7DC5DD4DF28998AB61B8672F0B74A3A8DD7D165828D69DCC1BAE4D45F707C3894E040BCC0AF7AA810A6D5CB89276217EB7AFAFE4966D68C10318E8C8CB23CA593E8057F29FF9154908B11D6530E6352F9406C81D9DAC5C298979320B4E0DD89203A1F680C8084154D0439DB6C53EDAF6FCC0E8682EC99D345180120AEC810CBB0C2F1B6D1B660ACEAAD5996A5D184659B6A1F11456BA6A5E94D223959D8171C030499A9DB458702CB35CA7E7CD75D26FF5E94640AB8740ECE82559784BB6D5CB4D041D053629BD3F4178077F3F7E280296C46A3F0FBC37813A1AA221FBA2612F0CFE56450E9B1F2C2AE278EC7A7AAB66D61FA9749FE997EDC31131091620897014D33B2386B490CFD80656B7D2EB08C9DA9928798986996D60F74D766EB8988E2FF676E38C587E7A6651AA28BEB8BB56EBBD6E641E92309AEAA671A5F2EC72629442D2C3A4C2B8E4304DC71B342CD116527832078E6B53C1E0A72909615B408E17625F7259ACA98E46359448FC141F57B51A069B8A402AE3A87E10AE7E910F3916BAC6CE716C539E825A06626673DE7EBD899A3982FCC599791E7CA964C0D37BB076708C03DC7C022980974025C0EA9B72CC3D0A03E4626E030E9C857ECF6B3807AC9E8E0F72098C7E80DAA05BFF60394A8374096878F015597DD5B22E65646A7DDC87B5F6AE68594DF39B0BDB2675A32369AD81FD62033146B8DA6A801E918572CBC70DEBA9F70D088D69425733ACE0084E60E7FCB459A5B71F74F711184B1AEA240834D28D049474BB2E7ED1B17AA2B5EB7D274341456834320BE8FB245B1C2B84A096E7E40573FEB7C2997ED16C8C2C62409B8064398ED220FA82C59E53AD7E864C24473FCC7F017B897D5855F092A9428957467EFD93F67D3FA302C578328A9484CD0496CC83BEAC96504F9601DA2048D25BF43B5A69E46234A164D854B89DF1DEDC36F0304BA5FC035B27E782087C3EC0A81840A3EC042204C63F9698CC74A818428039B23664C409529C4EDD822DF77819805023795EE625D524F12824C1F1FE99546DF75107AFFF7D424C4C3FB3D0BDA2E9BC0D93603457FFE44FABEAB1E6B62223B201D42784731BEE11E0FF0BF29C930DAF913F974739800522E2B9C4094475A5F35AA92E2939E5719EB4EE19446ADC9ECC7EE6BAB5D264C9E74AB6DE856D541146048341EB51734A34E33EF8D929F645E23FD902CB5676DA9C84C9F46490710DC8CF2AA922252C3885CBD8D0CB1D176CAFEB46A625C56BE949F487C6E35E2CE481F024C889E75F9737 +20170716115603 2 6 100 8191 5 DDFBC1CD4FB7E30639422038F1FFBA2CD3EC3915F3C923282C6588F6EB218FF7B24870C0FE4B48213AB0948E101686FB7B0093ED467B6CA413EDD4B0BFE2155AEBC4DA3D2DD0C78DA9AD989A0E989010D6D5E86A123C169E126F97826EE5F602FF641FDF642A107E7538CB61740CBAF69F6C7DC5DD4DF28998AB61B8672F0B74A3A8DD7D165828D69DCC1BAE4D45F707C3894E040BCC0AF7AA810A6D5CB89276217EB7AFAFE4966D68C10318E8C8CB23CA593E8057F29FF9154908B11D6530E6352F9406C81D9DAC5C298979320B4E0DD89203A1F680C8084154D0439DB6C53EDAF6FCC0E8682EC99D345180120AEC810CBB0C2F1B6D1B660ACEAAD5996A5D184659B6A1F11456BA6A5E94D223959D8171C030499A9DB458702CB35CA7E7CD75D26FF5E94640AB8740ECE82559784BB6D5CB4D041D053629BD3F4178077F3F7E280296C46A3F0FBC37813A1AA221FBA2612F0CFE56450E9B1F2C2AE278EC7A7AAB66D61FA9749FE997EDC31131091620897014D33B2386B490CFD80656B7D2EB08C9DA9928798986996D60F74D766EB8988E2FF676E38C587E7A6651AA28BEB8BB56EBBD6E641E92309AEAA671A5F2EC72629442D2C3A4C2B8E4304DC71B342CD116527832078E6B53C1E0A72909615B408E17625F7259ACA98E46359448FC141F57B51A069B8A402AE3A87E10AE7E910F3916BAC6CE716C539E825A06626673DE7EBD899A3982FCC599791E7CA964C0D37BB076708C03DC7C022980974025C0EA9B72CC3D0A03E4626E030E9C857ECF6B3807AC9E8E0F72098C7E80DAA05BFF60394A8374096878F015597DD5B22E65646A7DDC87B5F6AE68594DF39B0BDB2675A32369AD81FD62033146B8DA6A801E918572CBC70DEBA9F70D088D69425733ACE0084E60E7FCB459A5B71F74F711184B1AEA240834D28D049474BB2E7ED1B17AA2B5EB7D274341456834320BE8FB245B1C2B84A096E7E40573FEB7C2997ED16C8C2C62409B8064398ED220FA82C59E53AD7E864C24473FCC7F017B897D5855F092A9428957467EFD93F67D3FA302C578328A9484CD0496CC83BEAC96504F9601DA2048D25BF43B5A69E46234A164D854B89DF1DEDC36F0304BA5FC035B27E782087C3EC0A81840A3EC042204C63F9698CC74A818428039B23664C409529C4EDD822DF77819805023795EE625D524F12824C1F1FE99546DF75107AFFF7D424C4C3FB3D0BDA2E9BC0D93603457FFE44FABEAB1E6B62223B201D42784731BEE11E0FF0BF29C930DAF913F974739800522E2B9C4094475A5F35AA92E2939E5719EB4EE19446ADC9ECC7EE6BAB5D264C9E74AB6DE856D541146048341EB51734A34E33EF8D929F645E23FD902CB5676DA9C84C9F46490710DC8CF2AA922252C3885CBD8D0CB1D176CAFEB46A625C56BE949F487C6E35E2CE481F024C889E896321F +20170717072754 2 6 100 8191 5 DDFBC1CD4FB7E30639422038F1FFBA2CD3EC3915F3C923282C6588F6EB218FF7B24870C0FE4B48213AB0948E101686FB7B0093ED467B6CA413EDD4B0BFE2155AEBC4DA3D2DD0C78DA9AD989A0E989010D6D5E86A123C169E126F97826EE5F602FF641FDF642A107E7538CB61740CBAF69F6C7DC5DD4DF28998AB61B8672F0B74A3A8DD7D165828D69DCC1BAE4D45F707C3894E040BCC0AF7AA810A6D5CB89276217EB7AFAFE4966D68C10318E8C8CB23CA593E8057F29FF9154908B11D6530E6352F9406C81D9DAC5C298979320B4E0DD89203A1F680C8084154D0439DB6C53EDAF6FCC0E8682EC99D345180120AEC810CBB0C2F1B6D1B660ACEAAD5996A5D184659B6A1F11456BA6A5E94D223959D8171C030499A9DB458702CB35CA7E7CD75D26FF5E94640AB8740ECE82559784BB6D5CB4D041D053629BD3F4178077F3F7E280296C46A3F0FBC37813A1AA221FBA2612F0CFE56450E9B1F2C2AE278EC7A7AAB66D61FA9749FE997EDC31131091620897014D33B2386B490CFD80656B7D2EB08C9DA9928798986996D60F74D766EB8988E2FF676E38C587E7A6651AA28BEB8BB56EBBD6E641E92309AEAA671A5F2EC72629442D2C3A4C2B8E4304DC71B342CD116527832078E6B53C1E0A72909615B408E17625F7259ACA98E46359448FC141F57B51A069B8A402AE3A87E10AE7E910F3916BAC6CE716C539E825A06626673DE7EBD899A3982FCC599791E7CA964C0D37BB076708C03DC7C022980974025C0EA9B72CC3D0A03E4626E030E9C857ECF6B3807AC9E8E0F72098C7E80DAA05BFF60394A8374096878F015597DD5B22E65646A7DDC87B5F6AE68594DF39B0BDB2675A32369AD81FD62033146B8DA6A801E918572CBC70DEBA9F70D088D69425733ACE0084E60E7FCB459A5B71F74F711184B1AEA240834D28D049474BB2E7ED1B17AA2B5EB7D274341456834320BE8FB245B1C2B84A096E7E40573FEB7C2997ED16C8C2C62409B8064398ED220FA82C59E53AD7E864C24473FCC7F017B897D5855F092A9428957467EFD93F67D3FA302C578328A9484CD0496CC83BEAC96504F9601DA2048D25BF43B5A69E46234A164D854B89DF1DEDC36F0304BA5FC035B27E782087C3EC0A81840A3EC042204C63F9698CC74A818428039B23664C409529C4EDD822DF77819805023795EE625D524F12824C1F1FE99546DF75107AFFF7D424C4C3FB3D0BDA2E9BC0D93603457FFE44FABEAB1E6B62223B201D42784731BEE11E0FF0BF29C930DAF913F974739800522E2B9C4094475A5F35AA92E2939E5719EB4EE19446ADC9ECC7EE6BAB5D264C9E74AB6DE856D541146048341EB51734A34E33EF8D929F645E23FD902CB5676DA9C84C9F46490710DC8CF2AA922252C3885CBD8D0CB1D176CAFEB46A625C56BE949F487C6E35E2CE481F024C889F528B29F +20170718103850 2 6 100 8191 5 DDFBC1CD4FB7E30639422038F1FFBA2CD3EC3915F3C923282C6588F6EB218FF7B24870C0FE4B48213AB0948E101686FB7B0093ED467B6CA413EDD4B0BFE2155AEBC4DA3D2DD0C78DA9AD989A0E989010D6D5E86A123C169E126F97826EE5F602FF641FDF642A107E7538CB61740CBAF69F6C7DC5DD4DF28998AB61B8672F0B74A3A8DD7D165828D69DCC1BAE4D45F707C3894E040BCC0AF7AA810A6D5CB89276217EB7AFAFE4966D68C10318E8C8CB23CA593E8057F29FF9154908B11D6530E6352F9406C81D9DAC5C298979320B4E0DD89203A1F680C8084154D0439DB6C53EDAF6FCC0E8682EC99D345180120AEC810CBB0C2F1B6D1B660ACEAAD5996A5D184659B6A1F11456BA6A5E94D223959D8171C030499A9DB458702CB35CA7E7CD75D26FF5E94640AB8740ECE82559784BB6D5CB4D041D053629BD3F4178077F3F7E280296C46A3F0FBC37813A1AA221FBA2612F0CFE56450E9B1F2C2AE278EC7A7AAB66D61FA9749FE997EDC31131091620897014D33B2386B490CFD80656B7D2EB08C9DA9928798986996D60F74D766EB8988E2FF676E38C587E7A6651AA28BEB8BB56EBBD6E641E92309AEAA671A5F2EC72629442D2C3A4C2B8E4304DC71B342CD116527832078E6B53C1E0A72909615B408E17625F7259ACA98E46359448FC141F57B51A069B8A402AE3A87E10AE7E910F3916BAC6CE716C539E825A06626673DE7EBD899A3982FCC599791E7CA964C0D37BB076708C03DC7C022980974025C0EA9B72CC3D0A03E4626E030E9C857ECF6B3807AC9E8E0F72098C7E80DAA05BFF60394A8374096878F015597DD5B22E65646A7DDC87B5F6AE68594DF39B0BDB2675A32369AD81FD62033146B8DA6A801E918572CBC70DEBA9F70D088D69425733ACE0084E60E7FCB459A5B71F74F711184B1AEA240834D28D049474BB2E7ED1B17AA2B5EB7D274341456834320BE8FB245B1C2B84A096E7E40573FEB7C2997ED16C8C2C62409B8064398ED220FA82C59E53AD7E864C24473FCC7F017B897D5855F092A9428957467EFD93F67D3FA302C578328A9484CD0496CC83BEAC96504F9601DA2048D25BF43B5A69E46234A164D854B89DF1DEDC36F0304BA5FC035B27E782087C3EC0A81840A3EC042204C63F9698CC74A818428039B23664C409529C4EDD822DF77819805023795EE625D524F12824C1F1FE99546DF75107AFFF7D424C4C3FB3D0BDA2E9BC0D93603457FFE44FABEAB1E6B62223B201D42784731BEE11E0FF0BF29C930DAF913F974739800522E2B9C4094475A5F35AA92E2939E5719EB4EE19446ADC9ECC7EE6BAB5D264C9E74AB6DE856D541146048341EB51734A34E33EF8D929F645E23FD902CB5676DA9C84C9F46490710DC8CF2AA922252C3885CBD8D0CB1D176CAFEB46A625C56BE949F487C6E35E2CE481F024C889FB304F4F +20170718123146 2 6 100 8191 5 DDFBC1CD4FB7E30639422038F1FFBA2CD3EC3915F3C923282C6588F6EB218FF7B24870C0FE4B48213AB0948E101686FB7B0093ED467B6CA413EDD4B0BFE2155AEBC4DA3D2DD0C78DA9AD989A0E989010D6D5E86A123C169E126F97826EE5F602FF641FDF642A107E7538CB61740CBAF69F6C7DC5DD4DF28998AB61B8672F0B74A3A8DD7D165828D69DCC1BAE4D45F707C3894E040BCC0AF7AA810A6D5CB89276217EB7AFAFE4966D68C10318E8C8CB23CA593E8057F29FF9154908B11D6530E6352F9406C81D9DAC5C298979320B4E0DD89203A1F680C8084154D0439DB6C53EDAF6FCC0E8682EC99D345180120AEC810CBB0C2F1B6D1B660ACEAAD5996A5D184659B6A1F11456BA6A5E94D223959D8171C030499A9DB458702CB35CA7E7CD75D26FF5E94640AB8740ECE82559784BB6D5CB4D041D053629BD3F4178077F3F7E280296C46A3F0FBC37813A1AA221FBA2612F0CFE56450E9B1F2C2AE278EC7A7AAB66D61FA9749FE997EDC31131091620897014D33B2386B490CFD80656B7D2EB08C9DA9928798986996D60F74D766EB8988E2FF676E38C587E7A6651AA28BEB8BB56EBBD6E641E92309AEAA671A5F2EC72629442D2C3A4C2B8E4304DC71B342CD116527832078E6B53C1E0A72909615B408E17625F7259ACA98E46359448FC141F57B51A069B8A402AE3A87E10AE7E910F3916BAC6CE716C539E825A06626673DE7EBD899A3982FCC599791E7CA964C0D37BB076708C03DC7C022980974025C0EA9B72CC3D0A03E4626E030E9C857ECF6B3807AC9E8E0F72098C7E80DAA05BFF60394A8374096878F015597DD5B22E65646A7DDC87B5F6AE68594DF39B0BDB2675A32369AD81FD62033146B8DA6A801E918572CBC70DEBA9F70D088D69425733ACE0084E60E7FCB459A5B71F74F711184B1AEA240834D28D049474BB2E7ED1B17AA2B5EB7D274341456834320BE8FB245B1C2B84A096E7E40573FEB7C2997ED16C8C2C62409B8064398ED220FA82C59E53AD7E864C24473FCC7F017B897D5855F092A9428957467EFD93F67D3FA302C578328A9484CD0496CC83BEAC96504F9601DA2048D25BF43B5A69E46234A164D854B89DF1DEDC36F0304BA5FC035B27E782087C3EC0A81840A3EC042204C63F9698CC74A818428039B23664C409529C4EDD822DF77819805023795EE625D524F12824C1F1FE99546DF75107AFFF7D424C4C3FB3D0BDA2E9BC0D93603457FFE44FABEAB1E6B62223B201D42784731BEE11E0FF0BF29C930DAF913F974739800522E2B9C4094475A5F35AA92E2939E5719EB4EE19446ADC9ECC7EE6BAB5D264C9E74AB6DE856D541146048341EB51734A34E33EF8D929F645E23FD902CB5676DA9C84C9F46490710DC8CF2AA922252C3885CBD8D0CB1D176CAFEB46A625C56BE949F487C6E35E2CE481F024C889FC58729F +20170718203220 2 6 100 8191 2 DDFBC1CD4FB7E30639422038F1FFBA2CD3EC3915F3C923282C6588F6EB218FF7B24870C0FE4B48213AB0948E101686FB7B0093ED467B6CA413EDD4B0BFE2155AEBC4DA3D2DD0C78DA9AD989A0E989010D6D5E86A123C169E126F97826EE5F602FF641FDF642A107E7538CB61740CBAF69F6C7DC5DD4DF28998AB61B8672F0B74A3A8DD7D165828D69DCC1BAE4D45F707C3894E040BCC0AF7AA810A6D5CB89276217EB7AFAFE4966D68C10318E8C8CB23CA593E8057F29FF9154908B11D6530E6352F9406C81D9DAC5C298979320B4E0DD89203A1F680C8084154D0439DB6C53EDAF6FCC0E8682EC99D345180120AEC810CBB0C2F1B6D1B660ACEAAD5996A5D184659B6A1F11456BA6A5E94D223959D8171C030499A9DB458702CB35CA7E7CD75D26FF5E94640AB8740ECE82559784BB6D5CB4D041D053629BD3F4178077F3F7E280296C46A3F0FBC37813A1AA221FBA2612F0CFE56450E9B1F2C2AE278EC7A7AAB66D61FA9749FE997EDC31131091620897014D33B2386B490CFD80656B7D2EB08C9DA9928798986996D60F74D766EB8988E2FF676E38C587E7A6651AA28BEB8BB56EBBD6E641E92309AEAA671A5F2EC72629442D2C3A4C2B8E4304DC71B342CD116527832078E6B53C1E0A72909615B408E17625F7259ACA98E46359448FC141F57B51A069B8A402AE3A87E10AE7E910F3916BAC6CE716C539E825A06626673DE7EBD899A3982FCC599791E7CA964C0D37BB076708C03DC7C022980974025C0EA9B72CC3D0A03E4626E030E9C857ECF6B3807AC9E8E0F72098C7E80DAA05BFF60394A8374096878F015597DD5B22E65646A7DDC87B5F6AE68594DF39B0BDB2675A32369AD81FD62033146B8DA6A801E918572CBC70DEBA9F70D088D69425733ACE0084E60E7FCB459A5B71F74F711184B1AEA240834D28D049474BB2E7ED1B17AA2B5EB7D274341456834320BE8FB245B1C2B84A096E7E40573FEB7C2997ED16C8C2C62409B8064398ED220FA82C59E53AD7E864C24473FCC7F017B897D5855F092A9428957467EFD93F67D3FA302C578328A9484CD0496CC83BEAC96504F9601DA2048D25BF43B5A69E46234A164D854B89DF1DEDC36F0304BA5FC035B27E782087C3EC0A81840A3EC042204C63F9698CC74A818428039B23664C409529C4EDD822DF77819805023795EE625D524F12824C1F1FE99546DF75107AFFF7D424C4C3FB3D0BDA2E9BC0D93603457FFE44FABEAB1E6B62223B201D42784731BEE11E0FF0BF29C930DAF913F974739800522E2B9C4094475A5F35AA92E2939E5719EB4EE19446ADC9ECC7EE6BAB5D264C9E74AB6DE856D541146048341EB51734A34E33EF8D929F645E23FD902CB5676DA9C84C9F46490710DC8CF2AA922252C3885CBD8D0CB1D176CAFEB46A625C56BE949F487C6E35E2CE481F024C88A012AA89B +20170718211015 2 6 100 8191 2 DDFBC1CD4FB7E30639422038F1FFBA2CD3EC3915F3C923282C6588F6EB218FF7B24870C0FE4B48213AB0948E101686FB7B0093ED467B6CA413EDD4B0BFE2155AEBC4DA3D2DD0C78DA9AD989A0E989010D6D5E86A123C169E126F97826EE5F602FF641FDF642A107E7538CB61740CBAF69F6C7DC5DD4DF28998AB61B8672F0B74A3A8DD7D165828D69DCC1BAE4D45F707C3894E040BCC0AF7AA810A6D5CB89276217EB7AFAFE4966D68C10318E8C8CB23CA593E8057F29FF9154908B11D6530E6352F9406C81D9DAC5C298979320B4E0DD89203A1F680C8084154D0439DB6C53EDAF6FCC0E8682EC99D345180120AEC810CBB0C2F1B6D1B660ACEAAD5996A5D184659B6A1F11456BA6A5E94D223959D8171C030499A9DB458702CB35CA7E7CD75D26FF5E94640AB8740ECE82559784BB6D5CB4D041D053629BD3F4178077F3F7E280296C46A3F0FBC37813A1AA221FBA2612F0CFE56450E9B1F2C2AE278EC7A7AAB66D61FA9749FE997EDC31131091620897014D33B2386B490CFD80656B7D2EB08C9DA9928798986996D60F74D766EB8988E2FF676E38C587E7A6651AA28BEB8BB56EBBD6E641E92309AEAA671A5F2EC72629442D2C3A4C2B8E4304DC71B342CD116527832078E6B53C1E0A72909615B408E17625F7259ACA98E46359448FC141F57B51A069B8A402AE3A87E10AE7E910F3916BAC6CE716C539E825A06626673DE7EBD899A3982FCC599791E7CA964C0D37BB076708C03DC7C022980974025C0EA9B72CC3D0A03E4626E030E9C857ECF6B3807AC9E8E0F72098C7E80DAA05BFF60394A8374096878F015597DD5B22E65646A7DDC87B5F6AE68594DF39B0BDB2675A32369AD81FD62033146B8DA6A801E918572CBC70DEBA9F70D088D69425733ACE0084E60E7FCB459A5B71F74F711184B1AEA240834D28D049474BB2E7ED1B17AA2B5EB7D274341456834320BE8FB245B1C2B84A096E7E40573FEB7C2997ED16C8C2C62409B8064398ED220FA82C59E53AD7E864C24473FCC7F017B897D5855F092A9428957467EFD93F67D3FA302C578328A9484CD0496CC83BEAC96504F9601DA2048D25BF43B5A69E46234A164D854B89DF1DEDC36F0304BA5FC035B27E782087C3EC0A81840A3EC042204C63F9698CC74A818428039B23664C409529C4EDD822DF77819805023795EE625D524F12824C1F1FE99546DF75107AFFF7D424C4C3FB3D0BDA2E9BC0D93603457FFE44FABEAB1E6B62223B201D42784731BEE11E0FF0BF29C930DAF913F974739800522E2B9C4094475A5F35AA92E2939E5719EB4EE19446ADC9ECC7EE6BAB5D264C9E74AB6DE856D541146048341EB51734A34E33EF8D929F645E23FD902CB5676DA9C84C9F46490710DC8CF2AA922252C3885CBD8D0CB1D176CAFEB46A625C56BE949F487C6E35E2CE481F024C88A0186FF33 +20170719070720 2 6 100 8191 5 D84B8E9B7259F34AA46062684AD05873FD407C5FA804FFBC429D0DED5B497259FFF7F3C26D7A4C21592FCD658B607A5BDE7C4EAA7F5A3B6B713EAEDD5D0D47029CF51556BAFBBC91819DDA500332F7CE6777565C34CE56ED26BFE90830291C460891DDFEBF4FFFE5F217602081211E73EEC97612AC2C9FE8988738F0DC0FD2241B3C54357109D82FAAB532DB9C18B53B543D43B533FD67E36547972674968EB83AEE7EFC9F2AAF2C610C452EEA89A4FF5089BA6922F35128A844F6350A70671DD53C205AC7A75A1659CD3E57D385AB0BD78AF14DC129B1172884F1FCF5D795B6031A2BEB2410948A422D21AD3A215C85720F5EE695E235E36832E0A559DACDBD2B7CA3A1317CA005A963B49E3337829C40974C70F47540D89AAE625A1FD110874DC13D6E7B5711021F0CFD94C46D87582EBFF78EB2412B6D91DC0250A0B805F5E3B096ACB247C2A247A39164337FB3CB818AD4A950E6347B801DA742E5B532F4FC48815AA62B894FDB23B6E4D448DB62713AA46CC33C7D83D60A44B2B70FE8D841A56A4150A01C82B19CB93AE0AAA65E765EFF95933AC55742E0240744158B9CEF9DA8E18C3736BC8894306BF86D9B927CD62252ABFD39A3B352168336404C6B5F0DB4AEE518069274266E0C424F45D487B500BC087F49B53B0FA822D306D8B272E66C035569FFF1A191D354728253419E5B49115B88EB94E8452A28A3D699E73709FFD95D30430D45B730AF36D90C4DF464241C059375E8215E02294DFEAF8169BF1B47F7EE6F6479CB772D552D604589CE0A80BF7C38AFB2D8111D02A11D02264E2D1634128E53835E5815A92C19027DD08493C23344883FA5F2802A67E586221E2E22DFB8C67D75903F7211D52D19DC92DAC9C2E55D5D23E4B316F4F36AE24526C0D7CB5D43A5FA64CD621E9BBEB44ADAC0FB50237872CF13E0008D4D8F3B53B7F97FF8FD71E7B6ECCE359F5FBF3F6128DFD062C1E1177C6DDB97CBB9ED8AF082BF55D2DDF76920020A8AFCA08235752DE7542237D273F0324767F297BD98F573642B54D55AAEDCD9A5DB65DDF24F1E52489E22A8CDB204653F03A45261E20C965772CC92D71AD8A9DCA1205CA72C3AE330CA9ABFC93BD4C0591279661736B131AE905D5EB899BED456FE76BE26C4700FDF3238999B250DEF64F155FED724D3E38BDCAAD31CAC112BF39F0BC0CD3A906BEA43676E126616B51546C9E282117163EA7B38F255797A803F663EA16485FE4A8C2510409D3B6EF809EAC2BF897277A17A9C6E58709B57591FDA62321CEC2F545FCDB0AEEAF33ED378707C81711E003F1E77EEEE292F61E37FDC2FC4F97CEA96E1A4FB8643A9F18C9D6780BC5B815E43AF81E3B1D47D68D5A559C194F35A143B9EAE147D975BEF88D55AF1408BC1705C02F112616D08BFE6A44C0EFAC373CBB557E4953C79ACAA225378FA20B88F +20170719080355 2 6 100 8191 2 D84B8E9B7259F34AA46062684AD05873FD407C5FA804FFBC429D0DED5B497259FFF7F3C26D7A4C21592FCD658B607A5BDE7C4EAA7F5A3B6B713EAEDD5D0D47029CF51556BAFBBC91819DDA500332F7CE6777565C34CE56ED26BFE90830291C460891DDFEBF4FFFE5F217602081211E73EEC97612AC2C9FE8988738F0DC0FD2241B3C54357109D82FAAB532DB9C18B53B543D43B533FD67E36547972674968EB83AEE7EFC9F2AAF2C610C452EEA89A4FF5089BA6922F35128A844F6350A70671DD53C205AC7A75A1659CD3E57D385AB0BD78AF14DC129B1172884F1FCF5D795B6031A2BEB2410948A422D21AD3A215C85720F5EE695E235E36832E0A559DACDBD2B7CA3A1317CA005A963B49E3337829C40974C70F47540D89AAE625A1FD110874DC13D6E7B5711021F0CFD94C46D87582EBFF78EB2412B6D91DC0250A0B805F5E3B096ACB247C2A247A39164337FB3CB818AD4A950E6347B801DA742E5B532F4FC48815AA62B894FDB23B6E4D448DB62713AA46CC33C7D83D60A44B2B70FE8D841A56A4150A01C82B19CB93AE0AAA65E765EFF95933AC55742E0240744158B9CEF9DA8E18C3736BC8894306BF86D9B927CD62252ABFD39A3B352168336404C6B5F0DB4AEE518069274266E0C424F45D487B500BC087F49B53B0FA822D306D8B272E66C035569FFF1A191D354728253419E5B49115B88EB94E8452A28A3D699E73709FFD95D30430D45B730AF36D90C4DF464241C059375E8215E02294DFEAF8169BF1B47F7EE6F6479CB772D552D604589CE0A80BF7C38AFB2D8111D02A11D02264E2D1634128E53835E5815A92C19027DD08493C23344883FA5F2802A67E586221E2E22DFB8C67D75903F7211D52D19DC92DAC9C2E55D5D23E4B316F4F36AE24526C0D7CB5D43A5FA64CD621E9BBEB44ADAC0FB50237872CF13E0008D4D8F3B53B7F97FF8FD71E7B6ECCE359F5FBF3F6128DFD062C1E1177C6DDB97CBB9ED8AF082BF55D2DDF76920020A8AFCA08235752DE7542237D273F0324767F297BD98F573642B54D55AAEDCD9A5DB65DDF24F1E52489E22A8CDB204653F03A45261E20C965772CC92D71AD8A9DCA1205CA72C3AE330CA9ABFC93BD4C0591279661736B131AE905D5EB899BED456FE76BE26C4700FDF3238999B250DEF64F155FED724D3E38BDCAAD31CAC112BF39F0BC0CD3A906BEA43676E126616B51546C9E282117163EA7B38F255797A803F663EA16485FE4A8C2510409D3B6EF809EAC2BF897277A17A9C6E58709B57591FDA62321CEC2F545FCDB0AEEAF33ED378707C81711E003F1E77EEEE292F61E37FDC2FC4F97CEA96E1A4FB8643A9F18C9D6780BC5B815E43AF81E3B1D47D68D5A559C194F35A143B9EAE147D975BEF88D55AF1408BC1705C02F112616D08BFE6A44C0EFAC373CBB557E4953C79ACAA225378FABF2F5B +20170719081323 2 6 100 8191 5 D84B8E9B7259F34AA46062684AD05873FD407C5FA804FFBC429D0DED5B497259FFF7F3C26D7A4C21592FCD658B607A5BDE7C4EAA7F5A3B6B713EAEDD5D0D47029CF51556BAFBBC91819DDA500332F7CE6777565C34CE56ED26BFE90830291C460891DDFEBF4FFFE5F217602081211E73EEC97612AC2C9FE8988738F0DC0FD2241B3C54357109D82FAAB532DB9C18B53B543D43B533FD67E36547972674968EB83AEE7EFC9F2AAF2C610C452EEA89A4FF5089BA6922F35128A844F6350A70671DD53C205AC7A75A1659CD3E57D385AB0BD78AF14DC129B1172884F1FCF5D795B6031A2BEB2410948A422D21AD3A215C85720F5EE695E235E36832E0A559DACDBD2B7CA3A1317CA005A963B49E3337829C40974C70F47540D89AAE625A1FD110874DC13D6E7B5711021F0CFD94C46D87582EBFF78EB2412B6D91DC0250A0B805F5E3B096ACB247C2A247A39164337FB3CB818AD4A950E6347B801DA742E5B532F4FC48815AA62B894FDB23B6E4D448DB62713AA46CC33C7D83D60A44B2B70FE8D841A56A4150A01C82B19CB93AE0AAA65E765EFF95933AC55742E0240744158B9CEF9DA8E18C3736BC8894306BF86D9B927CD62252ABFD39A3B352168336404C6B5F0DB4AEE518069274266E0C424F45D487B500BC087F49B53B0FA822D306D8B272E66C035569FFF1A191D354728253419E5B49115B88EB94E8452A28A3D699E73709FFD95D30430D45B730AF36D90C4DF464241C059375E8215E02294DFEAF8169BF1B47F7EE6F6479CB772D552D604589CE0A80BF7C38AFB2D8111D02A11D02264E2D1634128E53835E5815A92C19027DD08493C23344883FA5F2802A67E586221E2E22DFB8C67D75903F7211D52D19DC92DAC9C2E55D5D23E4B316F4F36AE24526C0D7CB5D43A5FA64CD621E9BBEB44ADAC0FB50237872CF13E0008D4D8F3B53B7F97FF8FD71E7B6ECCE359F5FBF3F6128DFD062C1E1177C6DDB97CBB9ED8AF082BF55D2DDF76920020A8AFCA08235752DE7542237D273F0324767F297BD98F573642B54D55AAEDCD9A5DB65DDF24F1E52489E22A8CDB204653F03A45261E20C965772CC92D71AD8A9DCA1205CA72C3AE330CA9ABFC93BD4C0591279661736B131AE905D5EB899BED456FE76BE26C4700FDF3238999B250DEF64F155FED724D3E38BDCAAD31CAC112BF39F0BC0CD3A906BEA43676E126616B51546C9E282117163EA7B38F255797A803F663EA16485FE4A8C2510409D3B6EF809EAC2BF897277A17A9C6E58709B57591FDA62321CEC2F545FCDB0AEEAF33ED378707C81711E003F1E77EEEE292F61E37FDC2FC4F97CEA96E1A4FB8643A9F18C9D6780BC5B815E43AF81E3B1D47D68D5A559C194F35A143B9EAE147D975BEF88D55AF1408BC1705C02F112616D08BFE6A44C0EFAC373CBB557E4953C79ACAA225378FAD37237 +20170719083433 2 6 100 8191 2 D84B8E9B7259F34AA46062684AD05873FD407C5FA804FFBC429D0DED5B497259FFF7F3C26D7A4C21592FCD658B607A5BDE7C4EAA7F5A3B6B713EAEDD5D0D47029CF51556BAFBBC91819DDA500332F7CE6777565C34CE56ED26BFE90830291C460891DDFEBF4FFFE5F217602081211E73EEC97612AC2C9FE8988738F0DC0FD2241B3C54357109D82FAAB532DB9C18B53B543D43B533FD67E36547972674968EB83AEE7EFC9F2AAF2C610C452EEA89A4FF5089BA6922F35128A844F6350A70671DD53C205AC7A75A1659CD3E57D385AB0BD78AF14DC129B1172884F1FCF5D795B6031A2BEB2410948A422D21AD3A215C85720F5EE695E235E36832E0A559DACDBD2B7CA3A1317CA005A963B49E3337829C40974C70F47540D89AAE625A1FD110874DC13D6E7B5711021F0CFD94C46D87582EBFF78EB2412B6D91DC0250A0B805F5E3B096ACB247C2A247A39164337FB3CB818AD4A950E6347B801DA742E5B532F4FC48815AA62B894FDB23B6E4D448DB62713AA46CC33C7D83D60A44B2B70FE8D841A56A4150A01C82B19CB93AE0AAA65E765EFF95933AC55742E0240744158B9CEF9DA8E18C3736BC8894306BF86D9B927CD62252ABFD39A3B352168336404C6B5F0DB4AEE518069274266E0C424F45D487B500BC087F49B53B0FA822D306D8B272E66C035569FFF1A191D354728253419E5B49115B88EB94E8452A28A3D699E73709FFD95D30430D45B730AF36D90C4DF464241C059375E8215E02294DFEAF8169BF1B47F7EE6F6479CB772D552D604589CE0A80BF7C38AFB2D8111D02A11D02264E2D1634128E53835E5815A92C19027DD08493C23344883FA5F2802A67E586221E2E22DFB8C67D75903F7211D52D19DC92DAC9C2E55D5D23E4B316F4F36AE24526C0D7CB5D43A5FA64CD621E9BBEB44ADAC0FB50237872CF13E0008D4D8F3B53B7F97FF8FD71E7B6ECCE359F5FBF3F6128DFD062C1E1177C6DDB97CBB9ED8AF082BF55D2DDF76920020A8AFCA08235752DE7542237D273F0324767F297BD98F573642B54D55AAEDCD9A5DB65DDF24F1E52489E22A8CDB204653F03A45261E20C965772CC92D71AD8A9DCA1205CA72C3AE330CA9ABFC93BD4C0591279661736B131AE905D5EB899BED456FE76BE26C4700FDF3238999B250DEF64F155FED724D3E38BDCAAD31CAC112BF39F0BC0CD3A906BEA43676E126616B51546C9E282117163EA7B38F255797A803F663EA16485FE4A8C2510409D3B6EF809EAC2BF897277A17A9C6E58709B57591FDA62321CEC2F545FCDB0AEEAF33ED378707C81711E003F1E77EEEE292F61E37FDC2FC4F97CEA96E1A4FB8643A9F18C9D6780BC5B815E43AF81E3B1D47D68D5A559C194F35A143B9EAE147D975BEF88D55AF1408BC1705C02F112616D08BFE6A44C0EFAC373CBB557E4953C79ACAA225378FB0C1BEB +20170719124018 2 6 100 8191 5 D84B8E9B7259F34AA46062684AD05873FD407C5FA804FFBC429D0DED5B497259FFF7F3C26D7A4C21592FCD658B607A5BDE7C4EAA7F5A3B6B713EAEDD5D0D47029CF51556BAFBBC91819DDA500332F7CE6777565C34CE56ED26BFE90830291C460891DDFEBF4FFFE5F217602081211E73EEC97612AC2C9FE8988738F0DC0FD2241B3C54357109D82FAAB532DB9C18B53B543D43B533FD67E36547972674968EB83AEE7EFC9F2AAF2C610C452EEA89A4FF5089BA6922F35128A844F6350A70671DD53C205AC7A75A1659CD3E57D385AB0BD78AF14DC129B1172884F1FCF5D795B6031A2BEB2410948A422D21AD3A215C85720F5EE695E235E36832E0A559DACDBD2B7CA3A1317CA005A963B49E3337829C40974C70F47540D89AAE625A1FD110874DC13D6E7B5711021F0CFD94C46D87582EBFF78EB2412B6D91DC0250A0B805F5E3B096ACB247C2A247A39164337FB3CB818AD4A950E6347B801DA742E5B532F4FC48815AA62B894FDB23B6E4D448DB62713AA46CC33C7D83D60A44B2B70FE8D841A56A4150A01C82B19CB93AE0AAA65E765EFF95933AC55742E0240744158B9CEF9DA8E18C3736BC8894306BF86D9B927CD62252ABFD39A3B352168336404C6B5F0DB4AEE518069274266E0C424F45D487B500BC087F49B53B0FA822D306D8B272E66C035569FFF1A191D354728253419E5B49115B88EB94E8452A28A3D699E73709FFD95D30430D45B730AF36D90C4DF464241C059375E8215E02294DFEAF8169BF1B47F7EE6F6479CB772D552D604589CE0A80BF7C38AFB2D8111D02A11D02264E2D1634128E53835E5815A92C19027DD08493C23344883FA5F2802A67E586221E2E22DFB8C67D75903F7211D52D19DC92DAC9C2E55D5D23E4B316F4F36AE24526C0D7CB5D43A5FA64CD621E9BBEB44ADAC0FB50237872CF13E0008D4D8F3B53B7F97FF8FD71E7B6ECCE359F5FBF3F6128DFD062C1E1177C6DDB97CBB9ED8AF082BF55D2DDF76920020A8AFCA08235752DE7542237D273F0324767F297BD98F573642B54D55AAEDCD9A5DB65DDF24F1E52489E22A8CDB204653F03A45261E20C965772CC92D71AD8A9DCA1205CA72C3AE330CA9ABFC93BD4C0591279661736B131AE905D5EB899BED456FE76BE26C4700FDF3238999B250DEF64F155FED724D3E38BDCAAD31CAC112BF39F0BC0CD3A906BEA43676E126616B51546C9E282117163EA7B38F255797A803F663EA16485FE4A8C2510409D3B6EF809EAC2BF897277A17A9C6E58709B57591FDA62321CEC2F545FCDB0AEEAF33ED378707C81711E003F1E77EEEE292F61E37FDC2FC4F97CEA96E1A4FB8643A9F18C9D6780BC5B815E43AF81E3B1D47D68D5A559C194F35A143B9EAE147D975BEF88D55AF1408BC1705C02F112616D08BFE6A44C0EFAC373CBB557E4953C79ACAA225378FDE8D93F +20170720083815 2 6 100 8191 5 D84B8E9B7259F34AA46062684AD05873FD407C5FA804FFBC429D0DED5B497259FFF7F3C26D7A4C21592FCD658B607A5BDE7C4EAA7F5A3B6B713EAEDD5D0D47029CF51556BAFBBC91819DDA500332F7CE6777565C34CE56ED26BFE90830291C460891DDFEBF4FFFE5F217602081211E73EEC97612AC2C9FE8988738F0DC0FD2241B3C54357109D82FAAB532DB9C18B53B543D43B533FD67E36547972674968EB83AEE7EFC9F2AAF2C610C452EEA89A4FF5089BA6922F35128A844F6350A70671DD53C205AC7A75A1659CD3E57D385AB0BD78AF14DC129B1172884F1FCF5D795B6031A2BEB2410948A422D21AD3A215C85720F5EE695E235E36832E0A559DACDBD2B7CA3A1317CA005A963B49E3337829C40974C70F47540D89AAE625A1FD110874DC13D6E7B5711021F0CFD94C46D87582EBFF78EB2412B6D91DC0250A0B805F5E3B096ACB247C2A247A39164337FB3CB818AD4A950E6347B801DA742E5B532F4FC48815AA62B894FDB23B6E4D448DB62713AA46CC33C7D83D60A44B2B70FE8D841A56A4150A01C82B19CB93AE0AAA65E765EFF95933AC55742E0240744158B9CEF9DA8E18C3736BC8894306BF86D9B927CD62252ABFD39A3B352168336404C6B5F0DB4AEE518069274266E0C424F45D487B500BC087F49B53B0FA822D306D8B272E66C035569FFF1A191D354728253419E5B49115B88EB94E8452A28A3D699E73709FFD95D30430D45B730AF36D90C4DF464241C059375E8215E02294DFEAF8169BF1B47F7EE6F6479CB772D552D604589CE0A80BF7C38AFB2D8111D02A11D02264E2D1634128E53835E5815A92C19027DD08493C23344883FA5F2802A67E586221E2E22DFB8C67D75903F7211D52D19DC92DAC9C2E55D5D23E4B316F4F36AE24526C0D7CB5D43A5FA64CD621E9BBEB44ADAC0FB50237872CF13E0008D4D8F3B53B7F97FF8FD71E7B6ECCE359F5FBF3F6128DFD062C1E1177C6DDB97CBB9ED8AF082BF55D2DDF76920020A8AFCA08235752DE7542237D273F0324767F297BD98F573642B54D55AAEDCD9A5DB65DDF24F1E52489E22A8CDB204653F03A45261E20C965772CC92D71AD8A9DCA1205CA72C3AE330CA9ABFC93BD4C0591279661736B131AE905D5EB899BED456FE76BE26C4700FDF3238999B250DEF64F155FED724D3E38BDCAAD31CAC112BF39F0BC0CD3A906BEA43676E126616B51546C9E282117163EA7B38F255797A803F663EA16485FE4A8C2510409D3B6EF809EAC2BF897277A17A9C6E58709B57591FDA62321CEC2F545FCDB0AEEAF33ED378707C81711E003F1E77EEEE292F61E37FDC2FC4F97CEA96E1A4FB8643A9F18C9D6780BC5B815E43AF81E3B1D47D68D5A559C194F35A143B9EAE147D975BEF88D55AF1408BC1705C02F112616D08BFE6A44C0EFAC373CBB557E4953C79ACAA2253790C2785C7 +20170720203303 2 6 100 8191 2 D84B8E9B7259F34AA46062684AD05873FD407C5FA804FFBC429D0DED5B497259FFF7F3C26D7A4C21592FCD658B607A5BDE7C4EAA7F5A3B6B713EAEDD5D0D47029CF51556BAFBBC91819DDA500332F7CE6777565C34CE56ED26BFE90830291C460891DDFEBF4FFFE5F217602081211E73EEC97612AC2C9FE8988738F0DC0FD2241B3C54357109D82FAAB532DB9C18B53B543D43B533FD67E36547972674968EB83AEE7EFC9F2AAF2C610C452EEA89A4FF5089BA6922F35128A844F6350A70671DD53C205AC7A75A1659CD3E57D385AB0BD78AF14DC129B1172884F1FCF5D795B6031A2BEB2410948A422D21AD3A215C85720F5EE695E235E36832E0A559DACDBD2B7CA3A1317CA005A963B49E3337829C40974C70F47540D89AAE625A1FD110874DC13D6E7B5711021F0CFD94C46D87582EBFF78EB2412B6D91DC0250A0B805F5E3B096ACB247C2A247A39164337FB3CB818AD4A950E6347B801DA742E5B532F4FC48815AA62B894FDB23B6E4D448DB62713AA46CC33C7D83D60A44B2B70FE8D841A56A4150A01C82B19CB93AE0AAA65E765EFF95933AC55742E0240744158B9CEF9DA8E18C3736BC8894306BF86D9B927CD62252ABFD39A3B352168336404C6B5F0DB4AEE518069274266E0C424F45D487B500BC087F49B53B0FA822D306D8B272E66C035569FFF1A191D354728253419E5B49115B88EB94E8452A28A3D699E73709FFD95D30430D45B730AF36D90C4DF464241C059375E8215E02294DFEAF8169BF1B47F7EE6F6479CB772D552D604589CE0A80BF7C38AFB2D8111D02A11D02264E2D1634128E53835E5815A92C19027DD08493C23344883FA5F2802A67E586221E2E22DFB8C67D75903F7211D52D19DC92DAC9C2E55D5D23E4B316F4F36AE24526C0D7CB5D43A5FA64CD621E9BBEB44ADAC0FB50237872CF13E0008D4D8F3B53B7F97FF8FD71E7B6ECCE359F5FBF3F6128DFD062C1E1177C6DDB97CBB9ED8AF082BF55D2DDF76920020A8AFCA08235752DE7542237D273F0324767F297BD98F573642B54D55AAEDCD9A5DB65DDF24F1E52489E22A8CDB204653F03A45261E20C965772CC92D71AD8A9DCA1205CA72C3AE330CA9ABFC93BD4C0591279661736B131AE905D5EB899BED456FE76BE26C4700FDF3238999B250DEF64F155FED724D3E38BDCAAD31CAC112BF39F0BC0CD3A906BEA43676E126616B51546C9E282117163EA7B38F255797A803F663EA16485FE4A8C2510409D3B6EF809EAC2BF897277A17A9C6E58709B57591FDA62321CEC2F545FCDB0AEEAF33ED378707C81711E003F1E77EEEE292F61E37FDC2FC4F97CEA96E1A4FB8643A9F18C9D6780BC5B815E43AF81E3B1D47D68D5A559C194F35A143B9EAE147D975BEF88D55AF1408BC1705C02F112616D08BFE6A44C0EFAC373CBB557E4953C79ACAA225379147CF99B +20170721064950 2 6 100 8191 2 D84B8E9B7259F34AA46062684AD05873FD407C5FA804FFBC429D0DED5B497259FFF7F3C26D7A4C21592FCD658B607A5BDE7C4EAA7F5A3B6B713EAEDD5D0D47029CF51556BAFBBC91819DDA500332F7CE6777565C34CE56ED26BFE90830291C460891DDFEBF4FFFE5F217602081211E73EEC97612AC2C9FE8988738F0DC0FD2241B3C54357109D82FAAB532DB9C18B53B543D43B533FD67E36547972674968EB83AEE7EFC9F2AAF2C610C452EEA89A4FF5089BA6922F35128A844F6350A70671DD53C205AC7A75A1659CD3E57D385AB0BD78AF14DC129B1172884F1FCF5D795B6031A2BEB2410948A422D21AD3A215C85720F5EE695E235E36832E0A559DACDBD2B7CA3A1317CA005A963B49E3337829C40974C70F47540D89AAE625A1FD110874DC13D6E7B5711021F0CFD94C46D87582EBFF78EB2412B6D91DC0250A0B805F5E3B096ACB247C2A247A39164337FB3CB818AD4A950E6347B801DA742E5B532F4FC48815AA62B894FDB23B6E4D448DB62713AA46CC33C7D83D60A44B2B70FE8D841A56A4150A01C82B19CB93AE0AAA65E765EFF95933AC55742E0240744158B9CEF9DA8E18C3736BC8894306BF86D9B927CD62252ABFD39A3B352168336404C6B5F0DB4AEE518069274266E0C424F45D487B500BC087F49B53B0FA822D306D8B272E66C035569FFF1A191D354728253419E5B49115B88EB94E8452A28A3D699E73709FFD95D30430D45B730AF36D90C4DF464241C059375E8215E02294DFEAF8169BF1B47F7EE6F6479CB772D552D604589CE0A80BF7C38AFB2D8111D02A11D02264E2D1634128E53835E5815A92C19027DD08493C23344883FA5F2802A67E586221E2E22DFB8C67D75903F7211D52D19DC92DAC9C2E55D5D23E4B316F4F36AE24526C0D7CB5D43A5FA64CD621E9BBEB44ADAC0FB50237872CF13E0008D4D8F3B53B7F97FF8FD71E7B6ECCE359F5FBF3F6128DFD062C1E1177C6DDB97CBB9ED8AF082BF55D2DDF76920020A8AFCA08235752DE7542237D273F0324767F297BD98F573642B54D55AAEDCD9A5DB65DDF24F1E52489E22A8CDB204653F03A45261E20C965772CC92D71AD8A9DCA1205CA72C3AE330CA9ABFC93BD4C0591279661736B131AE905D5EB899BED456FE76BE26C4700FDF3238999B250DEF64F155FED724D3E38BDCAAD31CAC112BF39F0BC0CD3A906BEA43676E126616B51546C9E282117163EA7B38F255797A803F663EA16485FE4A8C2510409D3B6EF809EAC2BF897277A17A9C6E58709B57591FDA62321CEC2F545FCDB0AEEAF33ED378707C81711E003F1E77EEEE292F61E37FDC2FC4F97CEA96E1A4FB8643A9F18C9D6780BC5B815E43AF81E3B1D47D68D5A559C194F35A143B9EAE147D975BEF88D55AF1408BC1705C02F112616D08BFE6A44C0EFAC373CBB557E4953C79ACAA2253791BAF7AFB +20170721151849 2 6 100 8191 5 D84B8E9B7259F34AA46062684AD05873FD407C5FA804FFBC429D0DED5B497259FFF7F3C26D7A4C21592FCD658B607A5BDE7C4EAA7F5A3B6B713EAEDD5D0D47029CF51556BAFBBC91819DDA500332F7CE6777565C34CE56ED26BFE90830291C460891DDFEBF4FFFE5F217602081211E73EEC97612AC2C9FE8988738F0DC0FD2241B3C54357109D82FAAB532DB9C18B53B543D43B533FD67E36547972674968EB83AEE7EFC9F2AAF2C610C452EEA89A4FF5089BA6922F35128A844F6350A70671DD53C205AC7A75A1659CD3E57D385AB0BD78AF14DC129B1172884F1FCF5D795B6031A2BEB2410948A422D21AD3A215C85720F5EE695E235E36832E0A559DACDBD2B7CA3A1317CA005A963B49E3337829C40974C70F47540D89AAE625A1FD110874DC13D6E7B5711021F0CFD94C46D87582EBFF78EB2412B6D91DC0250A0B805F5E3B096ACB247C2A247A39164337FB3CB818AD4A950E6347B801DA742E5B532F4FC48815AA62B894FDB23B6E4D448DB62713AA46CC33C7D83D60A44B2B70FE8D841A56A4150A01C82B19CB93AE0AAA65E765EFF95933AC55742E0240744158B9CEF9DA8E18C3736BC8894306BF86D9B927CD62252ABFD39A3B352168336404C6B5F0DB4AEE518069274266E0C424F45D487B500BC087F49B53B0FA822D306D8B272E66C035569FFF1A191D354728253419E5B49115B88EB94E8452A28A3D699E73709FFD95D30430D45B730AF36D90C4DF464241C059375E8215E02294DFEAF8169BF1B47F7EE6F6479CB772D552D604589CE0A80BF7C38AFB2D8111D02A11D02264E2D1634128E53835E5815A92C19027DD08493C23344883FA5F2802A67E586221E2E22DFB8C67D75903F7211D52D19DC92DAC9C2E55D5D23E4B316F4F36AE24526C0D7CB5D43A5FA64CD621E9BBEB44ADAC0FB50237872CF13E0008D4D8F3B53B7F97FF8FD71E7B6ECCE359F5FBF3F6128DFD062C1E1177C6DDB97CBB9ED8AF082BF55D2DDF76920020A8AFCA08235752DE7542237D273F0324767F297BD98F573642B54D55AAEDCD9A5DB65DDF24F1E52489E22A8CDB204653F03A45261E20C965772CC92D71AD8A9DCA1205CA72C3AE330CA9ABFC93BD4C0591279661736B131AE905D5EB899BED456FE76BE26C4700FDF3238999B250DEF64F155FED724D3E38BDCAAD31CAC112BF39F0BC0CD3A906BEA43676E126616B51546C9E282117163EA7B38F255797A803F663EA16485FE4A8C2510409D3B6EF809EAC2BF897277A17A9C6E58709B57591FDA62321CEC2F545FCDB0AEEAF33ED378707C81711E003F1E77EEEE292F61E37FDC2FC4F97CEA96E1A4FB8643A9F18C9D6780BC5B815E43AF81E3B1D47D68D5A559C194F35A143B9EAE147D975BEF88D55AF1408BC1705C02F112616D08BFE6A44C0EFAC373CBB557E4953C79ACAA225379217C124F +20170721220636 2 6 100 8191 2 D84B8E9B7259F34AA46062684AD05873FD407C5FA804FFBC429D0DED5B497259FFF7F3C26D7A4C21592FCD658B607A5BDE7C4EAA7F5A3B6B713EAEDD5D0D47029CF51556BAFBBC91819DDA500332F7CE6777565C34CE56ED26BFE90830291C460891DDFEBF4FFFE5F217602081211E73EEC97612AC2C9FE8988738F0DC0FD2241B3C54357109D82FAAB532DB9C18B53B543D43B533FD67E36547972674968EB83AEE7EFC9F2AAF2C610C452EEA89A4FF5089BA6922F35128A844F6350A70671DD53C205AC7A75A1659CD3E57D385AB0BD78AF14DC129B1172884F1FCF5D795B6031A2BEB2410948A422D21AD3A215C85720F5EE695E235E36832E0A559DACDBD2B7CA3A1317CA005A963B49E3337829C40974C70F47540D89AAE625A1FD110874DC13D6E7B5711021F0CFD94C46D87582EBFF78EB2412B6D91DC0250A0B805F5E3B096ACB247C2A247A39164337FB3CB818AD4A950E6347B801DA742E5B532F4FC48815AA62B894FDB23B6E4D448DB62713AA46CC33C7D83D60A44B2B70FE8D841A56A4150A01C82B19CB93AE0AAA65E765EFF95933AC55742E0240744158B9CEF9DA8E18C3736BC8894306BF86D9B927CD62252ABFD39A3B352168336404C6B5F0DB4AEE518069274266E0C424F45D487B500BC087F49B53B0FA822D306D8B272E66C035569FFF1A191D354728253419E5B49115B88EB94E8452A28A3D699E73709FFD95D30430D45B730AF36D90C4DF464241C059375E8215E02294DFEAF8169BF1B47F7EE6F6479CB772D552D604589CE0A80BF7C38AFB2D8111D02A11D02264E2D1634128E53835E5815A92C19027DD08493C23344883FA5F2802A67E586221E2E22DFB8C67D75903F7211D52D19DC92DAC9C2E55D5D23E4B316F4F36AE24526C0D7CB5D43A5FA64CD621E9BBEB44ADAC0FB50237872CF13E0008D4D8F3B53B7F97FF8FD71E7B6ECCE359F5FBF3F6128DFD062C1E1177C6DDB97CBB9ED8AF082BF55D2DDF76920020A8AFCA08235752DE7542237D273F0324767F297BD98F573642B54D55AAEDCD9A5DB65DDF24F1E52489E22A8CDB204653F03A45261E20C965772CC92D71AD8A9DCA1205CA72C3AE330CA9ABFC93BD4C0591279661736B131AE905D5EB899BED456FE76BE26C4700FDF3238999B250DEF64F155FED724D3E38BDCAAD31CAC112BF39F0BC0CD3A906BEA43676E126616B51546C9E282117163EA7B38F255797A803F663EA16485FE4A8C2510409D3B6EF809EAC2BF897277A17A9C6E58709B57591FDA62321CEC2F545FCDB0AEEAF33ED378707C81711E003F1E77EEEE292F61E37FDC2FC4F97CEA96E1A4FB8643A9F18C9D6780BC5B815E43AF81E3B1D47D68D5A559C194F35A143B9EAE147D975BEF88D55AF1408BC1705C02F112616D08BFE6A44C0EFAC373CBB557E4953C79ACAA225379260D3263 +20170722033935 2 6 100 8191 2 D84B8E9B7259F34AA46062684AD05873FD407C5FA804FFBC429D0DED5B497259FFF7F3C26D7A4C21592FCD658B607A5BDE7C4EAA7F5A3B6B713EAEDD5D0D47029CF51556BAFBBC91819DDA500332F7CE6777565C34CE56ED26BFE90830291C460891DDFEBF4FFFE5F217602081211E73EEC97612AC2C9FE8988738F0DC0FD2241B3C54357109D82FAAB532DB9C18B53B543D43B533FD67E36547972674968EB83AEE7EFC9F2AAF2C610C452EEA89A4FF5089BA6922F35128A844F6350A70671DD53C205AC7A75A1659CD3E57D385AB0BD78AF14DC129B1172884F1FCF5D795B6031A2BEB2410948A422D21AD3A215C85720F5EE695E235E36832E0A559DACDBD2B7CA3A1317CA005A963B49E3337829C40974C70F47540D89AAE625A1FD110874DC13D6E7B5711021F0CFD94C46D87582EBFF78EB2412B6D91DC0250A0B805F5E3B096ACB247C2A247A39164337FB3CB818AD4A950E6347B801DA742E5B532F4FC48815AA62B894FDB23B6E4D448DB62713AA46CC33C7D83D60A44B2B70FE8D841A56A4150A01C82B19CB93AE0AAA65E765EFF95933AC55742E0240744158B9CEF9DA8E18C3736BC8894306BF86D9B927CD62252ABFD39A3B352168336404C6B5F0DB4AEE518069274266E0C424F45D487B500BC087F49B53B0FA822D306D8B272E66C035569FFF1A191D354728253419E5B49115B88EB94E8452A28A3D699E73709FFD95D30430D45B730AF36D90C4DF464241C059375E8215E02294DFEAF8169BF1B47F7EE6F6479CB772D552D604589CE0A80BF7C38AFB2D8111D02A11D02264E2D1634128E53835E5815A92C19027DD08493C23344883FA5F2802A67E586221E2E22DFB8C67D75903F7211D52D19DC92DAC9C2E55D5D23E4B316F4F36AE24526C0D7CB5D43A5FA64CD621E9BBEB44ADAC0FB50237872CF13E0008D4D8F3B53B7F97FF8FD71E7B6ECCE359F5FBF3F6128DFD062C1E1177C6DDB97CBB9ED8AF082BF55D2DDF76920020A8AFCA08235752DE7542237D273F0324767F297BD98F573642B54D55AAEDCD9A5DB65DDF24F1E52489E22A8CDB204653F03A45261E20C965772CC92D71AD8A9DCA1205CA72C3AE330CA9ABFC93BD4C0591279661736B131AE905D5EB899BED456FE76BE26C4700FDF3238999B250DEF64F155FED724D3E38BDCAAD31CAC112BF39F0BC0CD3A906BEA43676E126616B51546C9E282117163EA7B38F255797A803F663EA16485FE4A8C2510409D3B6EF809EAC2BF897277A17A9C6E58709B57591FDA62321CEC2F545FCDB0AEEAF33ED378707C81711E003F1E77EEEE292F61E37FDC2FC4F97CEA96E1A4FB8643A9F18C9D6780BC5B815E43AF81E3B1D47D68D5A559C194F35A143B9EAE147D975BEF88D55AF1408BC1705C02F112616D08BFE6A44C0EFAC373CBB557E4953C79ACAA22537929DAE9CB +20170722155118 2 6 100 8191 5 D84B8E9B7259F34AA46062684AD05873FD407C5FA804FFBC429D0DED5B497259FFF7F3C26D7A4C21592FCD658B607A5BDE7C4EAA7F5A3B6B713EAEDD5D0D47029CF51556BAFBBC91819DDA500332F7CE6777565C34CE56ED26BFE90830291C460891DDFEBF4FFFE5F217602081211E73EEC97612AC2C9FE8988738F0DC0FD2241B3C54357109D82FAAB532DB9C18B53B543D43B533FD67E36547972674968EB83AEE7EFC9F2AAF2C610C452EEA89A4FF5089BA6922F35128A844F6350A70671DD53C205AC7A75A1659CD3E57D385AB0BD78AF14DC129B1172884F1FCF5D795B6031A2BEB2410948A422D21AD3A215C85720F5EE695E235E36832E0A559DACDBD2B7CA3A1317CA005A963B49E3337829C40974C70F47540D89AAE625A1FD110874DC13D6E7B5711021F0CFD94C46D87582EBFF78EB2412B6D91DC0250A0B805F5E3B096ACB247C2A247A39164337FB3CB818AD4A950E6347B801DA742E5B532F4FC48815AA62B894FDB23B6E4D448DB62713AA46CC33C7D83D60A44B2B70FE8D841A56A4150A01C82B19CB93AE0AAA65E765EFF95933AC55742E0240744158B9CEF9DA8E18C3736BC8894306BF86D9B927CD62252ABFD39A3B352168336404C6B5F0DB4AEE518069274266E0C424F45D487B500BC087F49B53B0FA822D306D8B272E66C035569FFF1A191D354728253419E5B49115B88EB94E8452A28A3D699E73709FFD95D30430D45B730AF36D90C4DF464241C059375E8215E02294DFEAF8169BF1B47F7EE6F6479CB772D552D604589CE0A80BF7C38AFB2D8111D02A11D02264E2D1634128E53835E5815A92C19027DD08493C23344883FA5F2802A67E586221E2E22DFB8C67D75903F7211D52D19DC92DAC9C2E55D5D23E4B316F4F36AE24526C0D7CB5D43A5FA64CD621E9BBEB44ADAC0FB50237872CF13E0008D4D8F3B53B7F97FF8FD71E7B6ECCE359F5FBF3F6128DFD062C1E1177C6DDB97CBB9ED8AF082BF55D2DDF76920020A8AFCA08235752DE7542237D273F0324767F297BD98F573642B54D55AAEDCD9A5DB65DDF24F1E52489E22A8CDB204653F03A45261E20C965772CC92D71AD8A9DCA1205CA72C3AE330CA9ABFC93BD4C0591279661736B131AE905D5EB899BED456FE76BE26C4700FDF3238999B250DEF64F155FED724D3E38BDCAAD31CAC112BF39F0BC0CD3A906BEA43676E126616B51546C9E282117163EA7B38F255797A803F663EA16485FE4A8C2510409D3B6EF809EAC2BF897277A17A9C6E58709B57591FDA62321CEC2F545FCDB0AEEAF33ED378707C81711E003F1E77EEEE292F61E37FDC2FC4F97CEA96E1A4FB8643A9F18C9D6780BC5B815E43AF81E3B1D47D68D5A559C194F35A143B9EAE147D975BEF88D55AF1408BC1705C02F112616D08BFE6A44C0EFAC373CBB557E4953C79ACAA225379320A3B27 +20170722181755 2 6 100 8191 2 D84B8E9B7259F34AA46062684AD05873FD407C5FA804FFBC429D0DED5B497259FFF7F3C26D7A4C21592FCD658B607A5BDE7C4EAA7F5A3B6B713EAEDD5D0D47029CF51556BAFBBC91819DDA500332F7CE6777565C34CE56ED26BFE90830291C460891DDFEBF4FFFE5F217602081211E73EEC97612AC2C9FE8988738F0DC0FD2241B3C54357109D82FAAB532DB9C18B53B543D43B533FD67E36547972674968EB83AEE7EFC9F2AAF2C610C452EEA89A4FF5089BA6922F35128A844F6350A70671DD53C205AC7A75A1659CD3E57D385AB0BD78AF14DC129B1172884F1FCF5D795B6031A2BEB2410948A422D21AD3A215C85720F5EE695E235E36832E0A559DACDBD2B7CA3A1317CA005A963B49E3337829C40974C70F47540D89AAE625A1FD110874DC13D6E7B5711021F0CFD94C46D87582EBFF78EB2412B6D91DC0250A0B805F5E3B096ACB247C2A247A39164337FB3CB818AD4A950E6347B801DA742E5B532F4FC48815AA62B894FDB23B6E4D448DB62713AA46CC33C7D83D60A44B2B70FE8D841A56A4150A01C82B19CB93AE0AAA65E765EFF95933AC55742E0240744158B9CEF9DA8E18C3736BC8894306BF86D9B927CD62252ABFD39A3B352168336404C6B5F0DB4AEE518069274266E0C424F45D487B500BC087F49B53B0FA822D306D8B272E66C035569FFF1A191D354728253419E5B49115B88EB94E8452A28A3D699E73709FFD95D30430D45B730AF36D90C4DF464241C059375E8215E02294DFEAF8169BF1B47F7EE6F6479CB772D552D604589CE0A80BF7C38AFB2D8111D02A11D02264E2D1634128E53835E5815A92C19027DD08493C23344883FA5F2802A67E586221E2E22DFB8C67D75903F7211D52D19DC92DAC9C2E55D5D23E4B316F4F36AE24526C0D7CB5D43A5FA64CD621E9BBEB44ADAC0FB50237872CF13E0008D4D8F3B53B7F97FF8FD71E7B6ECCE359F5FBF3F6128DFD062C1E1177C6DDB97CBB9ED8AF082BF55D2DDF76920020A8AFCA08235752DE7542237D273F0324767F297BD98F573642B54D55AAEDCD9A5DB65DDF24F1E52489E22A8CDB204653F03A45261E20C965772CC92D71AD8A9DCA1205CA72C3AE330CA9ABFC93BD4C0591279661736B131AE905D5EB899BED456FE76BE26C4700FDF3238999B250DEF64F155FED724D3E38BDCAAD31CAC112BF39F0BC0CD3A906BEA43676E126616B51546C9E282117163EA7B38F255797A803F663EA16485FE4A8C2510409D3B6EF809EAC2BF897277A17A9C6E58709B57591FDA62321CEC2F545FCDB0AEEAF33ED378707C81711E003F1E77EEEE292F61E37FDC2FC4F97CEA96E1A4FB8643A9F18C9D6780BC5B815E43AF81E3B1D47D68D5A559C194F35A143B9EAE147D975BEF88D55AF1408BC1705C02F112616D08BFE6A44C0EFAC373CBB557E4953C79ACAA22537933A7A623 +20170722212038 2 6 100 8191 2 D84B8E9B7259F34AA46062684AD05873FD407C5FA804FFBC429D0DED5B497259FFF7F3C26D7A4C21592FCD658B607A5BDE7C4EAA7F5A3B6B713EAEDD5D0D47029CF51556BAFBBC91819DDA500332F7CE6777565C34CE56ED26BFE90830291C460891DDFEBF4FFFE5F217602081211E73EEC97612AC2C9FE8988738F0DC0FD2241B3C54357109D82FAAB532DB9C18B53B543D43B533FD67E36547972674968EB83AEE7EFC9F2AAF2C610C452EEA89A4FF5089BA6922F35128A844F6350A70671DD53C205AC7A75A1659CD3E57D385AB0BD78AF14DC129B1172884F1FCF5D795B6031A2BEB2410948A422D21AD3A215C85720F5EE695E235E36832E0A559DACDBD2B7CA3A1317CA005A963B49E3337829C40974C70F47540D89AAE625A1FD110874DC13D6E7B5711021F0CFD94C46D87582EBFF78EB2412B6D91DC0250A0B805F5E3B096ACB247C2A247A39164337FB3CB818AD4A950E6347B801DA742E5B532F4FC48815AA62B894FDB23B6E4D448DB62713AA46CC33C7D83D60A44B2B70FE8D841A56A4150A01C82B19CB93AE0AAA65E765EFF95933AC55742E0240744158B9CEF9DA8E18C3736BC8894306BF86D9B927CD62252ABFD39A3B352168336404C6B5F0DB4AEE518069274266E0C424F45D487B500BC087F49B53B0FA822D306D8B272E66C035569FFF1A191D354728253419E5B49115B88EB94E8452A28A3D699E73709FFD95D30430D45B730AF36D90C4DF464241C059375E8215E02294DFEAF8169BF1B47F7EE6F6479CB772D552D604589CE0A80BF7C38AFB2D8111D02A11D02264E2D1634128E53835E5815A92C19027DD08493C23344883FA5F2802A67E586221E2E22DFB8C67D75903F7211D52D19DC92DAC9C2E55D5D23E4B316F4F36AE24526C0D7CB5D43A5FA64CD621E9BBEB44ADAC0FB50237872CF13E0008D4D8F3B53B7F97FF8FD71E7B6ECCE359F5FBF3F6128DFD062C1E1177C6DDB97CBB9ED8AF082BF55D2DDF76920020A8AFCA08235752DE7542237D273F0324767F297BD98F573642B54D55AAEDCD9A5DB65DDF24F1E52489E22A8CDB204653F03A45261E20C965772CC92D71AD8A9DCA1205CA72C3AE330CA9ABFC93BD4C0591279661736B131AE905D5EB899BED456FE76BE26C4700FDF3238999B250DEF64F155FED724D3E38BDCAAD31CAC112BF39F0BC0CD3A906BEA43676E126616B51546C9E282117163EA7B38F255797A803F663EA16485FE4A8C2510409D3B6EF809EAC2BF897277A17A9C6E58709B57591FDA62321CEC2F545FCDB0AEEAF33ED378707C81711E003F1E77EEEE292F61E37FDC2FC4F97CEA96E1A4FB8643A9F18C9D6780BC5B815E43AF81E3B1D47D68D5A559C194F35A143B9EAE147D975BEF88D55AF1408BC1705C02F112616D08BFE6A44C0EFAC373CBB557E4953C79ACAA225379359D2C63 +20170722230812 2 6 100 8191 5 D84B8E9B7259F34AA46062684AD05873FD407C5FA804FFBC429D0DED5B497259FFF7F3C26D7A4C21592FCD658B607A5BDE7C4EAA7F5A3B6B713EAEDD5D0D47029CF51556BAFBBC91819DDA500332F7CE6777565C34CE56ED26BFE90830291C460891DDFEBF4FFFE5F217602081211E73EEC97612AC2C9FE8988738F0DC0FD2241B3C54357109D82FAAB532DB9C18B53B543D43B533FD67E36547972674968EB83AEE7EFC9F2AAF2C610C452EEA89A4FF5089BA6922F35128A844F6350A70671DD53C205AC7A75A1659CD3E57D385AB0BD78AF14DC129B1172884F1FCF5D795B6031A2BEB2410948A422D21AD3A215C85720F5EE695E235E36832E0A559DACDBD2B7CA3A1317CA005A963B49E3337829C40974C70F47540D89AAE625A1FD110874DC13D6E7B5711021F0CFD94C46D87582EBFF78EB2412B6D91DC0250A0B805F5E3B096ACB247C2A247A39164337FB3CB818AD4A950E6347B801DA742E5B532F4FC48815AA62B894FDB23B6E4D448DB62713AA46CC33C7D83D60A44B2B70FE8D841A56A4150A01C82B19CB93AE0AAA65E765EFF95933AC55742E0240744158B9CEF9DA8E18C3736BC8894306BF86D9B927CD62252ABFD39A3B352168336404C6B5F0DB4AEE518069274266E0C424F45D487B500BC087F49B53B0FA822D306D8B272E66C035569FFF1A191D354728253419E5B49115B88EB94E8452A28A3D699E73709FFD95D30430D45B730AF36D90C4DF464241C059375E8215E02294DFEAF8169BF1B47F7EE6F6479CB772D552D604589CE0A80BF7C38AFB2D8111D02A11D02264E2D1634128E53835E5815A92C19027DD08493C23344883FA5F2802A67E586221E2E22DFB8C67D75903F7211D52D19DC92DAC9C2E55D5D23E4B316F4F36AE24526C0D7CB5D43A5FA64CD621E9BBEB44ADAC0FB50237872CF13E0008D4D8F3B53B7F97FF8FD71E7B6ECCE359F5FBF3F6128DFD062C1E1177C6DDB97CBB9ED8AF082BF55D2DDF76920020A8AFCA08235752DE7542237D273F0324767F297BD98F573642B54D55AAEDCD9A5DB65DDF24F1E52489E22A8CDB204653F03A45261E20C965772CC92D71AD8A9DCA1205CA72C3AE330CA9ABFC93BD4C0591279661736B131AE905D5EB899BED456FE76BE26C4700FDF3238999B250DEF64F155FED724D3E38BDCAAD31CAC112BF39F0BC0CD3A906BEA43676E126616B51546C9E282117163EA7B38F255797A803F663EA16485FE4A8C2510409D3B6EF809EAC2BF897277A17A9C6E58709B57591FDA62321CEC2F545FCDB0AEEAF33ED378707C81711E003F1E77EEEE292F61E37FDC2FC4F97CEA96E1A4FB8643A9F18C9D6780BC5B815E43AF81E3B1D47D68D5A559C194F35A143B9EAE147D975BEF88D55AF1408BC1705C02F112616D08BFE6A44C0EFAC373CBB557E4953C79ACAA22537936C5DA37 +20170723005838 2 6 100 8191 5 D84B8E9B7259F34AA46062684AD05873FD407C5FA804FFBC429D0DED5B497259FFF7F3C26D7A4C21592FCD658B607A5BDE7C4EAA7F5A3B6B713EAEDD5D0D47029CF51556BAFBBC91819DDA500332F7CE6777565C34CE56ED26BFE90830291C460891DDFEBF4FFFE5F217602081211E73EEC97612AC2C9FE8988738F0DC0FD2241B3C54357109D82FAAB532DB9C18B53B543D43B533FD67E36547972674968EB83AEE7EFC9F2AAF2C610C452EEA89A4FF5089BA6922F35128A844F6350A70671DD53C205AC7A75A1659CD3E57D385AB0BD78AF14DC129B1172884F1FCF5D795B6031A2BEB2410948A422D21AD3A215C85720F5EE695E235E36832E0A559DACDBD2B7CA3A1317CA005A963B49E3337829C40974C70F47540D89AAE625A1FD110874DC13D6E7B5711021F0CFD94C46D87582EBFF78EB2412B6D91DC0250A0B805F5E3B096ACB247C2A247A39164337FB3CB818AD4A950E6347B801DA742E5B532F4FC48815AA62B894FDB23B6E4D448DB62713AA46CC33C7D83D60A44B2B70FE8D841A56A4150A01C82B19CB93AE0AAA65E765EFF95933AC55742E0240744158B9CEF9DA8E18C3736BC8894306BF86D9B927CD62252ABFD39A3B352168336404C6B5F0DB4AEE518069274266E0C424F45D487B500BC087F49B53B0FA822D306D8B272E66C035569FFF1A191D354728253419E5B49115B88EB94E8452A28A3D699E73709FFD95D30430D45B730AF36D90C4DF464241C059375E8215E02294DFEAF8169BF1B47F7EE6F6479CB772D552D604589CE0A80BF7C38AFB2D8111D02A11D02264E2D1634128E53835E5815A92C19027DD08493C23344883FA5F2802A67E586221E2E22DFB8C67D75903F7211D52D19DC92DAC9C2E55D5D23E4B316F4F36AE24526C0D7CB5D43A5FA64CD621E9BBEB44ADAC0FB50237872CF13E0008D4D8F3B53B7F97FF8FD71E7B6ECCE359F5FBF3F6128DFD062C1E1177C6DDB97CBB9ED8AF082BF55D2DDF76920020A8AFCA08235752DE7542237D273F0324767F297BD98F573642B54D55AAEDCD9A5DB65DDF24F1E52489E22A8CDB204653F03A45261E20C965772CC92D71AD8A9DCA1205CA72C3AE330CA9ABFC93BD4C0591279661736B131AE905D5EB899BED456FE76BE26C4700FDF3238999B250DEF64F155FED724D3E38BDCAAD31CAC112BF39F0BC0CD3A906BEA43676E126616B51546C9E282117163EA7B38F255797A803F663EA16485FE4A8C2510409D3B6EF809EAC2BF897277A17A9C6E58709B57591FDA62321CEC2F545FCDB0AEEAF33ED378707C81711E003F1E77EEEE292F61E37FDC2FC4F97CEA96E1A4FB8643A9F18C9D6780BC5B815E43AF81E3B1D47D68D5A559C194F35A143B9EAE147D975BEF88D55AF1408BC1705C02F112616D08BFE6A44C0EFAC373CBB557E4953C79ACAA22537937F9469F +20170723041453 2 6 100 8191 2 D84B8E9B7259F34AA46062684AD05873FD407C5FA804FFBC429D0DED5B497259FFF7F3C26D7A4C21592FCD658B607A5BDE7C4EAA7F5A3B6B713EAEDD5D0D47029CF51556BAFBBC91819DDA500332F7CE6777565C34CE56ED26BFE90830291C460891DDFEBF4FFFE5F217602081211E73EEC97612AC2C9FE8988738F0DC0FD2241B3C54357109D82FAAB532DB9C18B53B543D43B533FD67E36547972674968EB83AEE7EFC9F2AAF2C610C452EEA89A4FF5089BA6922F35128A844F6350A70671DD53C205AC7A75A1659CD3E57D385AB0BD78AF14DC129B1172884F1FCF5D795B6031A2BEB2410948A422D21AD3A215C85720F5EE695E235E36832E0A559DACDBD2B7CA3A1317CA005A963B49E3337829C40974C70F47540D89AAE625A1FD110874DC13D6E7B5711021F0CFD94C46D87582EBFF78EB2412B6D91DC0250A0B805F5E3B096ACB247C2A247A39164337FB3CB818AD4A950E6347B801DA742E5B532F4FC48815AA62B894FDB23B6E4D448DB62713AA46CC33C7D83D60A44B2B70FE8D841A56A4150A01C82B19CB93AE0AAA65E765EFF95933AC55742E0240744158B9CEF9DA8E18C3736BC8894306BF86D9B927CD62252ABFD39A3B352168336404C6B5F0DB4AEE518069274266E0C424F45D487B500BC087F49B53B0FA822D306D8B272E66C035569FFF1A191D354728253419E5B49115B88EB94E8452A28A3D699E73709FFD95D30430D45B730AF36D90C4DF464241C059375E8215E02294DFEAF8169BF1B47F7EE6F6479CB772D552D604589CE0A80BF7C38AFB2D8111D02A11D02264E2D1634128E53835E5815A92C19027DD08493C23344883FA5F2802A67E586221E2E22DFB8C67D75903F7211D52D19DC92DAC9C2E55D5D23E4B316F4F36AE24526C0D7CB5D43A5FA64CD621E9BBEB44ADAC0FB50237872CF13E0008D4D8F3B53B7F97FF8FD71E7B6ECCE359F5FBF3F6128DFD062C1E1177C6DDB97CBB9ED8AF082BF55D2DDF76920020A8AFCA08235752DE7542237D273F0324767F297BD98F573642B54D55AAEDCD9A5DB65DDF24F1E52489E22A8CDB204653F03A45261E20C965772CC92D71AD8A9DCA1205CA72C3AE330CA9ABFC93BD4C0591279661736B131AE905D5EB899BED456FE76BE26C4700FDF3238999B250DEF64F155FED724D3E38BDCAAD31CAC112BF39F0BC0CD3A906BEA43676E126616B51546C9E282117163EA7B38F255797A803F663EA16485FE4A8C2510409D3B6EF809EAC2BF897277A17A9C6E58709B57591FDA62321CEC2F545FCDB0AEEAF33ED378707C81711E003F1E77EEEE292F61E37FDC2FC4F97CEA96E1A4FB8643A9F18C9D6780BC5B815E43AF81E3B1D47D68D5A559C194F35A143B9EAE147D975BEF88D55AF1408BC1705C02F112616D08BFE6A44C0EFAC373CBB557E4953C79ACAA2253793A1DBF1B +20170723051250 2 6 100 8191 2 D84B8E9B7259F34AA46062684AD05873FD407C5FA804FFBC429D0DED5B497259FFF7F3C26D7A4C21592FCD658B607A5BDE7C4EAA7F5A3B6B713EAEDD5D0D47029CF51556BAFBBC91819DDA500332F7CE6777565C34CE56ED26BFE90830291C460891DDFEBF4FFFE5F217602081211E73EEC97612AC2C9FE8988738F0DC0FD2241B3C54357109D82FAAB532DB9C18B53B543D43B533FD67E36547972674968EB83AEE7EFC9F2AAF2C610C452EEA89A4FF5089BA6922F35128A844F6350A70671DD53C205AC7A75A1659CD3E57D385AB0BD78AF14DC129B1172884F1FCF5D795B6031A2BEB2410948A422D21AD3A215C85720F5EE695E235E36832E0A559DACDBD2B7CA3A1317CA005A963B49E3337829C40974C70F47540D89AAE625A1FD110874DC13D6E7B5711021F0CFD94C46D87582EBFF78EB2412B6D91DC0250A0B805F5E3B096ACB247C2A247A39164337FB3CB818AD4A950E6347B801DA742E5B532F4FC48815AA62B894FDB23B6E4D448DB62713AA46CC33C7D83D60A44B2B70FE8D841A56A4150A01C82B19CB93AE0AAA65E765EFF95933AC55742E0240744158B9CEF9DA8E18C3736BC8894306BF86D9B927CD62252ABFD39A3B352168336404C6B5F0DB4AEE518069274266E0C424F45D487B500BC087F49B53B0FA822D306D8B272E66C035569FFF1A191D354728253419E5B49115B88EB94E8452A28A3D699E73709FFD95D30430D45B730AF36D90C4DF464241C059375E8215E02294DFEAF8169BF1B47F7EE6F6479CB772D552D604589CE0A80BF7C38AFB2D8111D02A11D02264E2D1634128E53835E5815A92C19027DD08493C23344883FA5F2802A67E586221E2E22DFB8C67D75903F7211D52D19DC92DAC9C2E55D5D23E4B316F4F36AE24526C0D7CB5D43A5FA64CD621E9BBEB44ADAC0FB50237872CF13E0008D4D8F3B53B7F97FF8FD71E7B6ECCE359F5FBF3F6128DFD062C1E1177C6DDB97CBB9ED8AF082BF55D2DDF76920020A8AFCA08235752DE7542237D273F0324767F297BD98F573642B54D55AAEDCD9A5DB65DDF24F1E52489E22A8CDB204653F03A45261E20C965772CC92D71AD8A9DCA1205CA72C3AE330CA9ABFC93BD4C0591279661736B131AE905D5EB899BED456FE76BE26C4700FDF3238999B250DEF64F155FED724D3E38BDCAAD31CAC112BF39F0BC0CD3A906BEA43676E126616B51546C9E282117163EA7B38F255797A803F663EA16485FE4A8C2510409D3B6EF809EAC2BF897277A17A9C6E58709B57591FDA62321CEC2F545FCDB0AEEAF33ED378707C81711E003F1E77EEEE292F61E37FDC2FC4F97CEA96E1A4FB8643A9F18C9D6780BC5B815E43AF81E3B1D47D68D5A559C194F35A143B9EAE147D975BEF88D55AF1408BC1705C02F112616D08BFE6A44C0EFAC373CBB557E4953C79ACAA2253793AB9FC9B +20170723112206 2 6 100 8191 5 D84B8E9B7259F34AA46062684AD05873FD407C5FA804FFBC429D0DED5B497259FFF7F3C26D7A4C21592FCD658B607A5BDE7C4EAA7F5A3B6B713EAEDD5D0D47029CF51556BAFBBC91819DDA500332F7CE6777565C34CE56ED26BFE90830291C460891DDFEBF4FFFE5F217602081211E73EEC97612AC2C9FE8988738F0DC0FD2241B3C54357109D82FAAB532DB9C18B53B543D43B533FD67E36547972674968EB83AEE7EFC9F2AAF2C610C452EEA89A4FF5089BA6922F35128A844F6350A70671DD53C205AC7A75A1659CD3E57D385AB0BD78AF14DC129B1172884F1FCF5D795B6031A2BEB2410948A422D21AD3A215C85720F5EE695E235E36832E0A559DACDBD2B7CA3A1317CA005A963B49E3337829C40974C70F47540D89AAE625A1FD110874DC13D6E7B5711021F0CFD94C46D87582EBFF78EB2412B6D91DC0250A0B805F5E3B096ACB247C2A247A39164337FB3CB818AD4A950E6347B801DA742E5B532F4FC48815AA62B894FDB23B6E4D448DB62713AA46CC33C7D83D60A44B2B70FE8D841A56A4150A01C82B19CB93AE0AAA65E765EFF95933AC55742E0240744158B9CEF9DA8E18C3736BC8894306BF86D9B927CD62252ABFD39A3B352168336404C6B5F0DB4AEE518069274266E0C424F45D487B500BC087F49B53B0FA822D306D8B272E66C035569FFF1A191D354728253419E5B49115B88EB94E8452A28A3D699E73709FFD95D30430D45B730AF36D90C4DF464241C059375E8215E02294DFEAF8169BF1B47F7EE6F6479CB772D552D604589CE0A80BF7C38AFB2D8111D02A11D02264E2D1634128E53835E5815A92C19027DD08493C23344883FA5F2802A67E586221E2E22DFB8C67D75903F7211D52D19DC92DAC9C2E55D5D23E4B316F4F36AE24526C0D7CB5D43A5FA64CD621E9BBEB44ADAC0FB50237872CF13E0008D4D8F3B53B7F97FF8FD71E7B6ECCE359F5FBF3F6128DFD062C1E1177C6DDB97CBB9ED8AF082BF55D2DDF76920020A8AFCA08235752DE7542237D273F0324767F297BD98F573642B54D55AAEDCD9A5DB65DDF24F1E52489E22A8CDB204653F03A45261E20C965772CC92D71AD8A9DCA1205CA72C3AE330CA9ABFC93BD4C0591279661736B131AE905D5EB899BED456FE76BE26C4700FDF3238999B250DEF64F155FED724D3E38BDCAAD31CAC112BF39F0BC0CD3A906BEA43676E126616B51546C9E282117163EA7B38F255797A803F663EA16485FE4A8C2510409D3B6EF809EAC2BF897277A17A9C6E58709B57591FDA62321CEC2F545FCDB0AEEAF33ED378707C81711E003F1E77EEEE292F61E37FDC2FC4F97CEA96E1A4FB8643A9F18C9D6780BC5B815E43AF81E3B1D47D68D5A559C194F35A143B9EAE147D975BEF88D55AF1408BC1705C02F112616D08BFE6A44C0EFAC373CBB557E4953C79ACAA2253793EBF09F7 +20170723140224 2 6 100 8191 2 D84B8E9B7259F34AA46062684AD05873FD407C5FA804FFBC429D0DED5B497259FFF7F3C26D7A4C21592FCD658B607A5BDE7C4EAA7F5A3B6B713EAEDD5D0D47029CF51556BAFBBC91819DDA500332F7CE6777565C34CE56ED26BFE90830291C460891DDFEBF4FFFE5F217602081211E73EEC97612AC2C9FE8988738F0DC0FD2241B3C54357109D82FAAB532DB9C18B53B543D43B533FD67E36547972674968EB83AEE7EFC9F2AAF2C610C452EEA89A4FF5089BA6922F35128A844F6350A70671DD53C205AC7A75A1659CD3E57D385AB0BD78AF14DC129B1172884F1FCF5D795B6031A2BEB2410948A422D21AD3A215C85720F5EE695E235E36832E0A559DACDBD2B7CA3A1317CA005A963B49E3337829C40974C70F47540D89AAE625A1FD110874DC13D6E7B5711021F0CFD94C46D87582EBFF78EB2412B6D91DC0250A0B805F5E3B096ACB247C2A247A39164337FB3CB818AD4A950E6347B801DA742E5B532F4FC48815AA62B894FDB23B6E4D448DB62713AA46CC33C7D83D60A44B2B70FE8D841A56A4150A01C82B19CB93AE0AAA65E765EFF95933AC55742E0240744158B9CEF9DA8E18C3736BC8894306BF86D9B927CD62252ABFD39A3B352168336404C6B5F0DB4AEE518069274266E0C424F45D487B500BC087F49B53B0FA822D306D8B272E66C035569FFF1A191D354728253419E5B49115B88EB94E8452A28A3D699E73709FFD95D30430D45B730AF36D90C4DF464241C059375E8215E02294DFEAF8169BF1B47F7EE6F6479CB772D552D604589CE0A80BF7C38AFB2D8111D02A11D02264E2D1634128E53835E5815A92C19027DD08493C23344883FA5F2802A67E586221E2E22DFB8C67D75903F7211D52D19DC92DAC9C2E55D5D23E4B316F4F36AE24526C0D7CB5D43A5FA64CD621E9BBEB44ADAC0FB50237872CF13E0008D4D8F3B53B7F97FF8FD71E7B6ECCE359F5FBF3F6128DFD062C1E1177C6DDB97CBB9ED8AF082BF55D2DDF76920020A8AFCA08235752DE7542237D273F0324767F297BD98F573642B54D55AAEDCD9A5DB65DDF24F1E52489E22A8CDB204653F03A45261E20C965772CC92D71AD8A9DCA1205CA72C3AE330CA9ABFC93BD4C0591279661736B131AE905D5EB899BED456FE76BE26C4700FDF3238999B250DEF64F155FED724D3E38BDCAAD31CAC112BF39F0BC0CD3A906BEA43676E126616B51546C9E282117163EA7B38F255797A803F663EA16485FE4A8C2510409D3B6EF809EAC2BF897277A17A9C6E58709B57591FDA62321CEC2F545FCDB0AEEAF33ED378707C81711E003F1E77EEEE292F61E37FDC2FC4F97CEA96E1A4FB8643A9F18C9D6780BC5B815E43AF81E3B1D47D68D5A559C194F35A143B9EAE147D975BEF88D55AF1408BC1705C02F112616D08BFE6A44C0EFAC373CBB557E4953C79ACAA2253794072005B +20170723170945 2 6 100 8191 5 D84B8E9B7259F34AA46062684AD05873FD407C5FA804FFBC429D0DED5B497259FFF7F3C26D7A4C21592FCD658B607A5BDE7C4EAA7F5A3B6B713EAEDD5D0D47029CF51556BAFBBC91819DDA500332F7CE6777565C34CE56ED26BFE90830291C460891DDFEBF4FFFE5F217602081211E73EEC97612AC2C9FE8988738F0DC0FD2241B3C54357109D82FAAB532DB9C18B53B543D43B533FD67E36547972674968EB83AEE7EFC9F2AAF2C610C452EEA89A4FF5089BA6922F35128A844F6350A70671DD53C205AC7A75A1659CD3E57D385AB0BD78AF14DC129B1172884F1FCF5D795B6031A2BEB2410948A422D21AD3A215C85720F5EE695E235E36832E0A559DACDBD2B7CA3A1317CA005A963B49E3337829C40974C70F47540D89AAE625A1FD110874DC13D6E7B5711021F0CFD94C46D87582EBFF78EB2412B6D91DC0250A0B805F5E3B096ACB247C2A247A39164337FB3CB818AD4A950E6347B801DA742E5B532F4FC48815AA62B894FDB23B6E4D448DB62713AA46CC33C7D83D60A44B2B70FE8D841A56A4150A01C82B19CB93AE0AAA65E765EFF95933AC55742E0240744158B9CEF9DA8E18C3736BC8894306BF86D9B927CD62252ABFD39A3B352168336404C6B5F0DB4AEE518069274266E0C424F45D487B500BC087F49B53B0FA822D306D8B272E66C035569FFF1A191D354728253419E5B49115B88EB94E8452A28A3D699E73709FFD95D30430D45B730AF36D90C4DF464241C059375E8215E02294DFEAF8169BF1B47F7EE6F6479CB772D552D604589CE0A80BF7C38AFB2D8111D02A11D02264E2D1634128E53835E5815A92C19027DD08493C23344883FA5F2802A67E586221E2E22DFB8C67D75903F7211D52D19DC92DAC9C2E55D5D23E4B316F4F36AE24526C0D7CB5D43A5FA64CD621E9BBEB44ADAC0FB50237872CF13E0008D4D8F3B53B7F97FF8FD71E7B6ECCE359F5FBF3F6128DFD062C1E1177C6DDB97CBB9ED8AF082BF55D2DDF76920020A8AFCA08235752DE7542237D273F0324767F297BD98F573642B54D55AAEDCD9A5DB65DDF24F1E52489E22A8CDB204653F03A45261E20C965772CC92D71AD8A9DCA1205CA72C3AE330CA9ABFC93BD4C0591279661736B131AE905D5EB899BED456FE76BE26C4700FDF3238999B250DEF64F155FED724D3E38BDCAAD31CAC112BF39F0BC0CD3A906BEA43676E126616B51546C9E282117163EA7B38F255797A803F663EA16485FE4A8C2510409D3B6EF809EAC2BF897277A17A9C6E58709B57591FDA62321CEC2F545FCDB0AEEAF33ED378707C81711E003F1E77EEEE292F61E37FDC2FC4F97CEA96E1A4FB8643A9F18C9D6780BC5B815E43AF81E3B1D47D68D5A559C194F35A143B9EAE147D975BEF88D55AF1408BC1705C02F112616D08BFE6A44C0EFAC373CBB557E4953C79ACAA225379427689A7 +20170724050156 2 6 100 8191 5 D84B8E9B7259F34AA46062684AD05873FD407C5FA804FFBC429D0DED5B497259FFF7F3C26D7A4C21592FCD658B607A5BDE7C4EAA7F5A3B6B713EAEDD5D0D47029CF51556BAFBBC91819DDA500332F7CE6777565C34CE56ED26BFE90830291C460891DDFEBF4FFFE5F217602081211E73EEC97612AC2C9FE8988738F0DC0FD2241B3C54357109D82FAAB532DB9C18B53B543D43B533FD67E36547972674968EB83AEE7EFC9F2AAF2C610C452EEA89A4FF5089BA6922F35128A844F6350A70671DD53C205AC7A75A1659CD3E57D385AB0BD78AF14DC129B1172884F1FCF5D795B6031A2BEB2410948A422D21AD3A215C85720F5EE695E235E36832E0A559DACDBD2B7CA3A1317CA005A963B49E3337829C40974C70F47540D89AAE625A1FD110874DC13D6E7B5711021F0CFD94C46D87582EBFF78EB2412B6D91DC0250A0B805F5E3B096ACB247C2A247A39164337FB3CB818AD4A950E6347B801DA742E5B532F4FC48815AA62B894FDB23B6E4D448DB62713AA46CC33C7D83D60A44B2B70FE8D841A56A4150A01C82B19CB93AE0AAA65E765EFF95933AC55742E0240744158B9CEF9DA8E18C3736BC8894306BF86D9B927CD62252ABFD39A3B352168336404C6B5F0DB4AEE518069274266E0C424F45D487B500BC087F49B53B0FA822D306D8B272E66C035569FFF1A191D354728253419E5B49115B88EB94E8452A28A3D699E73709FFD95D30430D45B730AF36D90C4DF464241C059375E8215E02294DFEAF8169BF1B47F7EE6F6479CB772D552D604589CE0A80BF7C38AFB2D8111D02A11D02264E2D1634128E53835E5815A92C19027DD08493C23344883FA5F2802A67E586221E2E22DFB8C67D75903F7211D52D19DC92DAC9C2E55D5D23E4B316F4F36AE24526C0D7CB5D43A5FA64CD621E9BBEB44ADAC0FB50237872CF13E0008D4D8F3B53B7F97FF8FD71E7B6ECCE359F5FBF3F6128DFD062C1E1177C6DDB97CBB9ED8AF082BF55D2DDF76920020A8AFCA08235752DE7542237D273F0324767F297BD98F573642B54D55AAEDCD9A5DB65DDF24F1E52489E22A8CDB204653F03A45261E20C965772CC92D71AD8A9DCA1205CA72C3AE330CA9ABFC93BD4C0591279661736B131AE905D5EB899BED456FE76BE26C4700FDF3238999B250DEF64F155FED724D3E38BDCAAD31CAC112BF39F0BC0CD3A906BEA43676E126616B51546C9E282117163EA7B38F255797A803F663EA16485FE4A8C2510409D3B6EF809EAC2BF897277A17A9C6E58709B57591FDA62321CEC2F545FCDB0AEEAF33ED378707C81711E003F1E77EEEE292F61E37FDC2FC4F97CEA96E1A4FB8643A9F18C9D6780BC5B815E43AF81E3B1D47D68D5A559C194F35A143B9EAE147D975BEF88D55AF1408BC1705C02F112616D08BFE6A44C0EFAC373CBB557E4953C79ACAA2253794A23E407 +20170724065019 2 6 100 8191 2 D84B8E9B7259F34AA46062684AD05873FD407C5FA804FFBC429D0DED5B497259FFF7F3C26D7A4C21592FCD658B607A5BDE7C4EAA7F5A3B6B713EAEDD5D0D47029CF51556BAFBBC91819DDA500332F7CE6777565C34CE56ED26BFE90830291C460891DDFEBF4FFFE5F217602081211E73EEC97612AC2C9FE8988738F0DC0FD2241B3C54357109D82FAAB532DB9C18B53B543D43B533FD67E36547972674968EB83AEE7EFC9F2AAF2C610C452EEA89A4FF5089BA6922F35128A844F6350A70671DD53C205AC7A75A1659CD3E57D385AB0BD78AF14DC129B1172884F1FCF5D795B6031A2BEB2410948A422D21AD3A215C85720F5EE695E235E36832E0A559DACDBD2B7CA3A1317CA005A963B49E3337829C40974C70F47540D89AAE625A1FD110874DC13D6E7B5711021F0CFD94C46D87582EBFF78EB2412B6D91DC0250A0B805F5E3B096ACB247C2A247A39164337FB3CB818AD4A950E6347B801DA742E5B532F4FC48815AA62B894FDB23B6E4D448DB62713AA46CC33C7D83D60A44B2B70FE8D841A56A4150A01C82B19CB93AE0AAA65E765EFF95933AC55742E0240744158B9CEF9DA8E18C3736BC8894306BF86D9B927CD62252ABFD39A3B352168336404C6B5F0DB4AEE518069274266E0C424F45D487B500BC087F49B53B0FA822D306D8B272E66C035569FFF1A191D354728253419E5B49115B88EB94E8452A28A3D699E73709FFD95D30430D45B730AF36D90C4DF464241C059375E8215E02294DFEAF8169BF1B47F7EE6F6479CB772D552D604589CE0A80BF7C38AFB2D8111D02A11D02264E2D1634128E53835E5815A92C19027DD08493C23344883FA5F2802A67E586221E2E22DFB8C67D75903F7211D52D19DC92DAC9C2E55D5D23E4B316F4F36AE24526C0D7CB5D43A5FA64CD621E9BBEB44ADAC0FB50237872CF13E0008D4D8F3B53B7F97FF8FD71E7B6ECCE359F5FBF3F6128DFD062C1E1177C6DDB97CBB9ED8AF082BF55D2DDF76920020A8AFCA08235752DE7542237D273F0324767F297BD98F573642B54D55AAEDCD9A5DB65DDF24F1E52489E22A8CDB204653F03A45261E20C965772CC92D71AD8A9DCA1205CA72C3AE330CA9ABFC93BD4C0591279661736B131AE905D5EB899BED456FE76BE26C4700FDF3238999B250DEF64F155FED724D3E38BDCAAD31CAC112BF39F0BC0CD3A906BEA43676E126616B51546C9E282117163EA7B38F255797A803F663EA16485FE4A8C2510409D3B6EF809EAC2BF897277A17A9C6E58709B57591FDA62321CEC2F545FCDB0AEEAF33ED378707C81711E003F1E77EEEE292F61E37FDC2FC4F97CEA96E1A4FB8643A9F18C9D6780BC5B815E43AF81E3B1D47D68D5A559C194F35A143B9EAE147D975BEF88D55AF1408BC1705C02F112616D08BFE6A44C0EFAC373CBB557E4953C79ACAA2253794B47E553 +20170725032628 2 6 100 8191 2 D84B8E9B7259F34AA46062684AD05873FD407C5FA804FFBC429D0DED5B497259FFF7F3C26D7A4C21592FCD658B607A5BDE7C4EAA7F5A3B6B713EAEDD5D0D47029CF51556BAFBBC91819DDA500332F7CE6777565C34CE56ED26BFE90830291C460891DDFEBF4FFFE5F217602081211E73EEC97612AC2C9FE8988738F0DC0FD2241B3C54357109D82FAAB532DB9C18B53B543D43B533FD67E36547972674968EB83AEE7EFC9F2AAF2C610C452EEA89A4FF5089BA6922F35128A844F6350A70671DD53C205AC7A75A1659CD3E57D385AB0BD78AF14DC129B1172884F1FCF5D795B6031A2BEB2410948A422D21AD3A215C85720F5EE695E235E36832E0A559DACDBD2B7CA3A1317CA005A963B49E3337829C40974C70F47540D89AAE625A1FD110874DC13D6E7B5711021F0CFD94C46D87582EBFF78EB2412B6D91DC0250A0B805F5E3B096ACB247C2A247A39164337FB3CB818AD4A950E6347B801DA742E5B532F4FC48815AA62B894FDB23B6E4D448DB62713AA46CC33C7D83D60A44B2B70FE8D841A56A4150A01C82B19CB93AE0AAA65E765EFF95933AC55742E0240744158B9CEF9DA8E18C3736BC8894306BF86D9B927CD62252ABFD39A3B352168336404C6B5F0DB4AEE518069274266E0C424F45D487B500BC087F49B53B0FA822D306D8B272E66C035569FFF1A191D354728253419E5B49115B88EB94E8452A28A3D699E73709FFD95D30430D45B730AF36D90C4DF464241C059375E8215E02294DFEAF8169BF1B47F7EE6F6479CB772D552D604589CE0A80BF7C38AFB2D8111D02A11D02264E2D1634128E53835E5815A92C19027DD08493C23344883FA5F2802A67E586221E2E22DFB8C67D75903F7211D52D19DC92DAC9C2E55D5D23E4B316F4F36AE24526C0D7CB5D43A5FA64CD621E9BBEB44ADAC0FB50237872CF13E0008D4D8F3B53B7F97FF8FD71E7B6ECCE359F5FBF3F6128DFD062C1E1177C6DDB97CBB9ED8AF082BF55D2DDF76920020A8AFCA08235752DE7542237D273F0324767F297BD98F573642B54D55AAEDCD9A5DB65DDF24F1E52489E22A8CDB204653F03A45261E20C965772CC92D71AD8A9DCA1205CA72C3AE330CA9ABFC93BD4C0591279661736B131AE905D5EB899BED456FE76BE26C4700FDF3238999B250DEF64F155FED724D3E38BDCAAD31CAC112BF39F0BC0CD3A906BEA43676E126616B51546C9E282117163EA7B38F255797A803F663EA16485FE4A8C2510409D3B6EF809EAC2BF897277A17A9C6E58709B57591FDA62321CEC2F545FCDB0AEEAF33ED378707C81711E003F1E77EEEE292F61E37FDC2FC4F97CEA96E1A4FB8643A9F18C9D6780BC5B815E43AF81E3B1D47D68D5A559C194F35A143B9EAE147D975BEF88D55AF1408BC1705C02F112616D08BFE6A44C0EFAC373CBB557E4953C79ACAA225379588A6BE3 +20170725142722 2 6 100 8191 2 D84B8E9B7259F34AA46062684AD05873FD407C5FA804FFBC429D0DED5B497259FFF7F3C26D7A4C21592FCD658B607A5BDE7C4EAA7F5A3B6B713EAEDD5D0D47029CF51556BAFBBC91819DDA500332F7CE6777565C34CE56ED26BFE90830291C460891DDFEBF4FFFE5F217602081211E73EEC97612AC2C9FE8988738F0DC0FD2241B3C54357109D82FAAB532DB9C18B53B543D43B533FD67E36547972674968EB83AEE7EFC9F2AAF2C610C452EEA89A4FF5089BA6922F35128A844F6350A70671DD53C205AC7A75A1659CD3E57D385AB0BD78AF14DC129B1172884F1FCF5D795B6031A2BEB2410948A422D21AD3A215C85720F5EE695E235E36832E0A559DACDBD2B7CA3A1317CA005A963B49E3337829C40974C70F47540D89AAE625A1FD110874DC13D6E7B5711021F0CFD94C46D87582EBFF78EB2412B6D91DC0250A0B805F5E3B096ACB247C2A247A39164337FB3CB818AD4A950E6347B801DA742E5B532F4FC48815AA62B894FDB23B6E4D448DB62713AA46CC33C7D83D60A44B2B70FE8D841A56A4150A01C82B19CB93AE0AAA65E765EFF95933AC55742E0240744158B9CEF9DA8E18C3736BC8894306BF86D9B927CD62252ABFD39A3B352168336404C6B5F0DB4AEE518069274266E0C424F45D487B500BC087F49B53B0FA822D306D8B272E66C035569FFF1A191D354728253419E5B49115B88EB94E8452A28A3D699E73709FFD95D30430D45B730AF36D90C4DF464241C059375E8215E02294DFEAF8169BF1B47F7EE6F6479CB772D552D604589CE0A80BF7C38AFB2D8111D02A11D02264E2D1634128E53835E5815A92C19027DD08493C23344883FA5F2802A67E586221E2E22DFB8C67D75903F7211D52D19DC92DAC9C2E55D5D23E4B316F4F36AE24526C0D7CB5D43A5FA64CD621E9BBEB44ADAC0FB50237872CF13E0008D4D8F3B53B7F97FF8FD71E7B6ECCE359F5FBF3F6128DFD062C1E1177C6DDB97CBB9ED8AF082BF55D2DDF76920020A8AFCA08235752DE7542237D273F0324767F297BD98F573642B54D55AAEDCD9A5DB65DDF24F1E52489E22A8CDB204653F03A45261E20C965772CC92D71AD8A9DCA1205CA72C3AE330CA9ABFC93BD4C0591279661736B131AE905D5EB899BED456FE76BE26C4700FDF3238999B250DEF64F155FED724D3E38BDCAAD31CAC112BF39F0BC0CD3A906BEA43676E126616B51546C9E282117163EA7B38F255797A803F663EA16485FE4A8C2510409D3B6EF809EAC2BF897277A17A9C6E58709B57591FDA62321CEC2F545FCDB0AEEAF33ED378707C81711E003F1E77EEEE292F61E37FDC2FC4F97CEA96E1A4FB8643A9F18C9D6780BC5B815E43AF81E3B1D47D68D5A559C194F35A143B9EAE147D975BEF88D55AF1408BC1705C02F112616D08BFE6A44C0EFAC373CBB557E4953C79ACAA2253795F8CFE9B +20170725192821 2 6 100 8191 2 D84B8E9B7259F34AA46062684AD05873FD407C5FA804FFBC429D0DED5B497259FFF7F3C26D7A4C21592FCD658B607A5BDE7C4EAA7F5A3B6B713EAEDD5D0D47029CF51556BAFBBC91819DDA500332F7CE6777565C34CE56ED26BFE90830291C460891DDFEBF4FFFE5F217602081211E73EEC97612AC2C9FE8988738F0DC0FD2241B3C54357109D82FAAB532DB9C18B53B543D43B533FD67E36547972674968EB83AEE7EFC9F2AAF2C610C452EEA89A4FF5089BA6922F35128A844F6350A70671DD53C205AC7A75A1659CD3E57D385AB0BD78AF14DC129B1172884F1FCF5D795B6031A2BEB2410948A422D21AD3A215C85720F5EE695E235E36832E0A559DACDBD2B7CA3A1317CA005A963B49E3337829C40974C70F47540D89AAE625A1FD110874DC13D6E7B5711021F0CFD94C46D87582EBFF78EB2412B6D91DC0250A0B805F5E3B096ACB247C2A247A39164337FB3CB818AD4A950E6347B801DA742E5B532F4FC48815AA62B894FDB23B6E4D448DB62713AA46CC33C7D83D60A44B2B70FE8D841A56A4150A01C82B19CB93AE0AAA65E765EFF95933AC55742E0240744158B9CEF9DA8E18C3736BC8894306BF86D9B927CD62252ABFD39A3B352168336404C6B5F0DB4AEE518069274266E0C424F45D487B500BC087F49B53B0FA822D306D8B272E66C035569FFF1A191D354728253419E5B49115B88EB94E8452A28A3D699E73709FFD95D30430D45B730AF36D90C4DF464241C059375E8215E02294DFEAF8169BF1B47F7EE6F6479CB772D552D604589CE0A80BF7C38AFB2D8111D02A11D02264E2D1634128E53835E5815A92C19027DD08493C23344883FA5F2802A67E586221E2E22DFB8C67D75903F7211D52D19DC92DAC9C2E55D5D23E4B316F4F36AE24526C0D7CB5D43A5FA64CD621E9BBEB44ADAC0FB50237872CF13E0008D4D8F3B53B7F97FF8FD71E7B6ECCE359F5FBF3F6128DFD062C1E1177C6DDB97CBB9ED8AF082BF55D2DDF76920020A8AFCA08235752DE7542237D273F0324767F297BD98F573642B54D55AAEDCD9A5DB65DDF24F1E52489E22A8CDB204653F03A45261E20C965772CC92D71AD8A9DCA1205CA72C3AE330CA9ABFC93BD4C0591279661736B131AE905D5EB899BED456FE76BE26C4700FDF3238999B250DEF64F155FED724D3E38BDCAAD31CAC112BF39F0BC0CD3A906BEA43676E126616B51546C9E282117163EA7B38F255797A803F663EA16485FE4A8C2510409D3B6EF809EAC2BF897277A17A9C6E58709B57591FDA62321CEC2F545FCDB0AEEAF33ED378707C81711E003F1E77EEEE292F61E37FDC2FC4F97CEA96E1A4FB8643A9F18C9D6780BC5B815E43AF81E3B1D47D68D5A559C194F35A143B9EAE147D975BEF88D55AF1408BC1705C02F112616D08BFE6A44C0EFAC373CBB557E4953C79ACAA22537962B35BAB +20170726032919 2 6 100 8191 5 D84B8E9B7259F34AA46062684AD05873FD407C5FA804FFBC429D0DED5B497259FFF7F3C26D7A4C21592FCD658B607A5BDE7C4EAA7F5A3B6B713EAEDD5D0D47029CF51556BAFBBC91819DDA500332F7CE6777565C34CE56ED26BFE90830291C460891DDFEBF4FFFE5F217602081211E73EEC97612AC2C9FE8988738F0DC0FD2241B3C54357109D82FAAB532DB9C18B53B543D43B533FD67E36547972674968EB83AEE7EFC9F2AAF2C610C452EEA89A4FF5089BA6922F35128A844F6350A70671DD53C205AC7A75A1659CD3E57D385AB0BD78AF14DC129B1172884F1FCF5D795B6031A2BEB2410948A422D21AD3A215C85720F5EE695E235E36832E0A559DACDBD2B7CA3A1317CA005A963B49E3337829C40974C70F47540D89AAE625A1FD110874DC13D6E7B5711021F0CFD94C46D87582EBFF78EB2412B6D91DC0250A0B805F5E3B096ACB247C2A247A39164337FB3CB818AD4A950E6347B801DA742E5B532F4FC48815AA62B894FDB23B6E4D448DB62713AA46CC33C7D83D60A44B2B70FE8D841A56A4150A01C82B19CB93AE0AAA65E765EFF95933AC55742E0240744158B9CEF9DA8E18C3736BC8894306BF86D9B927CD62252ABFD39A3B352168336404C6B5F0DB4AEE518069274266E0C424F45D487B500BC087F49B53B0FA822D306D8B272E66C035569FFF1A191D354728253419E5B49115B88EB94E8452A28A3D699E73709FFD95D30430D45B730AF36D90C4DF464241C059375E8215E02294DFEAF8169BF1B47F7EE6F6479CB772D552D604589CE0A80BF7C38AFB2D8111D02A11D02264E2D1634128E53835E5815A92C19027DD08493C23344883FA5F2802A67E586221E2E22DFB8C67D75903F7211D52D19DC92DAC9C2E55D5D23E4B316F4F36AE24526C0D7CB5D43A5FA64CD621E9BBEB44ADAC0FB50237872CF13E0008D4D8F3B53B7F97FF8FD71E7B6ECCE359F5FBF3F6128DFD062C1E1177C6DDB97CBB9ED8AF082BF55D2DDF76920020A8AFCA08235752DE7542237D273F0324767F297BD98F573642B54D55AAEDCD9A5DB65DDF24F1E52489E22A8CDB204653F03A45261E20C965772CC92D71AD8A9DCA1205CA72C3AE330CA9ABFC93BD4C0591279661736B131AE905D5EB899BED456FE76BE26C4700FDF3238999B250DEF64F155FED724D3E38BDCAAD31CAC112BF39F0BC0CD3A906BEA43676E126616B51546C9E282117163EA7B38F255797A803F663EA16485FE4A8C2510409D3B6EF809EAC2BF897277A17A9C6E58709B57591FDA62321CEC2F545FCDB0AEEAF33ED378707C81711E003F1E77EEEE292F61E37FDC2FC4F97CEA96E1A4FB8643A9F18C9D6780BC5B815E43AF81E3B1D47D68D5A559C194F35A143B9EAE147D975BEF88D55AF1408BC1705C02F112616D08BFE6A44C0EFAC373CBB557E4953C79ACAA22537967BE1D7F +20170726062511 2 6 100 8191 2 D84B8E9B7259F34AA46062684AD05873FD407C5FA804FFBC429D0DED5B497259FFF7F3C26D7A4C21592FCD658B607A5BDE7C4EAA7F5A3B6B713EAEDD5D0D47029CF51556BAFBBC91819DDA500332F7CE6777565C34CE56ED26BFE90830291C460891DDFEBF4FFFE5F217602081211E73EEC97612AC2C9FE8988738F0DC0FD2241B3C54357109D82FAAB532DB9C18B53B543D43B533FD67E36547972674968EB83AEE7EFC9F2AAF2C610C452EEA89A4FF5089BA6922F35128A844F6350A70671DD53C205AC7A75A1659CD3E57D385AB0BD78AF14DC129B1172884F1FCF5D795B6031A2BEB2410948A422D21AD3A215C85720F5EE695E235E36832E0A559DACDBD2B7CA3A1317CA005A963B49E3337829C40974C70F47540D89AAE625A1FD110874DC13D6E7B5711021F0CFD94C46D87582EBFF78EB2412B6D91DC0250A0B805F5E3B096ACB247C2A247A39164337FB3CB818AD4A950E6347B801DA742E5B532F4FC48815AA62B894FDB23B6E4D448DB62713AA46CC33C7D83D60A44B2B70FE8D841A56A4150A01C82B19CB93AE0AAA65E765EFF95933AC55742E0240744158B9CEF9DA8E18C3736BC8894306BF86D9B927CD62252ABFD39A3B352168336404C6B5F0DB4AEE518069274266E0C424F45D487B500BC087F49B53B0FA822D306D8B272E66C035569FFF1A191D354728253419E5B49115B88EB94E8452A28A3D699E73709FFD95D30430D45B730AF36D90C4DF464241C059375E8215E02294DFEAF8169BF1B47F7EE6F6479CB772D552D604589CE0A80BF7C38AFB2D8111D02A11D02264E2D1634128E53835E5815A92C19027DD08493C23344883FA5F2802A67E586221E2E22DFB8C67D75903F7211D52D19DC92DAC9C2E55D5D23E4B316F4F36AE24526C0D7CB5D43A5FA64CD621E9BBEB44ADAC0FB50237872CF13E0008D4D8F3B53B7F97FF8FD71E7B6ECCE359F5FBF3F6128DFD062C1E1177C6DDB97CBB9ED8AF082BF55D2DDF76920020A8AFCA08235752DE7542237D273F0324767F297BD98F573642B54D55AAEDCD9A5DB65DDF24F1E52489E22A8CDB204653F03A45261E20C965772CC92D71AD8A9DCA1205CA72C3AE330CA9ABFC93BD4C0591279661736B131AE905D5EB899BED456FE76BE26C4700FDF3238999B250DEF64F155FED724D3E38BDCAAD31CAC112BF39F0BC0CD3A906BEA43676E126616B51546C9E282117163EA7B38F255797A803F663EA16485FE4A8C2510409D3B6EF809EAC2BF897277A17A9C6E58709B57591FDA62321CEC2F545FCDB0AEEAF33ED378707C81711E003F1E77EEEE292F61E37FDC2FC4F97CEA96E1A4FB8643A9F18C9D6780BC5B815E43AF81E3B1D47D68D5A559C194F35A143B9EAE147D975BEF88D55AF1408BC1705C02F112616D08BFE6A44C0EFAC373CBB557E4953C79ACAA22537969930233 +20170726073958 2 6 100 8191 2 D84B8E9B7259F34AA46062684AD05873FD407C5FA804FFBC429D0DED5B497259FFF7F3C26D7A4C21592FCD658B607A5BDE7C4EAA7F5A3B6B713EAEDD5D0D47029CF51556BAFBBC91819DDA500332F7CE6777565C34CE56ED26BFE90830291C460891DDFEBF4FFFE5F217602081211E73EEC97612AC2C9FE8988738F0DC0FD2241B3C54357109D82FAAB532DB9C18B53B543D43B533FD67E36547972674968EB83AEE7EFC9F2AAF2C610C452EEA89A4FF5089BA6922F35128A844F6350A70671DD53C205AC7A75A1659CD3E57D385AB0BD78AF14DC129B1172884F1FCF5D795B6031A2BEB2410948A422D21AD3A215C85720F5EE695E235E36832E0A559DACDBD2B7CA3A1317CA005A963B49E3337829C40974C70F47540D89AAE625A1FD110874DC13D6E7B5711021F0CFD94C46D87582EBFF78EB2412B6D91DC0250A0B805F5E3B096ACB247C2A247A39164337FB3CB818AD4A950E6347B801DA742E5B532F4FC48815AA62B894FDB23B6E4D448DB62713AA46CC33C7D83D60A44B2B70FE8D841A56A4150A01C82B19CB93AE0AAA65E765EFF95933AC55742E0240744158B9CEF9DA8E18C3736BC8894306BF86D9B927CD62252ABFD39A3B352168336404C6B5F0DB4AEE518069274266E0C424F45D487B500BC087F49B53B0FA822D306D8B272E66C035569FFF1A191D354728253419E5B49115B88EB94E8452A28A3D699E73709FFD95D30430D45B730AF36D90C4DF464241C059375E8215E02294DFEAF8169BF1B47F7EE6F6479CB772D552D604589CE0A80BF7C38AFB2D8111D02A11D02264E2D1634128E53835E5815A92C19027DD08493C23344883FA5F2802A67E586221E2E22DFB8C67D75903F7211D52D19DC92DAC9C2E55D5D23E4B316F4F36AE24526C0D7CB5D43A5FA64CD621E9BBEB44ADAC0FB50237872CF13E0008D4D8F3B53B7F97FF8FD71E7B6ECCE359F5FBF3F6128DFD062C1E1177C6DDB97CBB9ED8AF082BF55D2DDF76920020A8AFCA08235752DE7542237D273F0324767F297BD98F573642B54D55AAEDCD9A5DB65DDF24F1E52489E22A8CDB204653F03A45261E20C965772CC92D71AD8A9DCA1205CA72C3AE330CA9ABFC93BD4C0591279661736B131AE905D5EB899BED456FE76BE26C4700FDF3238999B250DEF64F155FED724D3E38BDCAAD31CAC112BF39F0BC0CD3A906BEA43676E126616B51546C9E282117163EA7B38F255797A803F663EA16485FE4A8C2510409D3B6EF809EAC2BF897277A17A9C6E58709B57591FDA62321CEC2F545FCDB0AEEAF33ED378707C81711E003F1E77EEEE292F61E37FDC2FC4F97CEA96E1A4FB8643A9F18C9D6780BC5B815E43AF81E3B1D47D68D5A559C194F35A143B9EAE147D975BEF88D55AF1408BC1705C02F112616D08BFE6A44C0EFAC373CBB557E4953C79ACAA2253796A4B8B7B +20170726144150 2 6 100 8191 5 D84B8E9B7259F34AA46062684AD05873FD407C5FA804FFBC429D0DED5B497259FFF7F3C26D7A4C21592FCD658B607A5BDE7C4EAA7F5A3B6B713EAEDD5D0D47029CF51556BAFBBC91819DDA500332F7CE6777565C34CE56ED26BFE90830291C460891DDFEBF4FFFE5F217602081211E73EEC97612AC2C9FE8988738F0DC0FD2241B3C54357109D82FAAB532DB9C18B53B543D43B533FD67E36547972674968EB83AEE7EFC9F2AAF2C610C452EEA89A4FF5089BA6922F35128A844F6350A70671DD53C205AC7A75A1659CD3E57D385AB0BD78AF14DC129B1172884F1FCF5D795B6031A2BEB2410948A422D21AD3A215C85720F5EE695E235E36832E0A559DACDBD2B7CA3A1317CA005A963B49E3337829C40974C70F47540D89AAE625A1FD110874DC13D6E7B5711021F0CFD94C46D87582EBFF78EB2412B6D91DC0250A0B805F5E3B096ACB247C2A247A39164337FB3CB818AD4A950E6347B801DA742E5B532F4FC48815AA62B894FDB23B6E4D448DB62713AA46CC33C7D83D60A44B2B70FE8D841A56A4150A01C82B19CB93AE0AAA65E765EFF95933AC55742E0240744158B9CEF9DA8E18C3736BC8894306BF86D9B927CD62252ABFD39A3B352168336404C6B5F0DB4AEE518069274266E0C424F45D487B500BC087F49B53B0FA822D306D8B272E66C035569FFF1A191D354728253419E5B49115B88EB94E8452A28A3D699E73709FFD95D30430D45B730AF36D90C4DF464241C059375E8215E02294DFEAF8169BF1B47F7EE6F6479CB772D552D604589CE0A80BF7C38AFB2D8111D02A11D02264E2D1634128E53835E5815A92C19027DD08493C23344883FA5F2802A67E586221E2E22DFB8C67D75903F7211D52D19DC92DAC9C2E55D5D23E4B316F4F36AE24526C0D7CB5D43A5FA64CD621E9BBEB44ADAC0FB50237872CF13E0008D4D8F3B53B7F97FF8FD71E7B6ECCE359F5FBF3F6128DFD062C1E1177C6DDB97CBB9ED8AF082BF55D2DDF76920020A8AFCA08235752DE7542237D273F0324767F297BD98F573642B54D55AAEDCD9A5DB65DDF24F1E52489E22A8CDB204653F03A45261E20C965772CC92D71AD8A9DCA1205CA72C3AE330CA9ABFC93BD4C0591279661736B131AE905D5EB899BED456FE76BE26C4700FDF3238999B250DEF64F155FED724D3E38BDCAAD31CAC112BF39F0BC0CD3A906BEA43676E126616B51546C9E282117163EA7B38F255797A803F663EA16485FE4A8C2510409D3B6EF809EAC2BF897277A17A9C6E58709B57591FDA62321CEC2F545FCDB0AEEAF33ED378707C81711E003F1E77EEEE292F61E37FDC2FC4F97CEA96E1A4FB8643A9F18C9D6780BC5B815E43AF81E3B1D47D68D5A559C194F35A143B9EAE147D975BEF88D55AF1408BC1705C02F112616D08BFE6A44C0EFAC373CBB557E4953C79ACAA2253796EA9D3DF +20170726150548 2 6 100 8191 2 D84B8E9B7259F34AA46062684AD05873FD407C5FA804FFBC429D0DED5B497259FFF7F3C26D7A4C21592FCD658B607A5BDE7C4EAA7F5A3B6B713EAEDD5D0D47029CF51556BAFBBC91819DDA500332F7CE6777565C34CE56ED26BFE90830291C460891DDFEBF4FFFE5F217602081211E73EEC97612AC2C9FE8988738F0DC0FD2241B3C54357109D82FAAB532DB9C18B53B543D43B533FD67E36547972674968EB83AEE7EFC9F2AAF2C610C452EEA89A4FF5089BA6922F35128A844F6350A70671DD53C205AC7A75A1659CD3E57D385AB0BD78AF14DC129B1172884F1FCF5D795B6031A2BEB2410948A422D21AD3A215C85720F5EE695E235E36832E0A559DACDBD2B7CA3A1317CA005A963B49E3337829C40974C70F47540D89AAE625A1FD110874DC13D6E7B5711021F0CFD94C46D87582EBFF78EB2412B6D91DC0250A0B805F5E3B096ACB247C2A247A39164337FB3CB818AD4A950E6347B801DA742E5B532F4FC48815AA62B894FDB23B6E4D448DB62713AA46CC33C7D83D60A44B2B70FE8D841A56A4150A01C82B19CB93AE0AAA65E765EFF95933AC55742E0240744158B9CEF9DA8E18C3736BC8894306BF86D9B927CD62252ABFD39A3B352168336404C6B5F0DB4AEE518069274266E0C424F45D487B500BC087F49B53B0FA822D306D8B272E66C035569FFF1A191D354728253419E5B49115B88EB94E8452A28A3D699E73709FFD95D30430D45B730AF36D90C4DF464241C059375E8215E02294DFEAF8169BF1B47F7EE6F6479CB772D552D604589CE0A80BF7C38AFB2D8111D02A11D02264E2D1634128E53835E5815A92C19027DD08493C23344883FA5F2802A67E586221E2E22DFB8C67D75903F7211D52D19DC92DAC9C2E55D5D23E4B316F4F36AE24526C0D7CB5D43A5FA64CD621E9BBEB44ADAC0FB50237872CF13E0008D4D8F3B53B7F97FF8FD71E7B6ECCE359F5FBF3F6128DFD062C1E1177C6DDB97CBB9ED8AF082BF55D2DDF76920020A8AFCA08235752DE7542237D273F0324767F297BD98F573642B54D55AAEDCD9A5DB65DDF24F1E52489E22A8CDB204653F03A45261E20C965772CC92D71AD8A9DCA1205CA72C3AE330CA9ABFC93BD4C0591279661736B131AE905D5EB899BED456FE76BE26C4700FDF3238999B250DEF64F155FED724D3E38BDCAAD31CAC112BF39F0BC0CD3A906BEA43676E126616B51546C9E282117163EA7B38F255797A803F663EA16485FE4A8C2510409D3B6EF809EAC2BF897277A17A9C6E58709B57591FDA62321CEC2F545FCDB0AEEAF33ED378707C81711E003F1E77EEEE292F61E37FDC2FC4F97CEA96E1A4FB8643A9F18C9D6780BC5B815E43AF81E3B1D47D68D5A559C194F35A143B9EAE147D975BEF88D55AF1408BC1705C02F112616D08BFE6A44C0EFAC373CBB557E4953C79ACAA2253796EE14A73 diff --git a/rooter/0routerspecfic/ext-ssh/files/etc/ssh/ssh_config b/rooter/0routerspecfic/ext-ssh/files/etc/ssh/ssh_config new file mode 100644 index 0000000..ea30e3d --- /dev/null +++ b/rooter/0routerspecfic/ext-ssh/files/etc/ssh/ssh_config @@ -0,0 +1,49 @@ +# $OpenBSD: ssh_config,v 1.33 2017/05/07 23:12:57 djm Exp $ + +# This is the ssh client system-wide configuration file. See +# ssh_config(5) for more information. This file provides defaults for +# users, and the values can be changed in per-user configuration files +# or on the command line. + +# Configuration data is parsed as follows: +# 1. command line options +# 2. user-specific file +# 3. system-wide file +# Any configuration value is only changed the first time it is set. +# Thus, host-specific definitions should be at the beginning of the +# configuration file, and defaults at the end. + +# Site-wide defaults for some commonly used options. For a comprehensive +# list of available options, their meanings and defaults, please see the +# ssh_config(5) man page. + +# Host * +# ForwardAgent no +# ForwardX11 no +# PasswordAuthentication yes +# HostbasedAuthentication no +# GSSAPIAuthentication no +# GSSAPIDelegateCredentials no +# BatchMode no +# CheckHostIP yes +# AddressFamily any +# ConnectTimeout 0 +# StrictHostKeyChecking ask +# IdentityFile ~/.ssh/id_rsa +# IdentityFile ~/.ssh/id_dsa +# IdentityFile ~/.ssh/id_ecdsa +# IdentityFile ~/.ssh/id_ed25519 +# Port 22 +# Protocol 2 +# Ciphers aes128-ctr,aes192-ctr,aes256-ctr,aes128-cbc,3des-cbc +# MACs hmac-md5,hmac-sha1,umac-64@openssh.com +# EscapeChar ~ +# Tunnel no +# TunnelDevice any:any +# PermitLocalCommand no +# VisualHostKey no +# ProxyCommand ssh -q -W %h:%p gateway.example.com +# RekeyLimit 1G 1h + +# enable DSCP QoS values (per RFC-4594) +#IPQoS AF21 AF11 diff --git a/rooter/0routerspecfic/ext-ssh/files/etc/ssh/ssh_host_ecdsa_key b/rooter/0routerspecfic/ext-ssh/files/etc/ssh/ssh_host_ecdsa_key new file mode 100644 index 0000000..54f6b67 --- /dev/null +++ b/rooter/0routerspecfic/ext-ssh/files/etc/ssh/ssh_host_ecdsa_key @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIKZXyqVFZe7cRezB7I7Ro4NvdfdBaTCr81muBTDMXjAToAoGCCqGSM49 +AwEHoUQDQgAEPEAIY3VWttvqOPlt/LdQixGVohe8RMNlV+fuwInkTOliZgiCodD4 +jwmH3QnF8LAKs1bVndzKP7PIwQBWWXDxoQ== +-----END EC PRIVATE KEY----- diff --git a/rooter/0routerspecfic/ext-ssh/files/etc/ssh/ssh_host_ecdsa_key.pub b/rooter/0routerspecfic/ext-ssh/files/etc/ssh/ssh_host_ecdsa_key.pub new file mode 100644 index 0000000..61f2c95 --- /dev/null +++ b/rooter/0routerspecfic/ext-ssh/files/etc/ssh/ssh_host_ecdsa_key.pub @@ -0,0 +1 @@ +ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBDxACGN1Vrbb6jj5bfy3UIsRlaIXvETDZVfn7sCJ5EzpYmYIgqHQ+I8Jh90JxfCwCrNW1Z3cyj+zyMEAVllw8aE= root@turris diff --git a/rooter/0routerspecfic/ext-ssh/files/etc/ssh/ssh_host_ed25519_key b/rooter/0routerspecfic/ext-ssh/files/etc/ssh/ssh_host_ed25519_key new file mode 100644 index 0000000..cca7f69 --- /dev/null +++ b/rooter/0routerspecfic/ext-ssh/files/etc/ssh/ssh_host_ed25519_key @@ -0,0 +1,7 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW +QyNTUxOQAAACCAHDv6w/Pu5expKfxxcMjdwZSnZwRwLUNdzti8AQQVOAAAAJBx+cA4cfnA +OAAAAAtzc2gtZWQyNTUxOQAAACCAHDv6w/Pu5expKfxxcMjdwZSnZwRwLUNdzti8AQQVOA +AAAEAuYUyH5sKhsCf0WOtfm1YEf/I9Q5qS3R4aRZETsqlin4AcO/rD8+7l7Gkp/HFwyN3B +lKdnBHAtQ13O2LwBBBU4AAAAC3Jvb3RAdHVycmlzAQI= +-----END OPENSSH PRIVATE KEY----- diff --git a/rooter/0routerspecfic/ext-ssh/files/etc/ssh/ssh_host_ed25519_key.pub b/rooter/0routerspecfic/ext-ssh/files/etc/ssh/ssh_host_ed25519_key.pub new file mode 100644 index 0000000..13946ef --- /dev/null +++ b/rooter/0routerspecfic/ext-ssh/files/etc/ssh/ssh_host_ed25519_key.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIAcO/rD8+7l7Gkp/HFwyN3BlKdnBHAtQ13O2LwBBBU4 root@turris diff --git a/rooter/0routerspecfic/ext-ssh/files/etc/ssh/ssh_host_rsa_key b/rooter/0routerspecfic/ext-ssh/files/etc/ssh/ssh_host_rsa_key new file mode 100644 index 0000000..c358ee3 --- /dev/null +++ b/rooter/0routerspecfic/ext-ssh/files/etc/ssh/ssh_host_rsa_key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAy61T4RsAj2ebjwLoa3F/JkMCbgbg9XxyuvHq/w/mCYBy5s0/ +Js5gEahrKYRfez2xCwt7IXb6qOLenQHoD6YywhJZHo/g1HLtuOz+o44OVmwAOAN7 +P4k7igfe7tK7bJyb0zjOqQjiTxc5pkI07S1AEiLNo+BYdpzcRnpAaHrH8anN//6S +Z8xwzj4zI+9e2TkZUbtkPWjmk9Fa1Wlnt7fN1HSU/Rm72d5chUhQd85d5+WDkgzv +t21C2Wi7tUEsarR8Ac8RRfdfie6SilJsdmnlz+dgBWbWbUGyl9BI31ugIJfQqXx1 +PgzcHu7HROj1ab/8nrI3xpe9fdvmQQQxMnuORQIDAQABAoIBAQCtGJwttjYOqf3h +V5ZRIb7utIpPGdd7qg0TZd/Sbx+QObLtBcfC4idxOlIAkbhX08Ev4sz9TtGOUGji +xKkFC7kdiFxnBd4Mj7QKspdiRqtWtSimcgb/o1CPaUsEauHQV3Ry2VeA/sTedJ2Q +97llTEykXSGpQVPNUlg+KU2tvZNJhAMRRyEw0YkYTrOQntuDOGLb8iALOHCs87OW +GpNNsj/FBM+IoP89W/gvdPm/9ceDd1g8vfkxLQOs56Fnj1AaLJHgNoQtDS/LZaIH +y0z9eTKEP+HsQkthOp4zn3W7Rv1RDpUVgjBNOQgTNgDDIgINOFTwZ4YxVpyr9JZW +45lCg0ihAoGBAOk18Qf4fJHiUHoj/z3Vj0BYsb1xyN9YkHHFZhIk6Ws4Yx8RKM5R +I9amvJu9Tbkzjtu6+6eO7HJ7UMd3sfy2tqMpUq88FAWe0dvM0GYb6y2xeoUM/Ydq +lZon+dXkHpFJ4vwkSB7jV78SQVU2ofc2RD/npVaJQt6UfzwA1R36K6b5AoGBAN+U +kJtMgpUHE0U43aWJ/HOsaIYWKTpsWEoPImdDa8YqCmOUlNnQeKRFmTyMpuohYbhk +FxP+gFKkCxCLKPBLgDiHHHhg7TAiqA2gcHyAm0yN4jPgOq95ojYguk8ZbHYhjrsV +gQN9iWRiCPZo/tlAG4y570W4SbmEoNmKMsdtL3itAoGAauR9mRCtUFSyXHmZaWc0 +pOLCfTnlP3IhqvQ2x8RBdRLAZCICWSbZzW5Zbu0C7guSxGZdKL0a5ZJeQT88xr+c +0QaEzqsz5iuYty2Wq+bKEgSSSt/caTBSZ/lAy2gnFqMONlIO+JFty7d7WKqU7HHk +MIJlx1dc3hakhwU+qeHcFkkCgYEAh7eBCCQraBdBZVWdhez656SSVkKBiEtYVKxX +L+PHOiUu5T++E3HuqZjt6clfUOQuk2V+dM6aSo/1f3dZxHOwQ6AQcio0EHIZHRx0 +676Nhqzh0KeeOAJXqw+2yGkgY5z/LSViiSHdEqhH1Hvrpyi5EHWVfvbdGdYeZa70 +IAZxOIkCgYAUJlSS5/30F0oaANxD6We8vHifLzrYBiQouuED+aXpry/+Zq3kYhBy +Y5HPVDSbshwYBLQOJyOEN3ljG/ZzUJod+HlLu+YchAcPRS+svCFw4lNGvchOEz4y +RZGweJAyVwfEypWR5kI+O6TFmUZKkuTP4enkizqJ4/GPZVHHOUsdOA== +-----END RSA PRIVATE KEY----- diff --git a/rooter/0routerspecfic/ext-ssh/files/etc/ssh/ssh_host_rsa_key.pub b/rooter/0routerspecfic/ext-ssh/files/etc/ssh/ssh_host_rsa_key.pub new file mode 100644 index 0000000..c94565f --- /dev/null +++ b/rooter/0routerspecfic/ext-ssh/files/etc/ssh/ssh_host_rsa_key.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDLrVPhGwCPZ5uPAuhrcX8mQwJuBuD1fHK68er/D+YJgHLmzT8mzmARqGsphF97PbELC3shdvqo4t6dAegPpjLCElkej+DUcu247P6jjg5WbAA4A3s/iTuKB97u0rtsnJvTOM6pCOJPFzmmQjTtLUASIs2j4Fh2nNxGekBoesfxqc3//pJnzHDOPjMj717ZORlRu2Q9aOaT0VrVaWe3t83UdJT9GbvZ3lyFSFB3zl3n5YOSDO+3bULZaLu1QSxqtHwBzxFF91+J7pKKUmx2aeXP52AFZtZtQbKX0EjfW6Agl9CpfHU+DNwe7sdE6PVpv/yesjfGl7192+ZBBDEye45F root@turris diff --git a/rooter/0routerspecfic/ext-ssh/files/etc/ssh/sshd_config b/rooter/0routerspecfic/ext-ssh/files/etc/ssh/sshd_config new file mode 100644 index 0000000..d142fa5 --- /dev/null +++ b/rooter/0routerspecfic/ext-ssh/files/etc/ssh/sshd_config @@ -0,0 +1,120 @@ +# $OpenBSD: sshd_config,v 1.102 2018/02/16 02:32:40 djm Exp $ + +# This is the sshd server system-wide configuration file. See +# sshd_config(5) for more information. + +# This sshd was compiled with PATH=/usr/bin:/bin:/usr/sbin:/sbin + +# The strategy used for options in the default sshd_config shipped with +# OpenSSH is to specify options with their default value where +# possible, but leave them commented. Uncommented options override the +# default value. + +Port 23 +#AddressFamily any +#ListenAddress 0.0.0.0 +#ListenAddress :: + +HostKey /etc/ssh/ssh_host_rsa_key +HostKey /etc/ssh/ssh_host_ecdsa_key +HostKey /etc/ssh/ssh_host_ed25519_key + +# Ciphers and keying +#RekeyLimit default none + +# Logging +#SyslogFacility AUTH +#LogLevel INFO + +# Authentication: + +#LoginGraceTime 2m +PermitRootLogin yes +#StrictModes yes +#MaxAuthTries 6 +#MaxSessions 10 + +#PubkeyAuthentication yes + +# The default is to check both .ssh/authorized_keys and .ssh/authorized_keys2 +# but this is overridden so installations will only check .ssh/authorized_keys +AuthorizedKeysFile .ssh/authorized_keys + +#AuthorizedPrincipalsFile none + +#AuthorizedKeysCommand none +#AuthorizedKeysCommandUser nobody + +# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts +#HostbasedAuthentication no +# Change to yes if you don't trust ~/.ssh/known_hosts for +# HostbasedAuthentication +#IgnoreUserKnownHosts no +# Don't read the user's ~/.rhosts and ~/.shosts files +#IgnoreRhosts yes + +# To disable tunneled clear text passwords, change to no here! +#PasswordAuthentication yes +#PermitEmptyPasswords no + +# Change to no to disable s/key passwords +#ChallengeResponseAuthentication yes + +# Kerberos options +#KerberosAuthentication no +#KerberosOrLocalPasswd yes +#KerberosTicketCleanup yes +#KerberosGetAFSToken no + +# GSSAPI options +#GSSAPIAuthentication no +#GSSAPICleanupCredentials yes + +# Set this to 'yes' to enable PAM authentication, account processing, +# and session processing. If this is enabled, PAM authentication will +# be allowed through the ChallengeResponseAuthentication and +# PasswordAuthentication. Depending on your PAM configuration, +# PAM authentication via ChallengeResponseAuthentication may bypass +# the setting of "PermitRootLogin without-password". +# If you just want the PAM account and session checks to run without +# PAM authentication, then enable this but set PasswordAuthentication +# and ChallengeResponseAuthentication to 'no'. +#UsePAM no + +#AllowAgentForwarding yes +#AllowTcpForwarding yes +#GatewayPorts no +#X11Forwarding no +#X11DisplayOffset 10 +#X11UseLocalhost yes +#PermitTTY yes +#PrintMotd yes +#PrintLastLog yes +#TCPKeepAlive yes +#UseLogin no +#PermitUserEnvironment no +#Compression delayed +#ClientAliveInterval 0 +#ClientAliveCountMax 3 +#UseDNS no +#PidFile /var/run/sshd.pid +#MaxStartups 10:30:100 +#PermitTunnel no +#ChrootDirectory none +#VersionAddendum none + +# no default banner path +#Banner none + +# enable DSCP QoS values (per RFC-4594) +#IPQoS AF21 AF11 + +# override default of no subsystems +Subsystem sftp /usr/lib/sftp-server + +# Example of overriding settings on a per-user basis +#Match User anoncvs +# X11Forwarding no +# AllowTcpForwarding no +# PermitTTY no +# ForceCommand cvs server diff --git a/rooter/0routerspecfic/fscheck/Makefile b/rooter/0routerspecfic/fscheck/Makefile new file mode 100644 index 0000000..a18dcb3 --- /dev/null +++ b/rooter/0routerspecfic/fscheck/Makefile @@ -0,0 +1,36 @@ +#Owned by DairyMan@Whirlpool +# +#Copyright GNU act. +include $(TOPDIR)/rules.mk + +PKG_NAME:=fscheck +PKG_VERSION:=1.000 +PKG_RELEASE:=1 + +PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool +include $(INCLUDE_DIR)/package.mk + +define Package/fscheck + SECTION:=utils + CATEGORY:=ROOter + SUBMENU:=Router Specific + DEPENDS:=+e2fsprogs + TITLE:=Install scripts for FSCheck + PKGARCH:=all +endef + +define Package/fscheck/description + Helper scripts to install scripts for FSCheck +endef + + +define Build/Compile +endef + +define Package/fscheck/install + $(CP) ./files/* $(1)/ + + +endef + +$(eval $(call BuildPackage,fscheck)) diff --git a/rooter/0routerspecfic/fscheck/files/usr/lib/lua/luci/controller/filecheck.lua b/rooter/0routerspecfic/fscheck/files/usr/lib/lua/luci/controller/filecheck.lua new file mode 100644 index 0000000..37898de --- /dev/null +++ b/rooter/0routerspecfic/fscheck/files/usr/lib/lua/luci/controller/filecheck.lua @@ -0,0 +1,37 @@ +module("luci.controller.filecheck", package.seeall) + +function index() + local page + page = entry({"admin", "system", "filecheck"}, template("admin_system/filecheck"), _("File System Check"), 93) + entry({"admin", "system", "do_filecheck"}, call("action_filecheck")) + entry({"admin", "system", "do_reboot"}, call("action_rebt")) + page.dependent = true +end + +function action_filecheck() + local rv ={} + os.execute("/usr/lib/rooter/filecheck.sh") + result = "/tmp/fsresult" + local file = io.open(result, "r") + if file ~= nil then + rv["result"] = file:read("*all") + file:close() + os.execute("/usr/lib/rooter/luci/luaops.sh delete /tmp/fsresult") + else + rv["result"] = "No response" + end + file = io.open("/tmp/fsro", "r") + if file ~= nil then + rv["fsro"] = 1 + file:close() + else + rv["fsro"] = 0 + end + + luci.http.prepare_content("application/json") + luci.http.write_json(rv) +end + +function action_rebt() + os.execute("reboot &") +end \ No newline at end of file diff --git a/rooter/0routerspecfic/fscheck/files/usr/lib/lua/luci/view/admin_system/filecheck.htm b/rooter/0routerspecfic/fscheck/files/usr/lib/lua/luci/view/admin_system/filecheck.htm new file mode 100644 index 0000000..be2e7a9 --- /dev/null +++ b/rooter/0routerspecfic/fscheck/files/usr/lib/lua/luci/view/admin_system/filecheck.htm @@ -0,0 +1,104 @@ +<%# + Copyright 2008 Steven Barth + Copyright 2008 Jo-Philipp Wich + Licensed to the public under the Apache License 2.0. +-%> + +<%+header%> + + + + +
                          + +

                          <%:File System Check%>

                          + +

                          <%:Check and Fix Read-only File System Problem.%>

                          +
                          + +

                          +
                          + +

                          Details of Check

                          + + + + +
                          + +
                          + +
                          + + + + +
                          +<%+footer%> \ No newline at end of file diff --git a/rooter/0routerspecfic/fscheck/files/usr/lib/rooter/filecheck.sh b/rooter/0routerspecfic/fscheck/files/usr/lib/rooter/filecheck.sh new file mode 100644 index 0000000..1ed3169 --- /dev/null +++ b/rooter/0routerspecfic/fscheck/files/usr/lib/rooter/filecheck.sh @@ -0,0 +1,19 @@ +#!/bin/sh + +rm -f /tmp/fsresult +rm -f /tmp/fsro +if [ -e /dev/mmcblk0p2 ]; then + E2=$(e2fsck -y -v -f /dev/mmcblk0p2 2> /tmp/fsresult) + echo "$E2" >> /tmp/fsresult + E3=$(cat /tmp/fsresult | grep -o "aborting") + if [ ! -z $E3 ]; then + echo " " > /tmp/fsresult + echo " " >> /tmp/fsresult + echo " File System mounted as Read/Write" >> /tmp/fsresult + exit 0 + fi + echo "1" >> /tmp/fsro +else + echo "Not correct file system" > /tmp/fsresult +fi + diff --git a/rooter/0routerspecfic/h721/Makefile b/rooter/0routerspecfic/h721/Makefile new file mode 100644 index 0000000..ee1fb3a --- /dev/null +++ b/rooter/0routerspecfic/h721/Makefile @@ -0,0 +1,36 @@ +#Owned by DairyMan@Whirlpool +# +#Copyright GNU act. +include $(TOPDIR)/rules.mk + +PKG_NAME:=h721 +PKG_VERSION:=1.000 +PKG_RELEASE:=1 + +PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool +include $(INCLUDE_DIR)/package.mk + +define Package/h721 + SECTION:=utils + CATEGORY:=ROOter + SUBMENU:=Router Specific + DEPENDS:=+kmod-ath10k +kmod-ath9k \ + +ath10k-firmware-qca988x +ath10k-firmware-qca9984 \ + +ath10k-firmware-qca99x0 +ath10k-firmware-qca9888 + TITLE:=Install scripts for Dual-Q H721 + PKGARCH:=all +endef + +define Package/h721/description + Helper scripts to install scripts for Dual-Q H721 +endef + + +define Build/Compile +endef + +define Package/h721/install + $(CP) ./files/* $(1)/ +endef + +$(eval $(call BuildPackage,h721)) diff --git a/rooter/0routerspecfic/h721/files/etc/exportgpio.sh b/rooter/0routerspecfic/h721/files/etc/exportgpio.sh new file mode 100644 index 0000000..311f49e --- /dev/null +++ b/rooter/0routerspecfic/h721/files/etc/exportgpio.sh @@ -0,0 +1,24 @@ +#!/bin/sh + +for i in 502 503 +do +echo $i > /sys/class/gpio/export +echo out > /sys/class/gpio/gpio${i}/direction +echo 1 > /sys/class/gpio/gpio${i}/value +done + + +sleep 1 + +for i in 502 503 +do +echo 0 > /sys/class/gpio/gpio${i}/value +sleep 8 +done + +echo timer > /sys/class/leds/h761:green:4g5g/trigger +echo 0 > /sys/class/leds/h761:green:4g5g/delay_on +echo 1000 > /sys/class/leds/h761:green:4g5g/delay_off +echo timer > /sys/class/leds/h761:green:4g/trigger +echo 0 > /sys/class/leds/h761:green:4g/delay_on +echo 1000 > /sys/class/leds/h761:green:4g/delay_off diff --git a/rooter/0routerspecfic/h721/files/etc/init.d/custom b/rooter/0routerspecfic/h721/files/etc/init.d/custom new file mode 100644 index 0000000..ab68244 --- /dev/null +++ b/rooter/0routerspecfic/h721/files/etc/init.d/custom @@ -0,0 +1,10 @@ +#!/bin/sh /etc/rc.common + +. /lib/functions.sh + +START=10 + +start() +{ + /usr/lib/custom/custom.lua & +} diff --git a/rooter/0routerspecfic/h721/files/etc/init.d/exportgpio b/rooter/0routerspecfic/h721/files/etc/init.d/exportgpio new file mode 100644 index 0000000..bacc5ac --- /dev/null +++ b/rooter/0routerspecfic/h721/files/etc/init.d/exportgpio @@ -0,0 +1,15 @@ +#!/bin/sh /etc/rc.common +# Copyright (C) 2013 OpenWrt.org + +START=95 +USE_PROCD=1 + +log() { + logger -t "exportgpio" "$@" +} + +start_service() +{ + log "H761 Gpio Setup" + /etc/exportgpio.sh & +} diff --git a/rooter/0routerspecfic/h721/files/usr/lib/custom/custom.lua b/rooter/0routerspecfic/h721/files/usr/lib/custom/custom.lua new file mode 100644 index 0000000..f3b56d2 --- /dev/null +++ b/rooter/0routerspecfic/h721/files/usr/lib/custom/custom.lua @@ -0,0 +1,38 @@ +#!/usr/bin/lua + +printf = function(s,...) + if pflag ~= 0 then + io.write(s:format(...)) + local ss = s:format(...) + if echo == 1 then + os.execute("/usr/lib/rooter/logprint.sh " .. ss) + end + end +end + +function sleep(n) + os.execute("sleep " .. tonumber(n)) +end + +function file_exists(name) + local f=io.open(name,"r") + if f~=nil then io.close(f) return true else return false end +end + +while file_exists("/tmp/sysinfo/board_name") == false do + sleep(1) +end + +if file_exists("/etc/custom") then + file = io.open("/etc/custom", "r") + board = file:read("*line") + model = file:read("*line") + hostname = file:read("*line") + file:close() + + os.execute("/usr/lib/custom/hostname.sh " .. hostname) + os.execute("/usr/lib/custom/wifi.sh &") +end + + + diff --git a/rooter/0routerspecfic/h721/files/usr/lib/custom/hostname.sh b/rooter/0routerspecfic/h721/files/usr/lib/custom/hostname.sh new file mode 100644 index 0000000..af84554 --- /dev/null +++ b/rooter/0routerspecfic/h721/files/usr/lib/custom/hostname.sh @@ -0,0 +1,10 @@ +#!/bin/sh + +hostname=$1 + +HO=$(uci get system.@system[-1].hostname) +if [ $HO = "OpenWrt" -o $HO = "LEDE" ]; then + uci set system.@system[-1].hostname="$1" + echo "$1" > /proc/sys/kernel/hostname + uci commit system +fi diff --git a/rooter/0routerspecfic/h721/files/usr/lib/custom/wifi.sh b/rooter/0routerspecfic/h721/files/usr/lib/custom/wifi.sh new file mode 100644 index 0000000..273efd2 --- /dev/null +++ b/rooter/0routerspecfic/h721/files/usr/lib/custom/wifi.sh @@ -0,0 +1,30 @@ +#!/bin/sh +. /lib/functions.sh + + +do_radio() { + local config=$1 + local channel + mode="ap" + + config_get channel $1 channel + if [ $channel -lt 15 ]; then + RADIO=$config + ifname="$(ubus -S call network.wireless status | jsonfilter -l 1 -e "@.$RADIO.interfaces[@.config.mode=\"${mode}\"].ifname")" + if [ ! -z $ifname ]; then + iw reg set US + iwconfig $ifname txpower 30 + fi + fi +} + +while [ ! -e /etc/config/wireless ] +do + sleep 1 +done +sleep 3 +if [ ! -e /etc/maxwifi ]; then + config_load wireless + config_foreach do_radio wifi-device + echo "0" > /etc/maxwifi +fi diff --git a/rooter/0routerspecfic/h721/files/usr/lib/rooter/modem-led.sh b/rooter/0routerspecfic/h721/files/usr/lib/rooter/modem-led.sh new file mode 100644 index 0000000..d0422b7 --- /dev/null +++ b/rooter/0routerspecfic/h721/files/usr/lib/rooter/modem-led.sh @@ -0,0 +1,94 @@ +#!/bin/sh + +log() { + logger -t "modem-led " "$@" +} + +CURRMODEM=$1 +COMMD=$2 + +DEV=$(uci get modem.modem$CURRMODEM.device) +DEVV=${DEV:0:1} + +if [ $DEVV = "1" ]; then + case $COMMD in + "0" ) + echo timer > /sys/class/leds/h721:green:4g5g/trigger + echo 0 > /sys/class/leds/h721:green:4g5g/delay_on + echo 1000 > /sys/class/leds/h721:green:4g5g/delay_off + ;; + "1" ) + echo timer > /sys/class/leds/h721:green:4g5g/trigger + echo 500 > /sys/class/leds/h721:green:4g5g/delay_on + echo 500 > /sys/class/leds/h721:green:4g5g/delay_off + ;; + "2" ) + echo timer > /sys/class/leds/h721:green:4g5g/trigger + echo 200 > /sys/class/leds/h721:green:4g5g/delay_on + echo 200 > /sys/class/leds/h721:green:4g5g/delay_off + ;; + "3" ) + echo timer > /sys/class/leds/h721:green:4g5g/trigger + echo 1000 > /sys/class/leds/h721:green:4g5g/delay_on + echo 0 > /sys/class/leds/h721:green:4g5g/delay_off + ;; + "4" ) + sig2=$3 + echo timer > /sys/class/leds/h721:green:rssi_lte1/trigger + if [ $sig2 -lt 18 -a $sig2 -gt 0 ] 2>/dev/null;then + echo 500 > /sys/class/leds/h721:green:rssi_lte1/delay_on + echo 500 > /sys/class/leds/h721:green:rssi_lte1/delay_off + elif [ $sig2 -ge 18 -a $sig2 -lt 31 ] 2>/dev/null;then + echo 150 > /sys/class/leds/h721:green:rssi_lte1/delay_on + echo 150 > /sys/class/leds/h721:green:rssi_lte1/delay_off + elif [ $sig2 -eq 31 ] 2>/dev/null;then + echo 0 > /sys/class/leds/h721:green:rssi_lte1/delay_on + echo 1000 > /sys/class/leds/h721:green:rssi_lte1/delay_off + else + echo 950 > /sys/class/leds/h721:green:rssi_lte1/delay_on + echo 950 > /sys/class/leds/h721:green:rssi_lte1/delay_off + fi + ;; + esac +else + case $COMMD in + "0" ) + echo timer > /sys/class/leds/h721:green:4g/trigger + echo 0 > /sys/class/leds/h721:green:4g/delay_on + echo 1000 > /sys/class/leds/h721:green:4g/delay_off + ;; + "1" ) + echo timer > /sys/class/leds/h721:green:4g/trigger + echo 500 > /sys/class/leds/h721:green:4g/delay_on + echo 500 > /sys/class/leds/h721:green:4g/delay_off + ;; + "2" ) + echo timer > /sys/class/leds/h721:green:4g/trigger + echo 200 > /sys/class/leds/h721:green:4g/delay_on + echo 200 > /sys/class/leds/h721:green:4g/delay_off + ;; + "3" ) + echo timer > /sys/class/leds/h721:green:4g/trigger + echo 1000 > /sys/class/leds/h721:green:4g/delay_on + echo 0 > /sys/class/leds/h721:green:4g/delay_off + ;; + "4" ) + sig=$3 + echo timer > /sys/class/leds/h721:green:rssi_lte2/trigger + if [ $sig -lt 18 -a $sig -gt 0 ] 2>/dev/null;then + echo 500 > /sys/class/leds/h721:green:rssi_lte2/delay_on + echo 500 > /sys/class/leds/h721:green:rssi_lte2/delay_off + elif [ $sig -ge 18 -a $sig -lt 31 ] 2>/dev/null;then + echo 150 > /sys/class/leds/h721:green:rssi_lte2/delay_on + echo 150 > /sys/class/leds/h721:green:rssi_lte2/delay_off + elif [ $sig -eq 31 ] 2>/dev/null;then + echo 0 > /sys/class/leds/h721:green:rssi_lte2/delay_on + echo 1000 > /sys/class/leds/h721:green:rssi_lte2/delay_off + else + echo 950 > /sys/class/leds/h721:green:rssi_lte2/delay_on + echo 950 > /sys/class/leds/h721:green:rssi_lte2/delay_off + fi + ;; + esac + +fi \ No newline at end of file diff --git a/rooter/0routerspecfic/h721/files/usr/lib/rooter/special.sh b/rooter/0routerspecfic/h721/files/usr/lib/rooter/special.sh new file mode 100644 index 0000000..3f499d1 --- /dev/null +++ b/rooter/0routerspecfic/h721/files/usr/lib/rooter/special.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +wifi config +wifi up \ No newline at end of file diff --git a/rooter/0routerspecfic/mt1300/Makefile b/rooter/0routerspecfic/mt1300/Makefile new file mode 100644 index 0000000..15d2f31 --- /dev/null +++ b/rooter/0routerspecfic/mt1300/Makefile @@ -0,0 +1,35 @@ +#Owned by DairyMan@Whirlpool +# +#Copyright GNU act. +include $(TOPDIR)/rules.mk + +PKG_NAME:=mt1300 +PKG_VERSION:=1.000 +PKG_RELEASE:=1 + +PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool +include $(INCLUDE_DIR)/package.mk + +define Package/mt1300 + SECTION:=utils + CATEGORY:=ROOter + SUBMENU:=Router Specific + TITLE:=Install scripts for MT1300 + PKGARCH:=all +endef + +define Package/mt1300/description + Helper scripts to install scripts for MT1300 +endef + + +define Build/Compile +endef + +define Package/mt1300/install + $(CP) ./files/* $(1)/ + + +endef + +$(eval $(call BuildPackage,mt1300)) diff --git a/rooter/0routerspecfic/mt1300/files/etc/init.d/mt1300 b/rooter/0routerspecfic/mt1300/files/etc/init.d/mt1300 new file mode 100644 index 0000000..7ed8cc7 --- /dev/null +++ b/rooter/0routerspecfic/mt1300/files/etc/init.d/mt1300 @@ -0,0 +1,23 @@ +#!/bin/sh /etc/rc.common +# Copyright (C) 2013 OpenWrt.org + +START=90 +USE_PROCD=1 + +log() { + logger -t "mt1300" "$@" +} + +start_service() +{ + if [ ! -e /etc/mt1300 ]; then + uci set wireless.radio0.disabled=0 + uci set wireless.radio0.hwmode=11g + uci set wireless.radio0.htmode=HT20 + uci set wireless.radio0.channel=3 + uci set wireless.radio0.legacy_rates=0 + uci commit wireless + wifi reload + echo "0" > /etc/mt1300 + fi +} diff --git a/rooter/0routerspecfic/rbm11g/Makefile b/rooter/0routerspecfic/rbm11g/Makefile new file mode 100644 index 0000000..e100892 --- /dev/null +++ b/rooter/0routerspecfic/rbm11g/Makefile @@ -0,0 +1,35 @@ +#Owned by DairyMan@Whirlpool +# +#Copyright GNU act. +include $(TOPDIR)/rules.mk + +PKG_NAME:=rbm11g +PKG_VERSION:=1.000 +PKG_RELEASE:=1 + +PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool +include $(INCLUDE_DIR)/package.mk + +define Package/rbm11g + SECTION:=utils + CATEGORY:=ROOter + SUBMENU:=Router Specific + TITLE:=Install scripts for RBM11G + PKGARCH:=all +endef + +define Package/rbm11g/description + Helper scripts to install scripts for RBM11G +endef + + +define Build/Compile +endef + +define Package/rbm11g/install + $(CP) ./files/* $(1)/ + + +endef + +$(eval $(call BuildPackage,rbm11g)) diff --git a/rooter/0routerspecfic/rbm11g/files/usr/lib/rooter/modem-led.sh b/rooter/0routerspecfic/rbm11g/files/usr/lib/rooter/modem-led.sh new file mode 100644 index 0000000..43033ac --- /dev/null +++ b/rooter/0routerspecfic/rbm11g/files/usr/lib/rooter/modem-led.sh @@ -0,0 +1,124 @@ +#!/bin/sh + +log() { + logger -t "modem-led " "$@" +} + +CURRMODEM=$1 +COMMD=$2 + + case $COMMD in + "0" ) + echo none > /sys/class/leds/rbm11g:green:rssi0/trigger + echo 0 > /sys/class/leds/rbm11g:green:rssi0/brightness + echo none > /sys/class/leds/rbm11g:green:rssi1/trigger + echo 0 > /sys/class/leds/rbm11g:green:rssi1/brightness + echo none > /sys/class/leds/rbm11g:green:rssi2/trigger + echo 0 > /sys/class/leds/rbm11g:green:rssi2/brightness + echo none > /sys/class/leds/rbm11g:green:rssi3/trigger + echo 0 > /sys/class/leds/rbm11g:green:rssi3/brightness + echo none > /sys/class/leds/rbm11g:green:rssi4/trigger + echo 0 > /sys/class/leds/rbm11g:green:rssi4/brightness + echo none > /sys/class/leds/rbm11g:green:usr/trigger + echo 0 > /sys/class/leds/rbm11g:green:usr/brightness + ;; + "1" ) + echo timer > /sys/class/leds/rbm11g:green:usr/trigger + echo 500 > /sys/class/leds/rbm11g:green:usr/delay_on + echo 500 > /sys/class/leds/rbm11g:green:usr/delay_off + ;; + "2" ) + echo timer > /sys/class/leds/rbm11g:green:usr/trigger + echo 200 > /sys/class/leds/rbm11g:green:usr/delay_on + echo 200 > /sys/class/leds/rbm11g:green:usr/delay_off + ;; + "3" ) + echo timer > /sys/class/leds/rbm11g:green:usr/trigger + echo 1000 > /sys/class/leds/rbm11g:green:usr/delay_on + echo 0 > /sys/class/leds/rbm11g:green:usr/delay_off + ;; + "4" ) + #echo none > /sys/class/leds/rbm11g:green:rssi0/trigger + #echo 1 > /sys/class/leds/rbm11g:green:rssi0/brightness + sig2=$3 + if [ $sig2 -lt 5 -a $sig2 -gt 0 ] 2>/dev/null;then + echo none > /sys/class/leds/rbm11g:green:usr/trigger + echo 1 > /sys/class/leds/rbm11g:green:usr/brightness + echo none > /sys/class/leds/rbm11g:green:rssi0/trigger + echo 0 > /sys/class/leds/rbm11g:green:rssi0/brightness + echo none > /sys/class/leds/rbm11g:green:rssi1/trigger + echo 0 > /sys/class/leds/rbm11g:green:rssi1/brightness + echo none > /sys/class/leds/rbm11g:green:rssi2/trigger + echo 0 > /sys/class/leds/rbm11g:green:rssi2/brightness + echo none > /sys/class/leds/rbm11g:green:rssi3/trigger + echo 0 > /sys/class/leds/rbm11g:green:rssi3/brightness + echo none > /sys/class/leds/rbm11g:green:rssi4/trigger + echo 0 > /sys/class/leds/rbm11g:green:rssi4/brightness + elif [ $sig2 -ge 5 -a $sig2 -lt 10 ] 2>/dev/null;then + echo none > /sys/class/leds/rbm11g:green:usr/trigger + echo 1 > /sys/class/leds/rbm11g:green:usr/brightness + echo none > /sys/class/leds/rbm11g:green:rssi0/trigger + echo 0 > /sys/class/leds/rbm11g:green:rssi0/brightness + echo none > /sys/class/leds/rbm11g:green:rssi1/trigger + echo 0 > /sys/class/leds/rbm11g:green:rssi1/brightness + echo none > /sys/class/leds/rbm11g:green:rssi2/trigger + echo 0 > /sys/class/leds/rbm11g:green:rssi2/brightness + echo none > /sys/class/leds/rbm11g:green:rssi3/trigger + echo 0 > /sys/class/leds/rbm11g:green:rssi3/brightness + echo none > /sys/class/leds/rbm11g:green:rssi4/trigger + echo 1 > /sys/class/leds/rbm11g:green:rssi4/brightness + elif [ $sig2 -ge 10 -a $sig2 -lt 15 ] 2>/dev/null;then + echo none > /sys/class/leds/rbm11g:green:usr/trigger + echo 1 > /sys/class/leds/rbm11g:green:usr/brightness + echo none > /sys/class/leds/rbm11g:green:rssi0/trigger + echo 0 > /sys/class/leds/rbm11g:green:rssi0/brightness + echo none > /sys/class/leds/rbm11g:green:rssi1/trigger + echo 0 > /sys/class/leds/rbm11g:green:rssi1/brightness + echo none > /sys/class/leds/rbm11g:green:rssi2/trigger + echo 0 > /sys/class/leds/rbm11g:green:rssi2/brightness + echo none > /sys/class/leds/rbm11g:green:rssi3/trigger + echo 1 > /sys/class/leds/rbm11g:green:rssi3/brightness + echo none > /sys/class/leds/rbm11g:green:rssi4/trigger + echo 1 > /sys/class/leds/rbm11g:green:rssi4/brightness + elif [ $sig2 -ge 15 -a $sig2 -lt 20 ] 2>/dev/null;then + echo none > /sys/class/leds/rbm11g:green:usr/trigger + echo 1 > /sys/class/leds/rbm11g:green:usr/brightness + echo none > /sys/class/leds/rbm11g:green:rssi0/trigger + echo 0 > /sys/class/leds/rbm11g:green:rssi0/brightness + echo none > /sys/class/leds/rbm11g:green:rssi1/trigger + echo 0 > /sys/class/leds/rbm11g:green:rssi1/brightness + echo none > /sys/class/leds/rbm11g:green:rssi2/trigger + echo 1 > /sys/class/leds/rbm11g:green:rssi2/brightness + echo none > /sys/class/leds/rbm11g:green:rssi3/trigger + echo 1 > /sys/class/leds/rbm11g:green:rssi3/brightness + echo none > /sys/class/leds/rbm11g:green:rssi4/trigger + echo 1 > /sys/class/leds/rbm11g:green:rssi4/brightness + elif [ $sig2 -ge 20 -a $sig2 -lt 25 ] 2>/dev/null;then + echo none > /sys/class/leds/rbm11g:green:usr/trigger + echo 1 > /sys/class/leds/rbm11g:green:usr/brightness + echo none > /sys/class/leds/rbm11g:green:rssi0/trigger + echo 0 > /sys/class/leds/rbm11g:green:rssi0/brightness + echo none > /sys/class/leds/rbm11g:green:rssi1/trigger + echo 1 > /sys/class/leds/rbm11g:green:rssi1/brightness + echo none > /sys/class/leds/rbm11g:green:rssi2/trigger + echo 1 > /sys/class/leds/rbm11g:green:rssi2/brightness + echo none > /sys/class/leds/rbm11g:green:rssi3/trigger + echo 1 > /sys/class/leds/rbm11g:green:rssi3/brightness + echo none > /sys/class/leds/rbm11g:green:rssi4/trigger + echo 1 > /sys/class/leds/rbm11g:green:rssi4/brightness + else + echo none > /sys/class/leds/rbm11g:green:usr/trigger + echo 1 > /sys/class/leds/rbm11g:green:usr/brightness + echo none > /sys/class/leds/rbm11g:green:rssi0/trigger + echo 1 > /sys/class/leds/rbm11g:green:rssi0/brightness + echo none > /sys/class/leds/rbm11g:green:rssi1/trigger + echo 1 > /sys/class/leds/rbm11g:green:rssi1/brightness + echo none > /sys/class/leds/rbm11g:green:rssi2/trigger + echo 1 > /sys/class/leds/rbm11g:green:rssi2/brightness + echo none > /sys/class/leds/rbm11g:green:rssi3/trigger + echo 1 > /sys/class/leds/rbm11g:green:rssi3/brightness + echo none > /sys/class/leds/rbm11g:green:rssi4/trigger + echo 1 > /sys/class/leds/rbm11g:green:rssi4/brightness + fi + ;; + esac diff --git a/rooter/0routerspecfic/rbm11g/files/usr/lib/rooter/special.sh b/rooter/0routerspecfic/rbm11g/files/usr/lib/rooter/special.sh new file mode 100644 index 0000000..dca81af --- /dev/null +++ b/rooter/0routerspecfic/rbm11g/files/usr/lib/rooter/special.sh @@ -0,0 +1,11 @@ +#!/bin/sh +. /lib/functions.sh + +MODEM_DEVICES=`cat /sys/kernel/debug/usb/devices | grep 'Sierra' -A3 | grep '^C:' | awk '{print $3}'` +if [ $MODEM_DEVICES -eq 1 ]; then + echo "Sierra Modem in BOOTHOLD! Resetting pcie0_vcc state." > /dev/kmsg + echo "0" > /sys/class/gpio/gpio9/value + echo "Toggled pcie0_vcc: OFF" > /dev/kmsg + echo "1" > /sys/class/gpio/gpio9/value + echo "Toggled pcie0_vcc: ON" > /dev/kmsg +fi \ No newline at end of file diff --git a/rooter/0routerspecfic/rbm33g/Makefile b/rooter/0routerspecfic/rbm33g/Makefile new file mode 100644 index 0000000..4fa676f --- /dev/null +++ b/rooter/0routerspecfic/rbm33g/Makefile @@ -0,0 +1,35 @@ +#Owned by DairyMan@Whirlpool +# +#Copyright GNU act. +include $(TOPDIR)/rules.mk + +PKG_NAME:=rbm33g +PKG_VERSION:=1.000 +PKG_RELEASE:=1 + +PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool +include $(INCLUDE_DIR)/package.mk + +define Package/rbm33g + SECTION:=utils + CATEGORY:=ROOter + SUBMENU:=Router Specific + TITLE:=Install scripts for RBM33G + PKGARCH:=all +endef + +define Package/rbm33g/description + Helper scripts to install scripts for RBM33G +endef + + +define Build/Compile +endef + +define Package/rbm33g/install + $(CP) ./files/* $(1)/ + + +endef + +$(eval $(call BuildPackage,rbm33g)) diff --git a/rooter/0routerspecfic/rbm33g/files/usr/lib/rooter/special.sh b/rooter/0routerspecfic/rbm33g/files/usr/lib/rooter/special.sh new file mode 100644 index 0000000..ca8f81e --- /dev/null +++ b/rooter/0routerspecfic/rbm33g/files/usr/lib/rooter/special.sh @@ -0,0 +1,70 @@ +#!/bin/sh +. /lib/functions.sh + +VL=0 +do_vlan() { + local config=$1 + config_get ports $1 ports + if [ "$ports" = "1 2 6t" ]; then + uci set network."$config".ports="0 1 6t" + VL=1 + fi + if [ "$ports" = "0 6t" ]; then + uci set network."$config".ports="2 6t" + VL=1 + fi +} + +if [ ! -f /etc/rbm33 ]; then + config_load network + config_foreach do_vlan switch_vlan + + if [ $VL -eq 1 ]; then + uci commit network + /etc/init.d/network restart + fi + echo "0" > /etc/rbm33 +fi + +echo "1" > /sys/class/gpio/gpio9/value +sleep 1 +echo "1" > /sys/class/gpio/gpio12/value + +# 1 Check USB Devices, Rev=0.00 is probably a boothold device, awk reverses the line order +var="`cat /sys/kernel/debug/usb/devices | grep -E '^T:|^P:|^C:' | grep -E 'Rev= 0.00$' -C1 | awk '{a[i++]=$0} END {for (j=i-1; j>=0;) print a[j--] }'`" +while read -r line; do + case $line in 'T: Bus='*) + if [ $ProdID ] && [ $Vendor ]; then + BPort="`echo $line | awk -F'[ =]' '{print $3$9}'`" + case $BPort in + '0101') GPIO_PIN=gpio9; ;; # pcie0 + '0100') GPIO_PIN=gpio10; ;; # pcie1/USB in USB 2.0 mode + '0200') GPIO_PIN=gpio12; ;; # USB in USB 3.0 mode + *) unset GPIO_PIN; ;; + esac; + if [ $GPIO_PIN ]; then + echo "Modem in BOOTHOLD!" > /dev/kmsg + echo "0" > /sys/class/gpio/$GPIO_PIN/value + echo "1" > /sys/class/gpio/$GPIO_PIN/value + echo "Toggled GPIO $GPIO_PIN" > /dev/kmsg + unset GPIO_PIN + fi + fi + esac + unset Vendor + unset ProdID + case $line in 'P: Vendor='*) + if [ $trigger -eq 1 ]; then + # 3 add logic to check against VID/PID from list + Vendor=`echo $line | awk -F'[ =]' '{print $3}'` + ProdID=`echo $line | awk -F'[ =]' '{print $5}'` + trigger=0 + fi + esac + case $line in 'C:* #Ifs= 1'*) + # 2 Found a device with only one interface, so we'll assume is a boothold modem for now + trigger=1 + esac +done <]], scope\)\nif ok then\nreturn res\nend\nreturn luci.template.render\(\"sysauth\", scope\)/;ba" /usr/lib/lua/luci/dispatcher.lua +[ -f /usr/lib/lua/luci/view/themes/material/out_header_login.htm ] && mv -f /usr/lib/lua/luci/view/themes/material/out_header_login.htm /usr/lib/lua/luci/view/header_login.htm +rm -Rf /var/luci-modulecache +rm -Rf /var/luci-indexcache +exit 0 diff --git a/rooter/0routerspecfic/rbsxtr/files/usr/lib/rooter/modem-led.sh b/rooter/0routerspecfic/rbsxtr/files/usr/lib/rooter/modem-led.sh new file mode 100644 index 0000000..c331a5c --- /dev/null +++ b/rooter/0routerspecfic/rbsxtr/files/usr/lib/rooter/modem-led.sh @@ -0,0 +1,34 @@ +#!/bin/sh + +log() { + logger -t "modem-led " "$@" +} + +CURRMODEM=$1 +COMMD=$2 + + case $COMMD in + "0" ) + echo none > /sys/class/leds/green:lte/trigger + echo 0 > /sys/class/leds/green:lte/brightness + ;; + "1" ) + echo timer > /sys/class/leds/green:lte/trigger + echo 500 > /sys/class/leds/green:lte/delay_on + echo 500 > /sys/class/leds/green:lte/delay_off + ;; + "2" ) + echo timer > /sys/class/leds/green:lte/trigger + echo 200 > /sys/class/leds/green:lte/delay_on + echo 200 > /sys/class/leds/green:lte/delay_off + ;; + "3" ) + echo timer > /sys/class/leds/green:lte/trigger + echo 1000 > /sys/class/leds/green:lte/delay_on + echo 0 > /sys/class/leds/green:lte/delay_off + ;; + "4" ) + echo none > /sys/class/leds/green:lte/trigger + echo 1 > /sys/class/leds/green:lte/brightness + ;; + esac diff --git a/rooter/0routerspecfic/rbsxtr/files/www/luci-static/background/main_bg.jpg b/rooter/0routerspecfic/rbsxtr/files/www/luci-static/background/main_bg.jpg new file mode 100644 index 0000000..bd55ca0 Binary files /dev/null and b/rooter/0routerspecfic/rbsxtr/files/www/luci-static/background/main_bg.jpg differ diff --git a/rooter/0routerspecfic/rbsxtr/files/www/luci-static/img/open.png b/rooter/0routerspecfic/rbsxtr/files/www/luci-static/img/open.png new file mode 100644 index 0000000..7d06e6c Binary files /dev/null and b/rooter/0routerspecfic/rbsxtr/files/www/luci-static/img/open.png differ diff --git a/rooter/0routerspecfic/rd05a1/Makefile b/rooter/0routerspecfic/rd05a1/Makefile new file mode 100644 index 0000000..c4e21be --- /dev/null +++ b/rooter/0routerspecfic/rd05a1/Makefile @@ -0,0 +1,37 @@ +#Owned by DairyMan@Whirlpool +# +#Copyright GNU act. +include $(TOPDIR)/rules.mk + +PKG_NAME:=rd05a1 +PKG_VERSION:=1.000 +PKG_RELEASE:=1 + +PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool +include $(INCLUDE_DIR)/package.mk + +define Package/rd05a1 + SECTION:=utils + CATEGORY:=ROOter + SUBMENU:=Router Specific + DEPENDS:=+ath10k-firmware-qca9887-ct +ath9k-htc-firmware +kmod-ath10k-ct \ + +kmod-ath9k-htc + TITLE:=Install scripts for RD05A1 + PKGARCH:=all +endef + +define Package/rd05a1/description + Helper scripts to install scripts for RD05A1 +endef + + +define Build/Compile +endef + +define Package/rd05a1/install + $(CP) ./files/* $(1)/ + + +endef + +$(eval $(call BuildPackage,rd05a1)) diff --git a/rooter/0routerspecfic/rd05a1/files/etc/init.d/pciepwr b/rooter/0routerspecfic/rd05a1/files/etc/init.d/pciepwr new file mode 100644 index 0000000..f77fa81 --- /dev/null +++ b/rooter/0routerspecfic/rd05a1/files/etc/init.d/pciepwr @@ -0,0 +1,18 @@ +#!/bin/sh /etc/rc.common +# Copyright (C) 2013 OpenWrt.org + +START=87 +USE_PROCD=1 + +log() { + logger -t "RD05A1 PCie Power" "$@" +} + +start_service() +{ + gpio=13 + echo $gpio > /sys/class/gpio/export + echo out > /sys/class/gpio/gpio${gpio}/direction + echo 1 > /sys/class/gpio/gpio${gpio}/value + log "Turn on PCie Power" +} diff --git a/rooter/0routerspecfic/vpnpolicy/Makefile b/rooter/0routerspecfic/vpnpolicy/Makefile new file mode 100644 index 0000000..5d240b2 --- /dev/null +++ b/rooter/0routerspecfic/vpnpolicy/Makefile @@ -0,0 +1,31 @@ +#Owned by DairyMan@Whirlpool +# +#Copyright GNU act. +include $(TOPDIR)/rules.mk + +PKG_NAME:=vpnpolicy +PKG_VERSION:=1.000 +PKG_RELEASE:=1 + +PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool +include $(INCLUDE_DIR)/package.mk + +define Package/vpnpolicy + SECTION:=utils + CATEGORY:=ROOter + SUBMENU:=Router Specific + DEPENDS:=+vpn-policy-routing +luci-app-vpn-policy-routing \ + +ipset +resolveip +ip +kmod-ipt-ipset +iptables +dnsmasq-full + TITLE:=Install scripts for VPN Policy + PKGARCH:=all +endef + +define Package/vpnpolicy/description + Helper scripts to install scripts for VPN Policy +endef + + +define Build/Compile +endef + +$(eval $(call BuildPackage,vpnpolicy)) diff --git a/rooter/0routerspecfic/we826/Makefile b/rooter/0routerspecfic/we826/Makefile new file mode 100644 index 0000000..0c4c68d --- /dev/null +++ b/rooter/0routerspecfic/we826/Makefile @@ -0,0 +1,35 @@ +#Owned by DairyMan@Whirlpool +# +#Copyright GNU act. +include $(TOPDIR)/rules.mk + +PKG_NAME:=we826 +PKG_VERSION:=1.000 +PKG_RELEASE:=1 + +PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool +include $(INCLUDE_DIR)/package.mk + +define Package/we826 + SECTION:=utils + CATEGORY:=ROOter + SUBMENU:=Router Specific + TITLE:=Install scripts for WE826 Watchdog + PKGARCH:=all +endef + +define Package/we826/description + Helper scripts to install scripts for WE826 Watchdog +endef + + +define Build/Compile +endef + +define Package/we826/install + $(CP) ./files/* $(1)/ + + +endef + +$(eval $(call BuildPackage,we826)) diff --git a/rooter/0routerspecfic/we826/files/etc/init.d/wd-init b/rooter/0routerspecfic/we826/files/etc/init.d/wd-init new file mode 100644 index 0000000..baf6d77 --- /dev/null +++ b/rooter/0routerspecfic/we826/files/etc/init.d/wd-init @@ -0,0 +1,14 @@ +#!/bin/sh /etc/rc.common +# Copyright (C) 2013 OpenWrt.org + +START=50 +USE_PROCD=1 + +log() { + logger -t "usb-modeswitch" "$@" +} + +start_service() +{ + /usr/lib/custom/watchdog.sh & +} diff --git a/rooter/0routerspecfic/we826/files/usr/lib/custom/watchdog.sh b/rooter/0routerspecfic/we826/files/usr/lib/custom/watchdog.sh new file mode 100644 index 0000000..bf0afe6 --- /dev/null +++ b/rooter/0routerspecfic/we826/files/usr/lib/custom/watchdog.sh @@ -0,0 +1,19 @@ +#!/bin/sh + +#for example WE825-Q watchdog gpio is 2 +# WE826 is 11 +wd_gpio="11" + +echo $wd_gpio > /sys/class/gpio/export +echo out > /sys/class/gpio/gpio$wd_gpio/direction +echo 14 > /sys/class/gpio/export +echo out > /sys/class/gpio/gpio14/direction +echo 255 >/sys/class/gpio/gpio14/value + +while [ 1 ] +do + echo 255 >/sys/class/gpio/gpio$wd_gpio/value + sleep 1 + echo 0 >/sys/class/gpio/gpio$wd_gpio/value + sleep 1 +done diff --git a/rooter/0routerspecfic/we826q/Makefile b/rooter/0routerspecfic/we826q/Makefile new file mode 100644 index 0000000..36779cd --- /dev/null +++ b/rooter/0routerspecfic/we826q/Makefile @@ -0,0 +1,35 @@ +#Owned by DairyMan@Whirlpool +# +#Copyright GNU act. +include $(TOPDIR)/rules.mk + +PKG_NAME:=we826q +PKG_VERSION:=1.000 +PKG_RELEASE:=1 + +PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool +include $(INCLUDE_DIR)/package.mk + +define Package/we826q + SECTION:=utils + CATEGORY:=ROOter + SUBMENU:=Router Specific + TITLE:=Install scripts for WE826-Q + PKGARCH:=all +endef + +define Package/we826q/description + Helper scripts to install scripts for WE826-Q +endef + + +define Build/Compile +endef + +define Package/we826q/install + $(CP) ./files/* $(1)/ + + +endef + +$(eval $(call BuildPackage,we826q)) diff --git a/rooter/0routerspecfic/we826q/files/etc/init.d/wd-init b/rooter/0routerspecfic/we826q/files/etc/init.d/wd-init new file mode 100644 index 0000000..fde562a --- /dev/null +++ b/rooter/0routerspecfic/we826q/files/etc/init.d/wd-init @@ -0,0 +1,14 @@ +#!/bin/sh /etc/rc.common +# Copyright (C) 2013 OpenWrt.org + +START=20 +USE_PROCD=1 + +log() { + logger -t "usb-modeswitch" "$@" +} + +start_service() +{ + /usr/lib/custom/watchdog.sh & +} diff --git a/rooter/0routerspecfic/we826q/files/usr/lib/custom/watchdog.sh b/rooter/0routerspecfic/we826q/files/usr/lib/custom/watchdog.sh new file mode 100644 index 0000000..281cd4a --- /dev/null +++ b/rooter/0routerspecfic/we826q/files/usr/lib/custom/watchdog.sh @@ -0,0 +1,25 @@ +#!/bin/sh + +#for example WE825-Q watchdog gpio is 2 +wd_gpio="2" + +echo $wd_gpio > /sys/class/gpio/export +echo out > /sys/class/gpio/gpio$wd_gpio/direction + +while [ 1 ] +do + echo 1 >/sys/class/gpio/gpio$wd_gpio/value + sleep 1 + echo 0 >/sys/class/gpio/gpio$wd_gpio/value + sleep 1 + + echo 1 >/sys/class/gpio/gpio$wd_gpio/value + sleep 1 + echo 0 >/sys/class/gpio/gpio$wd_gpio/value + sleep 1 + + echo 1 >/sys/class/gpio/gpio$wd_gpio/value + sleep 1 + echo 0 >/sys/class/gpio/gpio$wd_gpio/value + sleep 1 +done diff --git a/rooter/0routerspecfic/wg1602/Makefile b/rooter/0routerspecfic/wg1602/Makefile new file mode 100644 index 0000000..bc608a7 --- /dev/null +++ b/rooter/0routerspecfic/wg1602/Makefile @@ -0,0 +1,36 @@ +#Owned by DairyMan@Whirlpool +# +#Copyright GNU act. +include $(TOPDIR)/rules.mk + +PKG_NAME:=wg1602 +PKG_VERSION:=1.000 +PKG_RELEASE:=1 + +PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool +include $(INCLUDE_DIR)/package.mk + +define Package/wg1602 + SECTION:=utils + CATEGORY:=ROOter + SUBMENU:=Router Specific + DEPENDS:=+kmod-mt7615e +kmod-mt76 +kmod-mt7603 +kmod-mt7615-firmware \ + +kmod-mt7615e +kmod-mt7663-firmware-ap +kmod-mt7663-firmware-sta \ + +kmod-mt76x2 + TITLE:=Install scripts for WG1602 + PKGARCH:=all +endef + +define Package/wg1602/description + Helper scripts to install scripts for WG1602 +endef + + +define Build/Compile +endef + +define Package/wg1602/install + $(CP) ./files/* $(1)/ +endef + +$(eval $(call BuildPackage,wg1602)) diff --git a/rooter/0routerspecfic/wg1602/files/etc/init.d/sw-init b/rooter/0routerspecfic/wg1602/files/etc/init.d/sw-init new file mode 100644 index 0000000..552a708 --- /dev/null +++ b/rooter/0routerspecfic/wg1602/files/etc/init.d/sw-init @@ -0,0 +1,15 @@ +#!/bin/sh /etc/rc.common +# Copyright (C) 2013 OpenWrt.org + +START=50 +USE_PROCD=1 + +log() { + logger -t "WatchDog" "$@" +} + +start_service() +{ + log "WG1602 USB Hub switch to USB3.0 infterface" + echo 0 > /sys/class/gpio/ext-usb/value +} diff --git a/rooter/0routerspecfic/wg1602/files/usr/lib/rooter/special.sh b/rooter/0routerspecfic/wg1602/files/usr/lib/rooter/special.sh new file mode 100644 index 0000000..11a7fde --- /dev/null +++ b/rooter/0routerspecfic/wg1602/files/usr/lib/rooter/special.sh @@ -0,0 +1,28 @@ +#!/bin/sh + +LED=0 +SM=$(uci get system.4G1) +if [ -z $SM ]; then + uci set system.4G1=led + uci set system.4G1.name="4G1" + uci set system.4G1.sysfs="green:4g1" + uci set system.4G1.trigger="netdev" + uci set system.4G1.dev="wwan0" + uci set system.4G1.mode="link tx rx" + LED=1 +fi +SM=$(uci get system.4G2) +if [ -z $SM ]; then + uci set system.4G2=led + uci set system.4G2.name="4G2" + uci set system.4G2.sysfs="green:4g2" + uci set system.4G2.trigger="netdev" + uci set system.4G2.dev="wwan1" + uci set system.4G2.mode="link tx rx" + LED=1 +fi + +if [ $LED -eq 1 ]; then + uci commit system + /etc/init.d/led restart +fi diff --git a/rooter/0routerspecfic/wg1608/Makefile b/rooter/0routerspecfic/wg1608/Makefile new file mode 100644 index 0000000..0e5ab8a --- /dev/null +++ b/rooter/0routerspecfic/wg1608/Makefile @@ -0,0 +1,36 @@ +#Owned by DairyMan@Whirlpool +# +#Copyright GNU act. +include $(TOPDIR)/rules.mk + +PKG_NAME:=wg1608 +PKG_VERSION:=1.000 +PKG_RELEASE:=1 + +PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool +include $(INCLUDE_DIR)/package.mk + +define Package/wg1608 + SECTION:=utils + CATEGORY:=ROOter + SUBMENU:=Router Specific + DEPENDS:=+kmod-mt7615e +kmod-mt76 +kmod-mt7603 +kmod-mt7615-firmware \ + +kmod-mt7615e +kmod-mt7663-firmware-ap +kmod-mt7663-firmware-sta \ + +kmod-mt76x2 + TITLE:=Install scripts for WG1608 + PKGARCH:=all +endef + +define Package/wg1608/description + Helper scripts to install scripts for WG1608 +endef + + +define Build/Compile +endef + +define Package/wg1608/install + $(CP) ./files/* $(1)/ +endef + +$(eval $(call BuildPackage,wg1608)) diff --git a/rooter/0routerspecfic/wg1608/files/etc/init.d/wd-init b/rooter/0routerspecfic/wg1608/files/etc/init.d/wd-init new file mode 100644 index 0000000..465976c --- /dev/null +++ b/rooter/0routerspecfic/wg1608/files/etc/init.d/wd-init @@ -0,0 +1,15 @@ +#!/bin/sh /etc/rc.common +# Copyright (C) 2013 OpenWrt.org + +START=50 +USE_PROCD=1 + +log() { + logger -t "WatchDog" "$@" +} + +start_service() +{ + /usr/lib/custom/watchdog.sh & + log "Start watchdog" +} diff --git a/rooter/0routerspecfic/wg1608/files/usr/lib/custom/watchdog.sh b/rooter/0routerspecfic/wg1608/files/usr/lib/custom/watchdog.sh new file mode 100644 index 0000000..befbcd7 --- /dev/null +++ b/rooter/0routerspecfic/wg1608/files/usr/lib/custom/watchdog.sh @@ -0,0 +1,23 @@ +#!/bin/sh + +dis=493 +echo $dis > /sys/class/gpio/export +echo out > /sys/class/gpio/gpio$dis/direction +echo 255 >/sys/class/gpio/gpio$dis/value + +echo none > /sys/class/leds/watchdog/trigger +while [ 1 ] +do + echo 1 >/sys/class/leds/watchdog/brightness + sleep 1 + echo 0 >/sys/class/leds/watchdog/brightness + sleep 1 + echo 1 >/sys/class/leds/watchdog/brightness + sleep 1 + echo 0 >/sys/class/leds/watchdog/brightness + sleep 1 + echo 1 >/sys/class/leds/watchdog/brightness + sleep 1 + echo 0 >/sys/class/leds/watchdog/brightness + sleep 5 +done diff --git a/rooter/0routerspecfic/wg1608/files/usr/lib/rooter/modem-led.sh b/rooter/0routerspecfic/wg1608/files/usr/lib/rooter/modem-led.sh new file mode 100644 index 0000000..25b0fa1 --- /dev/null +++ b/rooter/0routerspecfic/wg1608/files/usr/lib/rooter/modem-led.sh @@ -0,0 +1,51 @@ +#!/bin/sh + +log() { + logger -t "modem-led " "$@" +} + +CURRMODEM=$1 +COMMD=$2 + + case $COMMD in + "0" ) + echo none > /sys/class/leds/green:globe/trigger + echo 0 > /sys/class/leds/green:globe/brightness + echo none > /sys/class/leds/green:signal/trigger + echo 0 > /sys/class/leds/green:signal/brightness + ;; + "1" ) + echo timer > /sys/class/leds/green:globe/trigger + echo 500 > /sys/class/leds/green:globe/delay_on + echo 500 > /sys/class/leds/green:globe/delay_off + ;; + "2" ) + echo timer > /sys/class/leds/green:globe/trigger + echo 200 > /sys/class/leds/green:globe/delay_on + echo 200 > /sys/class/leds/green:globe/delay_off + ;; + "3" ) + echo timer > /sys/class/leds/green:globe/trigger + echo 1000 > /sys/class/leds/green:globe/delay_on + echo 0 > /sys/class/leds/green:globe/delay_off + ;; + "4" ) + echo none > /sys/class/leds/green:globe/trigger + echo 1 > /sys/class/leds/green:globe/brightness + sig2=$3 + echo timer > /sys/class/leds/green:signal/trigger + if [ $sig2 -lt 18 -a $sig2 -gt 0 ] 2>/dev/null;then + echo 500 > /sys/class/leds/green:signal/delay_on + echo 500 > /sys/class/leds/green:signal/delay_off + elif [ $sig2 -ge 18 -a $sig2 -lt 31 ] 2>/dev/null;then + echo 150 > /sys/class/leds/green:signal/delay_on + echo 150 > /sys/class/leds/green:signal/delay_off + elif [ $sig2 -eq 31 ] 2>/dev/null;then + echo 0 > /sys/class/leds/green:signal/delay_on + echo 1000 > /sys/class/leds/green:signal/delay_off + else + echo 950 > /sys/class/leds/green:signal/delay_on + echo 950 > /sys/class/leds/green:signal/delay_off + fi + ;; + esac diff --git a/rooter/0routerspecfic/wg1608/files/usr/lib/rooter/special.sh b/rooter/0routerspecfic/wg1608/files/usr/lib/rooter/special.sh new file mode 100644 index 0000000..92f36d5 --- /dev/null +++ b/rooter/0routerspecfic/wg1608/files/usr/lib/rooter/special.sh @@ -0,0 +1,15 @@ +#!/bin/sh + +LED=0 +SM=$(uci get system.wifi) +if [ -z $SM ]; then + uci set system.wifi=led + uci set system.wifi.name="5Ghzwifi" + uci set system.wifi.sysfs="wifi" + uci set system.wifi.trigger="netdev" + uci set system.wifi.dev="wlan1" + uci set system.wifi.mode="link tx rx" + uci commit system + /etc/init.d/led restart +fi + diff --git a/rooter/0routerspecfic/wg209/Makefile b/rooter/0routerspecfic/wg209/Makefile new file mode 100644 index 0000000..34852dd --- /dev/null +++ b/rooter/0routerspecfic/wg209/Makefile @@ -0,0 +1,33 @@ +#Owned by DairyMan@Whirlpool +# +#Copyright GNU act. +include $(TOPDIR)/rules.mk + +PKG_NAME:=wg209 +PKG_VERSION:=1.000 +PKG_RELEASE:=1 + +PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool +include $(INCLUDE_DIR)/package.mk + +define Package/wg209 + SECTION:=utils + CATEGORY:=ROOter + SUBMENU:=Router Specific + TITLE:=Install scripts for WG209 + PKGARCH:=all +endef + +define Package/wg209/description + Helper scripts to install scripts for WG209 +endef + + +define Build/Compile +endef + +define Package/wg209/install + $(CP) ./files/* $(1)/ +endef + +$(eval $(call BuildPackage,wg209)) diff --git a/rooter/0routerspecfic/wg209/files/usr/lib/rooter/modem-led.sh b/rooter/0routerspecfic/wg209/files/usr/lib/rooter/modem-led.sh new file mode 100644 index 0000000..9cdace0 --- /dev/null +++ b/rooter/0routerspecfic/wg209/files/usr/lib/rooter/modem-led.sh @@ -0,0 +1,76 @@ +#!/bin/sh + +log() { + logger -t "modem-led " "$@" +} + +CURRMODEM=$1 +COMMD=$2 + + case $COMMD in + "0" ) + echo none > /sys/class/leds/green:signal1/trigger + echo 0 > /sys/class/leds/green:signal1/brightness + echo none > /sys/class/leds/green:signal2/trigger + echo 0 > /sys/class/leds/green:signal2/brightness + echo none > /sys/class/leds/green:signal3/trigger + echo 0 > /sys/class/leds/green:signal3/brightness + echo none > /sys/class/leds/green:internet/trigger + echo 0 > /sys/class/leds/green:internet/brightness + ;; + "1" ) + echo timer > /sys/class/leds/green:internet/trigger + echo 500 > /sys/class/leds/green:internet/delay_on + echo 500 > /sys/class/leds/green:internet/delay_off + ;; + "2" ) + echo timer > /sys/class/leds/green:internet/trigger + echo 200 > /sys/class/leds/green:internet/delay_on + echo 200 > /sys/class/leds/green:internet/delay_off + ;; + "3" ) + echo timer > /sys/class/leds/green:internet/trigger + echo 1000 > /sys/class/leds/green:internet/delay_on + echo 0 > /sys/class/leds/green:internet/delay_off + ;; + "4" ) + sig2=$3 + if [ $sig2 -lt 8 -a $sig2 -gt 0 ] 2>/dev/null;then + echo none > /sys/class/leds/green:internet/trigger + echo 1 > /sys/class/leds/green:internet/brightness + echo none > /sys/class/leds/green:signal3/trigger + echo 0 > /sys/class/leds/green:signal3/brightness + echo none > /sys/class/leds/green:signal2/trigger + echo 0 > /sys/class/leds/green:signal2/brightness + echo none > /sys/class/leds/green:signal1/trigger + echo 0 > /sys/class/leds/green:signal1/brightness + elif [ $sig2 -ge 8 -a $sig2 -lt 16 ] 2>/dev/null;then + echo none > /sys/class/leds/green:internet/trigger + echo 1 > /sys/class/leds/green:internet/brightness + echo none > /sys/class/leds/green:signal3/trigger + echo 1 > /sys/class/leds/green:signal3/brightness + echo none > /sys/class/leds/green:signal2/trigger + echo 0 > /sys/class/leds/green:signal2/brightness + echo none > /sys/class/leds/green:signal1/trigger + echo 0 > /sys/class/leds/green:signal1/brightness + elif [ $sig2 -ge 16 -a $sig2 -lt 24 ] 2>/dev/null;then + echo none > /sys/class/leds/green:internet/trigger + echo 1 > /sys/class/leds/green:internet/brightness + echo none > /sys/class/leds/green:signal3/trigger + echo 1 > /sys/class/leds/green:signal3/brightness + echo none > /sys/class/leds/green:signal2/trigger + echo 1 > /sys/class/leds/green:signal2/brightness + echo none > /sys/class/leds/green:signal1/trigger + echo 0 > /sys/class/leds/green:signal1/brightness + elif [ $sig2 -ge 24 ] 2>/dev/null;then + echo none > /sys/class/leds/green:internet/trigger + echo 1 > /sys/class/leds/green:internet/brightness + echo none > /sys/class/leds/green:signal3/trigger + echo 1 > /sys/class/leds/green:signal3/brightness + echo none > /sys/class/leds/green:signal2/trigger + echo 1 > /sys/class/leds/green:signal2/brightness + echo none > /sys/class/leds/green:signal1/trigger + echo 1 > /sys/class/leds/green:signal1/brightness + fi + ;; + esac diff --git a/rooter/0routerspecfic/wg259/Makefile b/rooter/0routerspecfic/wg259/Makefile new file mode 100644 index 0000000..c0a41ae --- /dev/null +++ b/rooter/0routerspecfic/wg259/Makefile @@ -0,0 +1,34 @@ +#Owned by DairyMan@Whirlpool +# +#Copyright GNU act. +include $(TOPDIR)/rules.mk + +PKG_NAME:=wg259 +PKG_VERSION:=1.000 +PKG_RELEASE:=1 + +PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool +include $(INCLUDE_DIR)/package.mk + +define Package/wg259 + SECTION:=utils + CATEGORY:=ROOter + SUBMENU:=Router Specific + DEPENDS:=+kmod-mt76 +kmod-mt7603 +kmod-mt76x2 + TITLE:=Install scripts for WG259 + PKGARCH:=all +endef + +define Package/wg259/description + Helper scripts to install scripts for WG259 +endef + + +define Build/Compile +endef + +define Package/wg259/install + $(CP) ./files/* $(1)/ +endef + +$(eval $(call BuildPackage,wg259)) diff --git a/rooter/0routerspecfic/wg259/files/usr/lib/rooter/special.sh b/rooter/0routerspecfic/wg259/files/usr/lib/rooter/special.sh new file mode 100644 index 0000000..94ee31a --- /dev/null +++ b/rooter/0routerspecfic/wg259/files/usr/lib/rooter/special.sh @@ -0,0 +1,23 @@ +#!/bin/sh + +SM=$(uci get system.4g5g) +if [ -z $SM ]; then + uci set system.4g5g=led + uci set system.4g5g.name="4G5G" + uci set system.4g5g.sysfs="green:usb" + uci set system.4g5g.trigger="netdev" + uci set system.4g5g.dev="wwan0" + uci set system.4g5g.mode="link tx rx" + uci set system.4g5g.default='0' + + uci set system.sys=led + uci set system.sys.name="SYS" + uci set system.sys.sysfs="green:status" + uci set system.sys.trigger="netdev" + uci set system.sys.dev="br-lan" + uci set system.sys.mode="link tx rx" + uci set system.sys.default='0' + + uci commit system + /etc/init.d/led restart +fi diff --git a/rooter/0routerspecfic/wg3526/Makefile b/rooter/0routerspecfic/wg3526/Makefile new file mode 100644 index 0000000..8cb384e --- /dev/null +++ b/rooter/0routerspecfic/wg3526/Makefile @@ -0,0 +1,33 @@ +#Owned by DairyMan@Whirlpool +# +#Copyright GNU act. +include $(TOPDIR)/rules.mk + +PKG_NAME:=wg3526 +PKG_VERSION:=1.000 +PKG_RELEASE:=1 + +PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool +include $(INCLUDE_DIR)/package.mk + +define Package/wg3526 + SECTION:=utils + CATEGORY:=ROOter + SUBMENU:=Router Specific + TITLE:=Install scripts for wg3526 + PKGARCH:=all +endef + +define Package/wg3526/description + Helper scripts to install scripts for wg3526 +endef + + +define Build/Compile +endef + +define Package/wg3526/install + $(CP) ./files/* $(1)/ +endef + +$(eval $(call BuildPackage,wg3526)) diff --git a/rooter/0routerspecfic/wg3526/files/usr/lib/rooter/special.sh b/rooter/0routerspecfic/wg3526/files/usr/lib/rooter/special.sh new file mode 100644 index 0000000..e27a0b3 --- /dev/null +++ b/rooter/0routerspecfic/wg3526/files/usr/lib/rooter/special.sh @@ -0,0 +1,19 @@ +#!/bin/sh + + +echo none > /sys/class/leds/green:status/trigger +echo 0 > /sys/class/leds/green:status/brightness + +SM=$(uci get system.4g5g) +if [ -z $SM ]; then + uci set system.4g5g=led + uci set system.4g5g.name="4G5G" + uci set system.4g5g.sysfs="green:status" + uci set system.4g5g.trigger="netdev" + uci set system.4g5g.dev="wwan0" + uci set system.4g5g.mode="link tx rx" + uci set system.4g5g.default='0' + + uci commit system + /etc/init.d/led restart +fi \ No newline at end of file diff --git a/rooter/0routerspecfic/wg827/Makefile b/rooter/0routerspecfic/wg827/Makefile new file mode 100644 index 0000000..c8a419f --- /dev/null +++ b/rooter/0routerspecfic/wg827/Makefile @@ -0,0 +1,36 @@ +#Owned by DairyMan@Whirlpool +# +#Copyright GNU act. +include $(TOPDIR)/rules.mk + +PKG_NAME:=wg827 +PKG_VERSION:=1.000 +PKG_RELEASE:=1 + +PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool +include $(INCLUDE_DIR)/package.mk + +define Package/wg827 + SECTION:=utils + CATEGORY:=ROOter + SUBMENU:=Router Specific + DEPENDS:=+kmod-mt7615e +kmod-mt76 +kmod-mt7603 +kmod-mt7615-firmware \ + +kmod-mt7615e +kmod-mt7663-firmware-ap +kmod-mt7663-firmware-sta \ + +kmod-mt76x2 + TITLE:=Install scripts for WG827 + PKGARCH:=all +endef + +define Package/wg827/description + Helper scripts to install scripts for WG827 +endef + + +define Build/Compile +endef + +define Package/wg827/install + $(CP) ./files/* $(1)/ +endef + +$(eval $(call BuildPackage,wg827)) diff --git a/rooter/0routerspecfic/wg827/files/usr/lib/rooter/modem-led.sh b/rooter/0routerspecfic/wg827/files/usr/lib/rooter/modem-led.sh new file mode 100644 index 0000000..cdf5b4c --- /dev/null +++ b/rooter/0routerspecfic/wg827/files/usr/lib/rooter/modem-led.sh @@ -0,0 +1,38 @@ +#!/bin/sh + +log() { + logger -t "modem-led " "$@" +} + +CURRMODEM=$1 +COMMD=$2 + + case $COMMD in + "0" ) + echo none > /sys/class/leds/rgb:blue/trigger + echo 0 > /sys/class/leds/rgb:blue/brightness + echo none > /sys/class/leds/rgb:green/trigger + echo 1 > /sys/class/leds/rgb:green/brightness + ;; + "1" ) + echo timer > /sys/class/leds/rgb:blue/trigger + echo 500 > /sys/class/leds/rgb:blue/delay_on + echo 500 > /sys/class/leds/rgb:blue/delay_off + ;; + "2" ) + echo timer > /sys/class/leds/rgb:blue/trigger + echo 200 > /sys/class/leds/rgb:blue/delay_on + echo 200 > /sys/class/leds/rgb:blue/delay_off + ;; + "3" ) + echo timer > /sys/class/leds/rgb:blue/trigger + echo 1000 > /sys/class/leds/rgb:blue/delay_on + echo 0 > /sys/class/leds/rgb:blue/delay_off + ;; + "4" ) + echo none > /sys/class/leds/rgb:blue/trigger + echo 1 > /sys/class/leds/rgb:blue/brightness + echo none > /sys/class/leds/rgb:green/trigger + echo 0 > /sys/class/leds/rgb:green/brightness + ;; + esac diff --git a/rooter/0routerspecfic/wrt1900/Makefile b/rooter/0routerspecfic/wrt1900/Makefile new file mode 100644 index 0000000..843e6a6 --- /dev/null +++ b/rooter/0routerspecfic/wrt1900/Makefile @@ -0,0 +1,35 @@ +#Owned by DairyMan@Whirlpool +# +#Copyright GNU act. +include $(TOPDIR)/rules.mk + +PKG_NAME:=wrt1900 +PKG_VERSION:=1.000 +PKG_RELEASE:=1 + +PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool +include $(INCLUDE_DIR)/package.mk + +define Package/wrt1900 + SECTION:=utils + CATEGORY:=ROOter + SUBMENU:=Router Specific + TITLE:=Install scripts for WRT1900 + PKGARCH:=all +endef + +define Package/wrt1900/description + Helper scripts to install scripts for WRT1900 +endef + + +define Build/Compile +endef + +define Package/wrt1900/install + $(CP) ./files/* $(1)/ + + +endef + +$(eval $(call BuildPackage,wrt1900)) diff --git a/rooter/0routerspecfic/wrt1900/files/etc/init.d/amsdu b/rooter/0routerspecfic/wrt1900/files/etc/init.d/amsdu new file mode 100644 index 0000000..aa39594 --- /dev/null +++ b/rooter/0routerspecfic/wrt1900/files/etc/init.d/amsdu @@ -0,0 +1,14 @@ +#!/bin/sh /etc/rc.common +# Copyright (C) 2013 OpenWrt.org + +START=70 + +log() { + logger -t "AMSDU" "$@" +} + +start_service() +{ + echo 0 > /sys/kernel/debug/ieee80211/phy0/mwlwifi/tx_amsdu + echo 0 > /sys/kernel/debug/ieee80211/phy1/mwlwifi/tx_amsdu +} diff --git a/rooter/0routerspecfic/x750/Makefile b/rooter/0routerspecfic/x750/Makefile new file mode 100644 index 0000000..ad8caca --- /dev/null +++ b/rooter/0routerspecfic/x750/Makefile @@ -0,0 +1,33 @@ +#Owned by DairyMan@Whirlpool +# +#Copyright GNU act. +include $(TOPDIR)/rules.mk + +PKG_NAME:=x750 +PKG_VERSION:=1.000 +PKG_RELEASE:=1 + +PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool +include $(INCLUDE_DIR)/package.mk + +define Package/x750 + SECTION:=utils + CATEGORY:=ROOter + SUBMENU:=Router Specific + TITLE:=Install scripts for x750 + PKGARCH:=all +endef + +define Package/x750/description + Helper scripts to install scripts for x750 +endef + + +define Build/Compile +endef + +define Package/x750/install + $(CP) ./files/* $(1)/ +endef + +$(eval $(call BuildPackage,x750)) diff --git a/rooter/0routerspecfic/x750/files/usr/lib/rooter/special.sh b/rooter/0routerspecfic/x750/files/usr/lib/rooter/special.sh new file mode 100644 index 0000000..9787a19 --- /dev/null +++ b/rooter/0routerspecfic/x750/files/usr/lib/rooter/special.sh @@ -0,0 +1,23 @@ +#!/bin/sh + +SM=$(uci get system.4g5g) +if [ -z $SM ]; then + uci set system.4g5g=led + uci set system.4g5g.name="4G5G" + uci set system.4g5g.sysfs="green:4g" + uci set system.4g5g.trigger="netdev" + uci set system.4g5g.dev="wwan0" + uci set system.4g5g.mode="link tx rx" + uci set system.4g5g.default='0' + + uci commit system + /etc/init.d/led restart +fi + +uci set system.gpio2=gpio_switch +uci set system.gpio2.name='gpio2' +uci set system.gpio2.gpio_pin='2' +uci set system.gpio2.value='0' +uci commit system +/etc/init.d/system restart + diff --git a/rooter/0splash/ext-splash/Makefile b/rooter/0splash/ext-splash/Makefile new file mode 100644 index 0000000..8372994 --- /dev/null +++ b/rooter/0splash/ext-splash/Makefile @@ -0,0 +1,35 @@ +#Owned by DairyMan@Whirlpool +# +#Copyright GNU act. +include $(TOPDIR)/rules.mk + +PKG_NAME:=ext-splash +PKG_VERSION:=1.000 +PKG_RELEASE:=1 + +PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool +include $(INCLUDE_DIR)/package.mk + +define Package/ext-splash + SECTION:=utils + CATEGORY:=ROOter + SUBMENU:=Splash Screens + TITLE:=Added scripts for Login display + PKGARCH:=all +endef + +define Package/ext-splash/description + Added scripts for Login display +endef + + +define Build/Compile +endef + +define Package/ext-splash/install + $(CP) ./files/* $(1)/ + + +endef + +$(eval $(call BuildPackage,ext-splash)) diff --git a/rooter/0splash/ext-splash/files/etc/config/iframe b/rooter/0splash/ext-splash/files/etc/config/iframe new file mode 100644 index 0000000..a97bc1d --- /dev/null +++ b/rooter/0splash/ext-splash/files/etc/config/iframe @@ -0,0 +1,17 @@ + +config iframe 'iframe' + option splashpage '0' + option splashtitle 'ROOter' + option url 'www.ofmodemsandmen.com' + option dual '0' + option speed '0' + option band '0' + +config login 'login' + option logframe '0' + option logtype '3' + option logimage 'open.png' + option logimageheight '300' + option logimagewidth '300' + option logimagepos 'absmiddle' + diff --git a/rooter/0splash/ext-splash/files/etc/init.d/iframeint b/rooter/0splash/ext-splash/files/etc/init.d/iframeint new file mode 100644 index 0000000..79f6de6 --- /dev/null +++ b/rooter/0splash/ext-splash/files/etc/init.d/iframeint @@ -0,0 +1,18 @@ +#!/bin/sh /etc/rc.common +# Copyright (C) 2013 OpenWrt.org + +START=60 +USE_PROCD=1 + +log() { + logger -t "iframe" "$@" +} + +start_service() +{ + if [ ! -d /tmp/www ]; then + mkdir -p /tmp/www + fi + /usr/lib/iframe/create.sh & + /usr/lib/iframe/status.sh & +} diff --git a/rooter/0splash/ext-splash/files/usr/lib/iframe/band.html b/rooter/0splash/ext-splash/files/usr/lib/iframe/band.html new file mode 100644 index 0000000..9db882d --- /dev/null +++ b/rooter/0splash/ext-splash/files/usr/lib/iframe/band.html @@ -0,0 +1 @@ +
                          Bandwidth Usage
                          \ No newline at end of file diff --git a/rooter/0splash/ext-splash/files/usr/lib/iframe/bwdays.sh b/rooter/0splash/ext-splash/files/usr/lib/iframe/bwdays.sh new file mode 100644 index 0000000..1c5a776 --- /dev/null +++ b/rooter/0splash/ext-splash/files/usr/lib/iframe/bwdays.sh @@ -0,0 +1,109 @@ +#!/bin/sh +. /lib/functions.sh + +genline() { + MONLIST=$MONLIST"" + t1="
                          $START
                          " + t2="
                          $updata
                          " + t3="
                          $downdata
                          " + t4="
                          $totaldata
                          " + MONLIST=$MONLIST$t1$t2$t3$t4"" +} + +bwdata() { + START="-" + END="-" + header=0 + while IFS= read -r line; do + if [ $header -eq 0 ]; then + days=$line + read -r line + DOWN=$line + read -r line + UP=$line + read -r line + TOTAL=$line + read -r line + line=$(echo $line" " | tr "|" ",") + END=$(echo $line | cut -d, -f1) + START=$END + updata=$(echo $line | cut -d, -f2) + downdata=$(echo $line | cut -d, -f3) + totaldata=$(echo $line | cut -d, -f4) + genline + read -r line + header=1 + if [ -z "$line" ]; then + break + fi + fi + line=$(echo $line" " | tr "|" ",") + START=$(echo $line | cut -d, -f1) + updata=$(echo $line | cut -d, -f2) + downdata=$(echo $line | cut -d, -f3) + totaldata=$(echo $line | cut -d, -f4) + genline + + done < /usr/lib/bwmon/data/monthly.data +} + +currdata() { + while IFS= read -r line; do + if [ $line = '0' ]; then + break + else + cdays=$line + read -r line + read -r line + ctused=$line + read -r line + read -r line + ctdwn=$line + read -r line + read -r line + ctup=$line + read -r line + read -r line + cproject=$line + break + fi + done < /tmp/bwdata +} + + STEMP="/tmp/www/dtemp.html" + STATUS="/usr/lib/iframe/bwtemplate.html" + IFSTATUS="/tmp/www/daylist.html" + + MONLIST="" + + rm -f $STEMP + cp $STATUS $STEMP + if [ -e /usr/lib/bwmon/data/monthly.data ]; then + #MONLIST="" + bwdata + MONLIST=$MONLIST"
                          " + else + START="-" + END="-" + TOTAL="-" + DOWN="-" + UP="-" + fi + + currdata + + sed -i -e "s!#START#!$START!g" $STEMP + sed -i -e "s!#END#!$END!g" $STEMP + sed -i -e "s!#TOTAL#!$TOTAL!g" $STEMP + sed -i -e "s!#DOWN#!$DOWN!g" $STEMP + sed -i -e "s!#UP#!$UP!g" $STEMP + sed -i -e "s!#MONLIST#!$MONLIST!g" $STEMP + + sed -i -e "s!#CDAYS#!$cdays!g" $STEMP + sed -i -e "s!#CTOTAL#!$ctused!g" $STEMP + sed -i -e "s!#CDOWN#!$ctdwn!g" $STEMP + sed -i -e "s!#CUP#!$ctup!g" $STEMP + sed -i -e "s!#PROJECT#!$cproject!g" $STEMP + + mv $STEMP $IFSTATUS + diff --git a/rooter/0splash/ext-splash/files/usr/lib/iframe/bwtemplate.html b/rooter/0splash/ext-splash/files/usr/lib/iframe/bwtemplate.html new file mode 100644 index 0000000..81b6ec9 --- /dev/null +++ b/rooter/0splash/ext-splash/files/usr/lib/iframe/bwtemplate.html @@ -0,0 +1,85 @@ + + + + + + + + + +

                          Current Month's Bandwidth Usage

                          +
                          +
                          +
                          +
                          Days
                          + #CDAYS# +
                          +
                          +
                          Total Amount Used
                          + #CTOTAL# +
                          +
                          +
                          +
                          +
                          Downloaded
                          + #CDOWN# +
                          +
                          +
                          Uploaded
                          + #CUP# +
                          +
                          +
                          Projected Amount
                          + #PROJECT# +
                          +
                          +
                          + +

                          Last 30 Day Bandwidth Usage

                          + + +
                          +
                          +
                          +
                          Starting Date
                          + #START# +
                          +
                          +
                          Ending Date
                          + #END# +
                          +
                          +
                          +
                          +
                          Total
                          + #TOTAL# +
                          +
                          +
                          Download
                          + #DOWN# +
                          +
                          +
                          Upload
                          + #UP# +
                          +
                          +
                          + +
                          + + + + + + + + + #MONLIST# + + + diff --git a/rooter/0splash/ext-splash/files/usr/lib/iframe/create.sh b/rooter/0splash/ext-splash/files/usr/lib/iframe/create.sh new file mode 100644 index 0000000..5a292e5 --- /dev/null +++ b/rooter/0splash/ext-splash/files/usr/lib/iframe/create.sh @@ -0,0 +1,31 @@ +#!/bin/sh +. /lib/functions.sh + +bwdata() { + result=`ps | grep -i "create_data.lua" | grep -v "grep" | wc -l` + if [ $result -lt 1 ]; then + lua /usr/lib/bwmon/create_data.lua + fi + while [ true ] + do + if [ -e /tmp/bwdata ]; then + break + fi + sleep 1 + done +} + +bwdata +/usr/lib/iframe/update.sh +logtype=$(uci -q get iframe.login.logtype) +if [ $logtype = "1" ]; then + sleep 300 + while [ true ] + do + result=`ps | grep -i "update.sh" | grep -v "grep" | wc -l` + if [ $result -lt 1 ]; then + /usr/lib/iframe/update.sh + fi + sleep 300 + done +fi \ No newline at end of file diff --git a/rooter/0splash/ext-splash/files/usr/lib/iframe/daylist.html b/rooter/0splash/ext-splash/files/usr/lib/iframe/daylist.html new file mode 100644 index 0000000..ba5170d --- /dev/null +++ b/rooter/0splash/ext-splash/files/usr/lib/iframe/daylist.html @@ -0,0 +1,85 @@ + + + + + + + + + +

                          Current Month's Bandwidth Usage

                          +
                          +
                          +
                          +
                          Days
                          + 10 +
                          +
                          +
                          Total Amount Used
                          + 451.39 MB +
                          +
                          +
                          +
                          +
                          Downloaded
                          + 409.57 MB +
                          +
                          +
                          Uploaded
                          + 41.82 MB +
                          +
                          +
                          Projected Amount
                          + 1.35 GB +
                          +
                          +
                          + +

                          Last 30 Day Bandwidth Usage

                          + + +
                          +
                          +
                          +
                          Starting Date
                          + 2022-01-03 +
                          +
                          +
                          Ending Date
                          + 2022-01-15 +
                          +
                          +
                          +
                          +
                          Total
                          + 360.05 MB +
                          +
                          +
                          Download
                          + 322.79 MB +
                          +
                          +
                          Upload
                          + 37.25 MB +
                          +
                          +
                          + +
                          +
                          DATE
                          DOWN
                          UP
                          TOTAL
                          + + + + + + + +
                          DATE
                          DOWN
                          UP
                          TOTAL
                          2022-01-15
                          0.00 K
                          0.00 K
                          0.00 K
                          2022-01-14
                          0.00 K
                          0.00 K
                          0.00 K
                          2022-01-13
                          41.87 MB
                          1.71 MB
                          43.58 MB
                          2022-01-12
                          0.00 K
                          0.00 K
                          0.00 K
                          2022-01-07
                          18.56 MB
                          5.24 MB
                          23.80 MB
                          2022-01-06
                          175.59 MB
                          25.72 MB
                          201.32 MB
                          2022-01-04
                          56.19 MB
                          3.59 MB
                          59.78 MB
                          2022-01-03
                          30.58 MB
                          986.00 K
                          31.57 MB
                          +
                          + + diff --git a/rooter/0splash/ext-splash/files/usr/lib/iframe/iframe.html b/rooter/0splash/ext-splash/files/usr/lib/iframe/iframe.html new file mode 100644 index 0000000..aa47d93 --- /dev/null +++ b/rooter/0splash/ext-splash/files/usr/lib/iframe/iframe.html @@ -0,0 +1,41 @@ + + + + + + + + + +

                          #TITLE#

                          + +
                          +
                          +
                          +
                          Reporting Period (Days)
                          + #DAYS# +
                          +
                          +
                          +
                          +
                          Total Bandwidth Used
                          + #TOTAL# +
                          +
                          +
                          Projected Use
                          + #PROJ# +
                          +
                          +
                          +
                          +
                          Total Downloaded
                          + #DOWN# +
                          +
                          +
                          Total Uploaded
                          + #UP# +
                          +
                          +
                          + + diff --git a/rooter/0splash/ext-splash/files/usr/lib/iframe/image.html b/rooter/0splash/ext-splash/files/usr/lib/iframe/image.html new file mode 100644 index 0000000..a7b9893 --- /dev/null +++ b/rooter/0splash/ext-splash/files/usr/lib/iframe/image.html @@ -0,0 +1,11 @@ + + + + + + + +

                           

                          +

                          + + diff --git a/rooter/0splash/ext-splash/files/usr/lib/iframe/modem2.html b/rooter/0splash/ext-splash/files/usr/lib/iframe/modem2.html new file mode 100644 index 0000000..5957a8b --- /dev/null +++ b/rooter/0splash/ext-splash/files/usr/lib/iframe/modem2.html @@ -0,0 +1 @@ +

                          Modem 2

                          Strength (%)
                          #PER#
                          CSQ
                          #CSQ#
                          RSSI (dBm)
                          #RSSI#
                          RSCP (dBm) RSRP
                          #RSCP#
                          ECIO (dB) RSRQ
                          #RSRQ#
                          SINR (dB)
                          #SINR#

                          Network

                          Mode
                          #MODE#
                          MCC
                          #MCC#
                          MNC
                          #MNC#
                          RNC/eNB ID
                          #RNC# #RNCN#
                          LAC
                          #LAC# #LACN#
                          Channel (EARFCN)
                          #CHAN#
                          PCI
                          #CELLID#
                          Bands
                          #BAND#

                          Device

                          Modem
                          #MODEM#
                          Provider
                          #MODEMN#
                          Protocol
                          #PROTO#
                          Port
                          #PORT#
                          Temperature
                          #TEMP#
                          \ No newline at end of file diff --git a/rooter/0splash/ext-splash/files/usr/lib/iframe/open.html b/rooter/0splash/ext-splash/files/usr/lib/iframe/open.html new file mode 100644 index 0000000..fa7d40d --- /dev/null +++ b/rooter/0splash/ext-splash/files/usr/lib/iframe/open.html @@ -0,0 +1 @@ +
                          OpenSpeedTest
                          \ No newline at end of file diff --git a/rooter/0splash/ext-splash/files/usr/lib/iframe/speed.html b/rooter/0splash/ext-splash/files/usr/lib/iframe/speed.html new file mode 100644 index 0000000..0338c71 --- /dev/null +++ b/rooter/0splash/ext-splash/files/usr/lib/iframe/speed.html @@ -0,0 +1,114 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

                          OpenSpeedTest

                          + +
                          + +
                          + +
                          + + + + diff --git a/rooter/0splash/ext-splash/files/usr/lib/iframe/status.html b/rooter/0splash/ext-splash/files/usr/lib/iframe/status.html new file mode 100644 index 0000000..ddb0c69 --- /dev/null +++ b/rooter/0splash/ext-splash/files/usr/lib/iframe/status.html @@ -0,0 +1,150 @@ + + + + + + + + + + + + + + + + + + + + + #TITLEBAR# + #BUTTON# +
                          +

                          Modem 1

                          +
                          +
                          +
                          Strength (%)
                          + #PER# +
                          +
                          +
                          CSQ
                          + #CSQ# +
                          +
                          +
                          RSSI (dBm)
                          + #RSSI# +
                          +
                          +
                          RSCP (dBm) RSRP
                          + #RSCP# +
                          +
                          +
                          ECIO (dB) RSRQ
                          + #RSRQ# +
                          +
                          +
                          SINR (dB)
                          + #SINR# +
                          +
                          + +
                          +

                          Network

                          + +
                          +
                          +
                          Mode
                          + #MODE# +
                          +
                          +
                          MCC
                          + #MCC# +
                          +
                          +
                          MNC
                          + #MNC# +
                          +
                          +
                          RNC/eNB ID
                          + #RNC# #RNCN# +
                          + +
                          +
                          LAC
                          + #LAC# #LACN# +
                          +
                          +
                          Channel (EARFCN)
                          + #CHAN# +
                          +
                          +
                          PCI
                          + #CELLID# +
                          +
                          +
                          Bands
                          + #BAND# +
                          +
                          +
                          +
                          +

                          Device

                          + +
                          +
                          +
                          Router
                          + #ROUTER# +
                          +
                          +
                          Modem
                          + #MODEM# +
                          +
                          +
                          Provider
                          + #PROVIDER# +
                          +
                          +
                          Protocol
                          + #PROTO# +
                          +
                          +
                          Port
                          + #PORT# +
                          +
                          +
                          Temperature
                          + #TEMP# +
                          +
                          +
                          + #MODEM2# +
                          + + + #OPEN# + + #BWMON# + + + diff --git a/rooter/0splash/ext-splash/files/usr/lib/iframe/status.sh b/rooter/0splash/ext-splash/files/usr/lib/iframe/status.sh new file mode 100644 index 0000000..ed0881b --- /dev/null +++ b/rooter/0splash/ext-splash/files/usr/lib/iframe/status.sh @@ -0,0 +1,21 @@ +#!/bin/sh + +/usr/lib/rooter/signal/status.sh 1 "No Modem Present" + +while [ true ] +do + result=`ps | grep -i "stupdate.sh" | grep -v "grep" | wc -l` + if [ $result -lt 1 ]; then + /usr/lib/iframe/stupdate.sh + /usr/lib/iframe/bwdays.sh + fi + splash=$(uci -q get iframe.iframe.splashpage) + if [ $splash = "1" ]; then + mv /www/splash_files/check1.gif /www/splash_files/check.gif + ln -s /tmp/www/splash.html /www/splash.html + else + mv /www/splash_files/check.gif /www/splash_files/check1.gif + rm -f /www/splash.html + fi + sleep 10 +done \ No newline at end of file diff --git a/rooter/0splash/ext-splash/files/usr/lib/iframe/stupdate.sh b/rooter/0splash/ext-splash/files/usr/lib/iframe/stupdate.sh new file mode 100644 index 0000000..e66f255 --- /dev/null +++ b/rooter/0splash/ext-splash/files/usr/lib/iframe/stupdate.sh @@ -0,0 +1,352 @@ +#!/bin/sh +. /lib/functions.sh + +log() { + logger -t "Status Update" "$@" +} + +levelsper="101,85,70,55,40,25,10,1,0" +namesper="Perfect,Excellent,Good,Medium,Low,Bad,Dead" +levelsrssi="113,119,100,90,70,1,0" +namesrssi="None,Bad,Poor,Medium,High,Perfect" +levelsrscp="140,136,112,100,90,70,50,1,0" +namesrscp='None,None (3G) : Poor (4G),Weak (3G) : Medium (4G),Poor (3G) : Good (4G),Medium (3G) : High (4G),High (3G) :High (4G)' + +level2txt() { + tmp="$1" + key=$2 + front="" + tmp1="$tmp"" " + if [ "$tmp" = "-" ]; then + namev="""--""" + return + fi + if [ $key = "per" ]; then + tmp=$(echo "$tmp" | sed -e "s/%//g") + level=$levelsper + namev=$namesper + fi + if [ $key = "rssi" ]; then + front="-" + tmp=$(echo "$tmp" | sed -e "s/-//g") + tmp=$(echo "$tmp" | sed -e "s/dBm//g") + tmp1="$tmp"" " + level=$levelsrssi + namev=$namesrssi + fi + if [ $key = "rscp" ]; then + front="" + tmp=$(echo "$tmp" | sed -e "s/dBm//g") + tmp=$(echo "$tmp" | sed -e "s/([^)]*)//g") + tmp1="$tmp"" " + tmp=$(echo "$tmp" | sed -e "s/-//g") + tmp=$(echo "$tmp" | tr " " "," | cut -d, -f1 ) + tmp=$(printf %.0f "$tmp") + level=$levelsrscp + namev=$namesrscp + fi + + if [ $key = "single" ]; then + desc="" + tmp=$(echo "$tmp" | sed -e "s/dBm//g") + tmp=$(echo "$tmp" | sed -e "s/dB//g") + if [ $3 != "1" ];then + tmp=$(echo "$tmp" | sed -e "s/-//g") + fi + if [ $3 = "1" -o $3 = "0" ];then + desc="
                          "."
                          " + fi + namev="""$tmp"""$desc + return + fi + + namez=$namev + cindex=1 + nindex=6 + namev="-" + + while [ true ] + do + levelv=$(echo "$level" | cut -d, -f$cindex) + if [ $levelv = "0" ]; then + namev="-" + break + fi + if [ "$tmp" -lt "$levelv" ]; then + namev=$(echo "$namez" | cut -d, -f$nindex) + break + fi + cindex=$((${cindex}+1)) + nindex=$((${nindex}-1)) + done + + css="level_"$nindex + desc="
                          "$namev"
                          " + namev="""$front$tmp1"""$desc +} + +readstatus() { +modd=$1 + while IFS= read -r line; do + port="$line" + read -r line + csq="$line" + read -r line + per="$line" + read -r line + rssi="$line" + read -r line + modem="$line" + read -r line + cops="$line" + read -r line + mode="$line" + read -r line + lac="$line" + read -r line + lacn="$line" + read -r line + cid="$line" + + read -r line + cidn="$line" + read -r line + mcc="$line" + read -r line + mnc="$line" + read -r line + rnc="$line" + read -r line + rncn="$line" + read -r line + down="$line" + read -r line + up="$line" + read -r line + ecio="$line" + read -r line + rscp="$line" + read -r line + ecio1="$line" + + read -r line + rscp1="$line" + read -r line + netmode="$line" + read -r line + cell="$line" + read -r line + modtype="$line" + read -r line + conntype="$line" + read -r line + channel="$line" + read -r line + phone="$line" + read -r line + read -r line + lband="$line" + read -r line + tempur="$line" + + read -r line + proto="$line" + read -r line + pci="$line" + read -r line + sinr="$line" + break + done < /tmp/status$modd.file +} + +bwdata() { + while IFS= read -r line; do + if [ $line = '0' ]; then + nodata="1" + break + else + nodata="0" + days=$line + read -r line + read -r line + tused=$line + read -r line + read -r line + tdwn=$line + read -r line + read -r line + tup=$line + read -r line + read -r line + project=$line + break + fi + done < /tmp/bwdata +} + +splash=$(uci -q get iframe.iframe.splashpage) + +if [ $splash = "1" ]; then + STEMP="/tmp/www/stemp.html" + STATUS="/usr/lib/iframe/status.html" + SPSTATUS="/tmp/www/splash.html" + rm -f $STEMP + cp $STATUS $STEMP + button="" + sed -i -e "s!#BUTTON#!$button!g" $STEMP + sed -i -e "s!#LUCIS#!luci-static/!g" $STEMP + titlebar="" + url=$(uci -q get iframe.iframe.url) + if [ -z $url ]; then + url="www.ofmodemsandmen.com" + fi + titlebar=$(echo "$titlebar" | sed -e "s!#URL#!$url!g") + sed -i -e "s!#TITLEBAR#!$titlebar!g" $STEMP + title=$(uci -q get iframe.iframe.splashtitle) + sed -i -e "s!#TITLE#!$title!g" $STEMP + + readstatus 1 + level2txt "$csq" "single" 0 + sed -i -e "s!#CSQ#!$namev!g" $STEMP + level2txt "$per" "per" + sed -i -e "s!#PER#!$namev!g" $STEMP + level2txt "$rssi" "rssi" + sed -i -e "s!#RSSI#!$namev!g" $STEMP + level2txt "$rscp" "rscp" + sed -i -e "s!#RSCP#!$namev!g" $STEMP + level2txt "$ecio" "single" 1 + sed -i -e "s!#RSRQ#!$namev!g" $STEMP + level2txt "$sinr" "single" 1 + sed -i -e "s!#SINR#!$namev!g" $STEMP + + level2txt "$mode" "single" + sed -i -e "s!#MODE#!$namev!g" $STEMP + level2txt "$mcc" "single" + sed -i -e "s!#MCC#!$namev!g" $STEMP + level2txt "$mnc" "single" + sed -i -e "s!#MNC#!$namev!g" $STEMP + level2txt "$rnc" "single" + sed -i -e "s!#RNC#!$namev!g" $STEMP + level2txt "$rncn" "single" + sed -i -e "s!#RNCN#!$namev!g" $STEMP + level2txt "$lac" "single" + sed -i -e "s!#LAC#!$namev!g" $STEMP + level2txt "$lacn" "single" + sed -i -e "s!#LACN#!$namev!g" $STEMP + level2txt "$pci" "single" + sed -i -e "s!#CELLID#!$namev!g" $STEMP + level2txt "$channel" "single" + sed -i -e "s!#CHAN#!$namev!g" $STEMP + level2txt "$lband" "single" + sed -i -e "s!#BAND#!$namev!g" $STEMP + + if [ -e /etc/custom ]; then + mod="/etc/custom" + else + mod="/tmp/sysinfo/model" + fi + while IFS= read -r line; do + ROUTER=$line + break + done < $mod + level2txt "$ROUTER" "single" + sed -i -e "s!#ROUTER#!$namev!g" $STEMP + level2txt "$modem" "single" + sed -i -e "s!#MODEM#!$namev!g" $STEMP + level2txt "$cops" "single" + namev=$(echo "$namev" | tr -d '&') + sed -i -e "s!#PROVIDER#!$namev!g" $STEMP + level2txt "$proto" "single" + sed -i -e "s!#PROTO#!$namev!g" $STEMP + level2txt "$port" "single" + sed -i -e "s!#PORT#!$namev!g" $STEMP + level2txt "$tempur" "single" + sed -i -e "s!#TEMP#!$namev!g" $STEMP + + dual=$(uci -q get iframe.iframe.dual) + if [ $dual = "1" ]; then + STEMP2="/tmp/www/stemp2.html" + STATUS2="/usr/lib/iframe/modem2.html" + rm -f $STEMP2 + cp $STATUS2 $STEMP2 + + readstatus 2 + level2txt "$csq" "single" 0 + sed -i -e "s!#CSQ#!$namev!g" $STEMP2 + level2txt "$per" "per" + sed -i -e "s!#PER#!$namev!g" $STEMP2 + level2txt "$rssi" "rssi" + sed -i -e "s!#RSSI#!$namev!g" $STEMP2 + level2txt "$rscp" "rscp" + sed -i -e "s!#RSCP#!$namev!g" $STEMP2 + level2txt "$ecio" "single" 1 + sed -i -e "s!#RSRQ#!$namev!g" $STEMP2 + level2txt "$sinr" "single" 1 + sed -i -e "s!#SINR#!$namev!g" $STEMP2 + + level2txt "$mode" "single" + sed -i -e "s!#MODE#!$namev!g" $STEMP2 + level2txt "$mcc" "single" + sed -i -e "s!#MCC#!$namev!g" $STEMP2 + level2txt "$mnc" "single" + sed -i -e "s!#MNC#!$namev!g" $STEMP2 + level2txt "$rnc" "single" + sed -i -e "s!#RNC#!$namev!g" $STEMP2 + level2txt "$rncn" "single" + sed -i -e "s!#RNCN#!$namev!g" $STEMP2 + level2txt "$lac" "single" + sed -i -e "s!#LAC#!$namev!g" $STEMP2 + level2txt "$lacn" "single" + sed -i -e "s!#LACN#!$namev!g" $STEMP2 + level2txt "$pci" "single" + sed -i -e "s!#CELLID#!$namev!g" $STEMP2 + level2txt "$channel" "single" + sed -i -e "s!#CHAN#!$namev!g" $STEMP2 + level2txt "$lband" "single" + sed -i -e "s!#BAND#!$namev!g" $STEMP2 + + level2txt "$modem" "single" + sed -i -e "s!#MODEM#!$namev!g" $STEMP2 + level2txt "$cops" "single" + namev=$(echo "$namev" | tr -d '&') + sed -i -e "s!#MODEMN#!$namev!g" $STEMP2 + level2txt "$proto" "single" + sed -i -e "s!#PROTO#!$namev!g" $STEMP2 + level2txt "$port" "single" + sed -i -e "s!#PORT#!$namev!g" $STEMP2 + level2txt "$tempur" "single" + sed -i -e "s!#TEMP#!$namev!g" $STEMP2 + + MODEM2=$(cat $STEMP2) + sed -i -e "s!#MODEM2#!$MODEM2!g" $STEMP + else + sed -i -e "s!#MODEM2#!!g" $STEMP + fi + + open=$(uci -q get iframe.iframe.speed) + if [ $open = "1" ]; then + STEMP2="/tmp/www/stemp2.html" + STATUS2="/usr/lib/iframe/open.html" + rm -f $STEMP2 + cp $STATUS2 $STEMP2 + MODEM2=$(cat $STEMP2) + sed -i -e "s!#OPEN#!$MODEM2!g" $STEMP + else + sed -i -e "s!#OPEN#!!g" $STEMP + fi + + band=$(uci -q get iframe.iframe.band) + if [ $band = "1" ]; then + STEMP2="/tmp/www/stemp2.html" + STATUS2="/usr/lib/iframe/band.html" + rm -f $STEMP2 + cp $STATUS2 $STEMP2 + MODEM2=$(cat $STEMP2) + sed -i -e "s!#BWMON#!$MODEM2!g" $STEMP + else + sed -i -e "s!#BWMON#!!g" $STEMP + fi + + mv $STEMP $SPSTATUS +fi + diff --git a/rooter/0splash/ext-splash/files/usr/lib/iframe/update.sh b/rooter/0splash/ext-splash/files/usr/lib/iframe/update.sh new file mode 100644 index 0000000..bf67d98 --- /dev/null +++ b/rooter/0splash/ext-splash/files/usr/lib/iframe/update.sh @@ -0,0 +1,95 @@ +#!/bin/sh +. /lib/functions.sh + +bwdata() { + while IFS= read -r line; do + if [ $line = '0' ]; then + nodata="1" + break + else + nodata="0" + days=$line + read -r line + read -r line + tused=$line + read -r line + read -r line + tdwn=$line + read -r line + read -r line + tup=$line + read -r line + read -r line + project=$line + break + fi + done < /tmp/bwdata +} + +logtype=$(uci -q get iframe.login.logtype) +if [ $logtype = "1" ]; then + STEMP="/tmp/www/itemp.html" + STATUS="/usr/lib/iframe/iframe.html" + IFSTATUS="/tmp/www/display.html" + + rm -f $STEMP + cp $STATUS $STEMP + bwdata + + sed -i -e "s!#TITLE#!Bandwidth Usage!g" $STEMP + sed -i -e "s!#DAYS#!$days!g" $STEMP + sed -i -e "s!#TOTAL#!$tused!g" $STEMP + sed -i -e "s!#DOWN#!$tdwn!g" $STEMP + sed -i -e "s!#UP#!$tup!g" $STEMP + sed -i -e "s!#PROJ#!$project!g" $STEMP + + mv $STEMP $IFSTATUS +fi + +if [ $logtype = "2" ]; then + STEMP="/tmp/www/itemp.html" + STATUS="/usr/lib/iframe/image.html" + IFSTATUS="/tmp/www/display.html" + + rm -f $STEMP + cp $STATUS $STEMP + logimage=$(uci -q get iframe.login.logimage) + sed -i -e "s!#IMAGE#!$logimage!g" $STEMP + logimagewidth=$(uci -q get iframe.login.logimagewidth) + sed -i -e "s!#WIDTH#!$logimagewidth!g" $STEMP + + mv $STEMP $IFSTATUS +fi + +if [ $logtype = "4" ]; then + STEMP="/tmp/www/itemp.html" + STATUS="/usr/lib/iframe/speed.html" + IFSTATUS="/tmp/www/display.html" + + rm -f $STEMP + cp $STATUS $STEMP + + mv $STEMP $IFSTATUS +fi + +if [ $logtype = "3" ]; then + STEMP="/tmp/www/itemp.html" + STATUS="/usr/lib/iframe/zerotier.html" + IFSTATUS="/tmp/www/display.html" + + rm -f $STEMP + cp $STATUS $STEMP + + ID=$(uci -q get zerotier.zerotier.secret) + if [ -z $ID ]; then + ID="xxxxxxxxxx" + else + ID=${ID:0:10} + fi + + sed -i -e "s!#ID#!$ID!g" $STEMP + source /etc/codename + sed -i -e "s!#VER#!$CODENAME!g" $STEMP + + mv $STEMP $IFSTATUS +fi \ No newline at end of file diff --git a/rooter/0splash/ext-splash/files/usr/lib/iframe/zerotier.html b/rooter/0splash/ext-splash/files/usr/lib/iframe/zerotier.html new file mode 100644 index 0000000..aaba6a5 --- /dev/null +++ b/rooter/0splash/ext-splash/files/usr/lib/iframe/zerotier.html @@ -0,0 +1,14 @@ + + + + + + + + + +

                          Router ID : #ID#

                          +
                          Powered by : #VER#
                          + + + diff --git a/rooter/0splash/ext-splash/files/www/luci-static/display.html b/rooter/0splash/ext-splash/files/www/luci-static/display.html new file mode 100644 index 0000000..acc2f86 --- /dev/null +++ b/rooter/0splash/ext-splash/files/www/luci-static/display.html @@ -0,0 +1 @@ +/tmp/www/display.html \ No newline at end of file diff --git a/rooter/0splash/ext-splash/files/www/luci-static/iframe.html b/rooter/0splash/ext-splash/files/www/luci-static/iframe.html new file mode 100644 index 0000000..444edca --- /dev/null +++ b/rooter/0splash/ext-splash/files/www/luci-static/iframe.html @@ -0,0 +1 @@ +/tmp/www/daylist.html \ No newline at end of file diff --git a/rooter/0splash/ext-splash/files/www/luci-static/ifstatus.html b/rooter/0splash/ext-splash/files/www/luci-static/ifstatus.html new file mode 100644 index 0000000..1155573 --- /dev/null +++ b/rooter/0splash/ext-splash/files/www/luci-static/ifstatus.html @@ -0,0 +1 @@ +/tmp/www/ifstatus.html \ No newline at end of file diff --git a/rooter/0splash/ext-splash/files/www/luci-static/rooter/css/iconmoon_splash.css b/rooter/0splash/ext-splash/files/www/luci-static/rooter/css/iconmoon_splash.css new file mode 100644 index 0000000..5254b92 --- /dev/null +++ b/rooter/0splash/ext-splash/files/www/luci-static/rooter/css/iconmoon_splash.css @@ -0,0 +1,69 @@ +@font-face { + font-family: 'icomoon_splash'; + src: url('../fonts/icomoon_splash.eot?vja16g'); + src: url('../fonts/icomoon_splash.eot?vja16g#iefix') format('embedded-opentype'), + url('../fonts/icomoon_splash.ttf?vja16g') format('truetype'), + url('../fonts/icomoon_splash.woff?vja16g') format('woff'), + url('../fonts/icomoon_splash.svg?vja16g#icomoon_splash') format('svg'); + font-weight: normal; + font-style: normal; +} + +[class^="icon-"], [class*=" icon-"] { + /* use !important to prevent issues with browser extensions that change fonts */ + font-family: 'icomoon_splash' !important; + speak: none; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + + /* Better Font Rendering =========== */ + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + + +.icon-power-off:before { + content: "\f011"; +} +.icon-signal:before { + content: "\f012"; +} +.icon-cog:before { + content: "\f013"; +} +.icon-gear:before { + content: "\f013"; +} +.icon-home:before { + content: "\f015"; +} +.icon-exclamation-triangle:before { + content: "\f071"; +} +.icon-warning:before { + content: "\f071"; +} +.icon-comments:before { + content: "\f086"; +} +.icon-hdd-o:before { + content: "\f0a0"; +} +.icon-plug:before { + content: "\f1e6"; +} +.icon-wifi:before { + content: "\f1eb"; +} +.icon-connection:before { + content: "\e91b"; +} +.icon-podcast:before { + content: "\e91c"; +} +.icon-earth:before { + content: "\e9ca"; +} diff --git a/rooter/0splash/ext-splash/files/www/luci-static/rooter/css/splash.css b/rooter/0splash/ext-splash/files/www/luci-static/rooter/css/splash.css new file mode 100644 index 0000000..05040a4 --- /dev/null +++ b/rooter/0splash/ext-splash/files/www/luci-static/rooter/css/splash.css @@ -0,0 +1,342 @@ +/* @override http://src.dev.lo.lo/ROOter/www/luci-static/rooter/css/splash.css */ + +/* + CSS for ROOter splash pages + Copyright Francois Dechery + https://github.com/soif +*/ + +/* @group Splash Pages +--------------------------------------------------*/ + +.rooterSplash{ + padding: 0; + background: #F0F0F0; +} +.rooterPageHead{ + background: #55F; + padding: 20px 5px; + background: rgb(140,140,255); + background: -moz-linear-gradient(top, rgba(140,140,255,1) 0%, rgba(85,85,255,1) 100%); + background: -webkit-linear-gradient(top, rgba(140,140,255,1) 0%,rgba(85,85,255,1) 100%); + background: linear-gradient(to bottom, rgba(140,140,255,1) 0%,rgba(85,85,255,1) 100%); + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#8c8cff', endColorstr='#5555ff',GradientType=0 ); + border-bottom: 1px solid rgba(0,0,0,0.7); + +} +.rooterPageContent{ + border-top: 1px solid rgba(255,255,255,0.8); + border-bottom: 1px solid rgba(0,0,0, 0.1); + padding: 0px 0px; + max-width: 1200px; + margin: auto; +} + +.rooterPageContentBW{ + border-top: 1px solid rgba(255,255,255,0.8); + border-bottom: 1px solid rgba(0,0,0, 0.1); + padding: 10px 0px; + max-width: 600px; + margin: auto; +} + +.rooterHeadTitle{ + color: #fff; + text-align: center; + font-family: Georgia, "Times New Roman", Times, serif; + font-size: 32px; + line-height: 120%; + text-shadow: -1px -1px 2px rgba(0,0,0,0.5); +} +.rooterPageFoot{ + border-top: 1px solid rgba(255,255,255,0.8); + margin-top: 20px; + padding: 10px 10px; + max-width: 950px; + margin: auto; + font-size: 16px; +} +.rooterFootMenu{ + float: left; + margin-bottom: 10px; +} +.rooterFootMenu A{ + text-decoration: none; +} +.rooterFootMenu A:hover{ + color: #000; +} +.rooterFootMenu UL{ + padding: 0; + margin: 0; + overflow: hidden; + display: inline-block; +} +.rooterFootMenu LI{ + float: left; + padding: 0; + margin: 0; + list-style: none; +} +.rooterFootMenu LI A{ + padding: 0 10px; + color: #555; +} +.rooterFootMenu LI:first-child A{ + padding-left: 0; +} +.rooterFootCredits{ + float: right; + padding: 0; + margin: 0; + color: #999; + text-align: right; +} +.rooterFootCredits A{ + color: #777; +} +/* @end */ + + + + +/* @group Page: Home +--------------------------------------------------*/ + + +/* @group Logo +++++++++++++++++++ */ +.rooterHeadBox{ + font-size: 50px; + font-family: Georgia, "Times New Roman", Times, serif; + color: #fff; + line-height: 100%; + overflow: hidden; + width: 700px; + margin: auto; + padding-top: 10px; + opacity: 0; +} +.rooterLogo{ + background: url("../img/kangaroo_800.png") no-repeat; + background-size: 100%; + float: left; + height: 110px; + width: 250px; + opacity: 0.4; +} +.rooterTagline{ + margin-left: 100px; + padding-left: 10px; + text-shadow: 2px 2px 3px rgba(0,0,0,0.3); +} + +/* @end */ + +@media only screen and (max-width: 600px) { + .rooterHeadBox{ + text-align: center; + width: auto; + } + .rooterLogo{ + display: inline-block; + float: none; + } + .rooterTagline { + display: none; + } + .rooterFootCredits, + .rooterFootMenu{ + float: none; + text-align: center; + } +} + +#rooterItems{ + clear: both; + max-width: 600px ; + margin: auto; +} + +#rooterItemss{ + clear: both; + max-width: 300px ; + margin: auto; +} +.rooterItem{ + overflow: hidden; + border: 5px solid #00; + border-color: #00 #DDD #DDD #00; + padding: 20px 15px; + margin-bottom: 20px; + border-radius: 8px; + background-color: #AFAFAF; +} +.rooterItem:hover{ + background-color: #CFCFCF; + border-color: #AAA; +} +.rooterItemTitle{ + float: left; + font-size: 18px; + font-weight: bold; + padding-right: 10px; + color: #000; + line-height: 2em; +} +.rooterItemTitle .icon{ + color: #55F; + margin-right: 8px; + font-size: 2em; + vertical-align: middle; +} + +.rooterItemsp{ + overflow: hidden; + border: 5px solid #00; + border-color: #00 #DDD #DDD #00; + padding: 5px 15px; + margin-bottom: 5px; + border-radius: 8px; + background-color: #AFAFAF; + max-width: 300px ; +} +.rooterItemsp:hover{ + background-color: #CFCFCF; + border-color: #AAA; +} + +#rooterItems A{ + text-decoration: none; +} +.rooterItemDesc{ + font-size: 18px; + color: #777; + margin-left: 220px; + margin-top: 0.7em; +} +/* @end */ + + + +/* @group Page: Status +--------------------------------------------------*/ + +.modemStatusBlock{ + margin-bottom: 30px; +} +#rooterSplashStatus h3{ + clear:both; + font-size: 18px; + color: #55F; +} +#rooterSplashStatus h3 .icon{ + margin-right: 3px; +} +#rooterSplashStatus h3 .msCell{ + color: #666; +} +.modemStatusRow{ + clear:both; + padding-bottom: 20px; + overflow: hidden; +} +.modemStatusRow .msTitle{ + border-radius: 2px 2px 0 0; + padding: 5px 5px ; + background: #484848; + color: #fff; + background: rgb(99,99,99); + background: -moz-linear-gradient(top, rgba(99,99,99,1) 0%, rgba(72,72,72,1) 100%); + background: -webkit-linear-gradient(top, rgba(99,99,99,1) 0%,rgba(72,72,72,1) 100%); + background: linear-gradient(to bottom, rgba(99,99,99,1) 0%,rgba(72,72,72,1) 100%); + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#636363', endColorstr='#484848',GradientType=0 ); +} +.modemStatusRow .msCell{ + border-radius: 10px; + display: inline-block; + margin-top: 10px; + float:left; + border: 1px solid #ccc; + padding-bottom: 5px; + background: #fff; + +} +.modemStatusRow1 .msCell{ + width: 176px; + margin: 10px 5px 0 5px; + text-align: center; +} +.modemStatusRow1 SPAN B{ + font-weight: bold; + font-size: 35px; + line-height: 110%; + text-shadow: 1px 1px 1px rgba(0,0,0,0.4); +} +.modemStatusRow1 .msDesc{ + color: #000; + font-size: 12px; +} +.modemStatusRow2 .msCell{ + margin: 10px 5px; + text-align: center; +} +.modemStatusRow2 SPAN{ + display: inline-block; + padding: 5px 5px ; + font-size: 14px; +} +#counter_div{ + color: #000; + font-weight: normal; + font-size: 14px; +} +#counter_val{ + color: #F00; + font-size: 32px; + font-weight: bold; + text-shadow: 1px 1px 1px rgba(0,0,0,0.1); +} +#msCell_per{} +#msCell_csq{} +#msCell_rssi{} +#msCell_rscp{} +#msCell_ecio{} + +#rooterSplashStatus .level_0{ + color: #0F0; // green +} +#rooterSplashStatus .level_1{ + color: #0CB; // green blue +} +#rooterSplashStatus .level_2{ + color: #00F; // blue +} +#rooterSplashStatus .level_3{ + color: #F0F; // violet +} +#rooterSplashStatus .level_4{ + color: #F80; // orange +} +#rooterSplashStatus .level_5{ + color: #F00; // red +} +#rooterSplashStatus .level_6{ + color: #FF0; // yellow +} + +/* @end */ + + +/* Easy Color changer ------------- */ + +.rooterPageHead{ + /*background: #55F;*/ +} +.rooterItemTitle .icon, +#rooterSplashStatus h3{ + color: #55F; +} + + + diff --git a/rooter/0splash/ext-splash/files/www/luci-static/rooter/fonts/icomoon_splash.eot b/rooter/0splash/ext-splash/files/www/luci-static/rooter/fonts/icomoon_splash.eot new file mode 100644 index 0000000..29cd4d1 Binary files /dev/null and b/rooter/0splash/ext-splash/files/www/luci-static/rooter/fonts/icomoon_splash.eot differ diff --git a/rooter/0splash/ext-splash/files/www/luci-static/rooter/fonts/icomoon_splash.svg b/rooter/0splash/ext-splash/files/www/luci-static/rooter/fonts/icomoon_splash.svg new file mode 100644 index 0000000..dc2127b --- /dev/null +++ b/rooter/0splash/ext-splash/files/www/luci-static/rooter/fonts/icomoon_splash.svg @@ -0,0 +1,22 @@ + + + +Generated by IcoMoon + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/rooter/0splash/ext-splash/files/www/luci-static/rooter/fonts/icomoon_splash.ttf b/rooter/0splash/ext-splash/files/www/luci-static/rooter/fonts/icomoon_splash.ttf new file mode 100644 index 0000000..4e27645 Binary files /dev/null and b/rooter/0splash/ext-splash/files/www/luci-static/rooter/fonts/icomoon_splash.ttf differ diff --git a/rooter/0splash/ext-splash/files/www/luci-static/rooter/fonts/icomoon_splash.woff b/rooter/0splash/ext-splash/files/www/luci-static/rooter/fonts/icomoon_splash.woff new file mode 100644 index 0000000..63f5413 Binary files /dev/null and b/rooter/0splash/ext-splash/files/www/luci-static/rooter/fonts/icomoon_splash.woff differ diff --git a/rooter/0splash/ext-splash/files/www/luci-static/rooter/img/favicon.gif b/rooter/0splash/ext-splash/files/www/luci-static/rooter/img/favicon.gif new file mode 100644 index 0000000..bfbe292 Binary files /dev/null and b/rooter/0splash/ext-splash/files/www/luci-static/rooter/img/favicon.gif differ diff --git a/rooter/0splash/ext-splash/files/www/luci-static/rooter/img/kangaroo_800.png b/rooter/0splash/ext-splash/files/www/luci-static/rooter/img/kangaroo_800.png new file mode 100644 index 0000000..478fa6d Binary files /dev/null and b/rooter/0splash/ext-splash/files/www/luci-static/rooter/img/kangaroo_800.png differ diff --git a/rooter/0splash/ext-splash/files/www/splash_files/check1.gif b/rooter/0splash/ext-splash/files/www/splash_files/check1.gif new file mode 100644 index 0000000..75b945d Binary files /dev/null and b/rooter/0splash/ext-splash/files/www/splash_files/check1.gif differ diff --git a/rooter/0splash/ext-splashconfig/Makefile b/rooter/0splash/ext-splashconfig/Makefile new file mode 100644 index 0000000..c986ca8 --- /dev/null +++ b/rooter/0splash/ext-splashconfig/Makefile @@ -0,0 +1,36 @@ +#Owned by DairyMan@Whirlpool +# +#Copyright GNU act. +include $(TOPDIR)/rules.mk + +PKG_NAME:=ext-splashconfig +PKG_VERSION:=1.000 +PKG_RELEASE:=1 + +PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool +include $(INCLUDE_DIR)/package.mk + +define Package/ext-splashconfig + SECTION:=utils + CATEGORY:=ROOter + SUBMENU:=Splash Screens + DEPENDS:=+ext-splash + TITLE:=Added scripts for Login display + PKGARCH:=all +endef + +define Package/ext-splashconfig/description + Added scripts for Login display +endef + + +define Build/Compile +endef + +define Package/ext-splashconfig/install + $(CP) ./files/* $(1)/ + + +endef + +$(eval $(call BuildPackage,ext-splashconfig)) diff --git a/rooter/0splash/ext-splashconfig/files/usr/lib/lua/luci/controller/splash.lua b/rooter/0splash/ext-splashconfig/files/usr/lib/lua/luci/controller/splash.lua new file mode 100644 index 0000000..84f6b85 --- /dev/null +++ b/rooter/0splash/ext-splashconfig/files/usr/lib/lua/luci/controller/splash.lua @@ -0,0 +1,13 @@ +--[[ +ext-theme +]]-- + +module("luci.controller.splash", package.seeall) + +I18N = require "luci.i18n" +translate = I18N.translate + +function index() + entry({"admin", "splash"}, firstchild(), translate("Splash Screen"), 99).dependent=false + entry({"admin", "splash", "splash"}, cbi("splashm"), _(translate("Configuration")), 20) +end diff --git a/rooter/0splash/ext-splashconfig/files/usr/lib/lua/luci/model/cbi/splashm.lua b/rooter/0splash/ext-splashconfig/files/usr/lib/lua/luci/model/cbi/splashm.lua new file mode 100644 index 0000000..4703b22 --- /dev/null +++ b/rooter/0splash/ext-splashconfig/files/usr/lib/lua/luci/model/cbi/splashm.lua @@ -0,0 +1,44 @@ + + +local sys = require "luci.sys" +local zones = require "luci.sys.zoneinfo" +local fs = require "nixio.fs" +local conf = require "luci.config" + +m = Map("iframe", translate("Splash Screen Configuration"),translate("Change the configuration of the Splash and Login screen.")) +m:chain("luci") + +s = m:section(TypedSection, "iframe", translate("Status Page Configuration")) +s.anonymous = true +s.addremove = false + +c1 = s:option(ListValue, "splashpage", translate("Enable Network Status Page Before Login :")); +c1:value("0", translate("Disabled")) +c1:value("1", translate("Enabled")) +c1.default=0 + +a1 = s:option(Value, "splashtitle", translate("Network Status Title :")); +a1.optional=false; +a1.default = translate("ROOter Status") +a1:depends("splashpage", "1") + +dc1 = s:option(ListValue, "dual", translate("Enable Modem 2 Status :")); +dc1:value("0", translate("Disabled")) +dc1:value("1", translate("Enabled")) +dc1.default=0 +dc1:depends("splashpage", "1") + +cc1 = s:option(ListValue, "speed", translate("Enable OpenSpeedTest :")); +cc1:value("0", translate("Disabled")) +cc1:value("1", translate("Enabled")) +cc1.default=0 +cc1:depends("splashpage", "1") + +ec1 = s:option(ListValue, "band", translate("Enable Bandwidth Summary :")); +ec1:value("0", translate("Disabled")) +ec1:value("1", translate("Enabled")) +ec1.default=0 +ec1:depends("splashpage", "1") + + +return m \ No newline at end of file diff --git a/rooter/0splash/splash/Makefile b/rooter/0splash/splash/Makefile new file mode 100644 index 0000000..2941b94 --- /dev/null +++ b/rooter/0splash/splash/Makefile @@ -0,0 +1,35 @@ +#Owned by DairyMan@Whirlpool +# +#Copyright GNU act. +include $(TOPDIR)/rules.mk + +PKG_NAME:=splash +PKG_VERSION:=1.000 +PKG_RELEASE:=1 + +PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool +include $(INCLUDE_DIR)/package.mk + +define Package/splash + SECTION:=utils + CATEGORY:=ROOter + SUBMENU:=Splash Screens + TITLE:=Added scripts for Splash screen + PKGARCH:=all +endef + +define Package/splash/description + Added scripts for Splash screen +endef + + +define Build/Compile +endef + +define Package/splash/install + $(CP) ./files/* $(1)/ + + +endef + +$(eval $(call BuildPackage,splash)) diff --git a/rooter/0splash/splash/files/www/luci-static/rooter/css/iconmoon_splash.css b/rooter/0splash/splash/files/www/luci-static/rooter/css/iconmoon_splash.css new file mode 100644 index 0000000..5254b92 --- /dev/null +++ b/rooter/0splash/splash/files/www/luci-static/rooter/css/iconmoon_splash.css @@ -0,0 +1,69 @@ +@font-face { + font-family: 'icomoon_splash'; + src: url('../fonts/icomoon_splash.eot?vja16g'); + src: url('../fonts/icomoon_splash.eot?vja16g#iefix') format('embedded-opentype'), + url('../fonts/icomoon_splash.ttf?vja16g') format('truetype'), + url('../fonts/icomoon_splash.woff?vja16g') format('woff'), + url('../fonts/icomoon_splash.svg?vja16g#icomoon_splash') format('svg'); + font-weight: normal; + font-style: normal; +} + +[class^="icon-"], [class*=" icon-"] { + /* use !important to prevent issues with browser extensions that change fonts */ + font-family: 'icomoon_splash' !important; + speak: none; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + + /* Better Font Rendering =========== */ + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + + +.icon-power-off:before { + content: "\f011"; +} +.icon-signal:before { + content: "\f012"; +} +.icon-cog:before { + content: "\f013"; +} +.icon-gear:before { + content: "\f013"; +} +.icon-home:before { + content: "\f015"; +} +.icon-exclamation-triangle:before { + content: "\f071"; +} +.icon-warning:before { + content: "\f071"; +} +.icon-comments:before { + content: "\f086"; +} +.icon-hdd-o:before { + content: "\f0a0"; +} +.icon-plug:before { + content: "\f1e6"; +} +.icon-wifi:before { + content: "\f1eb"; +} +.icon-connection:before { + content: "\e91b"; +} +.icon-podcast:before { + content: "\e91c"; +} +.icon-earth:before { + content: "\e9ca"; +} diff --git a/rooter/0splash/splash/files/www/luci-static/rooter/css/splash.css b/rooter/0splash/splash/files/www/luci-static/rooter/css/splash.css new file mode 100644 index 0000000..76957ea --- /dev/null +++ b/rooter/0splash/splash/files/www/luci-static/rooter/css/splash.css @@ -0,0 +1,311 @@ +/* @override http://src.dev.lo.lo/ROOter/www/luci-static/rooter/css/splash.css */ + +/* + CSS for ROOter splash pages + Copyright Francois Dechery + https://github.com/soif +*/ + +/* @group Splash Pages +--------------------------------------------------*/ + +.rooterSplash{ + padding: 0; + background: #F0F0F0; +} +.rooterPageHead{ + background: #55F; + padding: 10px 5px; + background: rgb(140,140,255); + background: -moz-linear-gradient(top, rgba(140,140,255,1) 0%, rgba(85,85,255,1) 100%); + background: -webkit-linear-gradient(top, rgba(140,140,255,1) 0%,rgba(85,85,255,1) 100%); + background: linear-gradient(to bottom, rgba(140,140,255,1) 0%,rgba(85,85,255,1) 100%); + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#8c8cff', endColorstr='#5555ff',GradientType=0 ); + border-bottom: 1px solid rgba(0,0,0,0.7); + +} +.rooterPageContent{ + border-top: 1px solid rgba(255,255,255,0.8); + border-bottom: 1px solid rgba(0,0,0, 0.1); + padding: 25px 10px; + max-width: 950px; + margin: auto; +} +.rooterHeadTitle{ + color: #fff; + text-align: center; + font-family: Georgia, "Times New Roman", Times, serif; + font-size: 32px; + line-height: 120%; + text-shadow: -1px -1px 2px rgba(0,0,0,0.5); +} +.rooterPageFoot{ + border-top: 1px solid rgba(255,255,255,0.8); + margin-top: 20px; + padding: 10px 10px; + max-width: 950px; + margin: auto; + font-size: 11px; +} +.rooterFootMenu{ + float: left; + margin-bottom: 10px; +} +.rooterFootMenu A{ + text-decoration: none; +} +.rooterFootMenu A:hover{ + color: #000; +} +.rooterFootMenu UL{ + padding: 0; + margin: 0; + overflow: hidden; + display: inline-block; +} +.rooterFootMenu LI{ + float: left; + padding: 0; + margin: 0; + list-style: none; +} +.rooterFootMenu LI A{ + padding: 0 10px; + color: #555; +} +.rooterFootMenu LI:first-child A{ + padding-left: 0; +} +.rooterFootCredits{ + float: right; + padding: 0; + margin: 0; + color: #999; + text-align: right; +} +.rooterFootCredits A{ + color: #777; +} +/* @end */ + + + + +/* @group Page: Home +--------------------------------------------------*/ + + +/* @group Logo +++++++++++++++++++ */ +.rooterHeadBox{ + font-size: 50px; + font-family: Georgia, "Times New Roman", Times, serif; + color: #fff; + line-height: 100%; + overflow: hidden; + width: 700px; + margin: auto; + padding-top: 10px; + opacity: 0; +} +.rooterLogo{ + background: url("../img/kangaroo_800.png") no-repeat; + background-size: 100%; + float: left; + height: 110px; + width: 250px; + opacity: 0.4; +} +.rooterTagline{ + margin-left: 100px; + padding-left: 10px; + text-shadow: 2px 2px 3px rgba(0,0,0,0.3); +} + +/* @end */ + +@media only screen and (max-width: 600px) { + .rooterHeadBox{ + text-align: center; + width: auto; + } + .rooterLogo{ + display: inline-block; + float: none; + } + .rooterTagline { + display: none; + } + .rooterFootCredits, + .rooterFootMenu{ + float: none; + text-align: center; + } +} + +#rooterItems{ + clear: both; + max-width: 800px ; + margin: auto; +} +.rooterItem{ + overflow: hidden; + border: 1px solid #EEE; + border-color: #EEE #DDD #DDD #EEE; + padding: 20px 15px; + margin-bottom: 20px; + border-radius: 8px; + background-color: #fff; +} +.rooterItem:hover{ + background-color: #F3F3FF; + border-color: #AAA; +} +.rooterItemTitle{ + float: left; + font-size: 18px; + font-weight: bold; + padding-right: 10px; + color: #000; + line-height: 2em; +} +.rooterItemTitle .icon{ + color: #55F; + margin-right: 8px; + font-size: 2em; + vertical-align: middle; +} +#rooterItems A{ + text-decoration: none; +} +.rooterItemDesc{ + font-size: 14px; + color: #777; + margin-left: 220px; + margin-top: 0.7em; +} +/* @end */ + + + +/* @group Page: Status +--------------------------------------------------*/ + +.modemStatusBlock{ + margin-bottom: 30px; +} +#rooterSplashStatus h3{ + clear:both; + font-size: 18px; + color: #55F; +} +#rooterSplashStatus h3 .icon{ + margin-right: 3px; +} +#rooterSplashStatus h3 .msCell{ + color: #666; +} +.modemStatusRow{ + clear:both; + padding-bottom: 20px; + overflow: hidden; +} +.modemStatusRow .msTitle{ + border-radius: 2px 2px 0 0; + padding: 5px 5px ; + background: #484848; + color: #fff; + background: rgb(99,99,99); + background: -moz-linear-gradient(top, rgba(99,99,99,1) 0%, rgba(72,72,72,1) 100%); + background: -webkit-linear-gradient(top, rgba(99,99,99,1) 0%,rgba(72,72,72,1) 100%); + background: linear-gradient(to bottom, rgba(99,99,99,1) 0%,rgba(72,72,72,1) 100%); + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#636363', endColorstr='#484848',GradientType=0 ); +} +.modemStatusRow .msCell{ + border-radius: 10px; + display: inline-block; + margin-top: 10px; + float:left; + border: 1px solid #ccc; + padding-bottom: 5px; + background: #fff; + +} +.modemStatusRow1 .msCell{ + width: 176px; + margin: 10px 5px 0 5px; + text-align: center; +} +.modemStatusRow1 SPAN B{ + font-weight: bold; + font-size: 70px; + line-height: 110%; + text-shadow: 1px 1px 1px rgba(0,0,0,0.4); +} +.modemStatusRow1 .msDesc{ + color: #000; + font-size: 12px; +} +.modemStatusRow2 .msCell{ + margin: 10px 5px; + text-align: center; +} +.modemStatusRow2 SPAN{ + display: inline-block; + padding: 5px 5px ; + font-size: 14px; +} +#counter_div{ + color: #000; + font-weight: normal; + font-size: 14px; +} +#counter_val{ + color: #F00; + font-size: 32px; + font-weight: bold; + text-shadow: 1px 1px 1px rgba(0,0,0,0.1); +} +#msCell_per{} +#msCell_csq{} +#msCell_rssi{} +#msCell_rscp{} +#msCell_ecio{} + +#rooterSplashStatus .level_0{ + color: #0F0; // green +} +#rooterSplashStatus .level_1{ + color: #0CB; // green blue +} +#rooterSplashStatus .level_2{ + color: #00F; // blue +} +#rooterSplashStatus .level_3{ + color: #F0F; // violet +} +#rooterSplashStatus .level_4{ + color: #F80; // orange +} +#rooterSplashStatus .level_5{ + color: #F00; // red +} +#rooterSplashStatus .level_6{ + color: #FF0; // yellow +} + +/* @end */ + + +/* Easy Color changer ------------- */ + +.rooterPageHead{ + /*background: #55F;*/ +} +.rooterItemTitle .icon, +#rooterSplashStatus h3{ + color: #55F; +} + + + diff --git a/rooter/0splash/splash/files/www/luci-static/rooter/fonts/icomoon_splash.eot b/rooter/0splash/splash/files/www/luci-static/rooter/fonts/icomoon_splash.eot new file mode 100644 index 0000000..29cd4d1 Binary files /dev/null and b/rooter/0splash/splash/files/www/luci-static/rooter/fonts/icomoon_splash.eot differ diff --git a/rooter/0splash/splash/files/www/luci-static/rooter/fonts/icomoon_splash.svg b/rooter/0splash/splash/files/www/luci-static/rooter/fonts/icomoon_splash.svg new file mode 100644 index 0000000..dc2127b --- /dev/null +++ b/rooter/0splash/splash/files/www/luci-static/rooter/fonts/icomoon_splash.svg @@ -0,0 +1,22 @@ + + + +Generated by IcoMoon + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/rooter/0splash/splash/files/www/luci-static/rooter/fonts/icomoon_splash.ttf b/rooter/0splash/splash/files/www/luci-static/rooter/fonts/icomoon_splash.ttf new file mode 100644 index 0000000..4e27645 Binary files /dev/null and b/rooter/0splash/splash/files/www/luci-static/rooter/fonts/icomoon_splash.ttf differ diff --git a/rooter/0splash/splash/files/www/luci-static/rooter/fonts/icomoon_splash.woff b/rooter/0splash/splash/files/www/luci-static/rooter/fonts/icomoon_splash.woff new file mode 100644 index 0000000..63f5413 Binary files /dev/null and b/rooter/0splash/splash/files/www/luci-static/rooter/fonts/icomoon_splash.woff differ diff --git a/rooter/0splash/splash/files/www/luci-static/rooter/img/favicon.gif b/rooter/0splash/splash/files/www/luci-static/rooter/img/favicon.gif new file mode 100644 index 0000000..bfbe292 Binary files /dev/null and b/rooter/0splash/splash/files/www/luci-static/rooter/img/favicon.gif differ diff --git a/rooter/0splash/splash/files/www/luci-static/rooter/img/kangaroo_800.png b/rooter/0splash/splash/files/www/luci-static/rooter/img/kangaroo_800.png new file mode 100644 index 0000000..478fa6d Binary files /dev/null and b/rooter/0splash/splash/files/www/luci-static/rooter/img/kangaroo_800.png differ diff --git a/rooter/0splash/splash/files/www/splash.html b/rooter/0splash/splash/files/www/splash.html new file mode 100644 index 0000000..21de451 --- /dev/null +++ b/rooter/0splash/splash/files/www/splash.html @@ -0,0 +1,101 @@ + + + + Home - ROOter + + + + + + + + + + + + + + + + + + + +
                          + +
                          + +
                          The ROOter Project
                          +
                          +
                          + + + +
                          +
                          + +
                          +
                          + ROOter Splash Page by Soif and Dairyman +
                          +
                          + + + + diff --git a/rooter/0splash/splash/files/www/splash_files/cellular.png b/rooter/0splash/splash/files/www/splash_files/cellular.png new file mode 100644 index 0000000..953bf08 Binary files /dev/null and b/rooter/0splash/splash/files/www/splash_files/cellular.png differ diff --git a/rooter/0splash/splash/files/www/splash_files/check.gif b/rooter/0splash/splash/files/www/splash_files/check.gif new file mode 100644 index 0000000..75b945d Binary files /dev/null and b/rooter/0splash/splash/files/www/splash_files/check.gif differ diff --git a/rooter/0splash/splash/files/www/splash_files/check.jpg b/rooter/0splash/splash/files/www/splash_files/check.jpg new file mode 100644 index 0000000..f1fb739 Binary files /dev/null and b/rooter/0splash/splash/files/www/splash_files/check.jpg differ diff --git a/rooter/0splash/splash/files/www/splash_files/forum.png b/rooter/0splash/splash/files/www/splash_files/forum.png new file mode 100644 index 0000000..9e8b8c2 Binary files /dev/null and b/rooter/0splash/splash/files/www/splash_files/forum.png differ diff --git a/rooter/0splash/splash/files/www/splash_files/home.png b/rooter/0splash/splash/files/www/splash_files/home.png new file mode 100644 index 0000000..38687c7 Binary files /dev/null and b/rooter/0splash/splash/files/www/splash_files/home.png differ diff --git a/rooter/0splash/splash/files/www/splash_files/kanga1.png b/rooter/0splash/splash/files/www/splash_files/kanga1.png new file mode 100644 index 0000000..7f3420e Binary files /dev/null and b/rooter/0splash/splash/files/www/splash_files/kanga1.png differ diff --git a/rooter/0splash/splash/files/www/splash_files/openwrt.png b/rooter/0splash/splash/files/www/splash_files/openwrt.png new file mode 100644 index 0000000..0bec4c2 Binary files /dev/null and b/rooter/0splash/splash/files/www/splash_files/openwrt.png differ diff --git a/rooter/0splash/splash/files/www/splash_files/rooter.png b/rooter/0splash/splash/files/www/splash_files/rooter.png new file mode 100644 index 0000000..be8099f Binary files /dev/null and b/rooter/0splash/splash/files/www/splash_files/rooter.png differ diff --git a/rooter/0splash/splash/files/www/status.html b/rooter/0splash/splash/files/www/status.html new file mode 100644 index 0000000..930709f --- /dev/null +++ b/rooter/0splash/splash/files/www/status.html @@ -0,0 +1,254 @@ + + + + Live Network Status + + + + + + + + + + + + + + + +
                          +
                          ROOter Live Network Status
                          +
                          + +
                          + + + + + + + +
                          Enter your credentials :
                          + +
                          +

                          0 sec
                          + Signal

                          + +
                          +
                          +
                          Strength (%)
                          + - +
                          +
                          +
                          CSQ
                          + - +
                          +
                          +
                          RSSI (dBm)
                          + - +
                          +
                          +
                          RSCP (dBm) RSRP
                          + - +
                          +
                          +
                          ECIO (dB) RSRQ
                          + - +
                          +
                          +
                          + +
                          +

                          Network -

                          + +
                          +
                          +
                          Mode
                          + - +
                          +
                          +
                          MCC
                          + - +
                          +
                          +
                          MNC
                          + - +
                          +
                          +
                          RNC/eNB ID
                          + - - +
                          + +
                          +
                          LAC
                          + - - +
                          +
                          +
                          Cell ID
                          + - +
                          +
                          +
                          Channel
                          + - +
                          +
                          +
                          Bands
                          + - +
                          +
                          +
                          + +
                          +

                          Device -

                          + +
                          +
                          +
                          Modem
                          + - +
                          +
                          +
                          Protocol
                          + - +
                          +
                          +
                          Port
                          + - +
                          +
                          +
                          Temperature
                          + - +
                          +
                          +
                          + +
                          + +
                          +
                          + +
                          +
                          +
                          M2M Wireless -- Your Wireless Connection
                          +
                          +
                          + + + diff --git a/rooter/0splash/status/Makefile b/rooter/0splash/status/Makefile new file mode 100644 index 0000000..7bb30c0 --- /dev/null +++ b/rooter/0splash/status/Makefile @@ -0,0 +1,35 @@ +#Owned by DairyMan@Whirlpool +# +#Copyright GNU act. +include $(TOPDIR)/rules.mk + +PKG_NAME:=status +PKG_VERSION:=1.000 +PKG_RELEASE:=1 + +PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool +include $(INCLUDE_DIR)/package.mk + +define Package/status + SECTION:=utils + CATEGORY:=ROOter + SUBMENU:=Splash Screens + TITLE:=Added scripts for Status Splash screen + PKGARCH:=all +endef + +define Package/status/description + Added scripts for Status Splash screen +endef + + +define Build/Compile +endef + +define Package/status/install + $(CP) ./files/* $(1)/ + + +endef + +$(eval $(call BuildPackage,status)) diff --git a/rooter/0splash/status/files/etc/config/splash b/rooter/0splash/status/files/etc/config/splash new file mode 100644 index 0000000..6088b27 --- /dev/null +++ b/rooter/0splash/status/files/etc/config/splash @@ -0,0 +1,4 @@ +config settings 'settings' + option enabled '0' + option full '0' + \ No newline at end of file diff --git a/rooter/0splash/status/files/usr/lib/lua/luci/controller/splashset.lua b/rooter/0splash/status/files/usr/lib/lua/luci/controller/splashset.lua new file mode 100644 index 0000000..37b2799 --- /dev/null +++ b/rooter/0splash/status/files/usr/lib/lua/luci/controller/splashset.lua @@ -0,0 +1,11 @@ +--[[ +luci-app-argon-config +]]-- + +module("luci.controller.splash", package.seeall) + +function index() + if nixio.fs.access("/etc/config/splash") then + entry({"admin", "theme", "splash"}, cbi("splash"), _("Splash Screen"), 71) + end +end diff --git a/rooter/0splash/status/files/usr/lib/lua/luci/model/cbi/splash.lua b/rooter/0splash/status/files/usr/lib/lua/luci/model/cbi/splash.lua new file mode 100644 index 0000000..b36dc8b --- /dev/null +++ b/rooter/0splash/status/files/usr/lib/lua/luci/model/cbi/splash.lua @@ -0,0 +1,22 @@ +local fs = require "nixio.fs" +local sys = require "luci.sys" +local uci = require "luci.model.uci".cursor() +require("luci.util") +require("luci.model.ipkg") + +local m = Map("splash", translate("Splash Screen"), translate("Enable/disable Splash Screen")) + +m.on_after_save = function(self) + luci.sys.call("/usr/lib/splash/splash.sh &") +end + +gwx = m:section(TypedSection, "settings", translate("Management")) +gwx.anonymous = true + + +bl = gwx:option(ListValue, "enabled", "Enable Splash Screen :"); +bl:value("0", "Disabled") +bl:value("1", "Enabled") +bl.default=0 + +return m \ No newline at end of file diff --git a/rooter/0splash/status/files/usr/lib/splash/check.gif b/rooter/0splash/status/files/usr/lib/splash/check.gif new file mode 100644 index 0000000..75b945d Binary files /dev/null and b/rooter/0splash/status/files/usr/lib/splash/check.gif differ diff --git a/rooter/0splash/status/files/usr/lib/splash/full.gif b/rooter/0splash/status/files/usr/lib/splash/full.gif new file mode 100644 index 0000000..75b945d Binary files /dev/null and b/rooter/0splash/status/files/usr/lib/splash/full.gif differ diff --git a/rooter/0splash/status/files/usr/lib/splash/splash.sh b/rooter/0splash/status/files/usr/lib/splash/splash.sh new file mode 100644 index 0000000..6b1cca7 --- /dev/null +++ b/rooter/0splash/status/files/usr/lib/splash/splash.sh @@ -0,0 +1,21 @@ +#!/bin/sh + +log() { + logger -t "Splash Screen : " "$@" +} + +sleep 5 + +ENB=$(uci get splash.settings.enabled) +FULL=$(uci get splash.settings.full) + +if [ $ENB = "0" ]; then + rm -f /www/splash_files/check.gif + rm -f /www/splash_files/full.gif +else + cp /usr/lib/splash/check.gif /www/splash_files + rm -f /www/splash_files/full.gif + if [ $FULL = "1" ]; then + cp /usr/lib/splash/full.gif /www/splash_files + fi +fi \ No newline at end of file diff --git a/rooter/0splash/status/files/www/luci-static/rooter/css/iconmoon_splash.css b/rooter/0splash/status/files/www/luci-static/rooter/css/iconmoon_splash.css new file mode 100644 index 0000000..5254b92 --- /dev/null +++ b/rooter/0splash/status/files/www/luci-static/rooter/css/iconmoon_splash.css @@ -0,0 +1,69 @@ +@font-face { + font-family: 'icomoon_splash'; + src: url('../fonts/icomoon_splash.eot?vja16g'); + src: url('../fonts/icomoon_splash.eot?vja16g#iefix') format('embedded-opentype'), + url('../fonts/icomoon_splash.ttf?vja16g') format('truetype'), + url('../fonts/icomoon_splash.woff?vja16g') format('woff'), + url('../fonts/icomoon_splash.svg?vja16g#icomoon_splash') format('svg'); + font-weight: normal; + font-style: normal; +} + +[class^="icon-"], [class*=" icon-"] { + /* use !important to prevent issues with browser extensions that change fonts */ + font-family: 'icomoon_splash' !important; + speak: none; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + + /* Better Font Rendering =========== */ + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + + +.icon-power-off:before { + content: "\f011"; +} +.icon-signal:before { + content: "\f012"; +} +.icon-cog:before { + content: "\f013"; +} +.icon-gear:before { + content: "\f013"; +} +.icon-home:before { + content: "\f015"; +} +.icon-exclamation-triangle:before { + content: "\f071"; +} +.icon-warning:before { + content: "\f071"; +} +.icon-comments:before { + content: "\f086"; +} +.icon-hdd-o:before { + content: "\f0a0"; +} +.icon-plug:before { + content: "\f1e6"; +} +.icon-wifi:before { + content: "\f1eb"; +} +.icon-connection:before { + content: "\e91b"; +} +.icon-podcast:before { + content: "\e91c"; +} +.icon-earth:before { + content: "\e9ca"; +} diff --git a/rooter/0splash/status/files/www/luci-static/rooter/css/splash.css b/rooter/0splash/status/files/www/luci-static/rooter/css/splash.css new file mode 100644 index 0000000..bafcc6c --- /dev/null +++ b/rooter/0splash/status/files/www/luci-static/rooter/css/splash.css @@ -0,0 +1,311 @@ +/* @override http://src.dev.lo.lo/ROOter/www/luci-static/rooter/css/splash.css */ + +/* + CSS for ROOter splash pages + Copyright Francois Dechery + https://github.com/soif +*/ + +/* @group Splash Pages +--------------------------------------------------*/ + +.rooterSplash{ + padding: 0; + background: #F0F0F0; +} +.rooterPageHead{ + background: #55F; + padding: 10px 5px; + background: rgb(140,140,255); + background: -moz-linear-gradient(top, rgba(140,140,255,1) 0%, rgba(85,85,255,1) 100%); + background: -webkit-linear-gradient(top, rgba(140,140,255,1) 0%,rgba(85,85,255,1) 100%); + background: linear-gradient(to bottom, rgba(140,140,255,1) 0%,rgba(85,85,255,1) 100%); + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#8c8cff', endColorstr='#5555ff',GradientType=0 ); + border-bottom: 1px solid rgba(0,0,0,0.7); + +} +.rooterPageContent{ + border-top: 1px solid rgba(255,255,255,0.8); + border-bottom: 1px solid rgba(0,0,0, 0.1); + padding: 25px 10px; + max-width: 1200px; + margin: auto; +} +.rooterHeadTitle{ + color: #fff; + text-align: center; + font-family: Georgia, "Times New Roman", Times, serif; + font-size: 32px; + line-height: 120%; + text-shadow: -1px -1px 2px rgba(0,0,0,0.5); +} +.rooterPageFoot{ + border-top: 1px solid rgba(255,255,255,0.8); + margin-top: 20px; + padding: 10px 10px; + max-width: 950px; + margin: auto; + font-size: 16px; +} +.rooterFootMenu{ + float: left; + margin-bottom: 10px; +} +.rooterFootMenu A{ + text-decoration: none; +} +.rooterFootMenu A:hover{ + color: #000; +} +.rooterFootMenu UL{ + padding: 0; + margin: 0; + overflow: hidden; + display: inline-block; +} +.rooterFootMenu LI{ + float: left; + padding: 0; + margin: 0; + list-style: none; +} +.rooterFootMenu LI A{ + padding: 0 10px; + color: #555; +} +.rooterFootMenu LI:first-child A{ + padding-left: 0; +} +.rooterFootCredits{ + float: right; + padding: 0; + margin: 0; + color: #999; + text-align: right; +} +.rooterFootCredits A{ + color: #777; +} +/* @end */ + + + + +/* @group Page: Home +--------------------------------------------------*/ + + +/* @group Logo +++++++++++++++++++ */ +.rooterHeadBox{ + font-size: 50px; + font-family: Georgia, "Times New Roman", Times, serif; + color: #fff; + line-height: 100%; + overflow: hidden; + width: 700px; + margin: auto; + padding-top: 10px; + opacity: 0; +} +.rooterLogo{ + background: url("../img/kangaroo_800.png") no-repeat; + background-size: 100%; + float: left; + height: 110px; + width: 250px; + opacity: 0.4; +} +.rooterTagline{ + margin-left: 100px; + padding-left: 10px; + text-shadow: 2px 2px 3px rgba(0,0,0,0.3); +} + +/* @end */ + +@media only screen and (max-width: 600px) { + .rooterHeadBox{ + text-align: center; + width: auto; + } + .rooterLogo{ + display: inline-block; + float: none; + } + .rooterTagline { + display: none; + } + .rooterFootCredits, + .rooterFootMenu{ + float: none; + text-align: center; + } +} + +#rooterItems{ + clear: both; + max-width: 800px ; + margin: auto; +} +.rooterItem{ + overflow: hidden; + border: 1px solid #EEE; + border-color: #EEE #DDD #DDD #EEE; + padding: 20px 15px; + margin-bottom: 20px; + border-radius: 8px; + background-color: #fff; +} +.rooterItem:hover{ + background-color: #F3F3FF; + border-color: #AAA; +} +.rooterItemTitle{ + float: left; + font-size: 18px; + font-weight: bold; + padding-right: 10px; + color: #000; + line-height: 2em; +} +.rooterItemTitle .icon{ + color: #55F; + margin-right: 8px; + font-size: 2em; + vertical-align: middle; +} +#rooterItems A{ + text-decoration: none; +} +.rooterItemDesc{ + font-size: 14px; + color: #777; + margin-left: 220px; + margin-top: 0.7em; +} +/* @end */ + + + +/* @group Page: Status +--------------------------------------------------*/ + +.modemStatusBlock{ + margin-bottom: 30px; +} +#rooterSplashStatus h3{ + clear:both; + font-size: 18px; + color: #55F; +} +#rooterSplashStatus h3 .icon{ + margin-right: 3px; +} +#rooterSplashStatus h3 .msCell{ + color: #666; +} +.modemStatusRow{ + clear:both; + padding-bottom: 20px; + overflow: hidden; +} +.modemStatusRow .msTitle{ + border-radius: 2px 2px 0 0; + padding: 5px 5px ; + background: #484848; + color: #fff; + background: rgb(99,99,99); + background: -moz-linear-gradient(top, rgba(99,99,99,1) 0%, rgba(72,72,72,1) 100%); + background: -webkit-linear-gradient(top, rgba(99,99,99,1) 0%,rgba(72,72,72,1) 100%); + background: linear-gradient(to bottom, rgba(99,99,99,1) 0%,rgba(72,72,72,1) 100%); + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#636363', endColorstr='#484848',GradientType=0 ); +} +.modemStatusRow .msCell{ + border-radius: 10px; + display: inline-block; + margin-top: 10px; + float:left; + border: 1px solid #ccc; + padding-bottom: 5px; + background: #fff; + +} +.modemStatusRow1 .msCell{ + width: 176px; + margin: 10px 5px 0 5px; + text-align: center; +} +.modemStatusRow1 SPAN B{ + font-weight: bold; + font-size: 70px; + line-height: 110%; + text-shadow: 1px 1px 1px rgba(0,0,0,0.4); +} +.modemStatusRow1 .msDesc{ + color: #000; + font-size: 12px; +} +.modemStatusRow2 .msCell{ + margin: 10px 5px; + text-align: center; +} +.modemStatusRow2 SPAN{ + display: inline-block; + padding: 5px 5px ; + font-size: 14px; +} +#counter_div{ + color: #000; + font-weight: normal; + font-size: 14px; +} +#counter_val{ + color: #F00; + font-size: 32px; + font-weight: bold; + text-shadow: 1px 1px 1px rgba(0,0,0,0.1); +} +#msCell_per{} +#msCell_csq{} +#msCell_rssi{} +#msCell_rscp{} +#msCell_ecio{} + +#rooterSplashStatus .level_0{ + color: #0F0; // green +} +#rooterSplashStatus .level_1{ + color: #0CB; // green blue +} +#rooterSplashStatus .level_2{ + color: #00F; // blue +} +#rooterSplashStatus .level_3{ + color: #F0F; // violet +} +#rooterSplashStatus .level_4{ + color: #F80; // orange +} +#rooterSplashStatus .level_5{ + color: #F00; // red +} +#rooterSplashStatus .level_6{ + color: #FF0; // yellow +} + +/* @end */ + + +/* Easy Color changer ------------- */ + +.rooterPageHead{ + /*background: #55F;*/ +} +.rooterItemTitle .icon, +#rooterSplashStatus h3{ + color: #55F; +} + + + diff --git a/rooter/0splash/status/files/www/luci-static/rooter/fonts/icomoon_splash.eot b/rooter/0splash/status/files/www/luci-static/rooter/fonts/icomoon_splash.eot new file mode 100644 index 0000000..29cd4d1 Binary files /dev/null and b/rooter/0splash/status/files/www/luci-static/rooter/fonts/icomoon_splash.eot differ diff --git a/rooter/0splash/status/files/www/luci-static/rooter/fonts/icomoon_splash.svg b/rooter/0splash/status/files/www/luci-static/rooter/fonts/icomoon_splash.svg new file mode 100644 index 0000000..dc2127b --- /dev/null +++ b/rooter/0splash/status/files/www/luci-static/rooter/fonts/icomoon_splash.svg @@ -0,0 +1,22 @@ + + + +Generated by IcoMoon + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/rooter/0splash/status/files/www/luci-static/rooter/fonts/icomoon_splash.ttf b/rooter/0splash/status/files/www/luci-static/rooter/fonts/icomoon_splash.ttf new file mode 100644 index 0000000..4e27645 Binary files /dev/null and b/rooter/0splash/status/files/www/luci-static/rooter/fonts/icomoon_splash.ttf differ diff --git a/rooter/0splash/status/files/www/luci-static/rooter/fonts/icomoon_splash.woff b/rooter/0splash/status/files/www/luci-static/rooter/fonts/icomoon_splash.woff new file mode 100644 index 0000000..63f5413 Binary files /dev/null and b/rooter/0splash/status/files/www/luci-static/rooter/fonts/icomoon_splash.woff differ diff --git a/rooter/0splash/status/files/www/luci-static/rooter/img/favicon.gif b/rooter/0splash/status/files/www/luci-static/rooter/img/favicon.gif new file mode 100644 index 0000000..bfbe292 Binary files /dev/null and b/rooter/0splash/status/files/www/luci-static/rooter/img/favicon.gif differ diff --git a/rooter/0splash/status/files/www/luci-static/rooter/img/kangaroo_800.png b/rooter/0splash/status/files/www/luci-static/rooter/img/kangaroo_800.png new file mode 100644 index 0000000..478fa6d Binary files /dev/null and b/rooter/0splash/status/files/www/luci-static/rooter/img/kangaroo_800.png differ diff --git a/rooter/0splash/status/files/www/splash.html b/rooter/0splash/status/files/www/splash.html new file mode 100644 index 0000000..df6f0af --- /dev/null +++ b/rooter/0splash/status/files/www/splash.html @@ -0,0 +1,264 @@ + + + + Live Network Status + + + + + + + + + + + + + + + +
                          +
                          ROOter Live Network Status
                          +
                          + +
                          + + + + + + + +
                          Enter your password :
                          + + + +
                          +

                          0 sec
                          + Signal

                          + +
                          +
                          +
                          Strength (%)
                          + - +
                          +
                          +
                          CSQ
                          + - +
                          +
                          +
                          RSSI (dBm)
                          + - +
                          +
                          +
                          RSCP (dBm) RSRP
                          + - +
                          +
                          +
                          ECIO (dB) RSRQ
                          + - +
                          +
                          +
                          SINR (dB)
                          + - +
                          +
                          +
                          + +
                          +

                          Network -

                          + +
                          +
                          +
                          Mode
                          + - +
                          +
                          +
                          MCC
                          + - +
                          +
                          +
                          MNC
                          + - +
                          +
                          +
                          RNC/eNB ID
                          + - - +
                          + +
                          +
                          LAC
                          + - - +
                          +
                          +
                          Cell ID
                          + - +
                          +
                          +
                          Channel
                          + - +
                          +
                          +
                          Bands
                          + - +
                          +
                          +
                          + +
                          +

                          Device -

                          + +
                          +
                          +
                          Modem
                          + - +
                          +
                          +
                          Protocol
                          + - +
                          +
                          +
                          Port
                          + - +
                          +
                          +
                          Temperature
                          + - +
                          +
                          +
                          + +
                          + +
                          +
                          + ROOter Splash Page by Soif and Dairyman +
                          +
                          + + + diff --git a/rooter/0splash/status/files/www/splash_files/cellular.png b/rooter/0splash/status/files/www/splash_files/cellular.png new file mode 100644 index 0000000..953bf08 Binary files /dev/null and b/rooter/0splash/status/files/www/splash_files/cellular.png differ diff --git a/rooter/0splash/status/files/www/splash_files/check.jpg b/rooter/0splash/status/files/www/splash_files/check.jpg new file mode 100644 index 0000000..f1fb739 Binary files /dev/null and b/rooter/0splash/status/files/www/splash_files/check.jpg differ diff --git a/rooter/0splash/status/files/www/splash_files/forum.png b/rooter/0splash/status/files/www/splash_files/forum.png new file mode 100644 index 0000000..9e8b8c2 Binary files /dev/null and b/rooter/0splash/status/files/www/splash_files/forum.png differ diff --git a/rooter/0splash/status/files/www/splash_files/home.png b/rooter/0splash/status/files/www/splash_files/home.png new file mode 100644 index 0000000..38687c7 Binary files /dev/null and b/rooter/0splash/status/files/www/splash_files/home.png differ diff --git a/rooter/0splash/status/files/www/splash_files/kanga1.png b/rooter/0splash/status/files/www/splash_files/kanga1.png new file mode 100644 index 0000000..7f3420e Binary files /dev/null and b/rooter/0splash/status/files/www/splash_files/kanga1.png differ diff --git a/rooter/0splash/status/files/www/splash_files/openwrt.png b/rooter/0splash/status/files/www/splash_files/openwrt.png new file mode 100644 index 0000000..0bec4c2 Binary files /dev/null and b/rooter/0splash/status/files/www/splash_files/openwrt.png differ diff --git a/rooter/0splash/status/files/www/splash_files/rooter.png b/rooter/0splash/status/files/www/splash_files/rooter.png new file mode 100644 index 0000000..be8099f Binary files /dev/null and b/rooter/0splash/status/files/www/splash_files/rooter.png differ diff --git a/rooter/0splash/status/files/www/splashfull.html b/rooter/0splash/status/files/www/splashfull.html new file mode 100644 index 0000000..1624809 --- /dev/null +++ b/rooter/0splash/status/files/www/splashfull.html @@ -0,0 +1,101 @@ + + + + Home - ROOter + + + + + + + + + + + + + + + + + + + +
                          + +
                          + +
                          The ROOter Project
                          +
                          +
                          + + + +
                          +
                          + +
                          +
                          + ROOter Splash Page by Soif and Dairyman +
                          +
                          + + + + diff --git a/rooter/0splash/status/files/www/statusfull.html b/rooter/0splash/status/files/www/statusfull.html new file mode 100644 index 0000000..6e37899 --- /dev/null +++ b/rooter/0splash/status/files/www/statusfull.html @@ -0,0 +1,271 @@ + + + + Live Network Status + + + + + + + + + + + + + + + +
                          +
                          ROOter Live Network Status
                          +
                          + +
                          + + + + + + + +
                          Enter your password :
                          + + + +
                          +

                          0 sec
                          + Signal

                          + +
                          +
                          +
                          Strength (%)
                          + - +
                          +
                          +
                          CSQ
                          + - +
                          +
                          +
                          RSSI (dBm)
                          + - +
                          +
                          +
                          RSCP (dBm) RSRP
                          + - +
                          +
                          +
                          ECIO (dB) RSRQ
                          + - +
                          +
                          +
                          SINR (dB)
                          + - +
                          +
                          +
                          + +
                          +

                          Network -

                          + +
                          +
                          +
                          Mode
                          + - +
                          +
                          +
                          MCC
                          + - +
                          +
                          +
                          MNC
                          + - +
                          +
                          +
                          RNC/eNB ID
                          + - - +
                          + +
                          +
                          LAC
                          + - - +
                          +
                          +
                          Cell ID
                          + - +
                          +
                          +
                          Channel
                          + - +
                          +
                          +
                          Bands
                          + - +
                          +
                          +
                          + +
                          +

                          Device -

                          + +
                          +
                          +
                          Modem
                          + - +
                          +
                          +
                          Protocol
                          + - +
                          +
                          +
                          Port
                          + - +
                          +
                          +
                          Temperature
                          + - +
                          +
                          +
                          + +
                          + +
                          +
                          + +
                          +
                          + ROOter Splash Page by Soif and Dairyman +
                          +
                          + + + diff --git a/rooter/ext-rooter-basic/Makefile b/rooter/ext-rooter-basic/Makefile new file mode 100644 index 0000000..6e5e0ba --- /dev/null +++ b/rooter/ext-rooter-basic/Makefile @@ -0,0 +1,43 @@ +#Owned by DairyMan@Whirlpool +# +#Copyright GNU act. +include $(TOPDIR)/rules.mk + +PKG_NAME:=ext-rooter-basic +PKG_VERSION:=4.500 +PKG_RELEASE:=1 + +PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool +include $(INCLUDE_DIR)/package.mk + +# +kmod-rt2800-usb + +define Package/ext-rooter-basic + SECTION:=utils + CATEGORY:=ROOter + SUBMENU:=Basic Support + DEPENDS:=+luci-compat +kmod-usb-net +kmod-usb-net-huawei-cdc-ncm +kmod-usb-net-cdc-ether +kmod-usb-acm \ + +kmod-usb-net-qmi-wwan +kmod-usb-net-rndis +kmod-usb-serial-qualcomm \ + +kmod-usb-net-sierrawireless +kmod-usb-ohci +kmod-usb-serial +kmod-nls-utf8 \ + +kmod-usb-serial-option +kmod-usb-serial-sierrawireless +luci-proto-3x \ + +kmod-usb-uhci +kmod-usb2 +luci-proto-3g \ + +usb-modeswitch +wireless-tools +rmbim +rqmi +ext-sms +ext-buttons +luci-app-pcimodem + TITLE:=ROOter support for usbmodems + PKGARCH:=all +endef + +define Package/ext-rooter-basic/description + Helper scripts to enable ROOter to manage usb modem interfaces +endef + + +define Build/Compile +endef + +define Package/ext-rooter-basic/install + $(CP) ./files/* $(1)/ + + +endef + +$(eval $(call BuildPackage,ext-rooter-basic)) diff --git a/rooter/ext-rooter-basic/files/etc/codename b/rooter/ext-rooter-basic/files/etc/codename new file mode 100644 index 0000000..252dcda --- /dev/null +++ b/rooter/ext-rooter-basic/files/etc/codename @@ -0,0 +1 @@ +CODENAME="GoldenOrb-Version-1" \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/etc/config/custom b/rooter/ext-rooter-basic/files/etc/config/custom new file mode 100644 index 0000000..67d0a8e --- /dev/null +++ b/rooter/ext-rooter-basic/files/etc/config/custom @@ -0,0 +1,64 @@ + +config bwallocate 'bwallocate' + option rollover '1' + option allocate '1000' + option password '1234' + option lock '0' + option enabled '0' + +config texting 'texting' + option text '0' + option phone '1222333444' + option time '72' + option ident 'John Doe' + option method '0' + option days '1' + option increment '50' + option used '0' + option tore '0' + +config menu 'menu' + option password '1234' + option full '0' + option enabled '0' + option default '0' + +config atcmd 'atcmd' + option lock '0' + option enabled '1' + option password '1234' + option sierra '/etc/sierracmd' + option quectel '/etc/quectelcmd' + option generic '/etc/genericcmd' + +config bandlock 'bandlock' + option enabled '1' + option cenable1 '0' + option earfcn1 '0' + option pci1 '0' + +config zerotier 'zerotier' + option password '1234' + option lock '0' + option networkid 'xxxxxxxxxxxxxxxx' + +config logo 'logo' + option size 'large' + +config connect 'connect' + option ipv6 '1' + +config profile 'profile' + option save '0' + +config multi 'multiuser' + option multi '0' + option root '0' + +config bwday 'bwday' + option bwday '0' + option phone '0' + option delay '8' + +config simpin 'simpin' + option pin '' \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/etc/config/modem b/rooter/ext-rooter-basic/files/etc/config/modem new file mode 100644 index 0000000..617a570 --- /dev/null +++ b/rooter/ext-rooter-basic/files/etc/config/modem @@ -0,0 +1,18 @@ + +config info 'general' + option modemnum '1' + option max '6' + +config new 'customize' + +config modem 'modem1' + option empty '1' + +config minfo1 'modeminfo1' + +config modem 'modem2' + option empty '1' + +config minfo2 'modeminfo2' + + diff --git a/rooter/ext-rooter-basic/files/etc/config/profile b/rooter/ext-rooter-basic/files/etc/config/profile new file mode 100644 index 0000000..d383cad --- /dev/null +++ b/rooter/ext-rooter-basic/files/etc/config/profile @@ -0,0 +1,19 @@ + +config default 'default' + option auth '0' + option ppp '0' + option lock '0' + option log '0' + option lb '1' + option alive '0' + option delay '5' + option at '0' + option apn '3gnet' + option tzone '0' + option nodhcp '0' + option pdptype '0' + +config disable 'disable' + option enabled '0' + +config simpin 'simpin' diff --git a/rooter/ext-rooter-basic/files/etc/config/ttl b/rooter/ext-rooter-basic/files/etc/config/ttl new file mode 100644 index 0000000..e7e7367 --- /dev/null +++ b/rooter/ext-rooter-basic/files/etc/config/ttl @@ -0,0 +1,11 @@ + +config ttl 'ttl' + option enabled '0' + option value '65' + +config hotspot 'hotspot' + option enable '0' + option oldenable '0' + option amt '10000' + option total '0' + diff --git a/rooter/ext-rooter-basic/files/etc/config/variable b/rooter/ext-rooter-basic/files/etc/config/variable new file mode 100644 index 0000000..5755430 --- /dev/null +++ b/rooter/ext-rooter-basic/files/etc/config/variable @@ -0,0 +1,4 @@ + config info 'info' + option smssleep '20' + option buffersize '50' + \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/etc/genericcmd b/rooter/ext-rooter-basic/files/etc/genericcmd new file mode 100644 index 0000000..b6b15bc --- /dev/null +++ b/rooter/ext-rooter-basic/files/etc/genericcmd @@ -0,0 +1,4 @@ +AT+CRSM=176,12258,0,0,10 +ICCID +at+csq +Signal Information diff --git a/rooter/ext-rooter-basic/files/etc/header_msg b/rooter/ext-rooter-basic/files/etc/header_msg new file mode 100644 index 0000000..e3f2398 --- /dev/null +++ b/rooter/ext-rooter-basic/files/etc/header_msg @@ -0,0 +1,4 @@ + +/img/header.png +/img/rosy.png +/img/tomato.png \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/etc/hotplug.d/iface/10-lan b/rooter/ext-rooter-basic/files/etc/hotplug.d/iface/10-lan new file mode 100644 index 0000000..3512e42 --- /dev/null +++ b/rooter/ext-rooter-basic/files/etc/hotplug.d/iface/10-lan @@ -0,0 +1,27 @@ +#!/bin/sh + +logger -t URL-DEBUG "hotplug (iface): action='$ACTION' interface='$INTERFACE'" + +if [ "$ACTION" = ifup -a "$INTERFACE" = "lan" ]; then + IP=$(uci get network.lan.ipaddr) + ipaddr=$(cat /etc/dnsmasq.conf | grep "address=/rooter.local/") + if [ ! -z $ipaddr ]; then + ipaddr=$(echo "$ipaddr" | sed -e "s!address=/rooter.local/!!g") + if [ $ipaddr != $IP ]; then + cp -f /etc/dnsmasq.conf /etc/dnsmasq.conf.bk + sed /"#StartURL"/,/"#EndURL"/d /etc/dnsmasq.conf.bk > /etc/dnsmasq.conf + rm -f /etc/dnsmasq.conf.bk + echo "#StartURL" >> /etc/dnsmasq.conf + echo "address=/rooter.local/$IP" >> /etc/dnsmasq.conf + echo "address=/www.rooter.local/$IP" >> /etc/dnsmasq.conf + echo "#EndURL" >> /etc/dnsmasq.conf + /etc/init.d/dnsmasq restart + fi + else + echo "#StartURL" >> /etc/dnsmasq.conf + echo "address=/rooter.local/$IP" >> /etc/dnsmasq.conf + echo "address=/www.rooter.local/$IP" >> /etc/dnsmasq.conf + echo "#EndURL" >> /etc/dnsmasq.conf + /etc/init.d/dnsmasq restart + fi +fi \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/etc/hotplug.d/iface/19-rooter b/rooter/ext-rooter-basic/files/etc/hotplug.d/iface/19-rooter new file mode 100644 index 0000000..e0ecea9 --- /dev/null +++ b/rooter/ext-rooter-basic/files/etc/hotplug.d/iface/19-rooter @@ -0,0 +1,42 @@ +#!/bin/sh +# +# /etc/hotplug.d/iface/19-rooter +# + +log() { + logger -t "19-ROOTER" "$@" +} + +for I in `seq 1 $(uci get modem.general.modemnum)` +do + IFACE="wan"$I + + [ "$ACTION" = ifup -o "$ACTION" = ifupdate ] || exit 0 + if [ ${INTERFACE} = "$IFACE" ]; then + if [ ${ACTION} = "ifup" ]; then + # TTL fix + if [ 1 = 0 ]; then + ttl=$(uci -q get modem.modeminfo$I.ttl) + if [ -z $ttl ]; then + ttl=0 + fi + if [ $ttl -eq 0 ]; then + ENB=$(uci get ttl.ttl.enabled) + if [ ! -z "$ENB" ]; then + #exst=$(cat /etc/firewall.user | grep " mangle .* $DEVICE " | wc -l) + #[ "$exst" -eq 4 ] || /usr/lib/custom/ttlx.sh + /usr/lib/custom/ttlx.sh + fi + fi + fi + MTU=$(uci get modem.modeminfo$I.mtu) + if [ -z $MTU ]; then + MTU=1500 + fi + if [ -n "$MTU" ]; then + ip link set mtu $MTU dev $DEVICE + logger -t "Custom MTU" $DEVICE set to $MTU + fi + fi + fi +done diff --git a/rooter/ext-rooter-basic/files/etc/hotplug.d/tty/30-3x b/rooter/ext-rooter-basic/files/etc/hotplug.d/tty/30-3x new file mode 100644 index 0000000..664d4ae --- /dev/null +++ b/rooter/ext-rooter-basic/files/etc/hotplug.d/tty/30-3x @@ -0,0 +1,31 @@ +#!/bin/sh +. /lib/functions.sh +. /lib/netifd/netifd-proto.sh + +find_3g_iface() { + local cfg="$1" + local tty="$2" + local proto + config_get proto "$cfg" proto + [ "$proto" = 3x ] || return 0 + + # bypass state vars here because 00-netstate could clobber .device + local dev=$(uci_get network "$cfg" device) + if [ "${dev##*/}" = "${tty##*/}" ]; then + if [ "$ACTION" = add ]; then + available=1 + else + available=0 + fi + proto_set_available "$cfg" $available + fi +} + +case "$DEVICENAME" in + tty*) + [ -e "/dev/$DEVICENAME" ] || [ "$ACTION" = remove ] || exit 0 + config_load network + config_foreach find_3g_iface interface "/dev/$DEVICENAME" + ;; +esac + diff --git a/rooter/ext-rooter-basic/files/etc/hotplug.d/usb/20-usb_mode b/rooter/ext-rooter-basic/files/etc/hotplug.d/usb/20-usb_mode new file mode 100644 index 0000000..aef0620 --- /dev/null +++ b/rooter/ext-rooter-basic/files/etc/hotplug.d/usb/20-usb_mode @@ -0,0 +1,3 @@ +#!/bin/sh + +/usr/lib/rooter/modeswitch.sh & \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/etc/init.d/clear b/rooter/ext-rooter-basic/files/etc/init.d/clear new file mode 100644 index 0000000..a924aaa --- /dev/null +++ b/rooter/ext-rooter-basic/files/etc/init.d/clear @@ -0,0 +1,21 @@ +#!/bin/sh /etc/rc.common +# Copyright (C) 2006 OpenWrt.org + +START=19 + +start() { + COUNTER=1 + while [ $COUNTER -le 5 ]; do + INEX=$(uci -q get network.wan$COUNTER) + if [ -z $INEX ]; then + break + else + uci delete network.wan$COUNTER + uci commit network + fi + let COUNTER=COUNTER+1 + done + uci delete network.wg0 + uci delete network.wg1 + uci commit network +} diff --git a/rooter/ext-rooter-basic/files/etc/init.d/iphone b/rooter/ext-rooter-basic/files/etc/init.d/iphone new file mode 100644 index 0000000..625b1e0 --- /dev/null +++ b/rooter/ext-rooter-basic/files/etc/init.d/iphone @@ -0,0 +1,22 @@ +#!/bin/sh /etc/rc.common +# Copyright (C) 2006 OpenWrt.org + +START=95 + +start() { + if [ ! -d "/var/lib/lockdown" ];then + mkdir -p /var/lib/lockdown + fi + bkp_files=`ls /etc/lockdown/locks` + for file in $bkp_files; + do + if [ ! -f "/var/lib/lockdown/$file" ];then + cp /etc/lockdown/locks/$file /var/lib/lockdown/ + fi + done + proc_usbmuxd=`ps | grep usbmuxd` + nb_usbmuxd=`echo "$proc_usbmuxd" | grep /usr/sbin/usbmuxd | wc -l` + if [ ! "$nb_usbmuxd" -eq 1 ];then + [ -x /usr/sbin/usbmuxd ] && usbmuxd -v + fi +} \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/etc/init.d/rooter b/rooter/ext-rooter-basic/files/etc/init.d/rooter new file mode 100644 index 0000000..1199b98 --- /dev/null +++ b/rooter/ext-rooter-basic/files/etc/init.d/rooter @@ -0,0 +1,9 @@ +#!/bin/sh /etc/rc.common +# Copyright (C) 2006 OpenWrt.org + +START=99 + +start() { + /usr/lib/rooter/initialize.sh +} + diff --git a/rooter/ext-rooter-basic/files/etc/init.d/usbmode b/rooter/ext-rooter-basic/files/etc/init.d/usbmode new file mode 100644 index 0000000..441b70a --- /dev/null +++ b/rooter/ext-rooter-basic/files/etc/init.d/usbmode @@ -0,0 +1,14 @@ +#!/bin/sh /etc/rc.common +# Copyright (C) 2013 OpenWrt.org + +START=88 +USE_PROCD=1 + +log() { + logger -t "usb-modeswitch" "$@" +} + +start_service() +{ + log "Remove early Modeswitch" +} diff --git a/rooter/ext-rooter-basic/files/etc/lockdown/locks/0000000000000000000000000000000000000000.plist b/rooter/ext-rooter-basic/files/etc/lockdown/locks/0000000000000000000000000000000000000000.plist new file mode 100644 index 0000000..e69de29 diff --git a/rooter/ext-rooter-basic/files/etc/netspeed b/rooter/ext-rooter-basic/files/etc/netspeed new file mode 100644 index 0000000..c227083 --- /dev/null +++ b/rooter/ext-rooter-basic/files/etc/netspeed @@ -0,0 +1 @@ +0 \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/etc/newstyle b/rooter/ext-rooter-basic/files/etc/newstyle new file mode 100644 index 0000000..e69de29 diff --git a/rooter/ext-rooter-basic/files/etc/quectelcmd b/rooter/ext-rooter-basic/files/etc/quectelcmd new file mode 100644 index 0000000..a87e3b5 --- /dev/null +++ b/rooter/ext-rooter-basic/files/etc/quectelcmd @@ -0,0 +1,6 @@ +AT+CRSM=176,12258,0,0,10 +ICCID +AT+QMBNCFG="AutoSel",0 +APNFIX#1 +AT+QMBNCFG="Deactivate" +APNFIX#2 diff --git a/rooter/ext-rooter-basic/files/etc/sierracmd b/rooter/ext-rooter-basic/files/etc/sierracmd new file mode 100644 index 0000000..d62aaa1 --- /dev/null +++ b/rooter/ext-rooter-basic/files/etc/sierracmd @@ -0,0 +1,4 @@ +AT+CRSM=176,12258,0,0,10 +ICCID +at+csq +Signal Strength diff --git a/rooter/ext-rooter-basic/files/etc/ttl.user b/rooter/ext-rooter-basic/files/etc/ttl.user new file mode 100644 index 0000000..98707a2 --- /dev/null +++ b/rooter/ext-rooter-basic/files/etc/ttl.user @@ -0,0 +1,4 @@ +# +# TTL Setting +# + diff --git a/rooter/ext-rooter-basic/files/etc/usb-mode.json b/rooter/ext-rooter-basic/files/etc/usb-mode.json new file mode 100644 index 0000000..90a68be --- /dev/null +++ b/rooter/ext-rooter-basic/files/etc/usb-mode.json @@ -0,0 +1,3180 @@ +{ + "messages" : [ + "555342431234567800000000000006d0000000000000000000000000000000", + "55534243123456780002000000000a2a000000003300000100000000000000", + "5553424312345678000000000000061b004600000000000000000000000000", + "0f00010142", + "55534243f0298d8124000000800006bc626563240000000000000000000000", + "0902200001010080fa0904000002080650000705010200020007058102000200", + "55534243785634120100000080000601000000000000000000000000000000", + "55534243123456780000000000000616000000000000000000000000000000", + "55534243123456782400000080000612000024000000000000000000000000", + "5553424312345678000000000000061b000000ff0000000000000000000000", + "5553424368032c882400000080000612000000240000000000000000000000", + "5553424308306384c000000080000671030000000000000000000000000000", + "5553424312345678c00000008000069f140000000000000000000000000000", + "01b0000000000000000000000000000000000000000000000000000000000000", + "555342431234567800000000000006bd000000020000000000000000000000", + "1b5a01", + "5553424312345678c000000080010606f50402527000000000000000000000", + "55534243123456788000000080000606f50402527000000000000000000000", + "555342431234567800000000000006f0010300000000000000000000000000", + "55534243123456780000000000000aff554d53434847000000000000000000", + "555342431234567803000000800006f1010100000000000000000000000000", + "555342431234567800000000000005f1010100000000000000000000000000", + "555342431234567824000000800008ff024445564348470000000000000000", + "555342431234567824000000800008ff020000000000000000000000000000", + "55534243b82e238c24000000800008ff020000000000000000000000000000", + "55534243123456780600000080000601000000000000000000000000000000", + "55534243123456780600000080010a11060000000000000000000000000000", + "55534243123456780000000000000601000000000000000000000000000000", + "555342431234567824000000800008ff524445564348470000000000000000", + "555342431234567824000000800008ff524445564348473100000000000000", + "55534243123456782400000080000dfe524445564348473d4e444953000000", + "55534243d85dd88524000000800008ff524445564348470000000000000000", + "55534243123456702000000080000c85010101180101010101000000000000", + "55534243123456782400000080000685000000240000000000000000000000", + "55534243d8a523862400000080000685000000240000000000000000000000", + "5553424348c4758600000000000010ff000000000000000000000000000000", + "555342431234567824000000800006bc626563240000000000000000000000", + "5553424330f4cf8124000000800108df200000000000000000000000000000", + "5553424312345678c00000008000069f030000000000000000000000000000", + "555342431234567824000000800008FF05B112AEE102000000000000000000", + "55534243123456780000000000000606f50402527000000000000000000000", + "55534243123456780000000080000606f50402527000000000000000000000", + "555342431234567800000000000001ff000000000000000000000000000000", + "55534243123456781200000080000603000000020000000000000000000000", + "55534243123456780000000000000cff020000000000000000000000000000", + "5553424312345678800000008000060619181a207000000000000000000000", + "555342431234567800000000000010ff000000000000000000000000000000", + "555342431234567800000000000008ff000000000000030000000000000000", + "555342431234567824000000800108df200000000000000000000000000000", + "55534243f8d2e6838000000080000606f50402527000000000000000000000", + "555342431234567800000000000003f0010100000000000000000000000000", + "55534243123456780000000000000600000000000000000000000000000000", + "5553424312345679c000000080000671030000000000000000000000000000", + "555342430820298900000000000003f0010100000000000000000000000000", + "55534243123456700000000000000616aa0000000000000000000000000000", + "5553424312345678c000000080000671010000000000000000000000000000", + "5553424340799288C000000080010A16000000C00000000000000000000000", + "555342431234567800000000000006161f6d62706b00000000000000000000", + "5553424398e2c4812400000080000bff524445564348473d43440000000000" + ], + + "devices" : { + "03f0:002a": { + "*": { + "t_class": 7, + "msg": [ 0 ] + } + }, + "03f0:032a": { + "*": { + "t_class": 7, + "msg": [ 0 ] + } + }, + "03f0:371d": { + "*": { + "msg": [ ], + "config": 0 + } + }, + "03f0:4b1d": { + "*": { + "msg": [ ], + "config": 0 + } + }, + "03f0:4e1d": { + "*": { + "msg": [ ], + "config": 0 + } + }, + "03f0:521d": { + "*": { + "msg": [ ], + "config": 0 + } + }, + "03f0:531d": { + "*": { + "msg": [ ], + "config": 0 + } + }, + "03f0:541d": { + "*": { + "msg": [ ], + "config": 0 + } + }, + "03f0:581d": { + "*": { + "msg": [ ], + "config": 0 + } + }, + "03f0:631d": { + "*": { + "msg": [ ], + "config": 0 + } + }, + "03f0:641d": { + "*": { + "msg": [ ], + "config": 0 + } + }, + "03f0:681d": { + "*": { + "msg": [ ], + "config": 0 + } + }, + "03f0:911d": { + "*": { + "msg": [ ], + "config": 0 + } + }, + "03f0:931d": { + "*": { + "msg": [ ], + "config": 0 + } + }, + "03f0:9a1d": { + "*": { + "msg": [ ], + "config": 0 + } + }, + "03f0:9d1d": { + "*": { + "msg": [ ], + "config": 0 + } + }, + "03f0:a31d": { + "*": { + "msg": [ ], + "config": 0 + } + }, + "0408:1000": { + "*": { + "t_vendor": 1032, + "t_product": [ 59906 ], + "msg": [ 1 ] + } + }, + "0408:ea17": { + "*": { + "t_vendor": 1032, + "t_product": [ 59926 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "0408:ea43": { + "*": { + "t_vendor": 1032, + "t_product": [ 59975, 59977, 59981 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "0408:f000": { + ":uMa=Yota": { + "t_vendor": 1032, + "t_product": [ 53257 ], + "msg": [ 2 ] + } + }, + "0421:060c": { + "*": { + "t_vendor": 1057, + "t_product": [ 1550 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "0421:0610": { + "*": { + "t_vendor": 1057, + "t_product": [ 1554 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "0421:0618": { + "*": { + "t_vendor": 1057, + "t_product": [ 1561 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "0421:061d": { + "*": { + "t_vendor": 1057, + "t_product": [ 1566 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "0421:0622": { + "*": { + "t_vendor": 1057, + "t_product": [ 1571 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "0421:0627": { + "*": { + "t_vendor": 1057, + "t_product": [ 1554, 1577 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "0421:062c": { + "*": { + "t_vendor": 1057, + "t_product": [ 1581, 1583 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "0421:0632": { + "*": { + "t_vendor": 1057, + "t_product": [ 1586 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "0421:0637": { + "*": { + "t_vendor": 1057, + "t_product": [ 1592 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "046d:c261": { + "*": { + "t_class": 3, + "msg_endpoint": 1, + "msg": [ 3 ], + "response_endpoint": 1 + } + }, + "0471:1210": { + ":uMa=Philips": { + "t_class": 255, + "mode": "StandardEject", + "msg": [ ] + }, + ":uMa=Wisue": { + "t_vendor": 7612, + "t_product": [ 5 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "0471:1237": { + "*": { + "t_vendor": 1137, + "t_product": [ 4614, 4660 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "0482:024d": { + "*": { + "msg": [ ], + "config": 2 + } + }, + "04bb:bccd": { + "*": { + "t_vendor": 1211, + "t_product": [ 2377 ], + "msg": [ 4 ] + } + }, + "04cc:2251": { + "*": { + "t_vendor": 1228, + "t_product": [ 8793, 8814 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "04cc:225c": { + "*": { + "msg": [ ], + "config": 2 + } + }, + "04cc:226e": { + "*": { + "msg": [ ], + "config": 2 + } + }, + "04cc:226f": { + "*": { + "msg": [ ], + "config": 2 + } + }, + "04e8:680c": { + "*": { + "t_vendor": 1256, + "t_product": [ 26514 ], + "msg": [ 5 ] + } + }, + "04e8:689a": { + "*": { + "t_vendor": 1256, + "t_product": [ 26761 ], + "msg": [ 6 ] + } + }, + "04e8:f000": { + ":sMo=U209": { + "t_vendor": 1256, + "t_product": [ 26113 ], + "msg": [ 7 ] + } + }, + "04fc:2140": { + "*": { + "t_vendor": 1276, + "t_product": [ 1557, 4672 ], + "msg": [ 8 ] + } + }, + "057c:62ff": { + "*": { + "t_vendor": 1404, + "t_product": [ 34049, 34050 ], + "msg": [ 9 ] + } + }, + "057c:84ff": { + "*": { + "t_vendor": 1404, + "t_product": [ 33793 ], + "msg": [ 9 ] + } + }, + "0586:2030": { + "*": { + "t_vendor": 1414, + "t_product": [ 13379, 13380 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "05c6:0010": { + "*": { + "t_vendor": 1478, + "t_product": [ 160 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "05c6:1000": { + ":uMa=AnyDATA": { + "t_vendor": 5845, + "t_product": [ 25858 ], + "mode": "StandardEject", + "msg": [ ] + }, + ":uMa=CELOT": { + "t_vendor": 8479, + "t_product": [ 26625, 26626 ], + "mode": "StandardEject", + "msg": [ ] + }, + ":uMa=Co.,Ltd": { + "t_vendor": 7433, + "t_product": [ 17158 ], + "mode": "StandardEject", + "msg": [ ] + }, + ":uMa=DGT": { + "t_vendor": 8479, + "t_product": [ 26626 ], + "mode": "StandardEject", + "msg": [ ] + }, + ":uMa=SAMSUNG": { + "t_vendor": 1256, + "t_product": [ 26113 ], + "msg": [ 7 ] + }, + ":uMa=SSE": { + "t_vendor": 1478, + "t_product": [ 24576 ], + "mode": "StandardEject", + "msg": [ ] + }, + ":uMa=StrongRising": { + "t_vendor": 650, + "t_product": [ 4102 ], + "mode": "StandardEject", + "msg": [ ] + }, + ":uMa=Vertex": { + "t_vendor": 8167, + "t_product": [ 256 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "05c6:2000": { + "*": { + "t_vendor": 1478, + "t_product": [ 21, 22, 24, 52759 ], + "msg": [ 10 ], + "response": true, + "check": true + } + }, + "05c6:2001": { + "*": { + "t_vendor": 7694, + "t_product": [ 52758, 52759, 52990 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "05c6:6503": { + "*": { + "t_vendor": 5845, + "t_product": [ 25858 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "05c6:9024": { + "*": { + "t_vendor": 1478, + "t_product": [ 36901 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "05c6:98ff": { + "*": { + "t_vendor": 1478, + "t_product": [ 24577 ], + "mode": "Sierra", + "msg": [ ] + } + }, + "05c6:f000": { + "*": { + "t_vendor": 1478, + "t_product": [ 22, 24576, 36864 ], + "mode": "StandardEject", + "msg": [ 11 ] + } + }, + "05c7:1000": { + "*": { + "t_vendor": 1479, + "t_product": [ 24576 ], + "msg": [ 12 ] + } + }, + "0685:2000": { + "*": { + "t_vendor": 7326, + "t_product": [ 38403 ], + "msg": [ 10 ], + "response": true + } + }, + "072f:100d": { + "*": { + "t_vendor": 1839, + "t_product": [ 37068 ], + "msg_endpoint": 2, + "msg": [ 13 ] + } + }, + "07d1:a800": { + "*": { + "t_vendor": 2001, + "t_product": [ 15873, 15874, 32268 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "07d1:a804": { + "*": { + "t_vendor": 2001, + "t_product": [ 32273 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "07d1:f000": { + "*": { + "t_vendor": 2001, + "t_product": [ 32263 ], + "msg": [ 14 ] + } + }, + "0846:0fff": { + "*": { + "t_vendor": 2118, + "t_product": [ 26835 ], + "mode": "Sierra", + "msg": [ ] + } + }, + "0922:1001": { + "*": { + "t_vendor": 2338, + "t_product": [ 4098 ], + "msg_endpoint": 1, + "msg": [ 15 ], + "response_endpoint": 1 + } + }, + "0922:1003": { + "*": { + "t_vendor": 2338, + "t_product": [ 4100 ], + "msg_endpoint": 1, + "msg": [ 15 ], + "response_endpoint": 1 + } + }, + "0922:1007": { + "*": { + "t_vendor": 2338, + "t_product": [ 4104 ], + "msg_endpoint": 1, + "msg": [ 15 ], + "response_endpoint": 1 + } + }, + "0930:0d46": { + "*": { + "t_vendor": 2352, + "t_product": [ 3397 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "0ace:2011": { + "*": { + "mode": "StandardEject", + "msg": [ ] + } + }, + "0ace:20ff": { + "*": { + "mode": "StandardEject", + "msg": [ ] + } + }, + "0af0:4007": { + "*": { + "t_vendor": 2800, + "t_product": [ 16389 ], + "mode": "Sierra", + "msg": [ ] + } + }, + "0b3c:c700": { + "*": { + "t_vendor": 2876, + "t_product": [ 49152, 49153, 49154 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "0b3c:f000": { + "*": { + "t_vendor": 2876, + "t_product": [ 49155, 49156 ], + "msg": [ 16 ], + "response": true + } + }, + "0b3c:f00c": { + "*": { + "t_vendor": 2876, + "t_product": [ 49162 ], + "msg": [ 17 ] + } + }, + "0b3c:f017": { + "*": { + "t_vendor": 2876, + "t_product": [ 49163 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "0bdb:190d": { + "*": { + "msg": [ ], + "config": 2 + } + }, + "0bdb:1910": { + "*": { + "msg": [ ], + "config": 2 + } + }, + "0cf3:20ff": { + "*": { + "t_vendor": 3315, + "t_product": [ 28688 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "0d46:45a1": { + "*": { + "t_vendor": 3398, + "t_product": [ 17833 ], + "mode": "Kobil", + "msg": [ ] + } + }, + "0d46:45a5": { + "*": { + "t_vendor": 3398, + "t_product": [ 17837 ], + "mode": "Kobil", + "msg": [ ] + } + }, + "0df7:0800": { + "*": { + "t_class": 255, + "mode": "MobileAction", + "msg": [ ] + } + }, + "0e8d:0002": { + ":uPr=MT": { + "t_vendor": 3725, + "t_product": [ 161, 162, 165 ], + "msg": [ 18 ] + }, + ":uPr=Product": { + "t_vendor": 3725, + "t_product": [ 161, 162, 165 ], + "msg": [ 18 ] + } + }, + "0e8d:7109": { + "*": { + "t_vendor": 3725, + "t_product": [ 28949, 28952 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "0fce:d0cf": { + "*": { + "msg": [ ], + "config": 3 + } + }, + "0fce:d0df": { + "*": { + "msg": [ ], + "config": 2 + } + }, + "0fce:d0e1": { + "*": { + "t_class": 2, + "mode": "Sony", + "msg": [ ], + "config": 2 + } + }, + "0fce:d103": { + "*": { + "t_class": 2, + "mode": "Sony", + "msg": [ ], + "config": 2 + } + }, + "0fd1:1000": { + "*": { + "msg": [ ], + "config": 3 + } + }, + "1004:1000": { + "*": { + "t_class": 255, + "msg": [ 19 ] + } + }, + "1004:607f": { + "*": { + "t_vendor": 4100, + "t_product": [ 24576, 24852 ], + "msg": [ 20 ], + "response": true + } + }, + "1004:610c": { + "*": { + "t_vendor": 4100, + "t_product": [ 24841 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "1004:613a": { + "*": { + "t_vendor": 4100, + "t_product": [ 24868 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "1004:613f": { + "*": { + "t_vendor": 4100, + "t_product": [ 24897 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "1004:614e": { + "*": { + "t_vendor": 4100, + "t_product": [ 24885 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "1004:6156": { + "*": { + "t_vendor": 4100, + "t_product": [ 24919 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "1004:6190": { + "*": { + "t_vendor": 4100, + "t_product": [ 24963, 24999 ], + "mode": "StandardEject", + "msg": [ ], + "wait": 10 + } + }, + "1004:61dd": { + "*": { + "t_vendor": 4100, + "t_product": [ 24975 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "1004:61e7": { + "*": { + "t_vendor": 4100, + "t_product": [ 25062 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "1004:61eb": { + "*": { + "t_vendor": 4100, + "t_product": [ 25066 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "1004:6327": { + "*": { + "t_vendor": 4100, + "t_product": [ 25382 ], + "msg": [ 21 ] + } + }, + "106c:3b03": { + "*": { + "t_vendor": 4204, + "t_product": [ 14101 ], + "msg": [ 22 ] + } + }, + "106c:3b05": { + "*": { + "t_vendor": 4204, + "t_product": [ 14102 ], + "msg": [ 23 ] + } + }, + "106c:3b06": { + "*": { + "t_vendor": 4204, + "t_product": [ 14103 ], + "msg": [ 24 ] + } + }, + "106c:3b11": { + "*": { + "t_vendor": 4204, + "t_product": [ 14104 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "106c:3b14": { + "*": { + "t_vendor": 4204, + "t_product": [ 14113 ], + "msg": [ 22 ] + } + }, + "1076:7f40": { + "*": { + "t_vendor": 4214, + "t_product": [ 32512 ], + "mode": "GCT", + "msg": [ ] + } + }, + "109b:f009": { + "*": { + "t_vendor": 4251, + "t_product": [ 37140 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "1199:0fff": { + "*": { + "t_vendor": 4505, + "t_product": [ 23, 24, 25, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 274, 288, 536, 544, 548, 769, 26626, 26627, 26628, 26629, 26632, 26633, 26642, 26643, 26645, 26646, 26656, 26657, 26658, 26674, 26675, 26676, 26677, 26680, 26681, 26682, 26683, 26684, 26685, 26686, 26704, 26705, 26706, 26707, 26709, 26710, 26713, 26714, 26752, 26768, 26769, 26770, 26771, 26786, 26787, 26794, 36881, 36882, 36945 ], + "mode": "Sierra", + "msg": [ ] + } + }, + "1199:9011": { + "*": { + "msg": [ ], + "config": 1 + } + }, + "1199:9013": { + "*": { + "msg": [ ], + "config": 1 + } + }, + "1199:9017": { + "*": { + "msg": [ ], + "config": 1 + } + }, + "1199:901b": { + "*": { + "msg": [ ], + "config": 1 + } + }, + "1199:901c": { + "*": { + "msg": [ ], + "config": 1 + } + }, + "1199:901f": { + "*": { + "msg": [ ], + "config": 1 + } + }, + "1199:9041": { + "*": { + "msg": [ ], + "config": 1 + } + }, + "1199:9051": { + "*": { + "msg": [ ], + "config": 1 + } + }, + "1199:9053": { + "*": { + "msg": [ ], + "config": 1 + } + }, + "1199:9063": { + "*": { + "msg": [ ], + "config": 1 + } + }, + "1266:1000": { + "*": { + "t_vendor": 4710, + "t_product": [ 4098, 4099, 4100, 4101, 4102, 4103, 4104, 4105, 4106, 4107, 4108, 4109, 4110, 4111, 4113, 4114 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "12d1:1001": { + "*": { + "t_class": 255, + "mode": "Huawei", + "msg": [ ] + } + }, + "12d1:1003": { + "*": { + "t_class": 255, + "mode": "Huawei", + "msg": [ ] + } + }, + "12d1:1009": { + "*": { + "t_class": 255, + "mode": "Huawei", + "msg": [ ] + } + }, + "12d1:1010": { + "*": { + "t_class": 255, + "mode": "Huawei", + "msg": [ ] + } + }, + "12d1:101e": { + "*": { + "t_class": 255, + "msg": [ 25 ] + } + }, + "12d1:1030": { + "*": { + "t_vendor": 4817, + "t_product": [ 4148 ], + "msg": [ 26 ] + } + }, + "12d1:1031": { + "*": { + "t_vendor": 4817, + "t_product": [ 4149 ], + "msg": [ 26 ] + } + }, + "12d1:1413": { + "*": { + "t_class": 255, + "mode": "Huawei", + "msg": [ ] + } + }, + "12d1:1414": { + "*": { + "t_class": 255, + "mode": "Huawei", + "msg": [ ] + } + }, + "12d1:1446": { + "*": { + "t_vendor": 4817, + "t_product": [ 4097, 5124, 5126, 5131, 5132, 5138, 5143, 5147, 5161, 5170, 5171, 5174, 5292, 5382, 5388, 5393 ], + "mode": "HuaweiNew", + "msg": [ ] + } + }, + "12d1:1449": { + "*": { + "t_vendor": 4817, + "t_product": [ 5188 ], + "mode": "HuaweiNew", + "msg": [ ] + } + }, + "12d1:14ad": { + "*": { + "t_vendor": 4817, + "t_product": [ 5294 ], + "mode": "HuaweiNew", + "msg": [ ] + } + }, + "12d1:14b5": { + "*": { + "t_vendor": 4817, + "t_product": [ 5288, 5290 ], + "mode": "HuaweiNew", + "msg": [ ] + } + }, + "12d1:14b7": { + "*": { + "t_vendor": 4817, + "t_product": [ 5324 ], + "mode": "HuaweiNew", + "msg": [ ] + } + }, + "12d1:14ba": { + "*": { + "t_vendor": 4817, + "t_product": [ 5330 ], + "mode": "HuaweiNew", + "msg": [ ] + } + }, + "12d1:14c1": { + "*": { + "t_vendor": 4817, + "t_product": [ 5318 ], + "mode": "HuaweiNew", + "msg": [ ] + } + }, + "12d1:14c3": { + "*": { + "t_vendor": 4817, + "t_product": [ 5320 ], + "mode": "HuaweiNew", + "msg": [ ] + } + }, + "12d1:14c4": { + "*": { + "t_vendor": 4817, + "t_product": [ 5322 ], + "mode": "HuaweiNew", + "msg": [ ] + } + }, + "12d1:14c5": { + "*": { + "t_vendor": 4817, + "t_product": [ 5323 ], + "mode": "HuaweiNew", + "msg": [ ] + } + }, + "12d1:14d1": { + "*": { + "t_vendor": 4817, + "t_product": [ 5321 ], + "mode": "HuaweiNew", + "msg": [ ] + } + }, + "12d1:14fe": { + "*": { + "t_vendor": 4817, + "t_product": [ 5382, 5391, 5405, 7198 ], + "mode": "HuaweiNew", + "msg": [ ] + } + }, + "12d1:1505": { + "*": { + "t_vendor": 4817, + "t_product": [ 5131, 5132, 5382, 5391, 5386 ], + "mode": "HuaweiNew", + "msg": [ ] + } + }, + "12d1:151a": { + "*": { + "t_vendor": 4817, + "t_product": [ 5403, 5405, 5406 ], + "mode": "HuaweiNew", + "msg": [ ] + } + }, + "12d1:1520": { + "*": { + "t_vendor": 4817, + "t_product": [ 5221 ], + "mode": "HuaweiNew", + "msg": [ ] + } + }, + "12d1:1521": { + "*": { + "t_vendor": 4817, + "t_product": [ 5220 ], + "mode": "HuaweiNew", + "msg": [ ] + } + }, + "12d1:1523": { + "*": { + "t_vendor": 4817, + "t_product": [ 5265 ], + "mode": "HuaweiNew", + "msg": [ ] + } + }, + "12d1:1526": { + "*": { + "t_vendor": 4817, + "t_product": [ 5327 ], + "mode": "HuaweiNew", + "msg": [ ] + } + }, + "12d1:1527": { + "*": { + "t_vendor": 4817, + "t_product": [ 5524 ], + "mode": "HuaweiNew", + "msg": [ ] + } + }, + "12d1:1553": { + "*": { + "t_vendor": 4817, + "t_product": [ 4097 ], + "mode": "HuaweiNew", + "msg": [ ] + } + }, + "12d1:1557": { + "*": { + "t_vendor": 4817, + "t_product": [ 5285 ], + "mode": "HuaweiNew", + "msg": [ ] + } + }, + "12d1:155a": { + "*": { + "t_vendor": 4817, + "t_product": [ 5325 ], + "mode": "HuaweiNew", + "msg": [ ] + } + }, + "12d1:155b": { + "*": { + "t_vendor": 4817, + "t_product": [ 5382 ], + "mode": "HuaweiNew", + "msg": [ ] + } + }, + "12d1:156a": { + "*": { + "t_vendor": 4817, + "t_product": [ 5483, 5484 ], + "mode": "HuaweiNew", + "msg": [ ] + } + }, + "12d1:1570": { + "*": { + "msg": [ ], + "config": 0 + } + }, + "12d1:1571": { + "*": { + "msg": [ ], + "config": 0 + } + }, + "12d1:1572": { + "*": { + "msg": [ ], + "config": 0 + } + }, + "12d1:1573": { + "*": { + "msg": [ ], + "config": 0 + } + }, + "12d1:157c": { + "*": { + "t_vendor": 4817, + "t_product": [ 5382 ], + "mode": "HuaweiNew", + "msg": [ ] + } + }, + "12d1:157d": { + "*": { + "t_vendor": 4817, + "t_product": [ 5339, 5340 ], + "mode": "HuaweiNew", + "msg": [ ] + } + }, + "12d1:1580": { + "*": { + "t_vendor": 4817, + "t_product": [ 5509 ], + "mode": "HuaweiNew", + "msg": [ ] + } + }, + "12d1:1581": { + "*": { + "t_vendor": 4817, + "t_product": [ 5511 ], + "mode": "HuaweiNew", + "msg": [ ] + } + }, + "12d1:1582": { + "*": { + "t_vendor": 4817, + "t_product": [ 5512 ], + "mode": "HuaweiNew", + "msg": [ ] + } + }, + "12d1:1583": { + "*": { + "t_vendor": 4817, + "t_product": [ 5513 ], + "mode": "HuaweiNew", + "msg": [ ] + } + }, + "12d1:1597": { + "*": { + "t_vendor": 4817, + "t_product": [ 5528 ], + "mode": "HuaweiNew", + "msg": [ ] + } + }, + "12d1:15bb": { + "*": { + "msg": [ ], + "config": 0 + } + }, + "12d1:15c0": { + "*": { + "msg": [ ], + "config": 0 + } + }, + "12d1:15c1": { + "*": { + "msg": [ ], + "config": 0 + } + }, + "12d1:15ca": { + "*": { + "t_vendor": 4817, + "t_product": [ 5382 ], + "mode": "HuaweiNew", + "msg": [ ] + } + }, + "12d1:15cd": { + "*": { + "t_vendor": 4817, + "t_product": [ 5382 ], + "mode": "HuaweiNew", + "msg": [ ] + } + }, + "12d1:15ce": { + "*": { + "t_vendor": 4817, + "t_product": [ 5553, 5555 ], + "mode": "HuaweiNew", + "msg": [ ] + } + }, + "12d1:15cf": { + "*": { + "t_vendor": 4817, + "t_product": [ 5382 ], + "mode": "HuaweiNew", + "msg": [ ] + } + }, + "12d1:15d0": { + "*": { + "t_vendor": 4817, + "t_product": [ 5585 ], + "mode": "HuaweiNew", + "msg": [ ] + } + }, + "12d1:15d2": { + "*": { + "t_vendor": 4817, + "t_product": [ 5587 ], + "mode": "HuaweiNew", + "msg": [ ] + } + }, + "12d1:15e7": { + "*": { + "t_vendor": 4817, + "t_product": [ 5382 ], + "mode": "HuaweiNew", + "msg": [ ] + } + }, + "12d1:15ec": { + "*": { + "t_vendor": 4817, + "t_product": [ 7206 ], + "mode": "HuaweiNew", + "msg": [ ] + } + }, + "12d1:15f0": { + "*": { + "msg": [ ], + "config": 0 + } + }, + "12d1:1805": { + "*": { + "t_class": 255, + "msg": [ 25 ] + } + }, + "12d1:1c0b": { + "*": { + "t_vendor": 4817, + "t_product": [ 7173, 7174, 7175, 7176, 7184 ], + "mode": "HuaweiNew", + "msg": [ ] + } + }, + "12d1:1c1b": { + "*": { + "t_vendor": 4817, + "t_product": [ 5382 ], + "mode": "HuaweiNew", + "msg": [ ] + } + }, + "12d1:1c24": { + "*": { + "t_vendor": 4817, + "t_product": [ 7186, 7203 ], + "mode": "HuaweiNew", + "msg": [ ] + } + }, + "12d1:1c25": { + "*": { + "msg": [ ], + "config": 0 + } + }, + "12d1:1d50": { + "*": { + "msg": [ ], + "config": 2 + } + }, + "12d1:1da1": { + "*": { + "t_vendor": 4817, + "t_product": [ 7433 ], + "mode": "Huawei", + "msg": [ ] + } + }, + "12d1:1f01": { + "*": { + "t_vendor": 4817, + "t_product": [ 5339, 5340 ], + "mode": "HuaweiNew", + "msg": [ ] + } + }, + "12d1:1f02": { + "*": { + "t_vendor": 4817, + "t_product": [ 5340 ], + "mode": "HuaweiNew", + "msg": [ ] + } + }, + "12d1:1f03": { + "*": { + "t_vendor": 4817, + "t_product": [ 5339 ], + "mode": "HuaweiNew", + "msg": [ ] + } + }, + "12d1:1f04": { + "*": { + "t_vendor": 4817, + "t_product": [ 5564 ], + "mode": "HuaweiNew", + "msg": [ ] + } + }, + "12d1:1f05": { + "*": { + "t_vendor": 4817, + "t_product": [ 5565 ], + "mode": "HuaweiNew", + "msg": [ ] + } + }, + "12d1:1f06": { + "*": { + "t_vendor": 4817, + "t_product": [ 5575 ], + "mode": "HuaweiNew", + "msg": [ ] + } + }, + "12d1:1f07": { + "*": { + "t_vendor": 4817, + "t_product": [ 5567 ], + "mode": "HuaweiNew", + "msg": [ ] + } + }, + "12d1:1f09": { + "*": { + "t_vendor": 4817, + "t_product": [ 7248 ], + "mode": "HuaweiNew", + "msg": [ ] + } + }, + "12d1:1f11": { + "*": { + "t_vendor": 4817, + "t_product": [ 5308 ], + "mode": "HuaweiNew", + "msg": [ ] + } + }, + "12d1:1f15": { + "*": { + "t_vendor": 4817, + "t_product": [ 5120, 5367 ], + "mode": "HuaweiNew", + "msg": [ ] + } + }, + "12d1:1f16": { + "*": { + "mode": "MBIM", + "msg": [ ] + } + }, + "12d1:1f17": { + "*": { + "t_vendor": 4817, + "t_product": [ 5494 ], + "mode": "HuaweiNew", + "msg": [ ] + } + }, + "12d1:1f18": { + "*": { + "t_vendor": 4817, + "t_product": [ 5495 ], + "mode": "HuaweiNew", + "msg": [ ] + } + }, + "12d1:1f19": { + "*": { + "t_vendor": 4817, + "t_product": [ 5370, 5493, 5496 ], + "mode": "HuaweiNew", + "msg": [ ] + } + }, + "12d1:1f1b": { + "*": { + "t_vendor": 4817, + "t_product": [ 5497 ], + "mode": "HuaweiNew", + "msg": [ ] + } + }, + "12d1:1f1c": { + "*": { + "t_vendor": 4817, + "t_product": [ 5498, 5520 ], + "mode": "HuaweiNew", + "msg": [ ] + } + }, + "12d1:1f1d": { + "*": { + "t_vendor": 4817, + "t_product": [ 5499, 5521 ], + "mode": "HuaweiNew", + "msg": [ ] + } + }, + "12d1:1f1e": { + "*": { + "t_vendor": 4817, + "t_product": [ 5503, 5522 ], + "mode": "HuaweiNew", + "msg": [ ] + } + }, + "12d1:380b": { + "*": { + "t_class": 2, + "mode": "StandardEject", + "msg": [ ] + } + }, + "1307:1169": { + "*": { + "t_vendor": 5041, + "t_product": [ 49 ], + "mode": "Cisco", + "msg": [ ] + } + }, + "1410:5010": { + "*": { + "t_vendor": 5136, + "t_product": [ 16640, 17408, 28720 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "1410:5020": { + "*": { + "t_vendor": 5136, + "t_product": [ 24576, 28673 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "1410:5023": { + "*": { + "t_vendor": 5136, + "t_product": [ 28720 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "1410:5030": { + "*": { + "t_vendor": 5136, + "t_product": [ 24576 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "1410:5031": { + "*": { + "t_vendor": 5136, + "t_product": [ 24578 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "1410:5041": { + "*": { + "t_vendor": 5136, + "t_product": [ 28673, 28675 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "1410:5055": { + "*": { + "t_vendor": 5136, + "t_product": [ 24626 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "1410:5059": { + "*": { + "t_vendor": 5136, + "t_product": [ 28721, 28738 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "1410:7001": { + "*": { + "t_class": 255, + "mode": "StandardEject", + "msg": [ ] + } + }, + "1410:9020": { + "*": { + "msg": [ ], + "config": 4 + } + }, + "148e:a000": { + "*": { + "t_class": 2, + "mode": "Sequans", + "msg": [ ] + } + }, + "148f:2578": { + "*": { + "t_vendor": 5263, + "t_product": [ 36897 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "148f:2878": { + "*": { + "t_vendor": 5263, + "t_product": [ 30209 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "15eb:7153": { + "*": { + "t_vendor": 5611, + "t_product": [ 29010 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "1614:0800": { + "*": { + "t_class": 255, + "msg": [ 27 ] + } + }, + "1614:0802": { + "*": { + "t_class": 255, + "msg": [ 27 ] + } + }, + "16d5:f000": { + "*": { + "t_vendor": 5845, + "t_product": [ 26115 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "16d8:6281": { + "*": { + "t_class": 255, + "msg": [ 28 ] + } + }, + "16d8:6803": { + "*": { + "t_class": 2, + "msg": [ 29 ] + } + }, + "16d8:6804": { + "*": { + "t_class": 255, + "msg": [ 28 ] + } + }, + "16d8:700a": { + "*": { + "t_class": 255, + "msg": [ 30 ] + } + }, + "16d8:700b": { + "*": { + "t_class": 255, + "msg": [ 30 ] + } + }, + "16d8:f000": { + "*": { + "t_vendor": 5848, + "t_product": [ 24582 ], + "msg": [ 31 ] + } + }, + "1726:1900": { + "*": { + "t_vendor": 5926, + "t_product": [ 4096 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "1726:f00e": { + "*": { + "t_vendor": 5926, + "t_product": [ 40960 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "1782:0003": { + "*": { + "msg": [ ], + "config": 2 + } + }, + "1782:0023": { + "*": { + "msg": [ ], + "config": 2 + } + }, + "198a:0003": { + "*": { + "t_vendor": 6538, + "t_product": [ 2 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "198f:bccd": { + "*": { + "t_vendor": 6543, + "t_product": [ 544 ], + "msg": [ 4 ] + } + }, + "19d2:0003": { + "*": { + "t_class": 255, + "mode": "StandardEject", + "msg": [ ] + } + }, + "19d2:0026": { + "*": { + "t_vendor": 6610, + "t_product": [ 115, 148, 338 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "19d2:0033": { + "*": { + "t_class": 255, + "mode": "StandardEject", + "msg": [ ] + } + }, + "19d2:0040": { + "*": { + "t_vendor": 6610, + "t_product": [ 34 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "19d2:0053": { + "*": { + "t_vendor": 6610, + "t_product": [ 49 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "19d2:0083": { + ":uPr=WCDMA": { + "t_vendor": 6610, + "t_product": [ 292 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "19d2:0090": { + "*": { + "t_vendor": 6610, + "t_product": [ 52 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "19d2:0101": { + "*": { + "t_vendor": 6610, + "t_product": [ 260 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "19d2:0103": { + "*": { + "t_vendor": 6610, + "t_product": [ 49 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "19d2:0110": { + "*": { + "t_vendor": 6610, + "t_product": [ 289 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "19d2:0115": { + "*": { + "t_vendor": 6610, + "t_product": [ 278 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "19d2:0120": { + "*": { + "t_vendor": 6610, + "t_product": [ 121 ], + "detach_storage": false, + "mode": "StandardEject", + "msg": [ ], + "response": false, + "interface": 0 + } + }, + "19d2:0146": { + "*": { + "t_vendor": 6610, + "t_product": [ 322, 323 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "19d2:0149": { + "*": { + "t_vendor": 6610, + "t_product": [ 292 ], + "mode": "StandardEject", + "msg": [ 32 ] + } + }, + "19d2:0150": { + "*": { + "t_vendor": 6610, + "t_product": [ 292 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "19d2:0154": { + "*": { + "t_vendor": 6610, + "t_product": [ 23, 279, 8195 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "19d2:0166": { + "*": { + "t_vendor": 6610, + "t_product": [ 359 ], + "msg": [ 33 ] + } + }, + "19d2:0169": { + "*": { + "t_vendor": 6610, + "t_product": [ 368 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "19d2:0198": { + "*": { + "t_vendor": 6610, + "t_product": [ 409 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "19d2:0266": { + "*": { + "t_vendor": 6610, + "t_product": [ 613 ], + "mode": "StandardEject", + "msg": [ 34 ] + } + }, + "19d2:0304": { + "*": { + "t_vendor": 6610, + "t_product": [ 841 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "19d2:0318": { + "*": { + "t_vendor": 6610, + "t_product": [ 791, 816 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "19d2:0325": { + "*": { + "t_vendor": 6610, + "t_product": [ 806 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "19d2:0388": { + "*": { + "t_vendor": 6610, + "t_product": [ 1095 ], + "msg": [ 33 ] + } + }, + "19d2:0413": { + "*": { + "t_vendor": 6610, + "t_product": [ 1042 ], + "msg": [ 34 ] + } + }, + "19d2:1001": { + "*": { + "t_vendor": 6610, + "t_product": [ 4098, 4099 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "19d2:1007": { + "*": { + "t_vendor": 6610, + "t_product": [ 4104 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "19d2:1009": { + "*": { + "t_vendor": 6610, + "t_product": [ 4112 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "19d2:1013": { + "*": { + "t_vendor": 6610, + "t_product": [ 4117 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "19d2:1017": { + "*": { + "t_vendor": 6610, + "t_product": [ 4120 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "19d2:1019": { + "*": { + "t_vendor": 6610, + "t_product": [ 4129 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "19d2:1020": { + "*": { + "t_vendor": 6610, + "t_product": [ 4129 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "19d2:1022": { + "*": { + "t_vendor": 6610, + "t_product": [ 4131, 4132 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "19d2:1026": { + "*": { + "t_vendor": 6610, + "t_product": [ 4135, 4136, 4137 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "19d2:1030": { + "*": { + "t_vendor": 6610, + "t_product": [ 4145, 4146 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "19d2:1034": { + "*": { + "t_vendor": 6610, + "t_product": [ 4149, 4150, 4151 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "19d2:1038": { + "*": { + "t_vendor": 6610, + "t_product": [ 4153, 4160 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "19d2:1042": { + "*": { + "t_vendor": 6610, + "t_product": [ 4163 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "19d2:1046": { + "*": { + "t_vendor": 6610, + "t_product": [ 4167 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "19d2:1171": { + "*": { + "t_vendor": 6610, + "t_product": [ 4467 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "19d2:1175": { + "*": { + "t_vendor": 6610, + "t_product": [ 4471 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "19d2:1179": { + "*": { + "t_vendor": 6610, + "t_product": [ 4481 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "19d2:1201": { + "*": { + "t_vendor": 6610, + "t_product": [ 4611 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "19d2:1207": { + "*": { + "t_vendor": 6610, + "t_product": [ 4616 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "19d2:1210": { + "*": { + "t_vendor": 6610, + "t_product": [ 4625 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "19d2:1216": { + "*": { + "t_vendor": 6610, + "t_product": [ 4631 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "19d2:1219": { + "*": { + "t_vendor": 6610, + "t_product": [ 4640, 4642 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "19d2:1224": { + "*": { + "t_vendor": 6610, + "t_product": [ 130 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "19d2:1225": { + "*": { + "t_vendor": 6610, + "t_product": [ 5125 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "19d2:1227": { + "*": { + "t_vendor": 6610, + "t_product": [ 4690 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "19d2:1232": { + "*": { + "t_vendor": 6610, + "t_product": [ 4712, 8195 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "19d2:1233": { + "*": { + "t_vendor": 6610, + "t_product": [ 4720 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "19d2:1237": { + "*": { + "t_vendor": 6610, + "t_product": [ 23 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "19d2:1238": { + "*": { + "t_vendor": 6610, + "t_product": [ 23 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "19d2:1420": { + "*": { + "t_vendor": 6610, + "t_product": [ 5125 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "19d2:1511": { + "*": { + "t_vendor": 6610, + "t_product": [ 5394 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "19d2:1514": { + "*": { + "t_vendor": 6610, + "t_product": [ 5397 ], + "msg": [ 35 ] + } + }, + "19d2:1517": { + "*": { + "t_vendor": 6610, + "t_product": [ 5401 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "19d2:1520": { + "*": { + "t_vendor": 6610, + "t_product": [ 322 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "19d2:1523": { + "*": { + "t_vendor": 6610, + "t_product": [ 5413 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "19d2:1528": { + "*": { + "t_vendor": 6610, + "t_product": [ 5415 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "19d2:1536": { + "*": { + "t_vendor": 6610, + "t_product": [ 5431, 5432 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "19d2:1542": { + "*": { + "t_vendor": 6610, + "t_product": [ 5444 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "19d2:1580": { + "*": { + "t_vendor": 6610, + "t_product": [ 5506 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "19d2:1588": { + "*": { + "t_vendor": 6610, + "t_product": [ 5513, 5521, 5522 ], + "mode": "StandardEject", + "msg": [ 32 ] + } + }, + "19d2:1595": { + "*": { + "t_vendor": 6610, + "t_product": [ 5428, 5522, 5526, 5632 ], + "mode": "StandardEject", + "msg": [ 32 ] + } + }, + "19d2:2000": { + "*": { + "t_vendor": 6610, + "t_product": [ 1, 2, 21, 22, 23, 25, 36, 49, 51, 55, 66, 82, 85, 97, 99, 100, 102, 145, 264, 279, 296, 337, 343, 375, 5122, 8194, 8195 ], + "mode": "StandardEject", + "msg": [ 32 ] + } + }, + "19d2:2004": { + "*": { + "t_vendor": 6610, + "t_product": [ 5122 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "19d2:bccd": { + "*": { + "t_vendor": 6610, + "t_product": [ 370 ], + "msg": [ 36 ] + } + }, + "19d2:ffde": { + "*": { + "t_vendor": 6610, + "t_product": [ 65501 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "19d2:ffe6": { + "*": { + "t_vendor": 6610, + "t_product": [ 65509 ], + "msg": [ 37 ] + } + }, + "19d2:fff5": { + "*": { + "t_vendor": 6610, + "t_product": [ 65508, 65513, 65521, 65534, 65535 ], + "msg": [ 38 ] + } + }, + "19d2:fff6": { + "*": { + "t_vendor": 6610, + "t_product": [ 65521 ], + "msg": [ 38 ] + } + }, + "1a8d:1000": { + "*": { + "t_vendor": 6797, + "t_product": [ 4098, 4103, 4105, 4109, 8198 ], + "mode": "StandardEject", + "msg": [ ], + "release_delay": 4000, + "response": true + } + }, + "1a8d:2000": { + "*": { + "t_vendor": 6797, + "t_product": [ 8198 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "1ab7:5700": { + "*": { + "t_vendor": 6839, + "t_product": [ 8192, 22321 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "1b7d:0700": { + "*": { + "t_vendor": 7037, + "t_product": [ 1 ], + "msg": [ 39 ] + } + }, + "1bbb:000f": { + "*": { + "t_vendor": 7099, + "t_product": [ 15 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "1bbb:00ca": { + "*": { + "t_class": 255, + "msg": [ 17 ] + } + }, + "1bbb:011f": { + "*": { + "t_vendor": 7099, + "t_product": [ 262 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "1bbb:022c": { + "*": { + "msg": [ ], + "config": 2 + } + }, + "1bbb:025e": { + "*": { + "t_vendor": 7099, + "t_product": [ 405 ], + "msg": [ 17 ] + } + }, + "1bbb:f000": { + "*": { + "t_vendor": 7099, + "t_product": [ 0, 23, 183, 286, 401, 405 ], + "msg": [ 17 ] + } + }, + "1bbb:f017": { + "*": { + "t_vendor": 7099, + "t_product": [ 23, 286, 515 ], + "msg": [ 17 ] + } + }, + "1bbb:f052": { + "*": { + "t_vendor": 7099, + "t_product": [ 82 ], + "msg": [ 17 ] + } + }, + "1c9e:1001": { + "*": { + "t_vendor": 7326, + "t_product": [ 24672, 24673 ], + "msg": [ 40 ] + } + }, + "1c9e:6000": { + "*": { + "t_class": 255, + "msg": [ 27 ] + } + }, + "1c9e:6061": { + ":uPr=Storage": { + "t_class": 255, + "msg": [ 40 ] + } + }, + "1c9e:9101": { + "*": { + "t_vendor": 7326, + "t_product": [ 37124 ], + "msg": [ 40 ] + } + }, + "1c9e:9200": { + "*": { + "t_vendor": 7326, + "t_product": [ 37378 ], + "msg": [ 40 ] + } + }, + "1c9e:9401": { + "*": { + "t_vendor": 7326, + "t_product": [ 37892 ], + "msg": [ 40 ] + } + }, + "1c9e:9800": { + "*": { + "t_class": 255, + "msg": [ 17 ] + } + }, + "1c9e:98ff": { + "*": { + "t_vendor": 7326, + "t_product": [ 26625, 38913, 38915 ], + "msg": [ 41 ] + } + }, + "1c9e:9bfe": { + "*": { + "t_vendor": 7326, + "t_product": [ 39681 ], + "msg": [ 40 ] + } + }, + "1c9e:9d00": { + "*": { + "t_class": 255, + "msg": [ 40 ] + } + }, + "1c9e:9e00": { + "*": { + "t_class": 255, + "msg": [ 40 ] + } + }, + "1c9e:9e08": { + "*": { + "t_vendor": 7326, + "t_product": [ 40472 ], + "mode": "Sierra", + "msg": [ ] + } + }, + "1c9e:f000": { + "*": { + "t_vendor": 7326, + "t_product": [ 36864, 38403, 38405, 38407, 39168 ], + "msg": [ 42 ], + "wait": 1 + }, + ":uMa=USB_Modem": { + "t_vendor": 7326, + "t_product": [ 36864, 38403, 38405, 38407, 39168, 39424 ], + "msg": [ 17 ], + "wait": 1 + } + }, + "1c9e:f010": { + "*": { + "t_vendor": 7326, + "t_product": [ 61697 ], + "msg": [ 40 ] + } + }, + "1d09:1000": { + "*": { + "t_vendor": 7433, + "t_product": [ 4112 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "1d09:1021": { + "*": { + "t_vendor": 7433, + "t_product": [ 4112 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "1d09:1025": { + "*": { + "t_vendor": 7433, + "t_product": [ 4134 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "1da5:f000": { + "*": { + "t_vendor": 7589, + "t_product": [ 17682 ], + "mode": "Qisda", + "msg": [ ] + } + }, + "1dbc:0669": { + "*": { + "msg": [ ], + "config": 2 + } + }, + "1dd6:1000": { + "*": { + "t_vendor": 7638, + "t_product": [ 4098 ], + "msg": [ 43 ], + "response": true + } + }, + "1de1:1101": { + "*": { + "t_vendor": 8679, + "t_product": [ 14 ], + "msg": [ 44 ] + } + }, + "1e0e:f000": { + "*": { + "t_vendor": 7694, + "t_product": [ 36864, 37120, 37376 ], + "msg": [ 14 ], + "response": true + } + }, + "1e89:f000": { + "*": { + "t_vendor": 7817, + "t_product": [ 6688 ], + "msg": [ 45 ] + } + }, + "1edf:6003": { + "*": { + "msg": [ ], + "config": 2 + } + }, + "1ee8:0003": { + "*": { + "t_vendor": 7912, + "t_product": [ 4 ], + "msg": [ 46 ], + "response": true + } + }, + "1ee8:0007": { + "*": { + "t_vendor": 7912, + "t_product": [ 11 ], + "msg": [ 46 ] + } + }, + "1ee8:0009": { + "*": { + "t_vendor": 7912, + "t_product": [ 11 ], + "msg": [ 46 ], + "response": true + } + }, + "1ee8:0013": { + "*": { + "t_vendor": 7912, + "t_product": [ 17, 18, 20 ], + "msg": [ 46 ], + "response": true + } + }, + "1ee8:0018": { + "*": { + "t_vendor": 7912, + "t_product": [ 23 ], + "msg": [ 46 ], + "response": true + } + }, + "1ee8:0040": { + "*": { + "t_vendor": 7912, + "t_product": [ 62, 63 ], + "msg": [ 46 ], + "response": true + } + }, + "1ee8:0045": { + "*": { + "t_vendor": 7912, + "t_product": [ 68 ], + "msg": [ 46 ], + "response": true + } + }, + "1ee8:0048": { + "*": { + "t_vendor": 7912, + "t_product": [ 73 ], + "msg": [ 46 ] + } + }, + "1ee8:004a": { + "*": { + "t_vendor": 7912, + "t_product": [ 73 ], + "msg": [ 46 ] + } + }, + "1ee8:004f": { + "*": { + "t_vendor": 7912, + "t_product": [ 78 ], + "msg": [ 46 ], + "response": true + } + }, + "1ee8:0054": { + "*": { + "t_vendor": 7912, + "t_product": [ 83 ], + "msg": [ 46 ], + "response": true + } + }, + "1ee8:0060": { + "*": { + "t_vendor": 7912, + "t_product": [ 95 ], + "msg": [ 47 ] + } + }, + "1ee8:0063": { + "*": { + "t_vendor": 7912, + "t_product": [ 100, 101 ], + "msg": [ 47 ] + } + }, + "1ee8:0068": { + "*": { + "t_vendor": 7912, + "t_product": [ 105 ], + "msg": [ 47 ] + } + }, + "1f28:0021": { + "*": { + "t_vendor": 7976, + "t_product": [ 32 ], + "msg": [ 48 ] + } + }, + "1fac:0032": { + "*": { + "msg": [ ], + "config": 2 + } + }, + "1fac:0130": { + "*": { + "t_vendor": 8108, + "t_product": [ 305 ], + "msg": [ 48 ] + } + }, + "1fac:0150": { + "*": { + "t_vendor": 8108, + "t_product": [ 337 ], + "msg": [ 48 ] + } + }, + "1fac:0151": { + "*": { + "msg": [ ], + "config": 2 + } + }, + "2001:00a6": { + "*": { + "t_vendor": 8193, + "t_product": [ 32002 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "2001:00a7": { + "*": { + "t_vendor": 8193, + "t_product": [ 32014 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "2001:7600": { + "*": { + "msg": [ ], + "config": 2 + } + }, + "2001:98ff": { + "*": { + "t_vendor": 8193, + "t_product": [ 32278 ], + "msg": [ 49 ], + "response": true + } + }, + "2001:a401": { + "*": { + "t_vendor": 8193, + "t_product": [ 32281 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "2001:a403": { + "*": { + "t_vendor": 8193, + "t_product": [ 32011, 32012 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "2001:a405": { + "*": { + "t_vendor": 8193, + "t_product": [ 32013 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "2001:a406": { + "*": { + "t_vendor": 8193, + "t_product": [ 32281 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "2001:a407": { + "*": { + "t_vendor": 8193, + "t_product": [ 32014 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "2001:a40a": { + "*": { + "t_vendor": 8193, + "t_product": [ 32016 ], + "msg": [ 50 ] + } + }, + "2001:a40d": { + "*": { + "t_vendor": 8193, + "t_product": [ 32312 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "2001:a706": { + "*": { + "t_vendor": 8193, + "t_product": [ 32001 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "2001:a707": { + "*": { + "t_vendor": 8193, + "t_product": [ 32002 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "2001:a708": { + "*": { + "t_vendor": 8193, + "t_product": [ 32003 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "2001:a805": { + "*": { + "t_vendor": 8193, + "t_product": [ 32274 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "2001:a809": { + "*": { + "t_vendor": 8193, + "t_product": [ 30976 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "2001:a80b": { + "*": { + "t_vendor": 8193, + "t_product": [ 32000 ], + "msg": [ 50 ], + "response": true + } + }, + "2001:ab00": { + "*": { + "t_vendor": 8193, + "t_product": [ 32309 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "2001:ac01": { + "*": { + "t_vendor": 8193, + "t_product": [ 32317 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "2015:0001": { + "*": { + "t_class": 255, + "mode": "StandardEject", + "msg": [ ] + } + }, + "201e:1023": { + "*": { + "t_vendor": 8222, + "t_product": [ 4130 ], + "msg": [ 51, 52 ], + "response": true + } + }, + "201e:2009": { + "*": { + "t_class": 255, + "mode": "StandardEject", + "msg": [ ] + } + }, + "2020:0002": { + "*": { + "t_vendor": 8224, + "t_product": [ 8192, 16384, 16400 ], + "msg": [ 53 ] + } + }, + "2020:f00e": { + "*": { + "t_vendor": 8224, + "t_product": [ 4101, 4104 ], + "mode": "StandardEject", + "msg": [ ], + "wait": 2 + } + }, + "2020:f00f": { + "*": { + "t_vendor": 8224, + "t_product": [ 4101 ], + "mode": "StandardEject", + "msg": [ ], + "wait": 2 + } + }, + "2077:1000": { + "*": { + "t_vendor": 8311, + "t_product": [ 28673, 28688, 28689 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "2077:f000": { + "*": { + "t_vendor": 8311, + "t_product": [ 36864, 36962, 40960, 40963 ], + "mode": "StandardEject", + "msg": [ 54 ] + } + }, + "20a6:f00a": { + "*": { + "t_vendor": 8358, + "t_product": [ 4096 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "20a6:f00e": { + "*": { + "t_vendor": 8358, + "t_product": [ 4357 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "20b9:1682": { + "*": { + "t_class": 255, + "mode": "StandardEject", + "msg": [ ] + } + }, + "21f5:1000": { + "*": { + "t_vendor": 8693, + "t_product": [ 8200 ], + "msg": [ 55 ] + } + }, + "21f5:3010": { + "*": { + "t_vendor": 8693, + "t_product": [ 4353 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "2262:0001": { + "*": { + "t_vendor": 8802, + "t_product": [ 2 ], + "msg": [ 56 ] + } + }, + "22de:6801": { + "*": { + "t_class": 255, + "mode": "StandardEject", + "msg": [ ] + } + }, + "22de:6802": { + "*": { + "t_class": 255, + "mode": "StandardEject", + "msg": [ ] + } + }, + "22de:6803": { + "*": { + "t_class": 255, + "mode": "StandardEject", + "msg": [ ] + } + }, + "22f4:0021": { + "*": { + "t_class": 255, + "mode": "StandardEject", + "msg": [ ] + } + }, + "230d:0001": { + "*": { + "msg": [ ], + "config": 3 + } + }, + "230d:0003": { + "*": { + "msg": [ ], + "config": 3 + } + }, + "230d:0007": { + "*": { + "msg": [ ], + "config": 3 + } + }, + "230d:000b": { + "*": { + "msg": [ ], + "config": 3 + } + }, + "230d:000c": { + "*": { + "msg": [ ], + "config": 3 + } + }, + "230d:000d": { + "*": { + "msg": [ ], + "config": 3 + } + }, + "230d:0101": { + "*": { + "msg": [ ], + "config": 2 + } + }, + "230d:0103": { + "*": { + "msg": [ ], + "config": 2 + } + }, + "2357:0200": { + "*": { + "t_vendor": 9047, + "t_product": [ 513 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "2357:f000": { + "*": { + "t_vendor": 9047, + "t_product": [ 36864 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "23a2:1010": { + "*": { + "t_vendor": 9122, + "t_product": [ 4660 ], + "msg": [ 57 ] + } + }, + "257a:a000": { + "*": { + "t_vendor": 9594, + "t_product": [ 5633, 5663, 5679, 9759, 9775, 13855, 13871 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "257a:b000": { + "*": { + "t_vendor": 9594, + "t_product": [ 5633, 5663, 5679, 9759, 9775, 13855, 13871 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "257a:c000": { + "*": { + "t_vendor": 9594, + "t_product": [ 5633, 5663, 5679, 9759, 9775, 13855, 13871 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "257a:d000": { + "*": { + "t_vendor": 9594, + "t_product": [ 5633, 5663, 5679, 9759, 9775, 13855, 13871 ], + "mode": "StandardEject", + "msg": [ ] + } + }, + "6000:1000": { + "*": { + "t_vendor": 1478, + "t_product": [ 24576 ], + "msg": [ 55 ] + } + }, + "8888:6500": { + "*": { + "t_vendor": 5848, + "t_product": [ 25907 ], + "msg": [ 58 ] + } + }, + "ed09:1021": { + "*": { + "t_vendor": 60681, + "t_product": [ 4112 ], + "mode": "StandardEject", + "msg": [ ] + } + } + } +} diff --git a/rooter/ext-rooter-basic/files/lib/netifd/proto/3x.sh b/rooter/ext-rooter-basic/files/lib/netifd/proto/3x.sh new file mode 100644 index 0000000..f8c71fd --- /dev/null +++ b/rooter/ext-rooter-basic/files/lib/netifd/proto/3x.sh @@ -0,0 +1,171 @@ +#!/bin/sh +INCLUDE_ONLY=1 + +. ../netifd-proto.sh +. ./ppp.sh +init_proto "$@" + +ROOTER=/usr/lib/rooter +ROOTER_LINK="/tmp/links" + +log() { + logger -t "Create PPP Connection" "$@" +} + +chcklog() { + OOX=$1 + CLOG=$(uci get modem.modeminfo$CURRMODEM.log) + if [ $CLOG = "1" ]; then + log "$OOX" + fi +} + +proto_3x_init_config() { + no_device=1 + available=1 + ppp_generic_init_config + proto_config_add_string "device" + proto_config_add_string "apn" + proto_config_add_string "service" + proto_config_add_string "pincode" + proto_config_add_string "dialnumber" +} + +proto_3x_setup() { + local interface="$1" + local chat + + if [ ! -f /tmp/bootend.file ]; then + return 0 + fi + + json_get_var device device + json_get_var apn apn + json_get_var service service + json_get_var pincode pincode + + CURRMODEM=$(uci get network.$interface.currmodem) + + uci set modem.modem$CURRMODEM.connected=0 + uci commit modem + jkillall getsignal$CURRMODEM + rm -f $ROOTER_LINK/getsignal$CURRMODEM + jkillall con_monitor$CURRMODEM + rm -f $ROOTER_LINK/con_monitor$CURRMODEM + + + + [ -e "$device" ] || { + proto_set_available "$interface" 0 + return 1 + } + + if [ $service = "umts" ]; then + idV=$(uci get modem.modem$CURRMODEM.idV) + if [ $idV = 12d1 ]; then + $ROOTER/gcom/gcom-locked "$device" "curc.gcom" "$CURRMODEM" + log "Unsolicited Responses Disabled" + fi + chat="/etc/chatscripts/3g.chat" + if [ -n "$pincode" ]; then + OX=$($ROOTER/gcom/gcom-locked "$device" "setpin.gcom" "$CURRMODEM") + ERROR="ERROR" + if `echo ${OX} | grep "${ERROR}" 1>/dev/null 2>&1` + then + log "Modem $CURRMODEM Failed to Unlock SIM Pin" + chcklog "$OX" + $ROOTER/signal/status.sh $CURRMODEM "$MAN $MOD" "Failed to Connect : Pin Locked" + proto_notify_error "$interface" PIN_FAILED + proto_block_restart "$interface" + return 1 + fi + fi + export SETUSER=$(uci get modem.modeminfo$CURRMODEM.user) + export SETPASS=$(uci get modem.modeminfo$CURRMODEM.pass) + export SETAUTH=$(uci get modem.modeminfo$CURRMODEM.auth) + OX=$($ROOTER/gcom/gcom-locked "$device" "connect-ppp.gcom" "$CURRMODEM") + ERROR="ERROR" + if `echo ${OX} | grep "${ERROR}" 1>/dev/null 2>&1` + then + log "Error for Modem $CURRMODEM on Authorization" + chcklog "$OX" + fi + + if [ -z "$dialnumber" ]; then + dialnumber="*99***1#" + fi + else + chat="/etc/chatscripts/evdo.chat" + fi + + connect="${apn:+USE_APN=$apn }DIALNUMBER=$dialnumber /usr/sbin/chat -t5 -v -E -f $chat" + + ppp_generic_setup "$interface" \ + noaccomp \ + nopcomp \ + novj \ + nobsdcomp \ + noauth \ + lock \ + crtscts \ + 115200 "$device" + + sleep 20 + MAN=$(uci get modem.modem$CURRMODEM.manuf) + MOD=$(uci get modem.modem$CURRMODEM.model) + $ROOTER/log/logger "Modem #$CURRMODEM Connected ($MAN $MOD)" + + if [ -e $ROOTER/modem-led.sh ]; then + $ROOTER/modem-led.sh $CURRMODEM 3 + fi + + PROT=$(uci get modem.modem$CURRMODEM.proto) + if [ $service = "umts" ]; then + ln -s $ROOTER/signal/modemsignal.sh $ROOTER_LINK/getsignal$CURRMODEM + $ROOTER_LINK/getsignal$CURRMODEM $CURRMODEM $PROT & + fi + ln -s $ROOTER/connect/reconnect-ppp.sh $ROOTER_LINK/reconnect$CURRMODEM + ln -s $ROOTER/connect/conmon.sh $ROOTER_LINK/con_monitor$CURRMODEM + $ROOTER_LINK/con_monitor$CURRMODEM $CURRMODEM & + uci set modem.modem$CURRMODEM.connected=1 + uci set modem.modem$CURRMODEM.interface="3x-"$interface + uci commit modem + CLB=$(uci get modem.modeminfo$CURRMODEM.lb) + if [ -e /etc/config/mwan3 ]; then + INTER=$(uci get modem.modeminfo$CURRMODEM.inter) + if [ -z $INTER ]; then + INTER=0 + else + if [ $INTER = 0 ]; then + INTER=$CURRMODEM + fi + fi + + if [ -e $ROOTER/timezone.sh ]; then + TZ=$(uci -q get modem.modeminfo$CURRMODEM.tzone) + if [ "$TZ" = "1" ]; then + log "Set TimeZone" + $ROOTER/timezone.sh & + fi + fi + + ENB=$(uci get mwan3.wan$CURRMODEM.enabled) + if [ ! -z $ENB ]; then + if [ $CLB = "1" ]; then + uci set mwan3.wan$INTER.enabled=1 + else + uci set mwan3.wan$INTER.enabled=0 + fi + uci commit mwan3 + /usr/sbin/mwan3 restart + fi + fi + rm -f /tmp/usbwait + return 0 +} + +proto_3x_teardown() { + proto_kill_command "$interface" +} + +add_protocol 3x diff --git a/rooter/ext-rooter-basic/files/lib/upgrade/keep.d/cronfiles b/rooter/ext-rooter-basic/files/lib/upgrade/keep.d/cronfiles new file mode 100644 index 0000000..16cdff4 --- /dev/null +++ b/rooter/ext-rooter-basic/files/lib/upgrade/keep.d/cronfiles @@ -0,0 +1,2 @@ +/etc/cronuser +/etc/cronbase diff --git a/rooter/ext-rooter-basic/files/lib/upgrade/keep.d/rc-local b/rooter/ext-rooter-basic/files/lib/upgrade/keep.d/rc-local new file mode 100644 index 0000000..b68cb69 --- /dev/null +++ b/rooter/ext-rooter-basic/files/lib/upgrade/keep.d/rc-local @@ -0,0 +1,3 @@ +/overlay/upper/etc/rc.local +/etc/rc.local +/usr/lib/scripts diff --git a/rooter/ext-rooter-basic/files/usr/bin/bmask128 b/rooter/ext-rooter-basic/files/usr/bin/bmask128 new file mode 100644 index 0000000..bfd5bde --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/bin/bmask128 @@ -0,0 +1,19 @@ +#!/bin/sh +# +printf "Band 128-bit bandmask\n" +LBAND=1 +BBAND=1 +while [ $LBAND -le 48 ] +do + printf "%-6s%016X%016X\n" "$LBAND" "0" "$BBAND" + LBAND=$(( $LBAND + 1 )) + BBAND=$(( $BBAND * 2 )) +done +LBAND=65 +BBAND=1 +while [ $LBAND -le 85 ] +do + printf "%-6s%016X%016X\n" "$LBAND" "$BBAND" "0" + LBAND=$(( $LBAND + 1 )) + BBAND=$(( $BBAND * 2 )) +done diff --git a/rooter/ext-rooter-basic/files/usr/bin/chan2band.sh b/rooter/ext-rooter-basic/files/usr/bin/chan2band.sh new file mode 100644 index 0000000..5b5bff0 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/bin/chan2band.sh @@ -0,0 +1,317 @@ +#!/bin/sh +CHAN=$1 +CHAN=$(echo "$CHAN" | grep -o "[0-9]*") + +decode_lte() { + if [ $CHAN -lt 600 ]; then + BAND="B1" + elif [ $CHAN -lt 1200 ]; then + BAND="B2" + elif [ $CHAN -lt 1950 ]; then + BAND="B3" + elif [ $CHAN -lt 2400 ]; then + BAND="B4" + elif [ $CHAN -lt 2650 ]; then + BAND="B5" + elif [ $CHAN -lt 2750 ]; then + BAND="B6" + elif [ $CHAN -lt 3450 ]; then + BAND="B7" + elif [ $CHAN -lt 3800 ]; then + BAND="B8" + elif [ $CHAN -lt 4150 ]; then + BAND="B9" + elif [ $CHAN -lt 4750 ]; then + BAND="B10" + elif [ $CHAN -lt 4950 ]; then + BAND="B11" + elif [ $CHAN -lt 5010 ]; then + BAND="-" + elif [ $CHAN -lt 5180 ]; then + BAND="B12" + elif [ $CHAN -lt 5280 ]; then + BAND="B13" + elif [ $CHAN -lt 5380 ]; then + BAND="B14" + elif [ $CHAN -lt 5730 ]; then + BAND="-" + elif [ $CHAN -lt 5850 ]; then + BAND="B17" + elif [ $CHAN -lt 6000 ]; then + BAND="B18" + elif [ $CHAN -lt 6150 ]; then + BAND="B19" + elif [ $CHAN -lt 6450 ]; then + BAND="B20" + elif [ $CHAN -lt 6600 ]; then + BAND="B21" + elif [ $CHAN -lt 7400 ]; then + BAND="B22" + elif [ $CHAN -lt 7500 ]; then + BAND="-" + elif [ $CHAN -lt 7700 ]; then + BAND="B23" + elif [ $CHAN -lt 8040 ]; then + BAND="B24" + elif [ $CHAN -lt 8690 ]; then + BAND="B25" + elif [ $CHAN -lt 9040 ]; then + BAND="B26" + elif [ $CHAN -lt 9210 ]; then + BAND="B27" + elif [ $CHAN -lt 9660 ]; then + BAND="B28" + elif [ $CHAN -lt 9770 ]; then + BAND="B29" + elif [ $CHAN -lt 9870 ]; then + BAND="B30" + elif [ $CHAN -lt 9920 ]; then + BAND="B31" + elif [ $CHAN -lt 10400 ]; then + BAND="B32" + elif [ $CHAN -lt 36000 ]; then + BAND="-" + elif [ $CHAN -lt 36200 ]; then + BAND="B33" + elif [ $CHAN -lt 36350 ]; then + BAND="B34" + elif [ $CHAN -lt 36950 ]; then + BAND="B35" + elif [ $CHAN -lt 37550 ]; then + BAND="B36" + elif [ $CHAN -lt 37750 ]; then + BAND="B37" + elif [ $CHAN -lt 38250 ]; then + BAND="B38" + elif [ $CHAN -lt 38650 ]; then + BAND="B39" + elif [ $CHAN -lt 39650 ]; then + BAND="B40" + elif [ $CHAN -lt 41590 ]; then + BAND="B41" + elif [ $CHAN -lt 43590 ]; then + BAND="B42" + elif [ $CHAN -lt 45590 ]; then + BAND="B43" + elif [ $CHAN -lt 46590 ]; then + BAND="B44" + elif [ $CHAN -lt 46790 ]; then + BAND="B45" + elif [ $CHAN -lt 54540 ]; then + BAND="B46" + elif [ $CHAN -lt 55240 ]; then + BAND="B47" + elif [ $CHAN -lt 56740 ]; then + BAND="B48" + elif [ $CHAN -lt 58240 ]; then + BAND="B49" + elif [ $CHAN -lt 59090 ]; then + BAND="B50" + elif [ $CHAN -lt 59140 ]; then + BAND="B51" + elif [ $CHAN -lt 60140 ]; then + BAND="B52" + elif [ $CHAN -lt 60255 ]; then + BAND="B53" + elif [ $CHAN -lt 65536 ]; then + BAND="-" + elif [ $CHAN -lt 66436 ]; then + BAND="B65" + elif [ $CHAN -lt 67336 ]; then + BAND="B66" + elif [ $CHAN -lt 67536 ]; then + BAND="B67" + elif [ $CHAN -lt 67836 ]; then + BAND="B68" + elif [ $CHAN -lt 68336 ]; then + BAND="B69" + elif [ $CHAN -lt 68586 ]; then + BAND="B70" + elif [ $CHAN -lt 68936 ]; then + BAND="B71" + elif [ $CHAN -lt 68986 ]; then + BAND="B72" + elif [ $CHAN -lt 69036 ]; then + BAND="B73" + elif [ $CHAN -lt 69466 ]; then + BAND="B74" + elif [ $CHAN -lt 70316 ]; then + BAND="B75" + elif [ $CHAN -lt 70366 ]; then + BAND="B76" + elif [ $CHAN -lt 70546 ]; then + BAND="B85" + elif [ $CHAN -lt 70596 ]; then + BAND="B87" + elif [ $CHAN -lt 70646 ]; then + BAND="B88" + else + BAND="-" + fi +} + +decode_nr5g() { + if [ $CHAN -lt 123400 ]; then + BAND="-" + elif [ $CHAN -le 130400 ]; then + BAND="n71" + elif [ $CHAN -lt 143400 ]; then + BAND="-" + elif [ $CHAN -lt 145600 ]; then + BAND="n29" + elif [ $CHAN -eq 145600 ]; then + BAND="n29|n85" + elif [ $CHAN -lt 145800 ]; then + BAND="n85" + elif [ $CHAN -eq 145800 ]; then + BAND="n12|n85" + elif [ $CHAN -lt 147600 ]; then + BAND="n12|n85" + elif [ $CHAN -lt 149200 ]; then + BAND="n12|n67|n85" + elif [ $CHAN -eq 149200 ]; then + BAND="n12|n13|n67|n85" + elif [ $CHAN -le 151200 ]; then + BAND="n13|n67" + elif [ $CHAN -lt 151600 ]; then + BAND="n67" + elif [ $CHAN -eq 151600 ]; then + BAND="n14|n28|n67" + elif [ $CHAN -le 153600 ]; then + BAND="n14|n28" + elif [ $CHAN -lt 158200 ]; then + BAND="n28" + elif [ $CHAN -eq 158200 ]; then + BAND="n14|n20|n28" + elif [ $CHAN -le 160600 ]; then + BAND="n20|n28" + elif [ $CHAN -le 164200 ]; then + BAND="n20" + elif [ $CHAN -lt 171800 ]; then + BAND="-" + elif [ $CHAN -lt 172000 ]; then + BAND="n26" + elif [ $CHAN -lt 173800 ]; then + BAND="n18|n26" + elif [ $CHAN -le 175000 ]; then + BAND="n5|n18|n26" + elif [ $CHAN -le 178800 ]; then + BAND="n5|n26" + elif [ $CHAN -lt 185000 ]; then + BAND="-" + elif [ $CHAN -le 192000 ]; then + BAND="n8" + elif [ $CHAN -lt 285400 ]; then + BAND="-" + elif [ $CHAN -lt 286400 ]; then + BAND="n51|n76|n91|n93" + elif [ $CHAN -eq 286400 ]; then + BAND="n50|n51|n75|n76|n91|92|n93|94" + elif [ $CHAN -lt 295000 ]; then + BAND="n50|n75|n92|n94" + elif [ $CHAN -eq 295000 ]; then + BAND="n50|n74|n75|n92|n94" + elif [ $CHAN -le 303400 ]; then + BAND="n50|n74|n75|n92|n94" + elif [ $CHAN -le 303600 ]; then + BAND="n74" + elif [ $CHAN -lt 305000 ]; then + BAND="-" + elif [ $CHAN -le 311800 ]; then + BAND="n24" + elif [ $CHAN -lt 361000 ]; then + BAND="-" + elif [ $CHAN -lt 376000 ]; then + BAND="n3" + elif [ $CHAN -eq 376000 ]; then + BAND="n3|n39" + elif [ $CHAN -le 384000 ]; then + BAND="n39" + elif [ $CHAN -lt 386000 ]; then + BAND="-" + elif [ $CHAN -le 398000 ]; then + BAND="n2|n25" + elif [ $CHAN -lt 399000 ]; then + BAND="n25" + elif [ $CHAN -eq 399000 ]; then + BAND="n25|n70" + elif [ $CHAN -lt 402000 ]; then + BAND="n70" + elif [ $CHAN -eq 402000 ]; then + BAND="n34|n70" + elif [ $CHAN -le 404000 ]; then + BAND="n34|n70" + elif [ $CHAN -le 405000 ]; then + BAND="n34" + elif [ $CHAN -lt 422000 ]; then + BAND="-" + elif [ $CHAN -le 434000 ]; then + BAND="n1|n65|n66" + elif [ $CHAN -le 440000 ]; then + BAND="n65|n66" + elif [ $CHAN -lt 460000 ]; then + BAND="-" + elif [ $CHAN -lt 470000 ]; then + BAND="n40" + elif [ $CHAN -eq 470000 ]; then + BAND="n30|n40" + elif [ $CHAN -le 472000 ]; then + BAND="n30|n40" + elif [ $CHAN -le 480000 ]; then + BAND="n40" + elif [ $CHAN -lt 496700 ]; then + BAND="-" + elif [ $CHAN -le 499000 ]; then + BAND="n53" + elif [ $CHAN -lt 499200 ]; then + BAND="-" + elif [ $CHAN -lt 514000 ]; then + BAND="n41|n90" + elif [ $CHAN -eq 514000 ]; then + BAND="n38|n41|n90" + elif [ $CHAN -lt 524000 ]; then + BAND="n38|n41|n90" + elif [ $CHAN -eq 524000 ]; then + BAND="n7|n38|n41|n90" + elif [ $CHAN -lt 538000 ]; then + BAND="n7|n41|n90" + elif [ $CHAN -eq 538000 ]; then + BAND="n7|n90" + elif [ $CHAN -lt 620000 ]; then + BAND="-" + elif [ $CHAN -lt 636667 ]; then + BAND="n77|n78" + elif [ $CHAN -le 646666 ]; then + BAND="n48|n77|n78" + elif [ $CHAN -le 653333 ]; then + BAND="n77|n78" + elif [ $CHAN -le 680000 ]; then + BAND="n77" + elif [ $CHAN -lt 693334 ]; then + BAND="-" + elif [ $CHAN -le 733333 ]; then + BAND="n79" + elif [ $CHAN -lt 743333 ]; then + BAND="-" + elif [ $CHAN -lt 795000 ]; then + BAND="n46" + elif [ $CHAN -eq 795000 ]; then + BAND="n46|n96" + elif [ $CHAN -le 875000 ]; then + BAND="n96" + else + BAND="-" + fi +} + +if [ -z "$CHAN" ]; then + BAND="-" +elif [ "$CHAN" -lt 123400 ]; then + decode_lte +elif [ "$CHAN" -le 875000 ]; then + decode_nr5g +else + BAND="-" +fi +echo $BAND +exit diff --git a/rooter/ext-rooter-basic/files/usr/bin/encodemask b/rooter/ext-rooter-basic/files/usr/bin/encodemask new file mode 100644 index 0000000..6b3ed14 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/bin/encodemask @@ -0,0 +1,24 @@ +#!/usr/bin/lua + +mtab = {} +vtab = {1, 2, 4, 8} + +for i = 1, 32 do + mtab[i] = 0 +end + +numarg = #arg +for argval = 1, numarg do + band = arg[argval] + if tonumber(band) <= 128 then + idx = math.floor((band - 1) / 4) + 1 + idxr = 33 - idx + val = vtab[(band - ((idx - 1) * 4 ))] + mtab[idxr] = mtab[idxr] + val + end +end +for i = 1, 32 do + mtab[i] = string.format("%X", mtab[i]) +end + +print(table.concat(mtab)) diff --git a/rooter/ext-rooter-basic/files/usr/bin/jkillall b/rooter/ext-rooter-basic/files/usr/bin/jkillall new file mode 100644 index 0000000..3802082 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/bin/jkillall @@ -0,0 +1,9 @@ +#!/bin/sh +LOOKFOR=$1 +KILLLIST=$(ps | grep $LOOKFOR) +echo "$KILLLIST" | while read line; do + if `echo "$line" | grep "/$LOOKFOR" > /dev/null` ; then + PIDV=$(echo $line | grep -o "^[0-9]\{1,5\}" | grep -o "[0-9]\{1,5\}") + kill $PIDV + fi +done \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/bin/rsrp2rssi b/rooter/ext-rooter-basic/files/usr/bin/rsrp2rssi new file mode 100644 index 0000000..06ad5b6 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/bin/rsrp2rssi @@ -0,0 +1,21 @@ +#!/usr/bin/lua + +rsrp = tonumber(arg[1]) +bw = tonumber(arg[2]) +if bw == 1.4 then + n = 6 +else + n = bw * 5 +end + +if tonumber(string.match(_VERSION, "%d+%.%d")) > 5.1 then + rssi = rsrp + (10 * math.log(n * 12, 10)) +else + rssi = rsrp + (10 * math.log10(n * 12)) +end +if rssi < -113 then + rssi = -113 +elseif rssi > -51 then + rssi = -51 +end +print(math.floor(rssi)) diff --git a/rooter/ext-rooter-basic/files/usr/bin/set_gpio b/rooter/ext-rooter-basic/files/usr/bin/set_gpio new file mode 100644 index 0000000..5fddfa7 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/bin/set_gpio @@ -0,0 +1,18 @@ +#!/bin/sh + +PIN=$1 +VALUE=$2 + +PIN_FILE=/sys/class/gpio/gpio$PIN + +if [ -z "$PIN" -o -z "$VALUE" ]; then + exit 1 +fi + +echo $PIN >/sys/class/gpio/export + +if [ $(cat $PIN_FILE/direction) = "out" ]; then + echo $VALUE >$PIN_FILE/value +fi + +echo $PIN >/sys/class/gpio/unexport \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/custom/locktype.sh b/rooter/ext-rooter-basic/files/usr/lib/custom/locktype.sh new file mode 100644 index 0000000..8d7f879 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/custom/locktype.sh @@ -0,0 +1,22 @@ +#!/bin/sh + +CURRMODEM=$1 + +uVid=$(uci get modem.modem$CURRMODEM.uVid) +uPid=$(uci get modem.modem$CURRMODEM.uPid) + +if [ $uVid == "2c7c" ]; then + qc=$(uci get custom.atcmd.quectel) + echo "$qc" > /tmp/modemlock + echo " " >> /tmp/modemlock +else + if [ $uVid == "1199" ]; then + qc=$(uci get custom.atcmd.sierra) + echo "$qc" > /tmp/modemlock + echo " " >> /tmp/modemlock + else + qc=$(uci get custom.atcmd.generic) + echo "$qc" > /tmp/modemlock + echo " " >> /tmp/modemlock + fi +fi \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/custom/ttlx.sh b/rooter/ext-rooter-basic/files/usr/lib/custom/ttlx.sh new file mode 100644 index 0000000..79e52bd --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/custom/ttlx.sh @@ -0,0 +1,11 @@ +#!/bin/sh + +log() { + logger -t "TTL Hack" "$@" +} + +cp -f /etc/firewall.user /etc/firewall.user.bk +sed /"#startTTL"/,/"#endTTL"/d /etc/firewall.user.bk > /etc/firewall.user +rm -f /etc/firewall.user.bk +/etc/init.d/firewall restart 2> /dev/null + diff --git a/rooter/ext-rooter-basic/files/usr/lib/gps/smsreply.sh b/rooter/ext-rooter-basic/files/usr/lib/gps/smsreply.sh new file mode 100644 index 0000000..9ca9af7 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/gps/smsreply.sh @@ -0,0 +1,115 @@ +#!/bin/sh + +ROOTER=/usr/lib/rooter + +log() { + logger -t "GPS" "$@" +} + +CURRMODEM=$1 +SMSdest=$2 +MODTYPE=$(uci -q get modem.modem$CURRMODEM.modemtype) +if [ "$MODTYPE" == "2" -o "$MODTYPE" == "6" ]; then + COMMPORT="/dev/ttyUSB"$(uci -q get modem.modem$CURRMODEM.commport) +else + log "SMS position request from $SMSdest failed, modem $CURRMODEM is neither a Sierra nor Quectel" + exit +fi +GPSon=$(uci -q get gps.configuration.enabled) +if [ "$GPSon" != "1" -o $CURRMODEM == "2" ]; then + GPSon="0" + if [ $MODTYPE == "2" ]; then + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "AT!CUSTOM?") + GPSsel=$(echo $OX | grep "GPSSEL") + GPSenable=$(echo $OX | grep "GPSENABLE") + if [ -z "$GPSsel" -o -z "$GPSenable" ]; then + ATCMDD="AT!ENTERCND=\"A710\"" + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + if [ -z "$GPSsel" ]; then + ATCMDD="at!custom=\"GPSSEL\",1" + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + fi + if [ -z "$GPSenable" ]; then + ATCMDD="at!custom=\"GPSENABLE\",1" + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + ATCMDD="AT+CFUN=0;+CFUN=1,1" + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + sleep 30 + fi + ATCMDD="AT!ENTERCND=\"AWRONG\"" + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + fi + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "AT!GPSTRACK=1,240,30,1000,5") + GPSendcmd="AT!GPSEND=0" + else + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "AT+QGPS?") + err=$(echo "$OX" | grep "+QGPS: 1") + if [ -z "$err" ]; then + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "AT+QGPS=1") + fi + ATCMDD="AT+QCFG=\"gpsdrx\"" + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + err=$(echo "$OX" | grep "0") + if [ -n "$err" ]; then + ATCMDD="AT+QCFG=\"gpsdrx\",1" + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + fi + GPSendcmd="AT+QGPSEND" + fi +fi +SMStime=$(($(date +%s) + 120)) +LAT="" +LON="" +while true; do + if [ $MODTYPE == "2" ]; then + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "AT!GPSLOC?") + LATx=$(echo $OX | grep -o "Lat:[^(]\+([^)]\+" | grep -o "0x.\+") + LONx=$(echo $OX | grep -o "Lon:[^(]\+([^)]\+" | grep -o "0x.\+") + if [ -n "$LATx" -a -n "$LONx" ]; then + if [ $(printf "%d" $LATx) -gt $(printf "%d" 0x7FFFFFFF) ]; then + LATx=$(( ($LATx ^ 0xFFFFFFFF) + 1 )) + LAT="-"$(lua -e "print(string.format(\"%.5f\", $LATx * (180 / 2^25)))") + else + LAT=$(lua -e "print(string.format(\"%.5f\", $LATx * (180 / 2^25)))") + fi + if [ $(printf "%d" $LONx) -gt $(printf "%d" 0x7FFFFFFF) ]; then + LONx=$(( ($LONx ^ 0xFFFFFFFF) + 1 )) + LON="-"$(lua -e "print(string.format(\"%.5f\", $LONx * (180 / 2^25)))") + else + LON=$(lua -e "print(string.format(\"%.5f\", $LONx * (180 / 2^25)))") + fi + fi + else + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "AT+QGPSLOC=2") + LAT=$(echo $OX | grep -o "+QGPSLOC:[ .0-9]\+,.\+" | cut -d, -f2) + LON=$(echo $OX | grep -o "+QGPSLOC:[ .0-9]\+,.\+" | cut -d, -f3) + fi + if [ -n "$LAT" -a -n "$LON" ]; then + SMSMODEM=$(uci -q get modem.general.smsnum) + if [ "$CURRMODEM" != "$SMSMODEM" ]; then + uci set modem.general.smsnum=$CURRMODEM + uci commit modem.general.smsnum + fi + OY=$(/usr/lib/sms/smsout.sh "$SMSdest" "$LAT $LON") + OYsent=$(echo $OY | grep -o "SMS sent") + if [ -n "$OYsent" ]; then + /usr/lib/sms/sys2sms.sh "ROOter" "GPS coordinates sent to $SMSdest" + log "GPS coordinates sent to $SMSdest" + else + log "Failed to send GPS coordinates sent to $SMSdest" + fi + if [ "$CURRMODEM" != "$SMSMODEM" ]; then + uci set modem.general.smsnum=$SMSMODEM + uci commit modem.general.smsnum + fi + break + fi + if [ $(date +%s) -gt $SMStime ]; then + log "Failed request from $SMSdest by SMS for LAT/LON, position not available" + break + fi + sleep 8 +done +if [ "$GPSon" != "1" ]; then + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$GPSendcmd") +fi diff --git a/rooter/ext-rooter-basic/files/usr/lib/lua/luci/controller/admin/modem.lua b/rooter/ext-rooter-basic/files/usr/lib/lua/luci/controller/admin/modem.lua new file mode 100644 index 0000000..ae033c6 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/lua/luci/controller/admin/modem.lua @@ -0,0 +1,664 @@ +module("luci.controller.admin.modem", package.seeall) + +I18N = require "luci.i18n" +translate = I18N.translate + +function index() + entry({"admin", "modem"}, firstchild(), translate("移动数据"), 25).dependent=false + entry({"admin", "modem", "prof"}, cbi("rooter/profiles"), translate("DNS / APN / 监控配置"), 2) + entry({"admin", "modem", "nets"}, template("rooter/net_status"), translate("信号状态 / 模块状态"), 30) + entry({"admin", "modem", "debug"}, template("rooter/debug"), translate("后台AT调试信息"), 50) + entry({"admin", "modem", "cust"}, cbi("rooter/customize"), translate("自定义模块端口配置"), 55) + entry({"admin", "modem", "log"}, template("rooter/log"), translate("连接日志"), 60) + entry({"admin", "modem", "misc"}, template("rooter/misc"), translate("锁频段 / 锁PCI / 切协议"), 40) + + entry({"admin", "modem", "block"}, + template("rooter/bandlock")) + + entry({"admin", "modem", "get_csq"}, call("action_get_csq")) + entry({"admin", "modem", "change_port"}, call("action_change_port")) + entry({"admin", "modem", "change_mode"}, call("action_change_mode")) + entry({"admin", "modem", "change_modem"}, call("action_change_modem")) + entry({"admin", "modem", "change_modemdn"}, call("action_change_modemdn")) + entry({"admin", "modem", "change_misc"}, call("action_change_misc")) + entry({"admin", "modem", "change_miscdn"}, call("action_change_miscdn")) + entry({"admin", "modem", "get_log"}, call("action_get_log")) + entry({"admin", "modem", "check_misc"}, call("action_check_misc")) + entry({"admin", "modem", "pwrtoggle"}, call("action_pwrtoggle")) + entry({"admin", "modem", "disconnect"}, call("action_disconnect")) + entry({"admin", "modem", "connect"}, call("action_connect")) + entry({"admin", "modem", "get_atlog"}, call("action_get_atlog")) + entry({"admin", "modem", "send_atcmd"}, call("action_send_atcmd")) + entry({"admin", "modem", "change_rate"}, call("action_change_rate")) + entry({"admin", "modem", "change_phone"}, call("action_change_phone")) + entry({"admin", "modem", "clear_log"}, call("action_clear_log")) + entry({"admin", "modem", "externalip"}, call("action_externalip")) + entry({"admin", "modem", "send_scancmd"}, call("action_send_scancmd")) + entry({"admin", "modem", "send_lockcmd"}, call("action_send_lockcmd")) + entry({"admin", "modem", "extping"}, call("action_extping")) + entry({"admin", "modem", "change_cell"}, call("action_change_cell")) + entry({"admin", "modem", "change_proto"}, call("action_change_proto")) + entry({"admin", "modem", "setpin"}, call("action_setpin")) +end + +function trim(s) + return (s:gsub("^%s*(.-)%s*$", "%1")) +end + +function action_get_atlog() + local file + local rv ={} + + file = io.open("/tmp/atlog", "r") + if file ~= nil then + local tmp = file:read("*all") + rv["log"] = tmp + file:close() + else + rv["log"] = "No entries in log file" + end + + luci.http.prepare_content("application/json") + luci.http.write_json(rv) +end + +function action_get_log() + local file + local rv ={} + + file = io.open("/usr/lib/rooter/log/connect.log", "r") + if file ~= nil then + local tmp = file:read("*all") + rv["log"] = tmp + file:close() + else + rv["log"] = translate("No entries in log file") + end + + luci.http.prepare_content("application/json") + luci.http.write_json(rv) +end + +function action_disconnect() + local set = luci.http.formvalue("set") + os.execute("/usr/lib/rooter/connect/disconnect.sh") +end + +function action_connect() + local set = luci.http.formvalue("set") + miscnum = luci.model.uci.cursor():get("modem", "general", "miscnum") + os.execute("/tmp/links/reconnect" .. miscnum .. " " .. miscnum) +end + +function action_pwrtoggle() + local set = luci.http.formvalue("set") + os.execute("/usr/lib/rooter/pwrtoggle.sh " .. set) +end + +function action_send_atcmd() + local rv ={} + modnum = luci.model.uci.cursor():get("modem", "general", "miscnum") + local file + local set = luci.http.formvalue("set") + fixed = string.gsub(set, "\"", "~") + os.execute("/usr/lib/rooter/luci/atcmd.sh \'" .. fixed .. "\'") + + result = "/tmp/result" .. modnum .. ".at" + file = io.open(result, "r") + if file ~= nil then + rv["result"] = file:read("*all") + file:close() + os.execute("/usr/lib/rooter/luci/luaops.sh delete /tmp/result" .. modnum .. ".at") + else + rv["result"] = " " + end + + luci.http.prepare_content("application/json") + luci.http.write_json(rv) +end + +function action_check_misc() + local rv ={} + local bnd1 = {} + local bnd2 = {} + local bnd31 = {} + local bnd32 = {} + local bnd33 = {} + local at1 = {} + local at2 = {} + local file + local file1 + local active + local connect + + miscnum = luci.model.uci.cursor():get("modem", "general", "miscnum") + conn = "Modem #" .. miscnum + rv["conntype"] = conn + empty = luci.model.uci.cursor():get("modem", "modem" .. miscnum, "empty") + if empty == "1" then + active = "0" + rv["netmode"] = "-" + else + active = luci.model.uci.cursor():get("modem", "modem" .. miscnum, "active") + if active == "1" then + connect = luci.model.uci.cursor():get("modem", "modem" .. miscnum, "connected") + if connect == "0" then + active = "1" + else + active = "2" + end + uVid = luci.model.uci.cursor():get("modem", "modem" .. miscnum, "uVid") + rv["uVid"] = uVid + uPid = luci.model.uci.cursor():get("modem", "modem" .. miscnum, "uPid") + rv["uPid"] = uPid + file = io.open("/etc/fake", "r") + if file == nil then + rv["fake"] = "0" + else + rv["fake"] = "1" + file:close() + end + + rv["cenable"] = luci.model.uci.cursor():get("custom", "bandlock", "cenable" .. miscnum) + if rv["cenable"] == nil then + rv["cenable"] = "0" + end + rv["earfcn"] = luci.model.uci.cursor():get("custom", "bandlock", "earfcn" .. miscnum) + if rv["earfcn"] == nil then + rv["earfcn"] = "0" + end + rv["pci"] = luci.model.uci.cursor():get("custom", "bandlock", "pci" .. miscnum) + if rv["pci"] == nil then + rv["pci"] = "0" + end + + rv["earfcn1"] = luci.model.uci.cursor():get("custom", "bandlock", "earfcn1" .. miscnum) + if rv["earfcn1"] == nil then + rv["earfcn1"] = "0" + end + rv["pci1"] = luci.model.uci.cursor():get("custom", "bandlock", "pci1" .. miscnum) + if rv["pci1"] == nil then + rv["pci1"] = "0" + end + + rv["earfcn2"] = luci.model.uci.cursor():get("custom", "bandlock", "earfcn2" .. miscnum) + if rv["earfcn2"] == nil then + rv["earfcn2"] = "0" + end + rv["pci2"] = luci.model.uci.cursor():get("custom", "bandlock", "pci2" .. miscnum) + if rv["pci2"] == nil then + rv["pci2"] = "0" + end + + rv["earfcn3"] = luci.model.uci.cursor():get("custom", "bandlock", "earfcn3" .. miscnum) + if rv["earfcn3"] == nil then + rv["earfcn3"] = "0" + end + rv["pci3"] = luci.model.uci.cursor():get("custom", "bandlock", "pci3" .. miscnum) + if rv["pci3"] == nil then + rv["pci3"] = "0" + end + + file = io.open("/tmp/bmask", "r") + if file == nil then + rv["bndstr"] = "0" + rv["bndsup"] = "0" + else + line = file:read("*line") + rv["bndstr"] = line + line = file:read("*line") + rv["bndstr5g"] = line + line = file:read("*line") + rv["bndstr5gsa"] = line + line = file:read("*line") + rv["bndsup"] = line + line = file:read("*line") + rv["bndsup5g"] = line + line = file:read("*line") + rv["bndsup5gsa"] = line + line = file:read("*line") + ca = line + if ca ~= nil then + line = file:read("*line") + ca3 = line + end + file:close() + + indx = 0 + if ca ~= nil then + file = io.open("/usr/lib/rooter/luci/" .. ca, "r") + if file ~= nil then + line = file:read("*line") + repeat + s, e = line:find(" ") + b1 = trim(line:sub(1, s-1)) + bnd1[indx] = b1 + b2 = trim(line:sub(s+1)) + bnd2[indx] = b2 + indx = indx +1 + line = file:read("*line") + until line == nil + file:close() + end + end + rv['b1'] = bnd1 + rv['b2'] = bnd2 + rv['indx'] = tostring(indx) + + indx3 = 0 + if ca3 ~= nil then + file = io.open("/usr/lib/rooter/luci/" .. ca3, "r") + if file ~= nil then + line = file:read("*line") + repeat + s, e = line:find(" ") + b1 = trim(line:sub(1, s-1)) + bnd31[indx3] = b1 + cs, ce = line:find(" ", s+1) + b2 = trim(line:sub(s+1, cs-1)) + bnd32[indx3] = b2 + b3 = trim(line:sub(cs+1)) + bnd33[indx3] = b3 + indx3 = indx3 +1 + line = file:read("*line") + until line == nil + file:close() + end + end + rv['b31'] = bnd31 + rv['b32'] = bnd32 + rv['b33'] = bnd33 + rv['indx3'] = tostring(indx3) + + end + end + netmode = luci.model.uci.cursor():get("modem", "modem" .. miscnum, "netmode") + rv["netmode"] = netmode + end + rv["pin"] = luci.model.uci.cursor():get("modem", "general", "pin") + rv["plock"] = luci.model.uci.cursor():get("custom", "atcmd", "lock") + if rv["plock"] == "1" then + rv["atlock"] = luci.model.uci.cursor():get("custom", "menu", "full") + generic = luci.model.uci.cursor():get("custom", "atcmd", "generic") + aindx = 0 + if active == "0" then + file = io.open(generic, "r") + else + os.execute("/usr/lib/custom/locktype.sh " .. miscnum ) + file1 = io.open("/tmp/modemlock", "r") + if file1 ~= nil then + linex = file1:read("*line") + file1:close() + file = io.open(linex, "r") + else + file = io.open(generic, "r") + end + end + if file ~= nil then + line = file:read("*line") + repeat + at1[aindx] = line + line = file:read("*line") + at2[aindx] = line + aindx = aindx +1 + line = file:read("*line") + until line == nil + file:close() + rv['at1'] = at1 + rv['at2'] = at2 + rv['aindx'] = tostring(aindx) + end + end + rv["active"] = active + file = io.open("/tmp/gpiopin", "r") + if file == nil then + rv.gpio = "0" + else + rv.gpio = "1" + line = file:read("*line") + line = file:read("*line") + if line ~= nil then + rv.gpio = "2" + end + file:close() + end + file = io.open("/sys/bus/usb/drivers/usb/usb1", "r") + if file == nil then + rv["usb"] = "0" + else + io.close(file) + rv["usb"] = "1" + end + file = io.open("/sys/bus/usb/drivers/usb/usb2", "r") + if file ~= nill then + io.close(file) + rv["usb"] = "2" + end + proto = luci.model.uci.cursor():get("modem", "modem" .. miscnum, "proto") + rv["proto"] = proto + + model = luci.model.uci.cursor():get("modem", "modem" .. miscnum, "model") + rv["model"] = model + + celltype = luci.model.uci.cursor():get("modem", "modem" .. miscnum, "celltype") + rv["celltype"] = celltype + cmode = luci.model.uci.cursor():get("modem", "modem" .. miscnum, "cmode") + if cmode == "0" then + rv["netmode"] = "10" + end + + luci.http.prepare_content("application/json") + luci.http.write_json(rv) +end + +function lshift(x, by) + return x * 2 ^ by +end + +function rshift(x, by) + return math.floor(x / 2 ^ by) +end + +function action_change_mode() + local set = tonumber(luci.http.formvalue("set")) + local modemtype = rshift(set, 4) + local temp = lshift(modemtype, 4) + local netmode = set - temp + os.execute("/usr/lib/rooter/luci/modechge.sh " .. modemtype .. " " .. netmode) +end + +function action_change_port() + local set = tonumber(luci.http.formvalue("set")) + if set ~= nil and set > 0 then + if set == 1 then + os.execute("/usr/lib/rooter/luci/portchge.sh dwn") + else + os.execute("/usr/lib/rooter/luci/portchge.sh up") + end + end +end + +function action_change_misc() + os.execute("/usr/lib/rooter/luci/modemchge.sh misc 1") +end + +function action_change_miscdn() + os.execute("/usr/lib/rooter/luci/modemchge.sh misc 0") +end + +function action_change_modem() + os.execute("/usr/lib/rooter/luci/modemchge.sh modem 1") +end + +function action_change_modemdn() + os.execute("/usr/lib/rooter/luci/modemchge.sh modem 0") +end + +function action_get_csq() + modnum = luci.model.uci.cursor():get("modem", "general", "modemnum") + local file + stat = "/tmp/status" .. modnum .. ".file" + file = io.open(stat, "r") + + local rv ={} + + rv["port"] = file:read("*line") + rv["csq"] = file:read("*line") + rv["per"] = file:read("*line") + rv["rssi"] = file:read("*line") + rv["modem"] = file:read("*line") + rv["cops"] = file:read("*line") + rv["mode"] = file:read("*line") + rv["lac"] = file:read("*line") + rv["lacn"] = file:read("*line") + rv["cid"] = file:read("*line") + rv["cidn"] = file:read("*line") + rv["mcc"] = file:read("*line") + rv["mnc"] = file:read("*line") + rv["rnc"] = file:read("*line") + rv["rncn"] = file:read("*line") + rv["down"] = file:read("*line") + rv["up"] = file:read("*line") + rv["ecio"] = file:read("*line") + rv["rscp"] = file:read("*line") + rv["ecio1"] = file:read("*line") + rv["rscp1"] = file:read("*line") + rv["netmode"] = file:read("*line") + rv["cell"] = file:read("*line") + rv["modtype"] = file:read("*line") + rv["conntype"] = file:read("*line") + rv["channel"] = file:read("*line") + rv["phone"] = file:read("*line") + file:read("*line") + rv["lband"] = file:read("*line") + rv["tempur"] = file:read("*line") + rv["proto"] = file:read("*line") + rv["pci"] = file:read("*line") + rv["sinr"] = file:read("*line") + --rv["lat"] = file:read("*line") + --rv["long"] = file:read("*line") + + file:close() + + cmode = luci.model.uci.cursor():get("modem", "modem" .. modnum, "cmode") + if cmode == "0" then + rv["netmode"] = "10" + end + + rssi = rv["rssi"] + ecio = rv["ecio"] + rscp = rv["rscp"] + ecio1 = rv["ecio1"] + rscp1 = rv["rscp1"] + + if ecio == nil then + ecio = "-" + end + if ecio1 == nil then + ecio1 = "-" + end + if rscp == nil then + rscp = "-" + end + if rscp1 == nil then + rscp1 = "-" + end + + if ecio ~= "-" then + rv["ecio"] = ecio .. " dB" + end + if rscp ~= "-" then + rv["rscp"] = rscp .. " dBm" + end + if ecio1 ~= " " then + rv["ecio1"] = " (" .. ecio1 .. " dB)" + end + if rscp1 ~= " " then + rv["rscp1"] = " (" .. rscp1 .. " dBm)" + end + + if not nixio.fs.access("/etc/netspeed") then + rv["crate"] = translate("快速(每10秒更新一次)") + else + rv["crate"] = translate("缓慢(每60秒更新一次)") + end + + stat = "/tmp/msimdata" .. modnum + file = io.open(stat, "r") + if file == nil then + rv["modid"] = " " + rv["imei"] = " " + rv["imsi"] = " " + rv["iccid"] = " " + rv["host"] = "0" + else + rv["modid"] = file:read("*line") + rv["imei"] = file:read("*line") + rv["imsi"] = file:read("*line") + rv["iccid"] = file:read("*line") + rv["host"] = file:read("*line") + file:close() + end + + gpsdata = "/tmp/gpsdata1" + file = io.open(gpsdata, "r") + if file == nil then + rv["lat"] = "-" + rv["long"] = "-" + else + rv["lat"] = file:read("*line") + rv["long"] = file:read("*line") + file:close() + end + + stat = "/tmp/msimnum" .. modnum + file = io.open(stat, "r") + if file == nil then + rv["phone"] = "-" + rv["phonen"] = " " + else + rv["phone"] = file:read("*line") + rv["phonen"] = file:read("*line") + file:close() + end + + stat = "/tmp/simpin" .. modnum + file = io.open(stat, "r") + if file == nil then + rv["simerr"] = "0" + else + typ = file:read("*line") + if typ == "0" then + rv["simerr"] = "1" + else + if typ == "1" then + rv["simerr"] = "2" + else + if typ == "2" then + rv["simerr"] = "3" + else + rv["simerr"] = "4" + end + end + end + file:close() + end + + luci.http.prepare_content("application/json") + luci.http.write_json(rv) +end + +function action_change_rate() + local set = luci.http.formvalue("set") + if set == "1" then + os.execute("rm -f /etc/netspeed") + else + os.execute("echo \"0\" > /etc/netspeed") + end +end + +function action_change_phone() + local set = luci.http.formvalue("set") + s, e = string.find(set, "|") + pno = string.sub(set, 1, s-1) + pnon = string.sub(set, e+1) + modnum = luci.model.uci.cursor():get("modem", "general", "modemnum") + os.execute("/usr/lib/rooter/common/phone.sh " .. modnum .. " " .. pno .. " \"" .. pnon .. "\"") +end + +function action_clear_log() + local file + file = io.open("/usr/lib/rooter/log/connect.log", "w") + file:close() + os.execute("/usr/lib/rooter/log/logger 'Connection Log Cleared by User'") +end + +function action_externalip() + local rv ={} + + os.execute("rm -f /tmp/ipip; wget -O /tmp/ipip http://ipecho.net/plain > /dev/null 2>&1") + file = io.open("/tmp/ipip", "r") + if file == nil then + rv["extip"] = translate("Not Available") + else + rv["extip"] = file:read("*line") + if rv["extip"] == nil then + rv["extip"] = translate("Not Available") + end + file:close() + end + + luci.http.prepare_content("application/json") + luci.http.write_json(rv) +end + +function action_send_scancmd() + local rv ={} + local file + os.execute("/usr/lib/rooter/luci/scancmd.sh") + + result = "/tmp/scan" + file = io.open(result, "r") + if file ~= nil then + rv["result"] = file:read("*all") + file:close() + os.execute("/usr/lib/rooter/luci/luaops.sh delete /tmp/scan") + else + rv["result"] = " " + end + + luci.http.prepare_content("application/json") + luci.http.write_json(rv) +end + +function action_send_lockcmd() + local set = luci.http.formvalue("set") + os.execute("/usr/lib/rooter/luci/lock.sh " .. set) +end + +function action_extping() + local rv ={} + + enable = luci.model.uci.cursor():get("ping", "ping", "enable") + if enable == "0" then + rv["extping"] = translate("Not Enabled") + else + conn = luci.model.uci.cursor():get("ping", "ping", "conn") + if conn == "1" then + rv["extping"] = translate("Enabled, Waiting for Modem to Connect") + else + if conn == "2" then + rv["extping"] = translate("Enabled, Ping Test was Good") + else + if conn == "3" then + rv["extping"] = translate("Enabled, Ping Test Failed, Restarting Modem, Waiting for Reconnection") + else + if conn == "4" then + rv["extping"] = translate("Enabled, Connected, Waiting for Ping Test") + else + rv["extping"] = translate("Enabled, Unknown State") + end + end + end + end + end + + luci.http.prepare_content("application/json") + luci.http.write_json(rv) +end + +function action_change_cell() + local set = luci.http.formvalue("set") + os.execute("/usr/lib/rooter/luci/setcell.sh " .. "\"" .. set .. "\"") +end + +function action_change_proto() + local set = luci.http.formvalue("set") + os.execute("/usr/lib/rooter/luci/protochnge.sh " ..set) +end + +function action_setpin() + local set = luci.http.formvalue("set") + os.execute("uci set modem.general.pin=" .. set .. "; uci commit modem") +end + diff --git a/rooter/ext-rooter-basic/files/usr/lib/lua/luci/controller/modlog.lua b/rooter/ext-rooter-basic/files/usr/lib/lua/luci/controller/modlog.lua new file mode 100644 index 0000000..b37f797 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/lua/luci/controller/modlog.lua @@ -0,0 +1,29 @@ +module("luci.controller.modlog", package.seeall) + +I18N = require "luci.i18n" +translate = I18N.translate + +function index() + local page + page = entry({"admin", "modem", "modlog"}, template("modlog/modlog"), _(translate("模块连接日志信息")), 61) + page.dependent = true + + entry({"admin", "status", "modlog"}, call("action_modlog")) +end + +function action_modlog() + local file + local rv ={} + + file = io.open("/tmp/modlog.log", "r") + if file ~= nil then + local tmp = file:read("*all") + rv["log"] = tmp + file:close() + else + rv["log"] = translate("No entries in log file") + end + + luci.http.prepare_content("application/json") + luci.http.write_json(rv) +end diff --git a/rooter/ext-rooter-basic/files/usr/lib/lua/luci/controller/poweroff.lua b/rooter/ext-rooter-basic/files/usr/lib/lua/luci/controller/poweroff.lua new file mode 100644 index 0000000..62918f2 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/lua/luci/controller/poweroff.lua @@ -0,0 +1,16 @@ +module("luci.controller.poweroff", package.seeall) + +I18N = require "luci.i18n" +translate = I18N.translate + +function index() + local page + page = entry({"admin", "system", "poweroff"}, template("admin_system/poweroff"), _(translate("System Stop")), 95) + entry({"admin", "system", "do_poweroff"}, call("action_poweroff")) + page.dependent = true +end + +function action_poweroff() + local set = luci.http.formvalue("set") + os.execute("/usr/lib/rooter/shutall.sh") +end diff --git a/rooter/ext-rooter-basic/files/usr/lib/lua/luci/controller/profile.lua b/rooter/ext-rooter-basic/files/usr/lib/lua/luci/controller/profile.lua new file mode 100644 index 0000000..fce9b46 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/lua/luci/controller/profile.lua @@ -0,0 +1,40 @@ +module("luci.controller.profile", package.seeall) +function index() + entry({"admin", "profile", "savecfg"}, call("action_savecfg")) + entry({"admin", "profile", "loadcfg"}, call("action_loadcfg")) + entry({"admin", "profile", "loadcfg1"}, call("action_loadcfg1")) + entry({"admin", "profile", "loadcfg2"}, call("action_loadcfg2")) +end + +function action_savecfg() + os.execute('/usr/lib/profile/savecfg.sh') +end + +function action_loadcfg() + local set = luci.http.formvalue("set") + local set1 = luci.http.formvalue("set1") + local tfile = io.open("/tmp/profilename", "w") + tfile:write(set, "\n") + if set1 ~= "~~" then + tfile:write(set1, "\n") + end + tfile:close() + os.execute("/usr/lib/profile/loadcfg.sh") +end + +function action_loadcfg1() + local set = luci.http.formvalue("set") + local tfile = io.open("/tmp/profilename", "w") + tfile:write(set) + tfile:close() +end + +function action_loadcfg2() + local set1 = luci.http.formvalue("set1") + if set1 ~= "~~" then + local tfile = io.open("/tmp/profilename", "a") + tfile:write(set1) + tfile:close() + end + os.execute("/usr/lib/profile/loadcfg.sh") +end \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/lua/luci/model/cbi/firewall/ttlx.lua b/rooter/ext-rooter-basic/files/usr/lib/lua/luci/model/cbi/firewall/ttlx.lua new file mode 100644 index 0000000..dcecccb --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/lua/luci/model/cbi/firewall/ttlx.lua @@ -0,0 +1,30 @@ +local utl = require "luci.util" +local uci = require "luci.model.uci".cursor() + +m = Map("ttl", translate("Firewall - Custom TTL Settings"), + translate("Enable and use a custom TTL value with modems")) + +m.on_after_save = function(self) + --luci.sys.call("/usr/lib/custom/ttlx.sh &") +end + +gw = m:section(TypedSection, translate("ttl"), translate("Settings")) +gw.anonymous = true + +en = gw:option(Flag, "enabled", translate("Enabled :"), translate("Enable the use of custom TTL value")); +en.default="0" +en.rmempty = false; +en.optional=false; + +val = gw:option(ListValue, "value", translate("TTL Value :"), translate("Custom TTL value to be used on modems")); +val.default="65" +val:depends("enabled", "1") +val:value("63", "63") +val:value("64", "64") +val:value("65", "65") +val:value("66", "66") +val:value("67", "67") +val:value("117", "117") +val:value("0", "TTL-INC 1") + +return m \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/lua/luci/model/cbi/rooter/customize.lua b/rooter/ext-rooter-basic/files/usr/lib/lua/luci/model/cbi/rooter/customize.lua new file mode 100644 index 0000000..acc7eb5 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/lua/luci/model/cbi/rooter/customize.lua @@ -0,0 +1,156 @@ +local utl = require "luci.util" + +local modemfile = "/etc/config/modem.data" +local modemdata = {} +local count +local tabdata = {} + +function process_line(xline, cnt) + local data = {} + local pline = xline + local start = 1 + for i=1,3 do + s, e = string.find(pline, " ") + data[i] = string.sub(pline, start, s-1) + pline = string.sub(pline, e+1) + end + data[4] = pline + modemdata[cnt] = data +end + +function read_modem() + count = 0 + local file = io.open(modemfile, "r") + if file == nil then + return + end + repeat + local line = file:read("*line") + if line == nil then + break + end + if string.len(line) < 5 then + break + end + count = count + 1 + process_line(line, count) + until 1==0 + file:close() +end + +function insert_modem() + local location = count + 1 + + if count > 0 then + for j=1,count do + local mdata = modemdata[j] + if mdata[1] == tabdata[1] and mdata[2] == tabdata[2] then + location = j + end + end + end + + if count == 0 then + count = 1 + else + if location > count then + count = count + 1 + end + end + modemdata[location] = tabdata +end + +function write_modem() + os.remove(modemfile) + local file = io.open(modemfile, "w") + for k=1,count do + local mdata = modemdata[k] + for l=1,3 do + file:write(mdata[l], " ") + end + file:write(mdata[4], "\n") + end + file:close() +end + +function process_tabdata() + if tabdata[1] ~= "nil" and tabdata[2] ~= "nil" then + read_modem() + insert_modem() + write_modem() + end +end + +m = Map("modem", translate("自定义4G/5G 模块支持"), translate(" 修改某个模块使用的通信端口")) + +m.on_after_commit = function(self) + -- all written config names are in self.parsechain + local sobj + for _, sobj in ipairs(self.children) do + local sids + if utl.instanceof(sobj, NamedSection) then + sids = { sobj.section } + elseif utl.instanceof(sobj, TypedSection) then + sids = sobj:cfgsections() + end + local sid, fld, fln + + if not utl.instanceof(sobj, SimpleSection) then + for _, sid in ipairs(sids) do + for fln, fld in ipairs(sobj.children) do + local val = fld:formvalue(sid) + if val == nil or string.len(val) == 0 then + val = "nil" + end + tabdata[fln] = val + end + end + end + end + process_tabdata() +end + +-- +-- Vid Pid Dataport Commport +-- + +e = m:section(TypedSection, "new", translate("模块端口 :")) + +a1 = e:option(Value, "vid", translate("模块 VID:")); +a1.optional=false; + +b1 = e:option(Value, "pid", translate("模块 ID :")); +b1.optional=false; + +p3 = e:option(ListValue, "port", translate("PPP 拨号端口 :")) +p3:value("tty", "default") +p3:value("tty0", "/dev/ttyUSB0") +p3:value("tty1", "/dev/ttyUSB1") +p3:value("tty2", "/dev/ttyUSB2") +p3:value("tty3", "/dev/ttyUSB3") +p3:value("tty4", "/dev/ttyUSB4") +p3:value("tty5", "/dev/ttyUSB5") +p3.default = "tty" + +p4 = e:option(ListValue, "comm", translate("通讯端口 :")) +p4:value("tty", "default") +p4:value("tty0", "/dev/ttyUSB0") +p4:value("tty1", "/dev/ttyUSB1") +p4:value("tty2", "/dev/ttyUSB2") +p4:value("tty3", "/dev/ttyUSB3") +p4:value("tty4", "/dev/ttyUSB4") +p4:value("tty5", "/dev/ttyUSB5") +p4.default = "tty" + +b3 = e:option(DummyValue, "blank", " "); + +btn = e:option(Button, "_btn", translate(" ")) +btn.inputtitle = translate("删除模块端口配置") +btn.inputstyle = "apply" +function btn.write() + luci.sys.call("/usr/lib/rooter/luci/luaops.sh delete /etc/config/modem.data") +end + +m:section(SimpleSection).template = "rooter/custom" + +return m diff --git a/rooter/ext-rooter-basic/files/usr/lib/lua/luci/model/cbi/rooter/profiles.lua b/rooter/ext-rooter-basic/files/usr/lib/lua/luci/model/cbi/rooter/profiles.lua new file mode 100644 index 0000000..89789eb --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/lua/luci/model/cbi/rooter/profiles.lua @@ -0,0 +1,828 @@ +local utl = require "luci.util" +local uci = require "luci.model.uci".cursor() +local sys = require "luci.sys" +local fs = require "nixio.fs" + +local maxmodem = luci.model.uci.cursor():get("modem", "general", "max") +local profsave = luci.model.uci.cursor():get("custom", "profile", "save") +if profsave == nil then + profsave ="0" +end +local multilock = luci.model.uci.cursor():get("custom", "multiuser", "multi") or "0" +local rootlock = luci.model.uci.cursor():get("custom", "multiuser", "root") or "0" + +m = Map("profile", translate("模块DNS / APN 配置"),translate("")) + +m.on_after_commit = function(self) + if profsave == "1" then + luci.sys.call("/usr/lib/profile/restart.sh &") + end +end + +if profsave == "1" then + m:section(SimpleSection).template = "rooter/profile" + ds = m:section(TypedSection, "simpin", translate("SIM卡Pin码 :"), translate("如果配置文件钟没有SIM PIN码则使用")) + ds.anonymous = true + + ms = ds:option(Value, "pin", translate("PIN :")); + ms.rmempty = true; + ms.default = "" +end + + +-- +-- Default profile +-- + +di = m:section(TypedSection, "default", translate("默认"), translate("一般只需要填写您运营商的APN即可,一般已经自动加载识别了,奇葩虚拟运营商你也可以继续填 Tips:模块下次重连后生效,如果你要现在生效,请保存后重启模块)## 华为天际通5G SA APN:5gscuiot ##")) +di.anonymous = true +di:tab("default", translate("通用")) +di:tab("advance", translate("高级")) +di:tab("connect", translate("连接状态监控")) +if (multilock == "0") or (multilock == "1" and rootlock == "1") then + di:tab("bwidth", translate("Bandwidth Reporting频宽报告")) +end + +this_tab = "default" + +ma = di:taboption(this_tab, Value, "apn", "APN :"); +ma.rmempty = true; +ma.default = "broadband" + +tt = di:taboption(this_tab, ListValue, "ttl", translate("设定TTL值 :")) +tt:value("0", translate("使用当前值")) +tt:value("1", translate("不配置TTL值")) +tt:value("63", "TTL 63") +tt:value("64", "TTL 64") +tt:value("65", "TTL 65") +tt:value("66", "TTL 66") +tt:value("67", "TTL 67") +tt:value("117", "TTL 117") +tt:value("TTL-INC 1", "TTL-INC 1") +tt.default = "0" + +ynl = di:taboption(this_tab, ListValue, "hostless", translate("设定通信模块TTL")); +ynl:value("0", "否") +ynl:value("1", translate("是")) +ynl.default=0 + +pt = di:taboption(this_tab, ListValue, "pdptype", translate("IP协议类型 :")) +pt:value("IP", "IPv4") +pt:value("IPV6", "IPv6") +pt:value("IPV4V6", "IPv4+IPv6") +pt:value("0", "默认") +pt.default = "0" + +cmcc = di:taboption(this_tab, Value, "context", translate("PDP Context for APN :")); +cmcc.optional=false; +cmcc.rmempty = true; +cmcc.datatype = "and(uinteger,min(1),max(10))" +cmcc.default = "1" + +mu = di:taboption(this_tab, Value, "user", translate("用户名 :")); +mu.optional=false; +mu.rmempty = true; + +mp = di:taboption(this_tab, Value, "passw", translate("密码 :")); +mp.optional=false; +mp.rmempty = true; +mp.password = true + +mpi = di:taboption(this_tab, Value, "pincode", translate("PIN码 :")); +mpi.optional=false; +mpi.rmempty = true; + +mau = di:taboption(this_tab, ListValue, "auth", translate("身份验证类型 :")) +mau:value("0", "None") +mau:value("1", "PAP") +mau:value("2", "CHAP") +mau.default = "0" + +mtz = di:taboption(this_tab, ListValue, "tzone", translate("自动设置时区"), translate("Tips:就是模块通网后会自动设置时区")); +mtz:value("0", "窝不要") +mtz:value("1", translate("窝要")) +mtz.default=1 + +ml = di:taboption(this_tab, ListValue, "lock", translate("阻止国际漫游选项并锁定特定运营商 :")); +ml:value("0", translate("否")) +ml:value("1", translate("强硬")) +ml:value("2", translate("软弱")) +ml.default=0 + +mcc = di:taboption(this_tab, Value, "mcc", translate("MCC :")); +mcc.optional=false; +mcc.rmempty = true; +mcc.datatype = "and(uinteger,min(1),max(999))" +mcc:depends("lock", "1") +mcc:depends("lock", "2") + +mnc = di:taboption(this_tab, Value, "mnc", translate("MNC :")); +mnc.optional=false; +mnc.rmempty = true; +mnc.datatype = "and(uinteger,min(1),max(999))" +mnc:depends("lock", "1") +mnc:depends("lock", "2") + +this_taba = "advance" + +mf = di:taboption(this_taba, ListValue, "ppp", translate("不使用常规协议,强制使用PPP拨号协议 :")); +mf:value("0", translate("启用")) +mf:value("1", translate("禁用")) +mf.default=0 + +md = di:taboption(this_taba, Value, "delay", translate("连接延时(秒为单位) :")); +md.optional=false; +md.rmempty = false; +md.default = 5 +md.datatype = "and(uinteger,min(5))" + +nl = di:taboption(this_taba, ListValue, "nodhcp", translate("强制QMI协议不使用模块的DHCP,从其他位置获取 :")); +nl:value("0", translate("禁用")) +nl:value("1", translate("启用")) +nl.default=0 + +mdns1 = di:taboption(this_taba, Value, "dns1", translate("自定义DNS 1 :")); +mdns1.rmempty = true; +mdns1.optional=false; +mdns1.datatype = "ipaddr" + +mdns2 = di:taboption(this_taba, Value, "dns2", translate("自定义DNS 2 :")); +mdns2.rmempty = true; +mdns2.optional=false; +mdns2.datatype = "ipaddr" + +mdns3 = di:taboption(this_taba, Value, "dns3", translate("自定义DNS 3 :")); +mdns3.rmempty = true; +mdns3.optional=false; +mdns3.datatype = "ipaddr" + +mdns4 = di:taboption(this_taba, Value, "dns4", translate("自定义DNS 4 :")); +mdns4.rmempty = true; +mdns4.optional=false; +mdns4.datatype = "ipaddr" + + +mlog = di:taboption(this_taba, ListValue, "log", translate("启用AT连接日志 :")); +mlog:value("0", translate("禁用")) +mlog:value("1", translate("是")) +mlog.default=0 + +if nixio.fs.access("/etc/config/mwan3") then + mlb = di:taboption(this_taba, ListValue, "lb", translate("在多个5G模块中开启流量负载均衡 :")); + mlb:value("0", translate("禁用")) + mlb:value("1", translate("启用")) + mlb.default=0 +end + +mtu = di:taboption(this_taba, Value, "mtu", translate("自定义MTU值 :"), + translate("不建议乱整,只能自定义1420到1500的范围的值")); +mtu.optional=true +mtu.rmempty = true +mtu.default = "1500" +mtu.datatype = "range(1420, 1500)" + +mat = di:taboption(this_taba, ListValue, "at", translate("连接时发送自定义AT命令 :")); +mat:value("0", translate("禁用")) +mat:value("1", translate("启用")) +mat.default=0 + +matc = di:taboption(this_taba, Value, "atc", translate("要执行的AT命令 :")); +matc.optional=false; +matc.rmempty = true; + +-- +-- Default Connection Monitoring +-- + +this_tab = "connect" + +alive = di:taboption(this_tab, ListValue, "alive", translate("连接状态监控 :")); +alive.rmempty = true; +alive:value("0", translate("禁用")) +alive:value("1", translate("启用掉线写入系统日志")) +alive:value("2", translate("启用 5G模块掉线 则 路由自动重启")) +alive:value("3", translate("启用 5G模块掉线 则 自动重拨")) +alive:value("4", translate("启用 5G模块掉线 则 重新上电模块,需要路由GPIO支持,否则将使用其他方式重连")) +alive.default=0 + +reliability = di:taboption(this_tab, Value, "reliability", translate("监测网络稳定性 :"), + translate("范围: 1-100,必须Ping通这些IP地址,这条通信链路才会被视为联网状态")) +reliability.datatype = "range(1, 100)" +reliability.default = "1" +reliability:depends("alive", "1") +reliability:depends("alive", "2") +reliability:depends("alive", "3") +reliability:depends("alive", "4") + +count = di:taboption(this_tab, ListValue, "count", translate("监测次数(Ping) :")) +count.default = "1" +count:value("1") +count:value("2") +count:value("3") +count:value("4") +count:value("5") +count:depends("alive", "1") +count:depends("alive", "2") +count:depends("alive", "3") +count:depends("alive", "4") + +interval = di:taboption(this_tab, ListValue, "pingtime", translate("监测时间间隔 (Ping) :"), + translate("监测Ping之间间隔时间的值")) +interval.default = "10" +interval:value("5", translate("5 秒/次")) +interval:value("10", translate("10 秒/次")) +interval:value("20", translate("20 秒/次 推荐")) +interval:value("30", translate("30 秒次")) +interval:value("60", translate("1 分钟/次 ")) +interval:value("300", translate("5 分钟/次")) +interval:value("600", translate("10 分钟/次")) +interval:value("900", translate("15 分钟/次")) +interval:value("1800", translate("30 分钟/次")) +interval:value("3600", translate("1 小时/次")) +interval:depends("alive", "1") +interval:depends("alive", "2") +interval:depends("alive", "3") +interval:depends("alive", "4") + +timeout = di:taboption(this_tab, ListValue, "pingwait", translate("Ping 超时 :")) +timeout.default = "2" +timeout:value("1", translate("1 秒")) +timeout:value("2", translate("2 秒")) +timeout:value("3", translate("3 秒")) +timeout:value("4", translate("4 秒")) +timeout:value("5", translate("5 秒")) +timeout:value("6", translate("6 秒")) +timeout:value("7", translate("7 秒")) +timeout:value("8", translate("8 秒")) +timeout:value("9", translate("9 秒")) +timeout:value("10", translate("10 秒")) +timeout:depends("alive", "1") +timeout:depends("alive", "2") +timeout:depends("alive", "3") +timeout:depends("alive", "4") + +packetsize = di:taboption(this_tab, Value, "packetsize", translate("Ping报文大小(字节为单位) :"), + translate("范围值 :4-56,ping报文发送的数据字节数,可以要根据运营商进行调整")) + packetsize.datatype = "range(4, 56)" + packetsize.default = "56" + packetsize:depends("alive", "1") + packetsize:depends("alive", "2") + packetsize:depends("alive", "3") + packetsize:depends("alive", "4") + +down = di:taboption(this_tab, ListValue, "down", translate("链路状态 异常判定次数 :"), + translate("如果达到设定值次数,Ping依旧失败后,接口就会被当做异常不在线")) +down.default = "3" +down:value("1") +down:value("2") +down:value("3") +down:value("4") +down:value("5") +down:value("6") +down:value("7") +down:value("8") +down:value("9") +down:value("10") +down:depends("alive", "1") +down:depends("alive", "2") +down:depends("alive", "3") +down:depends("alive", "4") + +up = di:taboption(this_tab, ListValue, "up", translate("链路状态 正常判定次数 :"), + translate("Tips:当达到设定值次数Ping监测后,网络都能Ping设定地址后,则链路状态会被视为正常啦~~")) +up.default = "3" +up:value("1") +up:value("2") +up:value("3") +up:value("4") +up:value("5") +up:value("6") +up:value("7") +up:value("8") +up:value("9") +up:value("10") +up:depends("alive", "1") +up:depends("alive", "2") +up:depends("alive", "3") +up:depends("alive", "4") + +cb2 = di:taboption(this_tab, DynamicList, "trackip", translate("追踪 IP :"), + translate("这个IP将被拿来做链路状态检测用,简单说就是Ping它,能通那么就算链路正常,不通那就以你刚配合的方法处理")) +cb2.datatype = "ipaddr" +cb2:depends("alive", "1") +cb2:depends("alive", "2") +cb2:depends("alive", "3") +cb2:depends("alive", "4") +cb2.optional=false; +cb2.default="114.114.114.114" + +if (multilock == "0") or (multilock == "1" and rootlock == "1") then + this_tab = "bwidth" + bwday = di:taboption(this_tab, ListValue, "bwday", translate("发送监测信息的日期 :"), + translate("每月发送监测报告文件的日期,请选择在每个月的第几日发送,不需要请选择禁用")) + bwday.default = "0" + bwday:value("0", translate("禁用")) + bwday:value("1", translate("1日")) + bwday:value("2", translate("2日")) + bwday:value("3", translate("3日")) + bwday:value("4", translate("4日")) + bwday:value("5", translate("5日")) + bwday:value("6", translate("6日")) + bwday:value("7", translate("7日")) + bwday:value("8", translate("8日")) + bwday:value("9", translate("9日")) + bwday:value("10", translate("10日")) + bwday:value("11", translate("11日")) + bwday:value("12", translate("12日")) + bwday:value("13", translate("13日")) + bwday:value("14", translate("14日")) + bwday:value("15", translate("15日")) + bwday:value("16", translate("16日")) + bwday:value("17", translate("17日")) + bwday:value("18", translate("18日")) + bwday:value("19", translate("19日")) + bwday:value("20", translate("20日")) + bwday:value("21", translate("21日")) + bwday:value("22", translate("22日")) + bwday:value("23", translate("23日")) + bwday:value("24", translate("24日")) + bwday:value("25", translate("25日")) + bwday:value("26", translate("26日")) + bwday:value("27", translate("27日")) + bwday:value("28", translate("28日")) + + phone = di:taboption(this_tab, Value, "phone", translate("手机号码 :"), translate("我们将会通过这个手机号码给你发送监测日志报告,物联卡就爬吧发不了的,短信费用按你套餐资费扣,介意就别踏马用了")) + phone.default = "填入接收监测报告的手机号码,我们将会以短信方式给你发送" + + bwdelay = di:taboption(this_tab, ListValue, "bwdelay", translate("发送前延迟 :"), + translate("凌晨后几个小时发送短信给你")) + bwdelay:value("0", translate("不延迟")) + bwdelay:value("1", translate("1 小时")) + bwdelay:value("2", translate("2 小时")) + bwdelay:value("3", translate("3 小时")) + bwdelay:value("4", translate("4 小时")) + bwdelay:value("5", translate("5 小时")) + bwdelay:value("6", translate("6 小时")) + bwdelay:value("7", translate("7 小时")) + bwdelay:value("8", translate("8 小时")) + bwdelay:value("9", translate("9 小时")) + bwdelay:value("10", translate("10 小时")) + bwdelay:value("11", translate("11 小时")) + bwdelay:value("12", translate("12 小时")) +end + +if fs.stat("/usr/lib/autoapn/apn.data") then + dda = m:section(TypedSection, "disable", translate("Use Automatic APN"), translate("Enable the use of the Automatic APN selection. This disables Custom Profiles.")) + dda.anonymous = true + aenabled = dda:option(Flag, "autoapn", translate("Enabled")) + aenabled.default="0" + aenabled.optional=false; +end + +dd = m:section(TypedSection, "disable", translate("禁用自动APN :"), translate("禁用自动APN后,所有4G/5G通信模块将会使用默认配置文件,不勾选就是默认启用")) +dd.anonymous = true + +enabled = dd:option(Flag, "enabled", translate("禁用")) +enabled.default="0" +enabled.optional=false; + +-- +-- Custom profile +-- + +s = m:section(TypedSection, "custom", translate("定制特定组合配置 :"), translate("可将某个特定配置应用在你所选中的4G/5G模块与SIM卡组合中")) +s.anonymous = true +s.addremove = true +s:tab("custom", translate("简要")) +s:tab("cadvanced", translate("高级")) +s:tab("cconnect", translate("网络异常自动处理")) +if (multilock == "0") or (multilock == "1" and rootlock == "1") then + s:tab("cbwidth", translate("通信模块频宽日志")) +end + +this_ctab = "custom" + +name = s:taboption(this_ctab, Value, "name", translate("配置名称 :")) + +enabled = s:taboption(this_ctab, Flag, "enabled", translate("启用")) +enabled.default="1" +enabled.optional=false; + +select = s:taboption(this_ctab, ListValue, "select", translate("选择对象 :")); +select:value("0", translate("模块 ID")) +select:value("1", translate("模块 IMEI")) +select:value("2", translate("模块名称")) +select:value("3", translate("SIM卡IMSI")) +select:value("4", translate("SIM卡ICCID")) +select.default=0 + +idV = s:taboption(this_ctab, Value, "vid", translate("USB VID :")); +idV.optional=false; +idV:depends("select", "0") +idV.default="xxxx" + +idP = s:taboption(this_ctab, Value, "pid", translate("USB PID :")); +idP.optional=false; +idP:depends("select", "0") +idP.default="xxxx" + +imei = s:taboption(this_ctab, Value, "imei", translate("通信模块IMEI :")); +imei.optional=false; +imei:depends("select", "1") +imei.datatype = "uinteger" +imei.default="1234567" + +model = s:taboption(this_ctab, Value, "model", translate("模块名称包含 :")); +model.optional=false; +model:depends("select", "2") +model.default="xxxx" + +imsi = s:taboption(this_ctab, Value, "imsi", translate("SIM卡IMSI :")); +imsi.optional=false; +imsi:depends("select", "3") +imsi.datatype = "uinteger" +imsi.default="1234567" + +iccid = s:taboption(this_ctab, Value, "iccid", translate("SIM卡ICCID :")); +iccid.optional=false; +iccid:depends("select", "4") +iccid.datatype = "uinteger" +iccid.default="1234567" + +select1 = s:taboption(this_ctab, ListValue, "select1", translate("选择组合对象 :")); +select1:value("0", "模块 ID") +select1:value("1", "模块 IMEI") +select1:value("2", "型号名称") +select1:value("3", "SIM卡IMSI") +select1:value("4", "SIM卡ICCID") +select1:value("10", "None") +select1.default=10 + +idV1 = s:taboption(this_ctab, Value, "vid1", translate("USB VID :")); +idV1.optional=false; +idV1:depends("select1", "0") +idV1.default="xxxx" + +idP1 = s:taboption(this_ctab, Value, "pid1", translate("USB PID :")); +idP1.optional=false; +idP1:depends("select1", "0") +idP1.default="xxxx" + +imei1 = s:taboption(this_ctab, Value, "imei1", translate("模块 IMEI :")); +imei1.optional=false; +imei1:depends("select1", "1") +imei1.datatype = "uinteger" +imei1.default="1234567" + +model1 = s:taboption(this_ctab, Value, "model1", translate("模块 名称包含 :")); +model1.optional=false; +model1:depends("select1", "2") +model1.default="xxxx" + +imsi1 = s:taboption(this_ctab, Value, "imsi1", translate("SIM卡IMSI :")); +imsi1.optional=false; +imsi1:depends("select1", "3") +imsi1.datatype = "uinteger" +imsi1.default="1234567" + +iccid1 = s:taboption(this_ctab, Value, "iccid1", translate("SIM卡ICCID :")); +iccid1.optional=false; +iccid1:depends("select1", "4") +iccid1.datatype = "uinteger" +iccid1.default="1234567" + +cma = s:taboption(this_ctab, Value, "apn", "APN :"); +cma.rmempty = true; + +tt = s:taboption(this_ctab, ListValue, "ttl", translate("自定义TTL值 :")) +tt:value("0", translate("Use Current Value")) +tt:value("1", translate("No TTL Value")) +tt:value("63", "TTL 63") +tt:value("64", "TTL 64") +tt:value("65", "TTL 65") +tt:value("66", "TTL 66") +tt:value("67", "TTL 67") +tt:value("117", "TTL 117") +tt:value("TTL-INC 1", "TTL-INC 1") +tt.default = "0" + +nl = s:taboption(this_ctab, ListValue, "hostless", translate("调整无主机(无主控)模块的TTL值 :")); +nl:value("0", translate("No")) +nl:value("1", translate("是")) +nl.default=0 + +pt = s:taboption(this_ctab, ListValue, "pdptype", translate("IP协议类型 :")) +pt:value("IP", "IPv4") +pt:value("IPv6", "IPv6") +pt:value("IPV4V6", "IPv4+IPv6") +pt:value("0", "Default") +pt.default = "0" + +cmcc = s:taboption(this_ctab, Value, "context", translate("PDP Context for APN :")); +cmcc.optional=false; +cmcc.rmempty = true; +cmcc.datatype = "and(uinteger,min(1),max(10))" +cmcc.default = "1" + +cmu = s:taboption(this_ctab, Value, "user", translate("用户名 :")); +cmu.optional=false; +cmu.rmempty = true; + +cmp = s:taboption(this_ctab, Value, "passw", translate("密码 :")); +cmp.optional=false; +cmp.rmempty = true; +cmp.password = true + +cmpi = s:taboption(this_ctab, Value, "pincode", "PIN码 :"); +cmpi.optional=false; +cmpi.rmempty = true; + +cmau = s:taboption(this_ctab, ListValue, "auth", translate("身份验证类型 :")) +cmau:value("0", "无") +cmau:value("1", "PAP") +cmau:value("2", "CHAP") +cmau.default = "0" + +cmtz = s:taboption(this_ctab, ListValue, "tzone", translate("自动设置时区"), translate("模块通网后自动设置时区")); +cmtz:value("0", translate("禁用")) +cmtz:value("1", translate("启用")) +cmtz.default=1 + +cml = s:taboption(this_ctab, ListValue, "lock", translate("是否锁定国际漫游运营商选项(国内不用管) :")); +cml:value("0", translate("否")) +cml:value("1", translate("强硬的")) +cml:value("2", translate("柔弱的")) +cml.default=0 + +cmcc = s:taboption(this_ctab, Value, "mcc", translate("MCC :")); +cmcc.optional=false; +cmcc.rmempty = true; +cmcc.datatype = "and(uinteger,min(1),max(999))" +cmcc:depends("lock", "1") +cmcc:depends("lock", "2") + +cmnc = s:taboption(this_ctab, Value, "mnc", translate("MNC :")); +cmnc.optional=false; +cmnc.rmempty = true; +cmnc.datatype = "and(uinteger,min(1),max(999))" +cmnc:depends("lock", "1") +cmnc:depends("lock", "2") + +this_ctaba = "cadvanced" + +cmf = s:taboption(this_ctaba, ListValue, "ppp", translate("强制使用3G PP协议拨号 :")); +cmf:value("0", translate("否")) +cmf:value("1", translate("是")) +cmf.default=0 + +cmw = s:taboption(this_ctaba, ListValue, "inter", translate("模块WAN口分配 :")); +cmw:value("0", "自动") +cmw:value("1", "WAN1") +cmw:value("2", "WAN2") +cmw:value("3", "关闭") +cmw.default=0 + +cmd = s:taboption(this_ctaba, Value, "delay", translate("连接延迟(以秒为单位) :")); +cmd.optional=false; +cmd.rmempty = false; +cmd.default = 5 +cmd.datatype = "and(uinteger,min(5))" + +cnl = s:taboption(this_ctaba, ListValue, "nodhcp", translate("强制QMI协议不使用模块的DHCP,从其他位置获取 :")); +cnl:value("0", translate("禁用")) +cnl:value("1", translate("启用")) +cnl.default=0 + +cmdns1 = s:taboption(this_ctaba, Value, "dns1", translate("自定义1 :")); +cmdns1.rmempty = true; +cmdns1.optional=false; +cmdns1.datatype = "ipaddr" + +cmdns2 = s:taboption(this_ctaba, Value, "dns2", translate("自定义2 :")); +cmdns2.rmempty = true; +cmdns2.optional=false; +cmdns2.datatype = "ipaddr" + +cmdns3 = s:taboption(this_ctaba, Value, "dns3", translate("自定义3 :")); +cmdns3.rmempty = true; +cmdns3.optional=false; +cmdns3.datatype = "ipaddr" + +cmdns4 = s:taboption(this_ctaba, Value, "dns4", translate("自定义4 :")); +cmdns4.rmempty = true; +cmdns4.optional=false; +cmdns4.datatype = "ipaddr" + +cmlog = s:taboption(this_ctaba, ListValue, "log", translate("启用连接日志 :")); +cmlog:value("0", translate("禁用")) +cmlog:value("1", translate("启用")) +cmlog.default=0 + +if nixio.fs.access("/etc/config/mwan3") then + cmlb = s:taboption(this_ctaba, ListValue, "lb", translate("在多个5G模块中开启流量负载均衡 :")); + cmlb:value("0", translate("禁用")) + cmlb:value("1", translate("启用")) + cmlb.default=0 +end + +mtu = s:taboption(this_ctaba, Value, "mtu", translate("自定义MTU值 :"), + translate("歪歪歪 米乱整窝,纸能自定义1420到1500的蜗 根据不同运营商进行调整的歪,理不鸡丢就不要瞎搞了蛙,等夏列个网炸嘿掉了鳖嘿来找我蜗~~")); +mtu.optional=true +mtu.rmempty = true +mtu.default = "1500" +mtu.datatype = "range(1420, 1500)" + +cmat = s:taboption(this_ctaba, ListValue, "at", translate("在连接模块时发送自定义AT命令 :")); +cmat:value("0", translate("禁用")) +cmat:value("1", translate("启用")) +cmat.default=0 + +cmatc = s:taboption(this_ctaba, Value, "atc", translate("自定义AT命令 :")); +cmatc.optional=false; +cmatc.rmempty = true; + +-- +-- Custom Connection Monitoring +-- + +this_ctab = "cconnect" + +calive = s:taboption(this_ctab, ListValue, "alive", translate("连接状态监控 :")); +calive.rmempty = true; +calive:value("0", translate("禁用")) +calive:value("1", translate("启用掉线写入系统日志")) +calive:value("2", translate("启用 5G模块掉线 则 路由自动重启")) +calive:value("3", translate("启用 5G模块掉线 则 自动重拨")) +calive:value("4", translate("启用 5G模块掉线 则 重新上电模块,需要路由GPIO支持,否则将使用其他方式重连")) +calive.default=0 + +reliability = s:taboption(this_ctab, Value, "reliability", translate("监测网络稳定性 :"), + translate("Acceptable values: 范围: 1-100,必须Ping通这些IP地址,这条通信链路才会被视为联网状态")) +reliability.datatype = "range(1, 100)" +reliability.default = "1" +reliability:depends("alive", "1") +reliability:depends("alive", "2") +reliability:depends("alive", "3") +reliability:depends("alive", "4") + +count = s:taboption(this_ctab, ListValue, "count", translate("监测次数(Ping):")) +count.default = "1" +count:value("1") +count:value("2") +count:value("3") +count:value("4") +count:value("5") +count:depends("alive", "1") +count:depends("alive", "2") +count:depends("alive", "3") +count:depends("alive", "4") + +interval = s:taboption(this_ctab, ListValue, "pingtime", translate("监测时间间隔 (Ping) :"), + translate("监测Ping之间间隔时间的值")) +interval.default = "10" +interval:value("5", translate("5 秒")) +interval:value("10", translate("10 秒")) +interval:value("20", translate("20 秒")) +interval:value("30", translate("30 秒")) +interval:value("60", translate("1 分钟")) +interval:value("300", translate("5 分钟")) +interval:value("600", translate("10 分钟")) +interval:value("900", translate("15 分钟")) +interval:value("1800", translate("30 分钟")) +interval:value("3600", translate("1 小时")) +interval:depends("alive", "1") +interval:depends("alive", "2") +interval:depends("alive", "3") +interval:depends("alive", "4") + +timeout = s:taboption(this_ctab, ListValue, "pingwait", translate("Ping 超时 :")) +timeout.default = "2" +timeout:value("1", translate("1 秒")) +timeout:value("2", translate("2 秒")) +timeout:value("3", translate("3 秒")) +timeout:value("4", translate("4 秒")) +timeout:value("5", translate("5 秒")) +timeout:value("6", translate("6 秒")) +timeout:value("7", translate("7 秒")) +timeout:value("8", translate("8 秒")) +timeout:value("9", translate("9 秒")) +timeout:value("10", translate("10 秒")) +timeout:depends("alive", "1") +timeout:depends("alive", "2") +timeout:depends("alive", "3") +timeout:depends("alive", "4") + +packetsize = s:taboption(this_ctab, Value, "packetsize", translate("Ping报文大小(字节为单位) :"), + translate("范围值 :4-56,ping报文发送的数据字节数,可以要根据运营商进行调整")) + packetsize.datatype = "range(4, 56)" + packetsize.default = "56" + packetsize:depends("alive", "1") + packetsize:depends("alive", "2") + packetsize:depends("alive", "3") + packetsize:depends("alive", "4") + +down = s:taboption(this_ctab, ListValue, "down", translate("链路状态 异常判定次数 :"), + translate("如果达到设定值次数,Ping依旧失败后,接口就会被当做异常不在线")) +down.default = "3" +down:value("1") +down:value("2") +down:value("3") +down:value("4") +down:value("5") +down:value("6") +down:value("7") +down:value("8") +down:value("9") +down:value("10") +down:depends("alive", "1") +down:depends("alive", "2") +down:depends("alive", "3") +down:depends("alive", "4") + +up = s:taboption(this_ctab, ListValue, "up", translate("链路状态 正常判定次数"), + translate("当达到设定值次数Ping监测后,网络都能Ping设定地址后,则链路状态会被视为正常啦~~")) +up.default = "3" +up:value("1") +up:value("2") +up:value("3") +up:value("4") +up:value("5") +up:value("6") +up:value("7") +up:value("8") +up:value("9") +up:value("10") +up:depends("alive", "1") +up:depends("alive", "2") +up:depends("alive", "3") +up:depends("alive", "4") + +cb2 = s:taboption(this_ctab, DynamicList, "trackip", translate("追踪 IP :"), + translate("这个IP将被拿来做链路状态检测用,简单说就是Ping它,能通那么就算链路正常,不通那就以你刚配合的方法处理")) +cb2.datatype = "ipaddr" +cb2:depends("alive", "1") +cb2:depends("alive", "2") +cb2:depends("alive", "3") +cb2:depends("alive", "4") +cb2.optional=false; +cb2.default="114.114.114.114" + +if (multilock == "0") or (multilock == "1" and rootlock == "1") then + this_ctab = "cbwidth" + bwday = s:taboption(this_ctab, ListValue, "bwday", translate("每个月发送网络稳定日志的日期"), + translate("每月发送监测报告文件的日期,请选择在每个月的第几日发送,不需要请选择禁用")) + bwday.default = "0" + bwday:value("0", translate("禁用")) + bwday:value("1", translate("1日")) + bwday:value("2", translate("2日")) + bwday:value("3", translate("3日")) + bwday:value("4", translate("4日")) + bwday:value("5", translate("5日")) + bwday:value("6", translate("6日")) + bwday:value("7", translate("7日")) + bwday:value("8", translate("8日")) + bwday:value("9", translate("9日")) + bwday:value("10", translate("10日")) + bwday:value("11", translate("11日")) + bwday:value("12", translate("12日")) + bwday:value("13", translate("13日")) + bwday:value("14", translate("14日")) + bwday:value("15", translate("15日")) + bwday:value("16", translate("16日")) + bwday:value("17", translate("17日")) + bwday:value("18", translate("18日")) + bwday:value("19", translate("19日")) + bwday:value("20", translate("20日")) + bwday:value("21", translate("21日")) + bwday:value("22", translate("22日")) + bwday:value("23", translate("23日")) + bwday:value("24", translate("24日")) + bwday:value("25", translate("25日")) + bwday:value("26", translate("26日")) + bwday:value("27", translate("27日")) + bwday:value("28", translate("28日")) + + phone = s:taboption(this_ctab, Value, "phone", translate("手机号码 :"), translate("我们将会通过这个手机号码给你发送监测日志报告,物联卡就爬吧发不了的,短信费用按你套餐资费扣,介意就不要用了")) + phone.default = "12223334444" + + bwdelay = s:taboption(this_ctab, ListValue, "bwdelay", translate("发送前延迟 :"), + translate("凌晨后几个小时发送短信给你")) + bwdelay:value("0", translate("No Delay")) + bwdelay:value("1", translate("1 小时")) + bwdelay:value("2", translate("2 小时")) + bwdelay:value("3", translate("3 小时")) + bwdelay:value("4", translate("4 小时")) + bwdelay:value("5", translate("5 小时")) + bwdelay:value("6", translate("6 小时")) + bwdelay:value("7", translate("7 小时")) + bwdelay:value("8", translate("8 小时")) + bwdelay:value("9", translate("9 小时")) + bwdelay:value("10", translate("10 小时")) + bwdelay:value("11", translate("11 小时")) + bwdelay:value("12", translate("12 小时")) +end + +return m + + + diff --git a/rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/admin_status/index/external.htm b/rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/admin_status/index/external.htm new file mode 100644 index 0000000..9aa6023 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/admin_status/index/external.htm @@ -0,0 +1 @@ +<%+rooter/external%> \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/admin_system/poweroff.htm b/rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/admin_system/poweroff.htm new file mode 100644 index 0000000..4749e48 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/admin_system/poweroff.htm @@ -0,0 +1,34 @@ +<%# + Copyright 2008 Steven Barth + Copyright 2008 Jo-Philipp Wich + Licensed to the public under the Apache License 2.0. +-%> + +<%+header%> + + + + +

                          <%:System%>

                          +

                          <%:System Stop%>

                          +

                          <%:Graceful system stop. De-power then re-power to restart.%>

                          +

                          +
                            +<%+footer%> \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/modlog/modlog.htm b/rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/modlog/modlog.htm new file mode 100644 index 0000000..edf4af4 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/modlog/modlog.htm @@ -0,0 +1,32 @@ +<%+header%> + + + + +
                            +

                            <%:Modem Logging%>

                            +
                            +
                            + <%:Log%> + + + + +
                            + +
                            + +
                            + +
                            + +<%+footer%> \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/rooter/bandlock.htm b/rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/rooter/bandlock.htm new file mode 100644 index 0000000..3dd5477 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/rooter/bandlock.htm @@ -0,0 +1,26 @@ +<%+header%> + + + + +
                            +
                            +

                            Band Locking Tutorial

                            +
                            Manually band lock a modem
                            +
                            + Versions + + + + + + +
                            Current Firmware :
                               
                              + +
                              +
                              +
                              +<%+footer%> \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/rooter/custom.htm b/rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/rooter/custom.htm new file mode 100644 index 0000000..e23d1e8 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/rooter/custom.htm @@ -0,0 +1,126 @@ +<% +local modemfile = "/etc/config/modem.data" +local modemdata = {} +local count + +function process_line(xline, cnt) + local data = {} + local pline = xline + local start = 1 + for i=1,3 do + s, e = string.find(pline, " ") + data[i] = string.sub(pline, start, s-1) + pline = string.sub(pline, e+1) + end + data[4] = pline + modemdata[cnt] = data +end + +function read_modem() + count = 0 + local file = io.open(modemfile, "r") + if file == nil then + return + end + repeat + local line = file:read("*line") + if line == nil then + break + end + if string.len(line) < 5 then + break + end + count = count + 1 + process_line(line, count) + until 1==0 + file:close() +end + +function process_family(index) + local t = { } + if count == 0 then + return t + end + local mdata = modemdata[index] + if mdata[1] ~= "nil" and mdata[2] ~= "nil" then + t[1] = mdata[1] .. ":" .. mdata[2] + if mdata[3] == "tty" then + t[2] = "default" + end + if mdata[3] == "tty0" then + t[2] = "ttyUSB0" + end + if mdata[3] == "tty1" then + t[2] = "ttyUSB1" + end + if mdata[3] == "tty2" then + t[2] = "ttyUSB2" + end + if mdata[3] == "tty3" then + t[2] = "ttyUSB3" + end + if mdata[3] == "tty4" then + t[2] = "ttyUSB4" + end + if mdata[3] == "tty5" then + t[2] = "ttyUSB5" + end + + if mdata[4] == "tty" then + t[3] = "default" + end + if mdata[4] == "tty0" then + t[3] = "ttyUSB0" + end + if mdata[4] == "tty1" then + t[3] = "ttyUSB1" + end + if mdata[4] == "tty2" then + t[3] = "ttyUSB2" + end + if mdata[4] == "tty3" then + t[3] = "ttyUSB3" + end + if mdata[4] == "tty4" then + t[3] = "ttyUSB4" + end + if mdata[4] == "tty5" then + t[3] = "ttyUSB5" + end + + end + return t +end + +read_modem() + +%> + +
                              + <%:自定义模块端口数据库%> + + + + + + + <% + if count > 0 then + for i=1,count do + t = process_family(i) %> + + + + + + <% + end + else %> + + + + <% + end %> +
                              <%:模块名称%><%:数据端口%><%:通信端口%>
                              <%=t[1]%><%=t[2]%><%=t[3]%>
                              <%:暂无数据%>  
                              +
                              + diff --git a/rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/rooter/debug.htm b/rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/rooter/debug.htm new file mode 100644 index 0000000..e9f0d9c --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/rooter/debug.htm @@ -0,0 +1,87 @@ +<%+header%> + +<% +local cnt = 0 +local tt = {} + +os.execute("cat /sys/kernel/debug/usb/devices > /tmp/modstat 2>&1") +local file = io.open("/tmp/modstat", "r") +repeat + local line = file:read("*line") + if line == nil then + break + end + if string.len(line) < 3 then + line = "********************************************************************************************************" + end + tt[cnt] = line + cnt = cnt + 1 +until 1 == 0 +cnt = cnt - 1 +file:close() +os.execute("/usr/lib/rooter/luci/luaops.sh delete /tmp/modstat") +%> + + + + +
                              +

                              <%:通信模块调试信息%>

                              +
                              +
                              + <%:自动化AT指令调试日志%> + + + + +
                              + +
                              + +
                              + +
                              + <%:设备信息%> + + + + + + + <% + for i=1,cnt do + s, e = string.find(tt[i], "供应商") + s1, e = string.find(tt[i], "品牌") + s2, e = string.find(tt[i], "模块型号") + if s ~= nil or s1 ~= nil or s2 ~= nil then + %> + + + + + + <% else + %> + + + + + + <% end + end %> +
                              <%=tt[i]%>
                              <%=tt[i]%>
                              +
                              +

                              +
                              + +<%+footer%> + diff --git a/rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/rooter/external.htm b/rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/rooter/external.htm new file mode 100644 index 0000000..91927b7 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/rooter/external.htm @@ -0,0 +1,26 @@ + + +
                              +

                              <%:External Internet IP Address%>

                              + + +
                              <%:IP Address%><%:Loading%> Collecting data...
                              +
                              + diff --git a/rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/rooter/log.htm b/rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/rooter/log.htm new file mode 100644 index 0000000..3928e06 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/rooter/log.htm @@ -0,0 +1,54 @@ +<%+header%> + + + + +
                              +
                              +

                              <%:连接日志%>

                              +
                              + +
                              + + + + + + + +
                              + +
                              + +
                              + +
                              + +
                              +
                              +<%+footer%> + diff --git a/rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/rooter/misc.htm b/rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/rooter/misc.htm new file mode 100644 index 0000000..05a087e --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/rooter/misc.htm @@ -0,0 +1,2387 @@ +<%+header%> +<% +local sys = require "luci.sys" +local utl = require "luci.util" +local fs = require "nixio.fs" +local uci = require "luci.model.uci".cursor() +local s = uci:get("custom", "bandlock", "enabled") +local a = uci:get("custom", "atcmd", "enabled") + +local multilock = uci:get("custom", "multiuser", "multi") or "0" +local rootlock = uci:get("custom", "multiuser", "root") or "0" +nomulti=1 +if (multilock == "0") or (multilock == "1" and rootlock == "1") then + nosms = 1 + if a == "1" then + nosms = 0 + end +else + nosms = 1 + nomulti = 0 +end +block = 1 +if s == "1" then + block = 0 +end + +function showicon(lck) + if lck == 0 then + return resource .. "/icons/unlock1.png" + else + return resource .. "/icons/lock1.png" + end +end + +-%> + + + +
                              +
                              +

                              <%:锁频段/锁PCI/切换协议/AT命令%>

                              +
                              <%:锁频段/锁PCI/切换协议/AT命令%>
                              + + + +
                              + <%:当前模块%> + + + + + + + +
                                + + + +
                                +
                                +
                                + <%:模块 连接/断开控制%> + + + + + + + +
                                + + + + + + + +
                                +
                                + +<% if nosms == 0 then %> +
                                + <%:AT命令终端%> + + + + + + + + + + + + + + + +
                                <%:AT命令 : %>
                                + + + +  
                                +
                                + + + + + + + + + + + + + + + + + +
                                <%:AT命令 : %>
                                 
                                + + + + + +
                                + +
                                + +
                                +<% end %> + +<% if nomulti == 1 then %> +<% if block == 0 then %> +
                                + <%:4G/5G频段锁定%> + + + + + +
                                 
                                + + + + + + +
                                <%:没有模块/模块未适配本插件%> 
                                + + + + + + + +
                                 
                                <%:4G LTE频段%>
                                 
                                + + + + +
                                + + + + + + + +
                                 
                                <%:5G NSA频段%>
                                 
                                + + + + +
                                + + + + + + + +
                                 
                                <%:5G SA 频段%>
                                 
                                + + + + +
                                + + + + + + + +
                                  
                                + + + + + +
                                 
                                + + + + + + +
                                 
                                + + + + + +
                                <%:2 x 载波聚合%>
                                + + + + +
                                + + + + + +
                                <%:3 x 载波聚合%>
                                + + + + +
                                + + + + + +
                                 
                                + + + + + + + + + +
                                 
                                <%:扫描可用的频段%>
                                 
                                + + + + + +
                                + +
                                + + + + + + + + + + +
                                  
                                <%:锁定基站%>
                                 
                                + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                <%:功能状态 : %>
                                   
                                <%:EARFCN 1 : %>
                                <%:PCI 1 : %>
                                 
                                <%:EARFCN 2 : %>
                                <%:PCI 2 : %>
                                 
                                <%:EARFCN 3 : %>
                                <%:PCI 3 : %>
                                 
                                <%:EARFCN 4 : %>
                                <%:PCI 4 : %>
                                 
                                + + + + + + +
                                 
                                + +
                                +<% end %> + +
                                + <%:模块连接协议切换%> + + + + + + + + + + + + + +
                                 
                                <%:当前模块连接协议 :%>
                                 
                                 
                                <%:更改蜂窝模式 :%>
                                + + +
                                +
                                + +
                                + <%:网络类型选择%> + + + + + + + + + + + + + +
                                <%:当前网络类型 :%>
                                 
                                <%:更改网络类型 :%>
                                + + + + +  
                                +
                                +<% end %> + +
                                + <%:GPS Message Pin%> + + + + + + + + +
                                 
                                <%:Message Pin :%>
                                 
                                +
                                + +
                                +
                                +<%+footer%> diff --git a/rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/rooter/net_status.htm b/rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/rooter/net_status.htm new file mode 100644 index 0000000..bcab6fa --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/rooter/net_status.htm @@ -0,0 +1,564 @@ +<%+header%> +<% +local fs = require "nixio.fs" +nosms = 1 +if not fs.stat("/etc/nosim") then + nosms = 0 +end +havegps = 0 +if fs.stat("/etc/havegps") then + havegps = 1 +end +-%> + + + + +
                                +
                                +

                                <%:信号状态/模块信息%>

                                +
                                请注意该插件所有功能并无适配所有5G模块,不用妄想冷门模块插上就能用(有能力者自行适配) +
                                + + + +
                                + <%:综合信息%> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                <%:模块 :%>
                                  + + + +
                                  <%:ID : %>
                                      
                                    <%:运营商 : %>
                                        
                                      <%:端口 :%>
                                        + + + +
                                        <%:温度 : %>
                                            
                                          <%:协议 : %>
                                              
                                            +
                                            + +<% if nosms == 0 then %> +
                                            + <%:通信模块/SIM卡信息%> + + + + + + + + + + + + + + + + + + + + + + +
                                            + +    
                                            <%:IMEI:%>
                                                
                                              <%:IMSI:%>
                                                <%:ICCID:%>
                                                  + + + + + + + + + + + + +
                                                  <%:SIM卡号码 : %>
                                                  + +   
                                                  <%:SIM卡名称 : %>
                                                  +
                                                  +<% end %> + +
                                                  + <%:信号状态%> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                                  <%:蜂窝网络类型 :%>
                                                     
                                                    <%:CSQ : %>
                                                       
                                                      <%:信号强度 : %>
                                                         
                                                        <%:信号接收强度 RSSI : %>
                                                           
                                                          <%:参考信号接收质量 RSRQ :%>
                                                           
                                                          <%:参考信号接收功率 RSRP :%>
                                                           
                                                          <%:信噪比 SINR : %>
                                                             
                                                            <%:连接状态监控 : %>
                                                               
                                                              +
                                                              + +
                                                              + <%:基站信息%> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                                              <%:MCC / MNC :%>
                                                               
                                                              <%:eNB ID :%>
                                                               
                                                              <%:TAC :%>
                                                               
                                                              <%:Cell ID : %>
                                                               
                                                              <%:频段 Band : %>
                                                                 
                                                                <%:频点 Channel : %>
                                                                   
                                                                  <%:物理小区标识 PCI : %>
                                                                     
                                                                    <%:最大Qos级别 Maximum Qos : %>
                                                                     
                                                                    +
                                                                    + +<% if havegps == 1 then %> +
                                                                    + <%:GPS 定位%> + + + + + + + + + + + +
                                                                    <%:纬度 :%>
                                                                       
                                                                      <%:经度 :%>
                                                                         
                                                                        +
                                                                        +<% end %> +
                                                                        + <%:刷新频率%> + + + + + + + + + + + + + +
                                                                        <%:当前刷新率 :%>
                                                                         
                                                                        <%:修改刷新时间 :%>
                                                                        + +  
                                                                        +
                                                                        + +
                                                                        +
                                                                        +<%+footer%> + diff --git a/rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/rooter/profile.htm b/rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/rooter/profile.htm new file mode 100644 index 0000000..64efa21 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/rooter/profile.htm @@ -0,0 +1,75 @@ +<% + +%> + + + +
                                                                        + <%:Import/Export the Profile Data%> + + + + + + + + + + + + + + + + +
                                                                         
                                                                        <%:Export Profile Data to Computer%>
                                                                         
                                                                        <%:Import Profile Data from Computer%>
                                                                          
                                                                        <%:Page will automatically refresh after file is loaded%>
                                                                        + +
                                                                        diff --git a/rooter/ext-rooter-basic/files/usr/lib/modlog/modlogger.sh b/rooter/ext-rooter-basic/files/usr/lib/modlog/modlogger.sh new file mode 100644 index 0000000..4c3a531 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/modlog/modlogger.sh @@ -0,0 +1,20 @@ +#!/bin/sh + +ROOTER=/usr/lib/rooter + +TEXT=$1 +DATE=$(date +%c) + +modlog="/tmp/modlog.log" +tmplog="/tmp/tmodlog" + +wc -l $modlog > /tmp/linecnt +read lcnt fle < /tmp/linecnt +rm -f /tmp/linecnt +if [ $lcnt -ge 200 ]; then + start=$((lcnt-1)) + tail +$start modlog > $tmplog + mv $tmplog $modlog +fi + +echo "$DATE : $TEXT" >> $modlog diff --git a/rooter/ext-rooter-basic/files/usr/lib/profile/loadcfg.sh b/rooter/ext-rooter-basic/files/usr/lib/profile/loadcfg.sh new file mode 100644 index 0000000..09648f2 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/profile/loadcfg.sh @@ -0,0 +1,14 @@ +#!/bin/sh +. /lib/functions.sh + +log() { + logger -t "Load" "$@" +} + +profile=$(cat /tmp/profilename) +valid=$(echo "$profile" | grep "**Profile**") +if [ ! -z "$valid" ]; then + echo "$profile" > /tmp/profile + sed -i '1d' /tmp/profile + cp /tmp/profile /etc/config/profile +fi diff --git a/rooter/ext-rooter-basic/files/usr/lib/profile/restart.sh b/rooter/ext-rooter-basic/files/usr/lib/profile/restart.sh new file mode 100644 index 0000000..cda742a --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/profile/restart.sh @@ -0,0 +1,18 @@ +#!/bin/sh +. /lib/functions.sh + +ROOTER=/usr/lib/rooter + +log() { + logger -t "Restart" "$@" +} + +sleep 3 + +CURRMODEM=1 +CPORT=$(uci -q get modem.modem$CURRMODEM.commport) + +if [ ! -z $CPORT ]; then + ATCMDD="AT+CFUN=1,1" + $ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD" +fi \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/profile/savecfg.sh b/rooter/ext-rooter-basic/files/usr/lib/profile/savecfg.sh new file mode 100644 index 0000000..ab8c026 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/profile/savecfg.sh @@ -0,0 +1,16 @@ +#!/bin/sh +. /lib/functions.sh + +log() { + logger -t "Save" "$@" +} + +PKI_DIR="/www" +cd ${PKI_DIR} +mkdir -p package +cd .. +chmod -R 0777 ${PKI_DIR}/package + +echo "***Profile***" > ${PKI_DIR}/package/profilecfg.profile +state=$(cat /etc/config/profile) +echo "$state" >> ${PKI_DIR}/package/profilecfg.profile \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/autoapn.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/autoapn.sh new file mode 100644 index 0000000..c461f46 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/autoapn.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +ROOTER=/usr/lib/rooter + +log() { + logger -t "SimLock " "$@" +} diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/cdmafind.lua b/rooter/ext-rooter-basic/files/usr/lib/rooter/cdmafind.lua new file mode 100644 index 0000000..b1f9922 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/cdmafind.lua @@ -0,0 +1,55 @@ +#!/usr/bin/lua + +drv = {} +idV = arg[1] +idP = arg[2] + +retval = 0 + +function trim(s) + return (s:gsub("^%s*(.-)%s*$", "%1")) +end + +-- MAIN + +local i=0 +local file = io.open("/tmp/cdma", "r") +repeat + local line = file:read("*line") + if line == nil then + break + end + if string.len(line) > 5 then + s, e = line:find("Vendor=") + if s ~= nil then + cs, ce = line:find(" ", e) + m_idV = trim(line:sub(e+1, cs-1)) + s, e = line:find("ProdID=") + cs, ce = line:find(" ", e) + m_idP = trim(line:sub(e+1, cs-1)) + if m_idV == idV and m_idP == idP then + repeat + line = file:read("*line") + if line == nil then + break + end + if string.len(line) > 5 then + s, e = line:find("Product=") + if s ~= nil then + s, e = line:find(" CDMA") + if s ~= nil then + retval = 1 + break + end + end + end + until 1==0 + break + end + end + end +until 1==0 +file:close() + + +os.exit(retval) \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/chan2band.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/chan2band.sh new file mode 100644 index 0000000..99b1ce3 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/chan2band.sh @@ -0,0 +1,273 @@ +#!/bin/sh +CHAN=$1 +CHAN=$(echo "$CHAN" | grep -o "[0-9]*") + +decode_lte() { + if [ $CHAN -lt 600 ]; then + BAND="B1" + elif [ $CHAN -lt 1200 ]; then + BAND="B2" + elif [ $CHAN -lt 1950 ]; then + BAND="B3" + elif [ $CHAN -lt 2400 ]; then + BAND="B4" + elif [ $CHAN -lt 2650 ]; then + BAND="B5" + elif [ $CHAN -lt 2750 ]; then + BAND="B6" + elif [ $CHAN -lt 3450 ]; then + BAND="B7" + elif [ $CHAN -lt 3800 ]; then + BAND="B8" + elif [ $CHAN -lt 4150 ]; then + BAND="B9" + elif [ $CHAN -lt 4750 ]; then + BAND="B10" + elif [ $CHAN -lt 4950 ]; then + BAND="B11" + elif [ $CHAN -lt 5010 ]; then + BAND="-" + elif [ $CHAN -lt 5180 ]; then + BAND="B12" + elif [ $CHAN -lt 5280 ]; then + BAND="B13" + elif [ $CHAN -lt 5380 ]; then + BAND="B14" + elif [ $CHAN -lt 5730 ]; then + BAND="-" + elif [ $CHAN -lt 5850 ]; then + BAND="B17" + elif [ $CHAN -lt 6000 ]; then + BAND="B18" + elif [ $CHAN -lt 6150 ]; then + BAND="B19" + elif [ $CHAN -lt 6450 ]; then + BAND="B20" + elif [ $CHAN -lt 6600 ]; then + BAND="B21" + elif [ $CHAN -lt 7400 ]; then + BAND="B22" + elif [ $CHAN -lt 7500 ]; then + BAND="-" + elif [ $CHAN -lt 7700 ]; then + BAND="B23" + elif [ $CHAN -lt 8040 ]; then + BAND="B24" + elif [ $CHAN -lt 8690 ]; then + BAND="B25" + elif [ $CHAN -lt 9040 ]; then + BAND="B26" + elif [ $CHAN -lt 9210 ]; then + BAND="B27" + elif [ $CHAN -lt 9660 ]; then + BAND="B28" + elif [ $CHAN -lt 9770 ]; then + BAND="B29" + elif [ $CHAN -lt 9870 ]; then + BAND="B30" + elif [ $CHAN -lt 9920 ]; then + BAND="B31" + elif [ $CHAN -lt 10400 ]; then + BAND="B32" + elif [ $CHAN -lt 36000 ]; then + BAND="-" + elif [ $CHAN -lt 36200 ]; then + BAND="B33" + elif [ $CHAN -lt 36350 ]; then + BAND="B34" + elif [ $CHAN -lt 36950 ]; then + BAND="B35" + elif [ $CHAN -lt 37550 ]; then + BAND="B36" + elif [ $CHAN -lt 37750 ]; then + BAND="B37" + elif [ $CHAN -lt 38250 ]; then + BAND="B38" + elif [ $CHAN -lt 38650 ]; then + BAND="B39" + elif [ $CHAN -lt 39650 ]; then + BAND="B40" + elif [ $CHAN -lt 41590 ]; then + BAND="B41" + elif [ $CHAN -lt 43590 ]; then + BAND="B42" + elif [ $CHAN -lt 45590 ]; then + BAND="B43" + elif [ $CHAN -lt 46590 ]; then + BAND="B44" + elif [ $CHAN -lt 46790 ]; then + BAND="B45" + elif [ $CHAN -lt 54540 ]; then + BAND="B46" + elif [ $CHAN -lt 55240 ]; then + BAND="B47" + elif [ $CHAN -lt 56740 ]; then + BAND="B48" + elif [ $CHAN -lt 58240 ]; then + BAND="B49" + elif [ $CHAN -lt 59090 ]; then + BAND="B50" + elif [ $CHAN -lt 59140 ]; then + BAND="B51" + elif [ $CHAN -lt 60140 ]; then + BAND="B52" + elif [ $CHAN -lt 60255 ]; then + BAND="B53" + elif [ $CHAN -lt 65536 ]; then + BAND="-" + elif [ $CHAN -lt 66436 ]; then + BAND="B65" + elif [ $CHAN -lt 67336 ]; then + BAND="B66" + elif [ $CHAN -lt 67536 ]; then + BAND="B67" + elif [ $CHAN -lt 67836 ]; then + BAND="B68" + elif [ $CHAN -lt 68336 ]; then + BAND="B69" + elif [ $CHAN -lt 68586 ]; then + BAND="B70" + elif [ $CHAN -lt 68936 ]; then + BAND="B71" + elif [ $CHAN -lt 68986 ]; then + BAND="B72" + elif [ $CHAN -lt 69036 ]; then + BAND="B73" + elif [ $CHAN -lt 69466 ]; then + BAND="B74" + elif [ $CHAN -lt 70316 ]; then + BAND="B75" + elif [ $CHAN -lt 70366 ]; then + BAND="B76" + elif [ $CHAN -lt 70546 ]; then + BAND="B85" + elif [ $CHAN -lt 70596 ]; then + BAND="B87" + elif [ $CHAN -lt 70646 ]; then + BAND="B88" + else + BAND="-" + fi +} + +decode_nr5g() { + if [ $CHAN -le 123400 ]; then + BAND="-" + elif [ $CHAN -le 130400 ]; then + BAND="n71" + elif [ $CHAN -le 143400 ]; then + BAND="-" + elif [ $CHAN -le 145600 ]; then + BAND="n29" + elif [ $CHAN -le 145800 ]; then + BAND="-" + elif [ $CHAN -le 149200 ]; then + BAND="n12" + elif [ $CHAN -le 151600 ]; then + BAND="-" + elif [ $CHAN -le 153600 ]; then + BAND="n14|n28" + elif [ $CHAN -le 158200 ]; then + BAND="n28" + elif [ $CHAN -le 160600 ]; then + BAND="n20|n28" + elif [ $CHAN -le 164200 ]; then + BAND="n20" + elif [ $CHAN -le 171800 ]; then + BAND="-" + elif [ $CHAN -le 172000 ]; then + BAND="n26" + elif [ $CHAN -le 173800 ]; then + BAND="n18|n26" + elif [ $CHAN -le 175000 ]; then + BAND="n5|n18|n26" + elif [ $CHAN -le 178800 ]; then + BAND="n5|n26" + elif [ $CHAN -le 185000 ]; then + BAND="-" + elif [ $CHAN -le 192000 ]; then + BAND="n8" + elif [ $CHAN -le 285400 ]; then + BAND="-" + elif [ $CHAN -le 286400 ]; then + BAND="n51|n76|n91|n93" + elif [ $CHAN -le 295000 ]; then + BAND="n50|n75|n92|n94" + elif [ $CHAN -le 303400 ]; then + BAND="n50|n74|n75|n92|n94" + elif [ $CHAN -le 303600 ]; then + BAND="n74" + elif [ $CHAN -le 361000 ]; then + BAND="-" + elif [ $CHAN -le 376000 ]; then + BAND="n3" + elif [ $CHAN -le 384000 ]; then + BAND="n39" + elif [ $CHAN -le 386000 ]; then + BAND="-" + elif [ $CHAN -le 398000 ]; then + BAND="n2|n25" + elif [ $CHAN -le 399000 ]; then + BAND="n25" + elif [ $CHAN -le 402000 ]; then + BAND="n70" + elif [ $CHAN -le 404000 ]; then + BAND="n34|n70" + elif [ $CHAN -le 405000 ]; then + BAND="n34" + elif [ $CHAN -le 422000 ]; then + BAND="-" + elif [ $CHAN -le 434000 ]; then + BAND="n1|n65|n66" + elif [ $CHAN -le 440000 ]; then + BAND="n65|n66" + elif [ $CHAN -le 460000 ]; then + BAND="-" + elif [ $CHAN -le 470000 ]; then + BAND="n40" + elif [ $CHAN -le 472000 ]; then + BAND="n30|n40" + elif [ $CHAN -le 480000 ]; then + BAND="n40" + elif [ $CHAN -le 496700 ]; then + BAND="-" + elif [ $CHAN -le 499000 ]; then + BAND="n53" + elif [ $CHAN -le 499200 ]; then + BAND="-" + elif [ $CHAN -le 514000 ]; then + BAND="n41|n90" + elif [ $CHAN -le 524000 ]; then + BAND="n38|n41|n90" + elif [ $CHAN -le 538000 ]; then + BAND="n7|n90" + elif [ $CHAN -le 620000 ]; then + BAND="-" + elif [ $CHAN -le 636667 ]; then + BAND="n77|n78" + elif [ $CHAN -le 646666 ]; then + BAND="n48|n77|n78" + elif [ $CHAN -le 653333 ]; then + BAND="n77|n78" + elif [ $CHAN -le 680000 ]; then + BAND="n77" + elif [ $CHAN -le 693334 ]; then + BAND="-" + elif [ $CHAN -le 733333 ]; then + BAND="n79" + else + BAND="-" + fi +} + +if [ -z "$CHAN" ]; then + BAND="-" +elif [ "$CHAN" -lt 123400 ]; then + decode_lte +elif [ "$CHAN" -lt 733333 ]; then + decode_nr5g +else + BAND="-" +fi +echo $BAND +exit diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/common/fibocomdata.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/common/fibocomdata.sh new file mode 100644 index 0000000..8e4ef40 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/common/fibocomdata.sh @@ -0,0 +1,476 @@ +#!/bin/sh + +ROOTER=/usr/lib/rooter + +log() { + logger -t "Fibocom Data" "$@" +} + +CURRMODEM=$1 +COMMPORT=$2 + +decode_signal() { + if [ "$CRAT" -eq 4 ]; then + RSCPs=$(($RSRP - 141)) + if [ -n "$RSCP" ]; then + RSCP=$RSCP" dBm
                                                                        "$RSCPs + else + RSCP=$RSCPs + fi + if [ -n "$ECIO" ]; then + ECIO=$ECIO" dB
                                                                        "$((($RSRQ / 2) - 20)) + else + ECIO=$((($RSRQ / 2) - 20)) + fi + elif [ "$CRAT" -eq 9 ]; then + RSCPs=$(($RSRP - 157)) + if [ -n "$RSCP" ]; then + RSCP=$RSCP" dBm
                                                                        "$RSCPs + else + RSCP=$RSCPs + fi + if [ -n "$ECIO" ]; then + ECIO=$ECIO" dB
                                                                        "$((($RSRQ / 2) - 43)) + else + ECIO=$((($RSRQ / 2) - 43)) + fi + fi +} +decode_bw() { + case $BW in + "0") + BW="1.4" ;; + "1") + BW="3" ;; + "2") + BW="5" ;; + "3") + BW="10" ;; + "4") + BW="15" ;; + "5") + BW="20" ;; + *) + BW="-";; + esac +} + +OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "fibocominfo.gcom" "$CURRMODEM") + +OX=$(echo $OX | tr 'a-z' 'A-Z') + +SERVING=$(echo $OX | grep -o "+GTCCINFO:.\+COPN:") +if [ -z "$SERVING" ]; then + SERVING=$(echo $OX | grep -o "+GTCCINFO:.\+GTRAT") +fi + +REGXa="[12],[249],[0-9]\{3\},[0-9]\{2,3\},[0-9A-F]\{0,5\},[0-9A-F]\{0,10\},[0-9A-F]\{1,8\},[0-9A-F]\{1,8\},[15][0-9]\{1,4\},[0-9]\{1,3\},[-0-9]\{1,5\},[0-9]\{1,3\},[0-9]\{1,3\},[0-9]\{1,3\}" + +REGXb="+GTCAINFO: 1,[0-9]\{1,2\},[0-9]\{3\},[0-9]\{2,3\},[0-9]\{1,5\},[0-9]\{3,9\},[0-9]\{1,3\},[0-9]\{1,3\},[0-9]\{1,3\},[-0-9]\{1,4\},[0-9]\{1,6\},[0-9]\{1,6\},[0-9]\{1,3\},[0-9]\{1,3\}" + +REGXc="+GTCAINFO: [2-9],[0-9]\{1,2\},[0-9]\{1,5\},[0-9]\{1,3\},[0-9]\{1,3\},[-0-9]\{1,4\},[0-9]\{1,5\},[0-9]\{1,5\},[0-9]\{1,3\},[0-9]\{1,3\}" + +REGXd="+XMCI: 2,[0-9]\{3\},[0-9]\{2,3\},[^,]\+,[^,]\+,[^,]\+,\"0X[0-9A-F]\{8\}\",[^,]\+,[^,]\+,[0-9]\{1,2\},[0-9]\{1,2\},[0-9]\{1,2\}" + +REGXe="+XMCI: 4,[0-9]\{3\},[0-9]\{2,3\},[^,]\+,[^,]\+,\"0X[0-9A-F]\{4\}\",\"0X[0-9A-F]\{8\}\",[^,]\+,[^,]\+,[0-9]\{1,2\},[0-9]\{1,2\},[-0-9]\{1,5\}" + +REGXf="SCC[0-9]: 1,0,[0-9]\{1,3\},1[0-9]\{2\},[0-9]\{1,6\},[0-9]\{1,3\}" + +REGXg="2,4,,,,,[0-9A-F]\{1,5\},[0-9A-F]\{1,3\},,[0-9]\{1,3\},[0-9]\{1,3\},[0-9]\{1,3\}" +REGXh="2,9,,,,,[0-9A-F]\{5\},[0-9A-F]\{1,3\},,[0-9]\{1,3\},[0-9]\{1,3\},[0-9]\{1,3\}" +REGXy="1,4,[0-9]\{3\},[0-9]\{2,3\},[0-9A-F]\{0,5\},[0-9A-F]\{0,10\},[0-9]\{1,8\}, ,[0-9]\{1,2\},[0-5], ," + +CHANNEL="-" +ECIO="-" +RSCP="-" +ECIO1=" " +RSCP1=" " +MODE="-" +NETMODE="-" +LBAND="-" +PCI="-" +CTEMP="-" +SINR="" +COPS_MCC="" + +CSQ=$(echo $OX | grep -o "+CSQ: [0-9]\{1,2\}" | grep -o "[0-9]\{1,2\}") +if [ "$CSQ" = "99" ]; then + CSQ="" +fi +if [ -n "$CSQ" ]; then + CSQ_PER=$(($CSQ * 100/31))"%" + CSQ_RSSI=$((2 * CSQ - 113))" dBm" +else + CSQ="-" + CSQ_PER="-" + CSQ_RSSI="-" +fi + +if [ -n "$SERVING" ]; then + MODE=$(echo $SERVING | grep -o "+GTCCINFO: .\+ SERVICE CELL:") + LENM=${#MODE} + if [ $LENM -gt 25 ]; then + MODE=${MODE:11:$LENM-25} + else + MODE="-" + fi + GTCCDATA=$(echo $SERVING | grep -o "$REGXa") + GTCCDATAy=$(echo $SERVING | grep -o "$REGXy") + LTENEIGH=$(echo $SERVING | grep -o "$REGXg") + NRNEIGH=$(echo $SERVING | grep -o "$REGXh") + echo "" > /tmp/scan$CURRMODEM + for NVAL in $(echo "$LTENEIGH"); do + CHAN=$(echo $NVAL | cut -d, -f7) + CHAN=$(printf "%d" 0x$CHAN) + BAND=$(/usr/lib/rooter/chan2band.sh $CHAN) + PCIx=$(echo $NVAL | cut -d, -f8) + PCIx=$(printf "%d" 0x$PCIx) + RSSI=$(echo $NVAL | cut -d, -f11) + RSSI=$(($RSSI - 141)) + echo -e "Band : $BAND\tPCI : $PCIx\tSignal : $RSSI (dBm)" >> /tmp/scan$CURRMODEM + done + for NVAL in $(echo "$NRNEIGH"); do + CHAN=$(echo $NVAL | cut -d, -f7) + CHAN=$(printf "%d" 0x$CHAN) + BAND=$(/usr/lib/rooter/chan2band.sh $CHAN) + PCIx=$(echo $NVAL | cut -d, -f8) + PCIx=$(printf "%d" 0x$PCIx) + RSSI=$(echo $NVAL | cut -d, -f11) + RSSI=$(($RSSI - 157)) + echo -e "Band : $BAND\tPCI : $PCIx\tSignal : $RSSI (dBm)" >> /tmp/scan$CURRMODEM + done + CADATA1="" + CADATA2="" + XUDATA="" + XLDATA="" +else + GTCCDATA="" + CADATA1=$(echo $OX | grep -o "$REGXb") + CADATA2=$(echo $OX | grep -o "$REGXc") + if [ -n "$CADATA2" ]; then + if [ "$(echo $CADATA2 | cut -d, -f7)" = "65535" ]; then + CADATA2="" + fi + fi + XUDATA=$(echo $OX | grep -o "$REGXd") + XLDATA=$(echo $OX | grep -o "$REGXe") +fi +CADATA3=$(echo $OX | grep -o "$REGXf") +if [ -n "$GTCCDATA" ]; then + COPS_MCC=$(echo $GTCCDATA | cut -d, -f3) + COPS_MNC=$(echo $GTCCDATA | cut -d, -f4) + COPX="" + COPN=$(echo $OX" " | grep -o "+COPN: .\+ OK " | tr " " "," | tr -d '"' ) + if [ -n "$COPN" ]; then + COPP=$(echo $COPN" " | sed "s/.*\($COPS_MCC$COPS_MNC,.*\)\,/\1/") + if [ -n "$COPP" ]; then + COPX=$(echo $COPP | cut -d, -f2) + fi + fi + + LBAND="" + CHANNEL="" + RSCP="" + ECIO="" + PCI="" + XUDATA="" + for CCVAL in $(echo "$GTCCDATA"); do + CELLTYPE=$(echo $CCVAL | cut -d, -f1) + CRAT=$(echo $CCVAL | cut -d, -f2) + BAND=$(echo $CCVAL | cut -d, -f9) + CHAN=$(echo $CCVAL | cut -d, -f7) + CHAN=$(printf "%d" 0x$CHAN) + PCID=$(echo $CCVAL | cut -d, -f8) + PCID=$(printf "%d" 0x$PCID) + BW=$(echo $CCVAL | cut -d, -f10) + if [ "$CRAT" -eq 4 ]; then + SSINR=$(echo $CCVAL | cut -d, -f11 | grep -o "[-0-9]\{1,4\}") + if [ -n "$SSINR" ] && [ "$SSINR" != "255" ]; then + SSINR=$(($SSINR / 2))" dB" + else + SSINR="-" + fi + if [ -n "$SINR" ]; then + SINR=$SINR"
                                                                        "$SSINR + else + SINR=$SSINR + fi + if [ $BW -gt 14 ]; then + BW=$(($(echo $BW) / 5)) + else + BW="1.4" + fi + BAND=${BAND:1} + if [ "$CELLTYPE" -eq 1 ]; then + BAND="B"$(($BAND + 0))" (Bandwidth: "$BW" MHz)" + else + BAND="B"$(($BAND + 0))" (CA, Bandwidth: "$BW" MHz)" + fi + fi + if [ "$CRAT" -eq 9 ]; then + SSINR=$(echo $CCVAL | cut -d, -f11 | grep -o "[0-9]\{1,3\}") + if [ -n "$SSINR" ] && [ "$SSINR" != "255" ]; then + SSINR=$((($SSINR - 47) / 2))" dB" + else + SSINR="-" + fi + if [ -n "$SINR" ]; then + SINR=$SINR"
                                                                        "$SSINR + else + SINR=$SSINR + fi + if [ "$CELLTYPE" -eq 1 ]; then + BAND="n"${BAND:2}" (Bandwidth: "$BW" MHz)" + else + BAND="n"${BAND:2}" (CA, Bandwidth: "$BW" MHz)" + fi + fi + if [ -n "$LBAND" ]; then + LBAND=$LBAND"
                                                                        "$BAND + else + LBAND=$BAND + fi + if [ -n "$CHANNEL" ]; then + CHANNEL=$CHANNEL","$CHAN + else + CHANNEL=$CHAN + fi + if [ -n "$PCI" ]; then + PCI=$PCI","$PCID + else + PCI=$PCID + fi + if [ "$CELLTYPE" -eq 1 ]; then + RSRP=$(echo $CCVAL | cut -d, -f13) + RSRQ=$(echo $CCVAL | cut -d, -f14) + if [ "$RSRP" -ne 255 ] && [ "$RSRQ" -ne 255 ]; then + decode_signal + RSSI=$(rsrp2rssi $RSCPs $BW) + CSQ_PER=$((100 - (($RSSI + 51) * 100/-62)))"%" + CSQ=$((($RSSI + 113) / 2)) + CSQ_RSSI=$RSSI" dBm" + fi + fi + done +fi + +if [ -n "$GTCCDATAy" ]; then + CHANNEL=$(echo $GTCCDATAy | cut -d, -f7) + BW=$(echo $GTCCDATAy | cut -d, -f10) + decode_bw + LBAND="B"$(echo $GTCCDATAy | cut -d, -f9)" (Bandwidth: "$BW" MHz)" + XUDATA="" +fi + +if [ -n "$XLDATA" ]; then + XLDATA=$(echo "${XLDATA//[\" ]/}") + XLEC=$(echo $OX | grep -o "+XLEC: [01],[0-9]\+,[0-5],.*BAND_LTE_[0-9]\{1,2\},[^ ]\+") + MODE="LTE" + PCI=$(echo $XLDATA | cut -d, -f6) + PCI=$(printf "%d" $PCI) + CHANNEL=$(echo $XLDATA | cut -d, -f7) + CHANNEL=$(printf "%d" $CHANNEL) + LBAND=$($ROOTER/chan2band.sh "$CHANNEL") + if [ -n "$XLEC" ]; then + BW=$(echo $XLEC | cut -d, -f3) + RAWLIST=$(echo $XLEC | grep -o "BAND_LTE_[0-9]\{1,2\}.\+" | grep -o "[,0-9]*" | tr ',' ' ') + BANDLIST="" + for BAND in $(echo "$RAWLIST"); do + if [ -n "$BAND" -a "$BAND" != "0" ]; then + if [ -n "$BANDLIST" ]; then + BANDLIST="$BANDLIST,$BAND" + else + BANDLIST="$BAND" + fi + fi + done + BAND="B"$(echo $BANDLIST | cut -d, -f1) + if [ "$BAND" = "$LBAND" ]; then + decode_bw + LBAND=$LBAND" (Bandwidth $BW MHz)" + NUMBR=$(echo $XLEC | cut -d, -f2) + for JJ in $(seq 2 $NUMBR); do + BAND=$(echo $BANDLIST | cut -d, -f$JJ) + if [ -n "$BAND" -a "$BAND" != "0" ]; then + KK=$(($JJ + 2)) + BW=$(echo $XLEC | cut -d, -f$KK) + decode_bw + if [ $BW != "-" ]; then + LBAND=$LBAND"
                                                                        B$BAND (CA, Bandwidth $BW MHz)" + fi + fi + done + fi + else + XLEC=$(echo $OX | grep -o "+XLEC: 0,[1-9],[0-5]") + if [ -n "$XLEC" ]; then + BW=$(echo $XLEC | cut -d, -f3) + decode_bw + LBAND=$LBAND" (Bandwidth $BW MHz)" + fi + fi + RSRP=$(echo $XLDATA | cut -d, -f10) + if [ $RSRP == 0 ]; then + RSRP=1 + fi + RSCP=$(($RSRP - 141)) + ECIO=$(echo $XLDATA | cut -d, -f11) + ECIO=$((($ECIO / 2) - 20)) + SINR=$(echo $XLDATA | cut -d, -f12 | grep -o "[-0-9]\{1,4\}") + if [ -n "$SINR" ] && [ "$SINR" != "255" ]; then + SINR=$(($SINR / 2))" dB" + fi + RSSI=$(rsrp2rssi $RSCP $BW) + CSQ_PER=$((100 - (($RSSI + 51) * 100/-62)))"%" + CSQ=$((($RSSI + 113) / 2)) + CSQ_RSSI=$RSSI" dBm" +fi +if [ -n "$XUDATA" ]; then + MODE="UMTS" + CHANNEL=$(echo $XUDATA | cut -d, -f7) + CHANNEL=${CHANNEL:1:10} + CHANNEL=$(printf "%d" $CHANNEL) + RSCP=$(echo $XUDATA | cut -d, -f11) + RSCP=$(($RSCP - 121)) + ECIO=$(echo $XUDATA | cut -d, -f12) + ECIO=$((($ECIO / 2) - 24)) +fi +if [ -n "$CADATA1" ]; then + RSCP="" + ECIO="" + BW=$(echo $CADATA1 | cut -d, -f13) + decode_bw + BWD=$BW + BW=$(echo $CADATA1 | cut -d, -f14) + decode_bw + BWU=$BW + LBAND="B"$(echo $CADATA1 | cut -d, -f2)" (Bandwidth $BWD MHz Down | $BWU MHz Up)" + CHANNEL=$(echo $CADATA1 | cut -d, -f11) + MODE="LTE" + CRAT="4" + RSRP=$(echo $CADATA1 | cut -d, -f8) + RSRQ=$(echo $CADATA1 | cut -d, -f9) + if [ "$RSRP" -ne 255 ] && [ "$RSRQ" -ne 255 ]; then + decode_signal + RSSI=$(rsrp2rssi $RSCPs $BWD) + CSQ_PER=$((100 - (($RSSI + 51) * 100/-62)))"%" + CSQ=$((($RSSI + 113) / 2)) + CSQ_RSSI=$RSSI" dBm" + else + RSRP="-" + RSRQ="-" + fi + PCI=$(echo $CADATA1 | cut -d, -f7) +fi +if [ -n "$CADATA2" ]; then + CADATA2=$(echo "${CADATA2//[ ]/}") + for CAVAL in $(echo "$CADATA2"); do + BW=$(echo $CAVAL | cut -d, -f9) + decode_bw + BWD=$BW + BW=$(echo $CAVAL | cut -d, -f10) + decode_bw + BWU=$BW + LBAND=$LBAND"
                                                                        B"$(echo $CAVAL | cut -d, -f2) + if [ $BWU = "-" ]; then + LBAND=$LBAND" (CA, Bandwidth: "$BWD" MHz)" + else + LBAND=$LBAND" (CA, Bandwidth $BWD MHz Down | $BWU MHz Up)" + fi + CHAN=$(echo $CAVAL | cut -d, -f7) + CHANNEL=$(echo "$CHANNEL", "$CHAN") + PCIX=$(echo $CAVAL | cut -d, -f3) + PCI=$(echo "$PCI", "$PCIX") + done +fi +if [ -n "$CADATA3" ]; then + CADATA3=$(echo "${CADATA3//[ ]/}") + for CAVAL in $(echo "$CADATA3"); do + BAND=$(echo $CAVAL | cut -d, -f3) + BAND=${BAND:1} + PCIX=$(echo $CAVAL | cut -d, -f4) + PCI=$(echo "$PCI", "$PCIX") + CHAN=$(echo $CAVAL | cut -d, -f5) + CHANNEL=$(echo "$CHANNEL", "$CHAN") + BW=$(echo $CAVAL | cut -d, -f6) + if [ $BW -gt 14 ]; then + BW=$(($(echo $BW) / 5)) + else + BW="1.4" + fi + LBAND=$LBAND"
                                                                        B"$(($BAND + 0))" (CA, Bandwidth: "$BW" MHz)" + done +fi + +MTEMP=$(echo $OX | grep -o "+MTSM: [0-9.]\{1,5\}") +if [ -n "$MTEMP" ]; then + CTEMP=$(echo $MTEMP | grep -o "[0-9.]\{1,5\}")$(printf "\xc2\xb0")"C" +fi + +MODTYPE="9" +MRAT=$(echo $OX | grep -o "+GTRAT: [0-9]\{1,2\}" | grep -o "[0-9]\{1,2\}") +if [ -n "$MRAT" ]; then +# If user inserted different SIM card, the Rat order will recover to default value (AT Commands manual) + case $MRAT in + "2" ) + NETMODE="5" ;; + "3" ) + NETMODE="7" ;; + "14" ) + NETMODE="9" ;; + "17"|"20" ) + NETMODE="8" ;; + * ) + NETMODE="1" ;; + esac +fi +XACT=$(echo $OX | grep -o "+XACT: [0-9]" | grep -o "[0-9]") +if [ -n "$XACT" ]; then + PREF=$(echo $OX | grep -o "+XACT: [0-9],[0-9]" | grep -o ",[0-9]") + case $XACT in + "1" ) + NETMODE="5" ;; + "2" ) + NETMODE="7" ;; + "4" ) + if [ "$PREF" = ",1" ]; then + NETMODE="4" + else + NETMODE="6" + fi ;; + * ) + NETMODE="6" ;; + esac +fi +CMODE=$(uci -q get modem.modem$CURRMODEM.cmode) +if [ "$CMODE" = 0 ]; then + NETMODE="10" +fi +if [ -z "$SINR" ]; then + SINR="-" +fi + +{ + echo 'CSQ="'"$CSQ"'"' + echo 'CSQ_PER="'"$CSQ_PER"'"' + echo 'CSQ_RSSI="'"$CSQ_RSSI"'"' + echo 'ECIO="'"$ECIO"'"' + echo 'RSCP="'"$RSCP"'"' + echo 'ECIO1="'"$ECIO1"'"' + echo 'RSCP1="'"$RSCP1"'"' + echo 'MODE="'"$MODE"'"' + echo 'MODTYPE="'"$MODTYPE"'"' + echo 'NETMODE="'"$NETMODE"'"' + echo 'CHANNEL="'"$CHANNEL"'"' + echo 'LBAND="'"$LBAND"'"' + echo 'PCI="'"$PCI"'"' + echo 'TEMP="'"$CTEMP"'"' + echo 'SINR="'"$SINR"'"' +} > /tmp/signal$CURRMODEM.file +if [ -n "$COPS_MCC" ]; then + echo 'COPS_MCC="'"$COPS_MCC"'"' >> /tmp/signal$CURRMODEM.file + echo 'COPS_MNC="'"$COPS_MNC"'"' >> /tmp/signal$CURRMODEM.file +fi +if [ -n "$COPX" ]; then + echo 'COPS="'"$COPX"'"' >> /tmp/signal$CURRMODEM.file +fi diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/common/gettype.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/common/gettype.sh new file mode 100644 index 0000000..19fad9f --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/common/gettype.sh @@ -0,0 +1,213 @@ +#!/bin/sh + +ROOTER=/usr/lib/rooter + +echo "0" > /tmp/block + +decode_crsm() { + i=0 + while [ $i -lt $length ]; do + c1=${sstring:$i:1} + let 'j=i+1' + c2=${sstring:$j:1} + xstring=$xstring$c2$c1 + let 'i=i+2' + done +} + +CURRMODEM=$1 +CPORT=$(uci get modem.modem$CURRMODEM.commport) + +OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "gettype.gcom" "$CURRMODEM") +OX=$($ROOTER/common/processat.sh "$OX") + +MANUF=$(echo "$OX" | awk -F[:] '/Manufacturer:/ { print $2}') + +if [ -z "$MANUF" ]; then + ATCMDD="AT+CGMI" + MANUF=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + MANUF=$(echo $MANUF) + MANUF=$(echo "${MANUF//[\"]/}") + MANUF=${MANUF::-3} + MPREFIX=${MANUF::8} + if [ "$MPREFIX" = "AT+CGMI " ]; then + MANUF=$(echo $MANUF | cut -c 9-) + fi + MPREFIX=${MANUF::7} + if [ "$MPREFIX" = "+CGMI: " ]; then + MANUF=$(echo $MANUF | cut -c 8-) + fi +fi +if [ -z "$MANUF" ]; then + MANUF=$(uci get modem.modem$CURRMODEM.manuf) +fi + +MODEL=$(echo "$OX" | awk -F[,\ ] '/^\+MODEL:/ {print $2}') + +if [ -z "$MODEL" ]; then + ATCMDD="AT+CGMM" + MODEL=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + MODEL=$(echo $MODEL) + MODEL=$(echo "${MODEL//[\"]/}") + MODEL=${MODEL::-3} + MPREFIX=${MODEL::8} + if [ "$MPREFIX" = "AT+CGMM " ]; then + MODEL=$(echo $MODEL | cut -c 9-) + fi + MPREFIX=${MODEL::7} + if [ "$MPREFIX" = "+CGMM: " ]; then + MODEL=$(echo $MODEL | cut -c 8-) + fi + MODEL=$(echo $MODEL | cut -d, -f1) +fi +if [ -z "$MODEL" ]; then + MODEL=$(uci get modem.modem$CURRMODEM.model) +fi + +uci set modem.modem$CURRMODEM.manuf="$MANUF" +uci set modem.modem$CURRMODEM.model="$MODEL" +uci commit modem + +$ROOTER/signal/status.sh $CURRMODEM "$MANUF $MODEL" "Connecting" + +IMEI=$(echo "$OX" | awk -F[,\ ] '/^\IMEI:/ {print $2}') + +if [ -z "$IMEI" ]; then + ATCMDD="AT+CGSN" + IMEI=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + IMEI=$(echo $IMEI | grep -o "[0-9]\{15\}") +fi + +if [ -z "$IMEI" ]; then + ATCMDD="ATI5" + IMEI=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + IMEI=$(echo $IMEI | grep -o "[0-9]\{15\}") +fi + +if [ -n "$IMEI" ]; then + IMEI=$(echo "$IMEI" | sed -e 's/"//g') + IMEI=${IMEI:0:15} +else + IMEI="Unknown" +fi +uci set modem.modem$CURRMODEM.imei=$IMEI + +IDP=$(uci get modem.modem$CURRMODEM.idP) +IDV=$(uci get modem.modem$CURRMODEM.idV) + +echo $IDV" : "$IDP > /tmp/msimdatax$CURRMODEM +echo "$IMEI" >> /tmp/msimdatax$CURRMODEM + +lua $ROOTER/signal/celltype.lua "$MODEL" $CURRMODEM +source /tmp/celltype$CURRMODEM +rm -f /tmp/celltype$CURRMODEM + +uci set modem.modem$CURRMODEM.celltype=$CELL +uci commit modem + +$ROOTER/luci/celltype.sh $CURRMODEM + +M2=$(echo "$OX" | grep -o "+CNUM:[^,]*,[^,]*,[0-9]\{3\}")"," +M2=${M2:6} +CNUMx=$(echo "$M2" | cut -d, -f1 | cut -d\" -f2) +CNUMx=$(echo $CNUMx) +CNUM=$(echo "$M2" | cut -d, -f2 | cut -d\" -f2) +CNUMtype=$(echo "$M2" | cut -d, -f3) +if [ "${CNUM:0:1}" != "+" -a "$CNUMtype" == "145" ]; then + CNUM="+"$CNUM +fi +if [ -z "$CNUM" ]; then + CNUM="*" +fi +if [ -z "$CNUMx" ]; then + CNUMx="*" +fi + +NLEN=$(echo "$OX" | awk -F[,\ ] '/^\+CPBR:/ {print $4}') +if [ "x$NLEN" != "x" ]; then + NLEN=$(echo "$NLEN" | sed -e 's/"//g') +else + NLEN="14" +fi +echo 'NLEN="'"$NLEN"'"' > /tmp/namelen$CURRMODEM + +ATCMDD="ATE1" +OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") +ATCMDD="AT+CTZU=1" +OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") +ATCMDD="AT\$QCPBMPREF?" +OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") +PBzero=$(echo "$OX" | grep "0") +if [ -n "$PBzero" ]; then + ATCMDD="AT\$QCPBMPREF=1" + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") +fi +if [ "$IDV" == "2c7c" ]; then + ATCMDD="AT+QLWCFG=\"startup\"" + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + LWon=$(echo "$OX" | grep "1") + if [ -n "$LWon" ]; then + ATCMDD="AT+QLWCFG=\"startup\",0" + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + fi + ATCMDD="AT+QCFG=\"ims\"" + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + IMSon=$(echo "$OX" | grep "1") + if [ -z "$IMSon" ]; then + ATCMDD="AT+QCFG=\"ims\",1" + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + fi +fi +ATCMDD="AT+CIMI" +OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") +OX=$($ROOTER/common/processat.sh "$OX") +ERROR="ERROR" +if `echo ${OX} | grep "${ERROR}" 1>/dev/null 2>&1` +then + ATCMDD="AT+CRSM=176,28423,0,0,9" + sstring=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD" | grep -o "[0-9F]\{18\}") + if [ -n "$sstring" ]; then + length=${#sstring} + decode_crsm + IMSI=${xstring:3} + else + IMSI="Unknown" + fi +else + OX=${OX//[!0-9]/} + IMSIL=${#OX} + IMSI=${OX:0:$IMSIL} +fi +echo "$IMSI" >> /tmp/msimdatax$CURRMODEM +uci set modem.modem$CURRMODEM.imsi=$IMSI + +ATCMDD="AT+CRSM=176,12258,0,0,10" +OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") +OX=$($ROOTER/common/processat.sh "$OX") +ERROR="ERROR" +if `echo ${OX} | grep "${ERROR}" 1>/dev/null 2>&1` +then + ICCID="Unknown" +else + ICCID=$(echo "$OX" | awk -F[,\ ] '/^\+CRSM:/ {print $4}') + if [ "x$ICCID" != "x" ]; then + sstring=$(echo "$ICCID" | sed -e 's/"//g') + length=${#sstring} + xstring="" + decode_crsm + ICCID=$xstring + else + ICCID="Unknown" + fi +fi +uci set modem.modem$CURRMODEM.iccid=$ICCID +uci commit modem +echo "$ICCID" >> /tmp/msimdatax$CURRMODEM +echo "0" >> /tmp/msimdatax$CURRMODEM +echo "$CNUM" > /tmp/msimnumx$CURRMODEM +echo "$CNUMx" >> /tmp/msimnumx$CURRMODEM + +mv -f /tmp/msimdatax$CURRMODEM /tmp/msimdata$CURRMODEM +mv -f /tmp/msimnumx$CURRMODEM /tmp/msimnum$CURRMODEM + +rm -f /tmp/block diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/common/huaweidata.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/common/huaweidata.sh new file mode 100644 index 0000000..8134784 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/common/huaweidata.sh @@ -0,0 +1,299 @@ +#!/bin/sh + +ROOTER=/usr/lib/rooter + +log() { + logger -t "Huawei Data" "$@" +} + +CURRMODEM=$1 +COMMPORT=$2 + +fix_data() { + O=$($ROOTER/common/processat.sh "$OY") +} + +process_csq() { + CSQ=$(echo "$O" | awk -F[,\ ] '/^\+CSQ:/ {print $2}') + [ "x$CSQ" = "x" ] && CSQ=-1 + if [ $CSQ -ge 0 -a $CSQ -le 31 ]; then + CSQ_PER=$(($CSQ * 100/31)) + CSQ_RSSI=$((2 * CSQ - 113)) + CSQX=$CSQ_RSSI + [ $CSQ -eq 0 ] && CSQ_RSSI="<= "$CSQ_RSSI + [ $CSQ -eq 31 ] && CSQ_RSSI=">= "$CSQ_RSSI + CSQ_PER=$CSQ_PER"%" + CSQ_RSSI=$CSQ_RSSI" dBm" + else + CSQ="-" + CSQ_PER="-" + CSQ_RSSI="-" + fi +} + +process_huawei() { + CSNR=$(echo "$O" | awk -F[,\ ] '/^\^CSNR:/ {print $2}') + if [ "x$CSNR" != "x" ]; then + RSCP=$CSNR + CSNR=$(echo "$O" | awk -F[,\ ] '/^\^CSNR:/ {print $3}') + if [ "x$CSNR" != "x" ]; then + ECIO=$CSNR + else + ECIO=`expr $RSCP - $CSQX` + fi + else + EC=$(echo "$O" | awk -F[,\ ] '/^\+CSQ:/ {print $4}') + if [ "x$EC" != "x" ]; then + ECIO=$EC + EX=$(printf %.0f $ECIO) + RSCP=`expr $CSQX + $EX` + fi + fi + + HCSQ=$(echo "$O" | grep -o "\^HCSQ:[ ]*\"LTE\",[^,]*,[^,]*,[0-9]\{1,3\}") + if [ -n "$HCSQ" ]; then + SINR=$(echo $HCSQ | cut -d, -f4) + if [ $SINR -lt 255 ]; then + SINR=$((($SINR / 5) - 20)) + else + SINR="-" + fi + fi + + LTERSRP=$(echo "$O" | awk -F[,\ ] '/^\^LTERSRP:/ {print $2}') + if [ "x$LTERSRP" != "x" ]; then + RSCP=$LTERSRP + LTERSRP=$(echo "$O" | awk -F[,\ ] '/^\^LTERSRP:/ {print $3}') + if [ "x$LTERSRP" != "x" ]; then + ECIO=$LTERSRP + else + ECIO=`expr $RSCP - $CSQX` + fi + fi + LBANDS=$(echo $O | grep -o "\^HFREQINFO:[0-9,]\+") + LBAND="" + CHANNEL="" + printf '%s\n' "$LBANDS" | while read LBANDL; do + CHANN=$(echo $LBANDL | cut -d, -f4 | grep -o "[0-9]\{2,6\}") + if [ -z "$CHANN" ]; then + LBAND="" + CHANNEL="" + else + BWU=$(($(echo $LBANDL | cut -d, -f9) / 1000)) + BWD=$(($(echo $LBANDL | cut -d, -f6) / 1000)) + LBANDL=$(echo $LBANDL | cut -d, -f3) + if [ -z "$LBANDL" ]; then + LBAND="" + else + if [ -n "$LBAND" ]; then + LBAND=$LBAND" aggregated with:
                                                                        " + fi + LBAND=$LBAND"B"$LBANDL" (Bandwidth $BWD MHz Down | $BWU MHz Up)" + fi + if [ -n "$CHANN" ]; then + if [ -n "$CHANNEL" ]; then + CHANNEL=$CHANNEL", "$CHANN + else + CHANNEL=$CHANN + fi + fi + + fi + { + echo "$LBAND" + echo "$CHANNEL" + } > /tmp/lbandvar$CURRMODEM + done + if [ -e /tmp/lbandvar$CURRMODEM ]; then + { + read LBAND + read CHANNEL + } < /tmp/lbandvar$CURRMODEM + rm /tmp/lbandvar$CURRMODEM + fi + if [ -z "$LBAND" ]; then + LBAND="-" + fi + if [ -z "$CHANNEL" ]; then + CHANNEL="-" + fi + + NETMODE="0" + SYSCFG=$(echo "$O" | awk -F[,\"] '/^\^SYSCFGEX:/ {print $2}') + if [ "x$SYSCFG" != "x" ]; then + MODTYPE="3" + case $SYSCFG in + "00" ) + NETMODE="1" + ;; + "01" ) + NETMODE="3" + ;; + "02" ) + NETMODE="5" + ;; + "03" ) + NETMODE="7" + ;; + * ) + ACQ=${SYSCFG:0:2} + case $ACQ in + "01" ) + NETMODE="2" + ;; + "02" ) + NETMODE="4" + ;; + "03" ) + NETMODE="6" + ;; + esac + ;; + esac + else + SYSCFG=$(echo "$O" | awk -F[,\ ] '/^\^SYSCFG:/ {print $2}') + if [ "x$SYSCFG" != "x" ]; then + MODTYPE="4" + case $SYSCFG in + "7" ) + NETMODE="1" + ;; + "13" ) + NETMODE="3" + ;; + "14" ) + NETMODE="5" + ;; + * ) + SYSCFG=$(echo "$O" | awk -F[,\ ] '/^\^SYSCFG:/ {print $3}') + case $SYSCFG in + "0" ) + NETMODE="1" + ;; + "1" ) + NETMODE="2" + ;; + "2" ) + NETMODE="4" + ;; + esac + ;; + esac + fi + fi + + NETMODEx=$(uci get modem.modem$CURRMODEM.netmode) + if [ "$NETMODE" != "$NETMODEx" ]; then + uci set modem.modem$CURRMODEM.netmode="$NETMODE" + uci commit modem + fi + + MODE="-" + TECH=$(echo "$O" | awk -F[,] '/^\^SYSINFOEX:/ {print $9}' | sed 's/"//g') + if [ "x$TECH" != "x" ]; then + MODE="$TECH" + fi + + if [ "x$MODE" = "x-" ]; then + TECH=$(echo "$O" | awk -F[,\ ] '/^\^SYSINFO:/ {print $8}') + if [ "x$TECH" != "x" ]; then + case $TECH in + 17*) MODE="HSPA+ (64QAM)";; + 18*) MODE="HSPA+ (MIMO)";; + 1*) MODE="GSM";; + 2*) MODE="GPRS";; + 3*) MODE="EDGE";; + 4*) MODE="WCDMA";; + 5*) MODE="HSDPA";; + 6*) MODE="HSUPA";; + 7*) MODE="HSPA";; + 9*) MODE="HSPA+";; + *) MODE=$TECH;; + esac + fi + fi + + TEMP=$(echo "$O" | awk -F[,] '/^\^CHIPTEMP:/ {print $2}') + if [ "x$TEMP" != "x" ]; then + TEMP=$((TEMP / 10))$(printf "\xc2\xb0")"C" + else + TEMP="unknown" + fi + + CMODE=$(uci get modem.modem$CURRMODEM.cmode) + if [ $CMODE = 0 ]; then + NETMODE="10" + fi +} + +CSQ="-" +CSQ_PER="-" +CSQ_RSSI="-" +ECIO="-" +RSCP="-" +ECIO1=" " +RSCP1=" " +MODE="-" +CHANNEL="-" +LBAND="-" +MODETYPE="-" +NETMODE="-" +TEMP="-" +PCI="-" +SINR="-" + +OY=$($ROOTER/gcom/gcom-locked "$COMMPORT" "huaweiinfo.gcom" "$CURRMODEM") + +fix_data +process_csq +process_huawei + +{ + echo 'CSQ="'"$CSQ"'"' + echo 'CSQ_PER="'"$CSQ_PER"'"' + echo 'CSQ_RSSI="'"$CSQ_RSSI"'"' + echo 'ECIO="'"$ECIO"'"' + echo 'RSCP="'"$RSCP"'"' + echo 'ECIO1="'"$ECIO1"'"' + echo 'RSCP1="'"$RSCP1"'"' + echo 'MODE="'"$MODE"'"' + echo 'MODTYPE="'"$MODTYPE"'"' + echo 'NETMODE="'"$NETMODE"'"' + echo 'CHANNEL="'"$CHANNEL"'"' + echo 'LBAND="'"$LBAND"'"' + echo 'PCI="'"$PCI"'"' + echo 'TEMP="'"$TEMP"'"' + echo 'SINR="'"$SINR"'"' +} > /tmp/signal$CURRMODEM.file + +CONNECT=$(uci get modem.modem$CURRMODEM.connected) +if [ $CONNECT -eq 0 ]; then + exit 0 +fi + +if [ $CSQ = "-" ]; then + log "$OY" +fi + +ENB="0" +if [ -e /etc/config/failover ]; then + ENB=$(uci get failover.enabled.enabled) +fi +if [ $ENB = "1" ]; then + exit 0 +fi + +WWANX=$(uci get modem.modem$CURRMODEM.interface) +OPER=$(cat /sys/class/net/$WWANX/operstate 2>/dev/null) +rm -f "/tmp/connstat"$CURRMODEM + +if [ ! $OPER ]; then + exit 0 +fi +if echo $OPER | grep -q "unknown"; then + exit 0 +fi + +if echo $OPER | grep -q "down"; then + echo "1" > "/tmp/connstat"$CURRMODEM +fi diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/common/lockchk.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/common/lockchk.sh new file mode 100644 index 0000000..5d096ad --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/common/lockchk.sh @@ -0,0 +1,104 @@ +#!/bin/sh + +ROOTER=/usr/lib/rooter + +log() { + logger -t "Lock Provider" "$@" +} + +setautocops() { + if [ "$MODTYPE" = "2" -o "$MODTYPE" = "6" -o "$MODTYPE" = "8" -o "$MODTYPE" = "11" ]; then + NETMODE=$(uci get modem.modem$CURRMODEM.netmode) + case $NETMODE in + "3") + ATCMDD="AT+COPS=0,,,0" ;; + "5") + ATCMDD="AT+COPS=0,,,2" ;; + "7") + ATCMDD="AT+COPS=0,,,7" ;; + "8") + ATCMDD="AT+COPS=0,,,13" ;; + "9") + ATCMDD="AT+COPS=0,,,12" ;; + *) + ATCMDD="AT+COPS=0" ;; + esac + else + ATCMDD="AT+COPS=0" + fi + OX=$($ROOTER/gcom/gcom-locked "$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + CLOG=$(uci get modem.modeminfo$CURRMODEM.log) + if [ $CLOG = "1" ]; then + log "$OX" + fi + exit 0 +} + +CURRMODEM=$1 +if [ -e /usr/lib/netroam/lock.sh ]; then + if [ -e /tmp/rlock ]; then + /usr/lib/netroam/lock.sh $CURRMODEM + exit 0 + fi +fi +CPORT=/dev/ttyUSB$(uci get modem.modem$CURRMODEM.commport) +MODTYPE=$(uci get modem.modem$CURRMODEM.modemtype) +LOCK=$(uci get modem.modeminfo$CURRMODEM.lock) +if [ "$LOCK" = "2" ]; then + LOCK="4" +fi +ATCMDD="AT+COPS=3,2;+COPS?" +OX=$($ROOTER/gcom/gcom-locked "$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") +COPSMODE=$(echo $OX | grep -o "+COPS:[ ]\?[014]" | grep -o "[014]") +COPSPLMN=$(echo $OX | grep -o "[0-9]\{5,6\}") + +if [ -z "$LOCK" -o "$LOCK" = "0" ]; then + if [ "$COPSMODE" = "0" ]; then + exit 0 + fi + setautocops +fi +MCC=$(uci -q get modem.modeminfo$CURRMODEM.mcc) +LMCC=${#MCC} +if [ $LMCC -ne 3 ]; then + setautocops +fi +MNC=$(uci -q get modem.modeminfo$CURRMODEM.mnc) +if [ -z $MNC ]; then + setautocops +fi +LMNC=${#MNC} +if [ $LMNC -eq 1 ]; then + MNC=0$MNC +fi +if [ "$COPSMODE$COPSPLMN" = "$LOCK$MCC$MNC" ]; then + exit 0 +fi +if [ "$MODTYPE" = "2" -o "$MODTYPE" = "6" -o "$MODTYPE" = "8" -o "$MODTYPE" = "11" ]; then + NETMODE=$(uci get modem.modem$CURRMODEM.netmode) + case $NETMODE in + "3") + ATCMDD="AT+COPS=$LOCK,2,\"$MCC$MNC\",0" ;; + "5") + ATCMDD="AT+COPS=$LOCK,2,\"$MCC$MNC\",2" ;; + "7") + ATCMDD="AT+COPS=$LOCK,2,\"$MCC$MNC\",7" ;; + "8") + ATCMDD="AT+COPS=$LOCK,2,\"$MCC$MNC\",13" ;; + "9") + ATCMDD="AT+COPS=$LOCK,2,\"$MCC$MNC\",12" ;; + *) + ATCMDD="AT+COPS=$LOCK,2,\"$MCC$MNC\"" ;; + esac +else + ATCMDD="AT+COPS=$LOCK,2,\"$MCC$MNC\"" +fi + +OX=$($ROOTER/gcom/gcom-locked "$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") +CLOG=$(uci get modem.modeminfo$CURRMODEM.log) +if [ $CLOG = "1" ]; then + log "Error While Locking to Provider" + log "$OX" +else + log "Locked to Provider $MCC $MNC" +fi diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/common/mdm9215data.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/common/mdm9215data.sh new file mode 100644 index 0000000..c552b0a --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/common/mdm9215data.sh @@ -0,0 +1,127 @@ +#!/bin/sh + +ROOTER=/usr/lib/rooter + +log() { + logger -t "MDM9215 Data" "$@" +} + +CURRMODEM=$1 +COMMPORT=$2 + +OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "mdm9215info.gcom" "$CURRMODEM" | tr 'a-z' 'A-Z') +O=$($ROOTER/common/processat.sh "$OX") +O=$(echo $O) + +RSRP="" +RSRQ="" +CHANNEL="-" +ECIO="-" +RSCP="-" +ECIO1=" " +RSCP1=" " +MODE="-" +MODTYPE="-" +NETMODE="-" +LBAND="-" +TEMP="-" +PCI="-" +SINR="-" + +Oup=$(echo $O | tr 'a-z' 'A-Z') + +CSQ=$(echo $O | grep -o "CSQ: [0-9]\+" | grep -o "[0-9]\+") +[ "x$CSQ" = "x" ] && CSQ=-1 + +if [ $CSQ -ge 0 -a $CSQ -le 31 ]; then + CSQ_PER=$(($CSQ * 100/31)) + CSQ_RSSI=$((2 * CSQ - 113)) + CSQX=$CSQ_RSSI + [ $CSQ -eq 0 ] && CSQ_RSSI="<= "$CSQ_RSSI + [ $CSQ -eq 31 ] && CSQ_RSSI=">= "$CSQ_RSSI + CSQ_PER=$CSQ_PER"%" + CSQ_RSSI=$CSQ_RSSI" dBm" +else + CSQ="-" + CSQ_PER="-" + CSQ_RSSI="-" +fi + +MODE="-" +WS46=$(echo $O" " | grep -o "+COPS: .\+ OK " | tr " " ",") +TECH=$(echo $WS46 | cut -d, -f5) + +if [ ! -z "$TECH" ]; then + MODE=$TECH + SGCELL=$(echo $O" " | grep -o "\$QCSQ .\+ OK " | tr " " "," | tr ",:" ",") + + WS46=$(echo $O" " | grep -o "AT\$QCSYSMODE? .\+ OK ") + WS46=$(echo "$WS46" | sed -e "s/AT\$QCSYSMODE? //g") + WS46=$(echo "$WS46" | sed -e "s/ OK//g") + + case $MODE in + *) + RSCP=$(echo $SGCELL | cut -d, -f8) + RSCP="-"$(echo $RSCP | grep -o "[0-9]\{1,3\}") + ECIO=$(echo $SGCELL| cut -d, -f5) + ECIO="-"$(echo $ECIO | grep -o "[0-9]\{1,3\}") + RSSI=$(echo $SGCELL | cut -d, -f4) + CSQ_RSSI="-"$(echo $RSSI | grep -o "[0-9]\{1,3\}")" dBm" + ;; + "7") + RSSI=$(echo $SGCELL | cut -d, -f4) + CSQ_RSSI=$(echo $RSSI | grep -o "[0-9]\{1,3\}")" dBm" + RSCP=$(echo $SGCELL | cut -d, -f8) + RSCP="-"$(echo $RSCP | grep -o "[0-9]\{1,3\}") + ECIO=$(echo $SGCELL| cut -d, -f4) + ECIO="-"$(echo $ECIO | grep -o "[0-9]\{1,3\}") + ;; + esac + + MODE=$WS46 +fi + +NETMODE="1" +MODTYPE="8" + +{ + echo 'CSQ="'"$CSQ"'"' + echo 'CSQ_PER="'"$CSQ_PER"'"' + echo 'CSQ_RSSI="'"$CSQ_RSSI"'"' + echo 'ECIO="'"$ECIO"'"' + echo 'RSCP="'"$RSCP"'"' + echo 'ECIO1="'"$ECIO1"'"' + echo 'RSCP1="'"$RSCP1"'"' + echo 'MODE="'"$MODE"'"' + echo 'MODTYPE="'"$MODTYPE"'"' + echo 'NETMODE="'"$NETMODE"'"' + echo 'CHANNEL="'"$CHANNEL"'"' + echo 'LBAND="'"$LBAND"'"' + echo 'PCI="'"$PCI"'"' + echo 'TEMP="'"$TEMP"'"' + echo 'SINR="'"$SINR"'"' +} > /tmp/signal$CURRMODEM.file + +CONNECT=$(uci get modem.modem$CURRMODEM.connected) +if [ $CONNECT -eq 0 ]; then + exit 0 +fi + +if [ "$CSQ" = "-" ]; then + log "$OX" +fi + +WWANX=$(uci get modem.modem$CURRMODEM.interface) +OPER=$(cat /sys/class/net/$WWANX/operstate 2>/dev/null) +rm -f "/tmp/connstat"$CURRMODEM + +if [ ! $OPER ]; then + exit 0 +fi +if echo $OPER | grep -q "unknown"; then + exit 0 +fi + +if echo $OPER | grep -q "down"; then + echo "1" > "/tmp/connstat"$CURRMODEM +fi diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/common/meigdata.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/common/meigdata.sh new file mode 100644 index 0000000..360a708 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/common/meigdata.sh @@ -0,0 +1,281 @@ +#!/bin/sh + +ROOTER=/usr/lib/rooter + +log() { + logger -t "Meig Data" "$@" +} + +CURRMODEM=$1 +COMMPORT=$2 + +OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "meiginfo.gcom" "$CURRMODEM" | tr 'a-z' 'A-Z') + +O=$($ROOTER/common/processat.sh "$OX") +O=$(echo $O) +OX=$(echo $OX) + +RSRP="" +RSRQ="" +CHANNEL="-" +ECIO="-" +RSCP="-" +ECIO1=" " +RSCP1=" " +MODE="-" +MODTYPE="-" +NETMODE="-" +LBAND="-" +TEMP="-" +PCI="-" +SINR="-" + +CSQ=$(echo $OX | grep -o "+CSQ: [0-9]\{1,2\}" | grep -o "[0-9]\{1,2\}") +if [ "$CSQ" = "99" ]; then + CSQ="" +fi +if [ -n "$CSQ" ]; then + CSQ_PER=$(($CSQ * 100/31))"%" + CSQ_RSSI=$((2 * CSQ - 113))" dBm" +else + CSQ="-" + CSQ_PER="-" + CSQ_RSSI="-" +fi + +MODE="-" +PSRAT=$(echo $O" " | grep -o "+PSRAT: .\+ OK " | tr " " ",") +TECH=$(echo $PSRAT | cut -d, -f2) +if [ -n "$TECH" ]; then + MODE=$TECH +fi + +ATECH=$(echo $OX | grep -o "+SGCELLINFOEX:[^,]\{2,6\}," | grep -o ":[ ]\?[-A-Z5]\{2,6\}" | grep -o "[-A-Z5]\{2,6\}") +if [ -n "$ATECH" ]; then + MODE=$ATECH +fi + +SGCELL=$(echo $O" " | grep -o "+SGCELLINFO: .\+ OK " | tr " " ",") + +MODEx=$MODE +case $MODEx in + "TD-LTE"|"FDD-LTE"|"FDD" ) + RSSI=$(echo $SGCELL | cut -d, -f5) + CSQ_RSSI="-"$(echo $RSSI | grep -o "[0-9]\{1,3\}")" dBm" + RSCP=$(echo $SGCELL | cut -d, -f6) + RSCP="-"$(echo $RSCP | grep -o "[0-9]\{1,3\}") + ECIO=$(echo $SGCELL| cut -d, -f7) + ECIO="-"$(echo $ECIO | grep -o "[0-9]\{1,3\}") + SSINR=$(echo $SGCELL | cut -d, -f8 | grep -o "[0-9]\{1,3\}") + if [ -n "$SSINR" -a "$SSINR" -le "250" ]; then + SINR=$((($SSINR / 5) - 20))" dB" + fi + LBAND=$(echo $SGCELL | cut -d, -f9) + LBAND=$(echo $LBAND | grep -o "[0-9]\{1,5\}") + let LBAND=LBAND-119 + LBAND="B"$LBAND + CHANNEL=$(echo $SGCELL | cut -d, -f10) + CHANNEL=$(echo $CHANNEL | grep -o "[0-9]\{1,5\}") + ICELL=$(echo $O" " | grep -o "+CELLINFO: .\+ OK " | tr " " ",") + PCI=$(echo $ICELL | cut -d, -f18) + PCI=$(echo $PCI | grep -o "[0-9]\{1,5\}") + if [ $MODE = "FDD" ]; then + MODE="FDD LTE" + fi + ;; + "LTE"|"EN-DC" ) + SGC=$(echo $OX | grep -o "+SGCELLINFOEX:[ ]\?[-CDELNTE]\{3,5\},.\+AT+CELLINFO") + MODE=$(echo $SGC | cut -d, -f2) + PCI=$(echo $SGC | cut -d, -f6) + LBAND="B"$(echo $SGC | cut -d, -f10) + BW=$(echo $SGC | cut -d, -f11 | grep -o "[0-9]\{1,3\}") + if [ $BW -gt 14 ]; then + let BW=BW/5 + else + BW="1.4" + fi + LBAND=$LBAND" (Bandwidth $BW Mhz)" + CHANNEL=$(echo $SGC | cut -d, -f12) + RSSI=$(echo $SGC | cut -d, -f14) + CSQ_RSSI=$(echo $RSSI | grep -o "[-0-9]\{1,3\}")" dBm" + RSCP=$(echo $SGC | cut -d, -f15) + ECIO=$(echo $SGC| cut -d, -f16) + SINR=$(echo $SGC | cut -d, -f18)" dB" + if [ $MODEx == "EN-DC" ]; then + NRSINR=$(echo $SGC | cut -d, -f31 | grep -o "[-0-9]\{1,4\}") + NRBAND=$(echo $SGC | cut -d, -f32 | grep -o "[0-9]\{1,3\}") + NRCHAN=$(echo $SGC | cut -d, -f33 | grep -o "[0-9]\{6,7\}") + NRBW=$(echo $SGC | cut -d, -f34 | grep -o "[0-9]\{1,3\}") + if [ -n "$NRBAND" -a -n "$NRCHAN" -a -n "$NRBW" -a -n $NRSINR ]; then + NRRSRP=$(echo $SGC | cut -d, -f29 | grep -o "[-0-9]\{2,4\}") + NRRSRQ=$(echo $SGC | cut -d, -f30 | grep -o "[-0-9]\{2,4\}") + NRPCI=$(echo $SGC | cut -d, -f35 | grep -o "[0-9]\{1,3\}") + let NRBW=NRBW/5 + LBAND=$LBAND"
                                                                        n"$NRBAND" (Bandwidth "$NRBW" MHz)" + RSCP=$RSCP" dBm
                                                                        "$NRRSRP + ECIO=$ECIO" dBm
                                                                        "$NRRSRQ + SINR=$SINR"
                                                                        "$((($NRSINR / 5) - 20))" dB" + CHANNEL=$CHANNEL","$NRCHAN + PCI=$PCI","$NRPCI + fi + fi + ;; + "5G" ) + SGC=$(echo $OX | grep -o "+SGCELLINFOEX:[ ]\?5G,.\+AT+CELLINFO") + MODE=$(echo $SGC | cut -d, -f2) + PCI=$(echo $SGC | cut -d, -f6) + LBAND="n"$(echo $SGC | cut -d, -f8) + BW=$(echo $SGC | cut -d, -f9 | grep -o "[0-9]\{1,3\}") + let BW=BW/5 + LBAND=$LBAND" (Bandwidth $BW Mhz)" + CHANNEL=$(echo $SGC | cut -d, -f12) + RSCP=$(echo $SGC | cut -d, -f15) + ECIO=$(echo $SGC| cut -d, -f16) + SINR=$(echo $SGC | cut -d, -f17) + SINR=$((($SINR / 5) - 20))" dB" + ;; + "HSPA+"|"HSUPA"|"HSDPA"|"WCDMA" ) + if [ -n "$ATECH" ]; then + SGC=$(echo $OX | grep -o "WCDMA,[0-9]\{3\},.\+AT+CELLINFO" | tr ' ' ',') + CHANNEL=$(echo $SGC | cut -d, -f11) + ECIO=$(echo $SGC | cut -d, -f14) + RSCP=$(echo $SGC | cut -d, -f16) + else + RSCP=$(echo $SGCELL | cut -d, -f11) + RSCP="-"$(echo $RSCP | grep -o "[0-9]\{1,3\}") + ECIO=$(echo $SGCELL| cut -d, -f12) + ECIO="-"$(echo $ECIO | grep -o "[0-9]\{1,3\}") + CHANNEL=$(echo $SGCELL | cut -d, -f8) + CHANNEL=$(echo $CHANNEL | grep -o "[0-9]\{1,4\}") + RSSI=$(echo $SGCELL | cut -d, -f10) + CSQ_RSSI=$(echo $RSSI | grep -o "[0-9]\{1,3\}")" dBm" + fi + ;; + *) + RSCP=$(echo $SGCELL | cut -d, -f10) + RSCP="-"$(echo $RSCP | grep -o "[0-9]\{1,3\}") + CHANNEL=$(echo $SGCELL | cut -d, -f8) + CHANNEL=$(echo $CHANNEL | grep -o "[0-9]\{1,4\}") + RSSI=$(echo $SGCELL | cut -d, -f9) + CSQ_RSSI=$(echo $RSSI | grep -o "[0-9]\{1,3\}")" dBm" + ;; +esac + +CALIST=$(echo "${OX//[ ]/}" | grep -o "+CELLINFO:\"SCC\",[0-9],2,[0-9],[0-9]\{1,6\},[0-9]\{1,4\},[0-9]\{1,3\},[0-9]\{1,3\},[-0-9]\{1,4\},[-0-9]\{1,4\},[-0-9]\{1,4\},[-0-9]\{1,4\}") + +for CAVAL in $(echo "$CALIST"); do + if [ "$(echo $CAVAL | cut -d, -f2)" == "1" ]; then + CATYPE="CA"$(printf "\xe2\x86\x91") + else + CATYPE="CA" + fi + CHANv=$(echo $CAVAL | cut -d, -f5) + BWv=$(echo $CAVAL | cut -d, -f6) + if [ $BWv -gt 14 ]; then + let BWv=BWv/5 + else + BWv="1.4" + fi + if [ $CHANv -ge 123400 ]; then + BANDv="n"$(echo $CAVAL | cut -d, -f7) + else + BANDv="B"$(echo $CAVAL | cut -d, -f7) + fi + LBAND=$LBAND"
                                                                        "$BANDv" ($CATYPE, Bandwidth "$BWv" MHz)" + PCI=$PCI","$(echo $CAVAL | cut -d, -f8) + ECIO=$ECIO" dBm
                                                                        "$(echo $CAVAL | cut -d, -f9) + RSCP=$RSCP" dBm
                                                                        "$(echo $CAVAL | cut -d, -f10) + SINRv=$(echo $CAVAL | cut -d, -f12) + SINRv=$((($SINRv / 5) - 20))" dB" + CHANNEL=$CHANNEL","$CHANv + SINR=$SINR"
                                                                        "$SINRv +done + +NETMODE="-" +NMODE=$(echo $O" " | grep -o "+MODODR: .\+ OK " | tr " " ",") +TECH=$(echo $NMODE | cut -d, -f2) +if [ -n "$TECH" ]; then + MODTYPE="7" + case $TECH in + "2" ) + NETMODE="1" # Auto + ;; + "1" ) + NETMODE="5" # 3G only + ;; + "4" ) + NETMODE="4" # 3G preferred + ;; + "3" ) + NETMODE="3" # 2G only + ;; + "5" ) + NETMODE="7" # LTE only + ;; + * ) + NETMODE="1" + ;; + esac +fi +RATs=$(echo "$OX" | grep -o "\^SYSCFGEX: \"[0-9]\{2,6\}\"" | grep -o "[0-9]\{2,6\}") +if [ -n "$RATs" ]; then + MODTYPE="7" + case $RATs in + "02" ) + NETMODE="5" ;; + "03" ) + NETMODE="7" ;; + "04" ) + NETMODE="9" ;; + "0203" | "0204" | "020304" | "020403" ) + NETMODE="4" ;; + "0304" | "0302" | "030402" | "030204" ) + NETMODE="6" ;; + "0403" ) + NETMODE="8" ;; + * ) + NETMODE="1" ;; + esac +fi + +{ + echo 'CSQ="'"$CSQ"'"' + echo 'CSQ_PER="'"$CSQ_PER"'"' + echo 'CSQ_RSSI="'"$CSQ_RSSI"'"' + echo 'ECIO="'"$ECIO"'"' + echo 'RSCP="'"$RSCP"'"' + echo 'ECIO1="'"$ECIO1"'"' + echo 'RSCP1="'"$RSCP1"'"' + echo 'MODE="'"$MODE"'"' + echo 'MODTYPE="'"$MODTYPE"'"' + echo 'NETMODE="'"$NETMODE"'"' + echo 'CHANNEL="'"$CHANNEL"'"' + echo 'LBAND="'"$LBAND"'"' + echo 'TEMP="'"$TEMP"'"' + echo 'PCI="'"$PCI"'"' + echo 'SINR="'"$SINR"'"' +} > /tmp/signal$CURRMODEM.file + +CONNECT=$(uci get modem.modem$CURRMODEM.connected) +if [ "$CONNECT" == "0" ]; then + exit 0 +fi + +if [ "$CSQ" = "-" ]; then + log "$OX" +fi + +WWANX=$(uci get modem.modem$CURRMODEM.interface) +OPER=$(cat /sys/class/net/$WWANX/operstate 2>/dev/null) +rm -f "/tmp/connstat"$CURRMODEM + +if [ ! "$OPER" ]; then + exit 0 +fi +if echo $OPER | grep -q "unknown"; then + exit 0 +fi + +if echo $OPER | grep -q "down"; then + echo "1" > "/tmp/connstat"$CURRMODEM +fi diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/common/modemchk.lua b/rooter/ext-rooter-basic/files/usr/lib/rooter/common/modemchk.lua new file mode 100644 index 0000000..4598cd8 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/common/modemchk.lua @@ -0,0 +1,120 @@ +#!/usr/bin/lua + +local uvid = arg[1] +local upid = arg[2] +local dport = arg[3] +local cport = arg[4] + +local modemfile = "/etc/config/modem.data" +local modemdata = {} +local count +local retval +local cretval + +function process_line(xline, cnt) + local data = {} + local pline = xline + local start = 1 + for i=1,3 do + s, e = string.find(pline, " ") + data[i] = string.sub(pline, start, s-1) + pline = string.sub(pline, e+1) + end + data[4] = pline + modemdata[cnt] = data +end + +function read_modem() + count = 0 + local file = io.open(modemfile, "r") + if file == nil then + return + end + repeat + local line = file:read("*line") + if line == nil then + break + end + if string.len(line) < 5 then + break + end + count = count + 1 + process_line(line, count) + until 1==0 + file:close() +end + +function process_port() + for l=1,count do + local mdata = modemdata[l] + if mdata[1] == uvid and mdata[2] == upid then + retval = 0 + if mdata[3] == "tty0" then + retval = 1 + end + if mdata[3] == "tty1" then + retval = 2 + end + if mdata[3] == "tty2" then + retval = 3 + end + if mdata[3] == "tty3" then + retval = 4 + end + if mdata[3] == "tty4" then + retval = 5 + end + if mdata[3] == "tty5" then + retval = 6 + end + + cretval = 0 + if mdata[4] == "tty0" then + cretval = 1 + end + if mdata[4] == "tty1" then + cretval = 2 + end + if mdata[4] == "tty2" then + cretval = 3 + end + if mdata[4] == "tty3" then + cretval = 4 + end + if mdata[4] == "tty4" then + cretval = 5 + end + if mdata[4] == "tty5" then + cretval = 6 + end + + break + end + end +end + +read_modem() +retval = 0 +cretval = 0 +if count > 0 then + process_port() +end +if retval > 0 then + retval = retval - 1 +else + retval = tonumber(dport) +end +if cretval > 0 then + cretval = cretval - 1 +else + cretval = tonumber(cport) +end + +dret = string.format("%d", retval) +cret = string.format("%d", cretval) +local file = io.open("/tmp/parmpass", "w") +file:write("DPORT=\"" .. dret .. "\"\n") +file:write("CPORT=\"" .. cret .. "\"\n") +file:close() + +os.exit(retval) diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/common/novateldata.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/common/novateldata.sh new file mode 100644 index 0000000..0b189ef --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/common/novateldata.sh @@ -0,0 +1,138 @@ +#!/bin/sh + +ROOTER=/usr/lib/rooter + +log() { + logger -t "Novatel Data" "$@" +} + +CURRMODEM=$1 +COMMPORT=$2 + +fix_data() { + OY=$(echo $OY | tr 'a-z' 'A-Z') + O=$($ROOTER/common/processat.sh "$OY") + O=$(echo $O" ") + O=$(echo "${O//[\"]/}") +} + +process_csq() { +CSQ=$(echo $OY | grep -o "+CSQ: [0-9]\{1,2\}" | grep -o "[0-9]\{1,2\}") + if [ "$CSQ" = "99" ]; then + CSQ="" + fi + if [ -n "$CSQ" ]; then + CSQ_PER=$(($CSQ * 100/31))"%" + CSQ_RSSI=$((2 * CSQ - 113))" dBm" + else + CSQ="-" + CSQ_PER="-" + CSQ_RSSI="-" + fi +} + +CSQ="-" +CSQ_PER="-" +CSQ_RSSI="-" +ECIO="-" +RSCP="-" +ECIO1=" " +RSCP1=" " +MODE="-" +MODTYPE="-" +NETMODE="-" +LBAND="-" +CHANNEL="-" +TEMP="-" +PCI="-" +SINR="-" + +OY=$($ROOTER/gcom/gcom-locked "$COMMPORT" "novatelinfo.gcom" "$CURRMODEM") + +fix_data +process_csq + +DEG=$(echo $O" " | grep -o "+NWDEGC: .\+ OK " | tr " " ",") +TMP=$(echo $DEG | cut -d, -f2) +if [ -n "$TMP" ]; then + TEMP=$TMP$(printf "\xc2\xb0")"C" +fi + +MODE="-" +PSRAT=$(echo $O" " | grep -o "\$NWRAT: .\+ OK " | tr " " ",") +TECH=$(echo $PSRAT | cut -d, -f4) +if [ -n "$TECH" ]; then + case "$TECH" in + "1"|"2"|"3") + MODE="UMTS" + ;; + "4"|"5"|"6") + MODE="GSM" + ;; + "7"|"8"|"9") + MODE="LTE" + VZWRSRP=$(echo "$O" | grep -o "VZWRSRP: [0-9]\{1,3\},[0-9]\{1,7\},[-.0-9]\{1,7\}" | tr " " ",") + PCI=$(echo "$VZWRSRP" | cut -d, -f2) + CHANNEL=$(echo "$VZWRSRP" | cut -d, -f3) + LBAND=$("$ROOTER/chan2band.sh" "$CHANNEL") + TMP=$(echo "$VZWRSRP" | cut -d, -f4) + if [ -n "$TMP" ]; then + RSCP=$TMP + fi + VZWRSRQ=$(echo "$O" | grep -o "VZWRSRQ: [0-9]\{1,3\},[0-9]\{1,7\},[-.0-9]\{1,7\}" | tr " " ",") + TMP=$(echo "$VZWRSRQ" | cut -d, -f4) + if [ -n "$TMP" ]; then + ECIO=$TMP + fi + ;; + *) + MODE="CDMA/HDR" + ;; + esac +fi + +{ + echo 'CSQ="'"$CSQ"'"' + echo 'CSQ_PER="'"$CSQ_PER"'"' + echo 'CSQ_RSSI="'"$CSQ_RSSI"'"' + echo 'ECIO="'"$ECIO"'"' + echo 'RSCP="'"$RSCP"'"' + echo 'ECIO1="'"$ECIO1"'"' + echo 'RSCP1="'"$RSCP1"'"' + echo 'MODE="'"$MODE"'"' + echo 'MODTYPE="'"$MODTYPE"'"' + echo 'NETMODE="'"$NETMODE"'"' + echo 'CHANNEL="'"$CHANNEL"'"' + echo 'LBAND="'"$LBAND"'"' + echo 'TEMP="'"$TEMP"'"' + echo 'PCI="'"$PCI"'"' + echo 'SINR="'"$SINR"'"' +} > /tmp/signal$CURRMODEM.file + +CONNECT=$(uci get modem.modem$CURRMODEM.connected) +if [ $CONNECT -eq 0 ]; then + exit 0 +fi + +ENB="0" +if [ -e /etc/config/failover ]; then + ENB=$(uci get failover.enabled.enabled) +fi +if [ $ENB = "1" ]; then + exit 0 +fi + +WWANX=$(uci get modem.modem$CURRMODEM.interface) +OPER=$(cat /sys/class/net/$WWANX/operstate 2>/dev/null) +rm -f "/tmp/connstat"$CURRMODEM + +if [ ! $OPER ]; then + exit 0 +fi +if echo $OPER | grep -q "unknown"; then + exit 0 +fi + +if echo $OPER | grep -q "down"; then + echo "1" > "/tmp/connstat"$CURRMODEM +fi diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/common/otherdata.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/common/otherdata.sh new file mode 100644 index 0000000..af68b66 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/common/otherdata.sh @@ -0,0 +1,97 @@ +#!/bin/sh + +ROOTER=/usr/lib/rooter + +log() { + logger -t "Other Data" "$@" +} + +CURRMODEM=$1 +COMMPORT=$2 + +fix_data() { + O=$($ROOTER/common/processat.sh "$OY") +} + +process_csq() { + CSQ=$(echo "$O" | awk -F[,\ ] '/^\+CSQ:/ {print $2}') + [ "x$CSQ" = "x" ] && CSQ=-1 + if [ $CSQ -ge 0 -a $CSQ -le 31 ]; then + CSQ_PER=$(($CSQ * 100/31)) + CSQ_RSSI=$((2 * CSQ - 113)) + CSQX=$CSQ_RSSI + [ $CSQ -eq 0 ] && CSQ_RSSI="<= "$CSQ_RSSI + [ $CSQ -eq 31 ] && CSQ_RSSI=">= "$CSQ_RSSI + CSQ_PER=$CSQ_PER"%" + CSQ_RSSI=$CSQ_RSSI" dBm" + else + CSQ="-" + CSQ_PER="-" + CSQ_RSSI="-" + fi +} + +CSQ="-" +CSQ_PER="-" +CSQ_RSSI="-" +ECIO="-" +RSCP="-" +ECIO1=" " +RSCP1=" " +MODE="-" +MODETYPE="-" +NETMODE="-" +LBAND="-" +TEMP="-" +PCI="-" +SINR="-" + +OY=$($ROOTER/gcom/gcom-locked "$COMMPORT" "otherinfo.gcom" "$CURRMODEM") + +fix_data +process_csq + +{ + echo 'CSQ="'"$CSQ"'"' + echo 'CSQ_PER="'"$CSQ_PER"'"' + echo 'CSQ_RSSI="'"$CSQ_RSSI"'"' + echo 'ECIO="'"$ECIO"'"' + echo 'RSCP="'"$RSCP"'"' + echo 'ECIO1="'"$ECIO1"'"' + echo 'RSCP1="'"$RSCP1"'"' + echo 'MODE="'"$MODE"'"' + echo 'MODTYPE="'"$MODTYPE"'"' + echo 'NETMODE="'"$NETMODE"'"' + echo 'LBAND="'"$LBAND"'"' + echo 'TEMP="'"$TEMP"'"' + echo 'PCI="'"$PCI"'"' + echo 'SINR="'"$SINR"'"' +} > /tmp/signal$CURRMODEM.file + +CONNECT=$(uci get modem.modem$CURRMODEM.connected) +if [ $CONNECT -eq 0 ]; then + exit 0 +fi + +ENB="0" +if [ -e /etc/config/failover ]; then + ENB=$(uci get failover.enabled.enabled) +fi +if [ $ENB = "1" ]; then + exit 0 +fi + +WWANX=$(uci get modem.modem$CURRMODEM.interface) +OPER=$(cat /sys/class/net/$WWANX/operstate 2>/dev/null) +rm -f "/tmp/connstat"$CURRMODEM + +if [ ! $OPER ]; then + exit 0 +fi +if echo $OPER | grep -q "unknown"; then + exit 0 +fi + +if echo $OPER | grep -q "down"; then + echo "1" > "/tmp/connstat"$CURRMODEM +fi diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/common/phone.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/common/phone.sh new file mode 100644 index 0000000..cf0a8b9 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/common/phone.sh @@ -0,0 +1,55 @@ +#!/bin/sh + +ROOTER=/usr/lib/rooter + +log() { + logger -t "Phone Change" "$@" +} + +CURRMODEM=$1 +PHONE=$2 +NAME=$3 + +CPORT=$(uci get modem.modem$CURRMODEM.commport) +PHONE=$(echo "$PHONE" | sed -e 's/ //g') + +log "Change Modem $CURRMODEM SIM phone number to $PHONE, name to $NAME" + +INTER=${PHONE:0:1} +if [ $INTER = "+" ]; then + TON="145" + PHONE=${PHONE:1} +else + TON="129" +fi + +ATCMDD="AT+CPBS=\"ON\";+CPBS?" +OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") +OX=$($ROOTER/common/processat.sh "$OX") + +ON=$(echo "$OX" | awk -F[,\ ] '/^\+CPBS:/ {print $2}') +if [ "$ON" = "\"ON\"" ]; then + ATCMDD="AT+CPBW=1,\"$PHONE\",$TON,\"$NAME\"" + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + ATCMDD="AT+CNUM" + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + OX=$($ROOTER/common/processat.sh "$OX") + M2=$(echo "$OX" | grep -o "+CNUM:[^,]*,[^,]*,[0-9]\{3\}")"," + M2=${M2:6} + CNUMx=$(echo "$M2" | cut -d, -f1 | cut -d\" -f2) + CNUMx=$(echo $CNUMx) + CNUM=$(echo "$M2" | cut -d, -f2 | cut -d\" -f2) + CNUMtype=$(echo "$M2" | cut -d, -f3) + if [ "${CNUM:0:1}" != "+" -a "$CNUMtype" == "145" ]; then + CNUM="+"$CNUM + fi + if [ -z "$CNUM" ]; then + CNUM="*" + fi + if [ -z "$CNUMx" ]; then + CNUMx="*" + fi + echo "$CNUM" > /tmp/msimnumx$CURRMODEM + echo "$CNUMx" >> /tmp/msimnumx$CURRMODEM + mv -f /tmp/msimnumx$CURRMODEM /tmp/msimnum$CURRMODEM +fi diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/common/processat.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/common/processat.sh new file mode 100644 index 0000000..16cba63 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/common/processat.sh @@ -0,0 +1,16 @@ +#!/bin/sh + +OX=$1 + +M6=$(echo "$OX" | sed -e "s/ / /g") +M5=$(echo "$M6" | sed -e "s/ / /g") +M4=$(echo "$M5" | sed -e "s/ / /g") +M3=$(echo "$M4" | sed -e "s/ / /g") +M2=$(echo "$M3" | sed -e "s/ / /g") +M2=$(echo "$M2" | sed -e "s/TAC:/ /;s/Tx Power:/ /;s/SINR/ /;s!SYSINFOEX:!SYSINFOEX: !;s!CNTI:!CNTI: !;s!SELRAT:!SELRAT: !;s!ZSNT:!ZSNT: !") +M1=$(echo "$M2" | sed -e "s!Car0 Tot Ec/Io!+ECIOx!;s!Car1 Tot Ec/Io!+ECIO1x!;s!Car0 RSCP!+RSCPx!;s!+CGMM: !!") +M2=$(echo "$M1" | sed -e "s!Car1 RSCP!+RSCP1x!;s!CSNR:!CSNR: !;s!RSSI (dBm):!RSSI4: !;s!AirCard !AirCard!;s!USB !USB!") +M3=$(echo "$M2" | sed -e "s!RSRP (dBm):!RSRP4: !;s!RSRQ (dB):!RSRQ4: !;s!LTERSRP:!LTERSRP: !;s!Model:!+MODEL: !;s!SYSCFGEX:!SYSCFGEX: !") +M7=$(echo "$M3" | sed -e "s!RX level Carrier 0 (dBm):!RSSI3: !;s!RX level Carrier 1 (dBm):!RSSI13: !;s!SYSCFG:!SYSCFG: !;s! ! !g") +OX=$(echo "$M7" | sed -e "s!WCDMA channel:!UMTS:!;s!SYSINFO:!SYSINFO: !;s!+PSRAT:!+PSRAT: !;s!+MODODR:!+MODODR: !") +echo "$OX" \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/common/quantadata.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/common/quantadata.sh new file mode 100644 index 0000000..729ef12 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/common/quantadata.sh @@ -0,0 +1,121 @@ +#!/bin/sh + +ROOTER=/usr/lib/rooter + +log() { + logger -t "Quanta Data" "$@" +} + +CURRMODEM=$1 +COMMPORT=$2 + +OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "quantainfo.gcom" "$CURRMODEM") + +OX=$(echo $OX | tr 'a-z' 'A-Z') + +RSRP="" +RSRQ="" +CHANNEL="-" +ECIO="-" +RSCP="-" +ECIO1=" " +RSCP1=" " +MODE="-" +LBAND="-" +PCI="-" +SINR="-" +TEMP="-" + +CSQ=$(echo $OX | grep -o "+CSQ: [0-9]\{1,2\}" | grep -o "[0-9]\{1,2\}") +if [ "$CSQ" = "99" ]; then + CSQ="" +fi +if [ -n "$CSQ" ]; then + CSQ_PER=$(($CSQ * 100/31))"%" + CSQ_RSSI=$((2 * CSQ - 113))" dBm" +else + CSQ="-" + CSQ_PER="-" + CSQ_RSSI="-" +fi + +REGX='*QRFINFO: \"LTE\",[0-9]\{1,2\},[0-9]\{1,5\},[.012345]\{1,3\},[0-9]\{1,3\},-[0-9]\{1,3\},[-0-9]\{1,3\},[.0-9]\{1,4\}' +LTE=$(echo $OX | grep -o "$REGX") +if [ -n "$LTE" ]; then + MODE="LTE" + BW=$(echo $LTE | cut -d, -f4) + LBAND="B"$(echo $LTE | cut -d, -f2)"(Bandwidth "$BW" MHz)" + RSCP=$(echo $LTE | cut -d, -f6) + ECIO=$(echo $LTE | cut -d, -f7) + CHANNEL=$(echo $LTE | cut -d, -f3) + PCI=$(echo $LTE | cut -d, -f5) + SINR=$(echo $LTE | cut -d, -f8)" dB" +else + REGX='*QRFINFO: \"WCDMA\",[0-9]\{1,2\},[0-9]\{1,5\},[^,],[0-9]\{1,3\},-[0-9]\{1,3\},[-0-9]\{1,3\}' + UMTS=$(echo $OX | grep -o "$REGX") + if [ -n "$UMTS" ]; then + MODE="WCDMA" + LBAND="B"$(echo $UMTS | cut -d, -f2) + RSCP=$(echo $UMTS | cut -d, -f6) + ECIO=$(echo $UMTS | cut -d, -f7) + CHANNEL=$(echo $UMTS | cut -d, -f3) + PCI=$(echo $UMTS | cut -d, -f5) + fi +fi + +TECH=$(echo $OX | grep -o "\^QCNCFG: \"[0123]\{2\}\"" | grep -o "[0123]\{2\}") +case $TECH in + "02") + NETMODE="5" + ;; + "03") + NETMODE="7" + ;; + *) + NETMODE="1" + ;; +esac + +MODTYPE="11" + +{ + echo 'CSQ="'"$CSQ"'"' + echo 'CSQ_PER="'"$CSQ_PER"'"' + echo 'CSQ_RSSI="'"$CSQ_RSSI"'"' + echo 'ECIO="'"$ECIO"'"' + echo 'RSCP="'"$RSCP"'"' + echo 'ECIO1="'"$ECIO1"'"' + echo 'RSCP1="'"$RSCP1"'"' + echo 'MODE="'"$MODE"'"' + echo 'MODTYPE="'"$MODTYPE"'"' + echo 'NETMODE="'"$NETMODE"'"' + echo 'CHANNEL="'"$CHANNEL"'"' + echo 'LBAND="'"$LBAND"'"' + echo 'PCI="'"$PCI"'"' + echo 'TEMP="'"$TEMP"'"' + echo 'SINR="'"$SINR"'"' +} > /tmp/signal$CURRMODEM.file + +CONNECT=$(uci get modem.modem$CURRMODEM.connected) +if [ $CONNECT -eq 0 ]; then + exit 0 +fi + +if [ "$CSQ" = "-" ]; then + log "$OX" +fi + +WWANX=$(uci get modem.modem$CURRMODEM.interface) +OPER=$(cat /sys/class/net/$WWANX/operstate 2>/dev/null) +rm -f "/tmp/connstat"$CURRMODEM + +if [ ! $OPER ]; then + exit 0 +fi +if echo $OPER | grep -q "unknown"; then + exit 0 +fi + +if echo $OPER | grep -q "down"; then + echo "1" > "/tmp/connstat"$CURRMODEM +fi diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/common/quecteldata.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/common/quecteldata.sh new file mode 100644 index 0000000..d1d575a --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/common/quecteldata.sh @@ -0,0 +1,376 @@ +#!/bin/sh + +ROOTER=/usr/lib/rooter + +CURRMODEM=$1 +COMMPORT=$2 + +lte_bw() { + BW=$(echo $BW | grep -o "[0-5]\{1\}") + case $BW in + "0") + BW="1.4" ;; + "1") + BW="3" ;; + "2"|"3"|"4"|"5") + BW=$((($(echo $BW) - 1) * 5)) ;; + esac +} + +nr_bw() { + BW=$(echo $BW | grep -o "[0-9]\{1,2\}") + case $BW in + "0"|"1"|"2"|"3"|"4"|"5") + BW=$((($(echo $BW) + 1) * 5)) ;; + "6"|"7"|"8"|"9"|"10"|"11"|"12") + BW=$((($(echo $BW) - 2) * 10)) ;; + "13") + BW="200" ;; + "14") + BW="400" ;; + esac +} + +OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "quectelinfo.gcom" "$CURRMODEM") + +OX=$(echo $OX | tr 'a-z' 'A-Z') + +RSRP="" +RSRQ="" +CHANNEL="-" +ECIO="-" +RSCP="-" +ECIO1=" " +RSCP1=" " +MODE="-" +MODTYPE="-" +NETMODE="-" +LBAND="-" +PCI="-" +CTEMP="-" +SINR="-" +CSQ=$(echo $OX | grep -o "+CSQ: [0-9]\{1,2\}" | grep -o "[0-9]\{1,2\}") +if [ "$CSQ" = "99" ]; then + CSQ="" +fi +if [ -n "$CSQ" ]; then + CSQ_PER=$(($CSQ * 100/31))"%" + CSQ_RSSI=$((2 * CSQ - 113))" dBm" +else + CSQ="-" + CSQ_PER="-" + CSQ_RSSI="-" +fi +NR_NSA=$(echo $OX | grep -o "+QENG:[ ]\?\"NR5G-NSA\",") +NR_SA=$(echo $OX | grep -o "+QENG: \"SERVINGCELL\",[^,]\+,\"NR5G-SA\",\"[DFT]\{3\}\",") +if [ -n "$NR_NSA" ]; then + QENG=",,"$(echo $OX" " | grep -o "+QENG: \"LTE\".\+\"NR5G-NSA\"," | tr " " ",") + QENG5=$(echo $OX | grep -o "+QENG:[ ]\?\"NR5G-NSA\",[0-9]\{3\},[0-9]\{2,3\},[0-9]\{1,5\},-[0-9]\{2,5\},[-0-9]\{1,3\},-[0-9]\{2,3\},[0-9]\{1,7\},[0-9]\{1,3\}.\{1,6\}") + if [ -z "$QENG5" ]; then + QENG5=$(echo $OX | grep -o "+QENG:[ ]\?\"NR5G-NSA\",[0-9]\{3\},[0-9]\{2,3\},[0-9]\{1,5\},-[0-9]\{2,3\},[-0-9]\{1,3\},-[0-9]\{2,3\}") + if [ -n "$QENG5" ]; then + QENG5=$QENG5",," + fi + fi +elif [ -n "$NR_SA" ]; then + QENG=$(echo $NR_SA | tr " " ",") + QENG5=$(echo $OX | grep -o "+QENG: \"SERVINGCELL\",[^,]\+,\"NR5G-SA\",\"[DFT]\{3\}\",[ 0-9]\{3,4\},[0-9]\{2,3\},[0-9A-F]\{1,10\},[0-9]\{1,5\},[0-9A-F]\{2,6\},[0-9]\{6,7\},[0-9]\{1,3\},[0-9]\{1,2\},-[0-9]\{2,5\},-[0-9]\{2,3\},[-0-9]\{1,3\}") +else + QENG=$(echo $OX" " | grep -o "+QENG: [^ ]\+ " | tr " " ",") +fi +QCA=$(echo $OX" " | grep -o "+QCAINFO: \"S[CS]\{2\}\".\+NWSCANMODE" | tr " " ",") +QNSM=$(echo $OX | grep -o "+QCFG: \"NWSCANMODE\",[0-9]") +QNWP=$(echo $OX | grep -o "+QNWPREFCFG: \"MODE_PREF\",[A-Z5:]\+" | cut -d, -f2) +QTEMP=$(echo $OX | grep -o "+QTEMP: [0-9]\{1,3\}") +if [ -z "$QTEMP" ]; then + QTEMP=$(echo $OX | grep -o "+QTEMP:[ ]\?\"XO[_-]THERM[_-][^,]\+,[\"]\?[0-9]\{1,3\}" | grep -o "[0-9]\{1,3\}") +fi +if [ -z "$QTEMP" ]; then + QTEMP=$(echo $OX | grep -o "+QTEMP:[ ]\?\"MDM-CORE-USR.\+[0-9]\{1,3\}\"" | cut -d\" -f4) +fi +if [ -z "$QTEMP" ]; then + QTEMP=$(echo $OX | grep -o "+QTEMP:[ ]\?\"MDMSS.\+[0-9]\{1,3\}\"" | cut -d\" -f4) +fi +if [ -n "$QTEMP" ]; then + CTEMP=$(echo $QTEMP | grep -o "[0-9]\{1,3\}")$(printf "\xc2\xb0")"C" +fi +RAT=$(echo $QENG | cut -d, -f4 | grep -o "[-A-Z5]\{3,7\}") +rm -f /tmp/modnetwork +case $RAT in + "GSM") + MODE="GSM" + ;; + "WCDMA") + MODE="WCDMA" + CHANNEL=$(echo $QENG | cut -d, -f9) + RSCP=$(echo $QENG | cut -d, -f12) + RSCP="-"$(echo $RSCP | grep -o "[0-9]\{1,3\}") + ECIO=$(echo $QENG | cut -d, -f13) + ECIO="-"$(echo $ECIO | grep -o "[0-9]\{1,3\}") + ;; + "LTE"|"CAT-M"|"CAT-NB") + MODE=$(echo $QENG | cut -d, -f5 | grep -o "[DFT]\{3\}") + if [ -n "$MODE" ]; then + MODE="$RAT $MODE" + else + MODE="$RAT" + fi + PCI=$(echo $QENG | cut -d, -f9) + CHANNEL=$(echo $QENG | cut -d, -f10) + LBAND=$(echo $QENG | cut -d, -f11 | grep -o "[0-9]\{1,3\}") + BW=$(echo $QENG | cut -d, -f12) + lte_bw + BWU=$BW + BW=$(echo $QENG | cut -d, -f13) + lte_bw + BWD=$BW + if [ -z "$BWD" ]; then + BWD="unknown" + fi + if [ -z "$BWU" ]; then + BWU="unknown" + fi + if [ -n "$LBAND" ]; then + LBAND="B"$LBAND" (Bandwidth $BWD MHz Down | $BWU MHz Up)" + fi + RSRP=$(echo $QENG | cut -d, -f15 | grep -o "[0-9]\{1,3\}") + if [ -n "$RSRP" ]; then + RSCP="-"$RSRP + RSRPLTE=$RSCP + fi + RSRQ=$(echo $QENG | cut -d, -f16 | grep -o "[0-9]\{1,3\}") + if [ -n "$RSRQ" ]; then + ECIO="-"$RSRQ + fi + RSSI=$(echo $QENG | cut -d, -f17 | grep -o "\-[0-9]\{1,3\}") + if [ -n "$RSSI" ]; then + CSQ_RSSI=$RSSI" dBm" + fi + SINRR=$(echo $QENG | cut -d, -f18 | grep -o "[0-9]\{1,3\}") + if [ -n "$SINRR" ]; then + if [ $SINRR -le 25 ]; then + SINR=$((($(echo $SINRR) * 2) -20))" dB" + fi + fi + + if [ -n "$NR_NSA" ]; then + MODE="LTE/NR EN-DC" + echo "0" > /tmp/modnetwork + if [ -n "$QENG5" ] && [ -n "$LBAND" ] && [ "$RSCP" != "-" ] && [ "$ECIO" != "-" ]; then + PCI="$PCI, "$(echo $QENG5 | cut -d, -f4) + SCHV=$(echo $QENG5 | cut -d, -f8) + SLBV=$(echo $QENG5 | cut -d, -f9) + BW=$(echo $QENG5 | cut -d, -f10 | grep -o "[0-9]\{1,3\}") + if [ -n "$SLBV" ]; then + LBAND=$LBAND"
                                                                        n"$SLBV + if [ -n "$BW" ]; then + nr_bw + LBAND=$LBAND" (Bandwidth $BW MHz)" + fi + if [ "$SCHV" -ge 123400 ]; then + CHANNEL=$CHANNEL", "$SCHV + else + CHANNEL=$CHANNEL", -" + fi + else + LBAND=$LBAND"
                                                                        nxx (unknown NR5G band)" + CHANNEL=$CHANNEL", -" + fi + RSCP=$RSCP" dBm
                                                                        "$(echo $QENG5 | cut -d, -f5) + SINRR=$(echo $QENG5 | cut -d, -f6 | grep -o "[0-9]\{1,3\}") + if [ -n "$SINRR" ]; then + if [ $SINRR -le 30 ]; then + SINR=$SINR"
                                                                        "$((($(echo $SINRR) * 2) -20))" dB" + fi + fi + ECIO=$ECIO" (4G) dB
                                                                        "$(echo $QENG5 | cut -d, -f7)" (5G) " + fi + fi + if [ -z "$LBAND" ]; then + LBAND="-" + else + if [ -n "$QCA" ]; then + QCA=$(echo $QCA | grep -o "\"S[CS]\{2\}\"[-0-9A-Z,\"]\+") + for QCAL in $(echo "$QCA"); do + if [ $(echo "$QCAL" | cut -d, -f7) = "2" ]; then + SCHV=$(echo $QCAL | cut -d, -f2 | grep -o "[0-9]\+") + SRATP="B" + if [ -n "$SCHV" ]; then + CHANNEL="$CHANNEL, $SCHV" + if [ "$SCHV" -gt 123400 ]; then + SRATP="n" + fi + fi + SLBV=$(echo $QCAL | cut -d, -f6 | grep -o "[0-9]\{1,2\}") + if [ -n "$SLBV" ]; then + LBAND=$LBAND"
                                                                        "$SRATP$SLBV + BWD=$(echo $QCAL | cut -d, -f3 | grep -o "[0-9]\{1,3\}") + if [ -n "$BWD" ]; then + UPDOWN=$(echo $QCAL | cut -d, -f13) + case "$UPDOWN" in + "UL" ) + CATYPE="CA"$(printf "\xe2\x86\x91") ;; + "DL" ) + CATYPE="CA"$(printf "\xe2\x86\x93") ;; + * ) + CATYPE="CA" ;; + esac + if [ $BWD -gt 14 ]; then + LBAND=$LBAND" ("$CATYPE", Bandwidth "$(($(echo $BWD) / 5))" MHz)" + else + LBAND=$LBAND" ("$CATYPE", Bandwidth 1.4 MHz)" + fi + fi + LBAND=$LBAND + fi + PCI="$PCI, "$(echo $QCAL | cut -d, -f8) + fi + done + fi + fi + if [ $RAT = "CAT-M" ] || [ $RAT = "CAT-NB" ]; then + LBAND="B$(echo $QENG | cut -d, -f11) ($RAT)" + fi + ;; + "NR5G-SA") + MODE="NR5G-SA" + echo "0" > /tmp/modnetwork + if [ -n "$QENG5" ]; then + MODE="$RAT $(echo $QENG5 | cut -d, -f4)" + PCI=$(echo $QENG5 | cut -d, -f8) + CHANNEL=$(echo $QENG5 | cut -d, -f10) + LBAND=$(echo $QENG5 | cut -d, -f11) + BW=$(echo $QENG5 | cut -d, -f12) + nr_bw + LBAND="n"$LBAND" (Bandwidth $BW MHz)" + RSCP=$(echo $QENG5 | cut -d, -f13) + ECIO=$(echo $QENG5 | cut -d, -f14) + if [ "$CSQ_PER" = "-" ]; then + RSSI=$(rsrp2rssi $RSCP $BW) + CSQ_PER=$((100 - (($RSSI + 51) * 100/-62)))"%" + CSQ=$((($RSSI + 113) / 2)) + CSQ_RSSI=$RSSI" dBm" + fi + SINRR=$(echo $QENG5 | cut -d, -f15 | grep -o "[0-9]\{1,3\}") + if [ -n "$SINRR" ]; then + if [ $SINRR -le 30 ]; then + SINR=$((($(echo $SINRR) * 2) -20))" dB" + fi + fi + fi + ;; +esac + +QRSRP=$(echo "$OX" | grep -o "+QRSRP:[^,]\+,-[0-9]\{1,5\},-[0-9]\{1,5\},-[0-9]\{1,5\}[^ ]*") +if [ -n "$QRSRP" ] && [ "$RAT" != "WCDMA" ]; then + QRSRP1=$(echo $QRSRP | cut -d, -f1 | grep -o "[-0-9]\+") + QRSRP2=$(echo $QRSRP | cut -d, -f2) + QRSRP3=$(echo $QRSRP | cut -d, -f3) + QRSRP4=$(echo $QRSRP | cut -d, -f4) + QRSRPtype=$(echo $QRSRP | cut -d, -f5) + if [ "$QRSRPtype" == "NR5G" ]; then + if [ -n "$NR_SA" ]; then + RSCP=$QRSRP1 + if [ -n "$QRPRP2" -a "$QRSRP2" != "-32768" ]; then + RSCP1="RxD "$QRSRP2 + fi + if [ -n "$QRSRP3" -a "$QRSRP3" != "-32768" ]; then + RSCP=$RSCP" dBm
                                                                        "$QRSRP3 + fi + if [ -n "$QRSRP4" -a "$QRSRP4" != "-32768" ]; then + RSCP1="RxD "$QRSRP4 + fi + else + RSCP=$RSRPLTE + if [ -n "$QRSRP1" -a "$QRSRP1" != "-32768" ]; then + RSCP=$RSCP" (4G) dBm
                                                                        "$QRSRP1 + if [ -n "$QRSRP2" -a "$QRSRP2" != "-32768" ]; then + RSCP="$RSCP,$QRSRP2" + if [ -n "$QRSRP3" -a "$QRSRP3" != "-32768" ]; then + RSCP="$RSCP,$QRSRP3" + if [ -n "$QRSRP4" -a "$QRSRP4" != "-32768" ]; then + RSCP="$RSCP,$QRSRP4" + fi + fi + RSCP=$RSCP" (5G) " + fi + fi + fi + elif [ "$QRSRP2$QRSRP3$QRSRP4" != "-44-44-44" -a -z "$QENG5" ]; then + RSCP=$QRSRP1 + if [ "$QRSRP3$QRSRP4" == "-140-140" -o "$QRSRP3$QRSRP4" == "-44-44" -o "$QRSRP3$QRSRP4" == "-32768-32768" ]; then + RSCP1="RxD "$(echo $QRSRP | cut -d, -f2) + else + RSCP=$RSCP" dBm (RxD "$QRSRP2" dBm)
                                                                        "$QRSRP3 + RSCP1="RxD "$QRSRP4 + fi + fi +fi + +QNSM=$(echo "$QNSM" | grep -o "[0-9]") +if [ -n "$QNSM" ]; then + MODTYPE="6" + case $QNSM in + "0" ) + NETMODE="1" ;; + "1" ) + NETMODE="3" ;; + "2"|"5" ) + NETMODE="5" ;; + "3" ) + NETMODE="7" ;; + esac +fi +if [ -n "$QNWP" ]; then + MODTYPE="6" + case $QNWP in + "AUTO" ) + NETMODE="1" ;; + "WCDMA" ) + NETMODE="5" ;; + "LTE" ) + NETMODE="7" ;; + "LTE:NR5G" ) + NETMODE="8" ;; + "NR5G" ) + NETMODE="9" ;; + esac +fi + +CMODE=$(uci -q get modem.modem$CURRMODEM.cmode) +if [ "$CMODE" = 0 ]; then + NETMODE="10" +fi + +{ + echo 'CSQ="'"$CSQ"'"' + echo 'CSQ_PER="'"$CSQ_PER"'"' + echo 'CSQ_RSSI="'"$CSQ_RSSI"'"' + echo 'ECIO="'"$ECIO"'"' + echo 'RSCP="'"$RSCP"'"' + echo 'ECIO1="'"$ECIO1"'"' + echo 'RSCP1="'"$RSCP1"'"' + echo 'MODE="'"$MODE"'"' + echo 'MODTYPE="'"$MODTYPE"'"' + echo 'NETMODE="'"$NETMODE"'"' + echo 'CHANNEL="'"$CHANNEL"'"' + echo 'LBAND="'"$LBAND"'"' + echo 'PCI="'"$PCI"'"' + echo 'TEMP="'"$CTEMP"'"' + echo 'SINR="'"$SINR"'"' +} > /tmp/signal$CURRMODEM.file + +WWANX=$(uci get modem.modem$CURRMODEM.interface) +OPER=$(cat /sys/class/net/$WWANX/operstate 2>/dev/null) +rm -f "/tmp/connstat"$CURRMODEM + +if [ ! $OPER ]; then + exit 0 +fi +if echo $OPER | grep -q "unknown"; then + exit 0 +fi + +if echo $OPER | grep -q "down"; then + echo "1" > "/tmp/connstat"$CURRMODEM +fi diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/common/sierradata.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/common/sierradata.sh new file mode 100644 index 0000000..11f1e99 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/common/sierradata.sh @@ -0,0 +1,258 @@ +#!/bin/sh + +ROOTER=/usr/lib/rooter + +log() { + logger -t "Sierra Data" "$@" +} + +read_ssc() { + SLBAND=$(echo $OX | grep -o "LTE "$SSCx" BAND: B[0-9]\+ LTE "$SSCx" BW :") + SLBAND=$(echo $SLBAND | grep -o " BAND: B[0-9]\+ ") + if [ -n "$SLBAND" ]; then + SLBAND=$(echo $SLBAND | grep -o "[0-9]\+") + SLBAND=$(printf "
                                                                        B%d" $SLBAND) + BWD=$(echo $OX | grep -o " LTE "$SSCx" BW : [.012345]\+ [ML]") + BWD=$(echo $BWD | grep -o " BW : [.012345]\+" | grep -o "[.012345]\+") + if [ -n "$BWD" ]; then + SLBAND=$SLBAND$(printf " (CA, Bandwidth %s MHz)" $BWD) + else + SLBAND=$SLBAND$(printf " (CA, Bandwidth unknown)") + fi + LBAND=$LBAND$SLBAND + XTRACHAN=$(echo $OX | grep -o " LTE "$SSCx" CHAN: [0-9]\+") + XTRACHAN=$(echo "$XTRACHAN" | grep -o "[0-9]\{2,6\}") + if [ -n "$XTRACHAN" ]; then + CHANNEL=$(echo "$CHANNEL", "$XTRACHAN") + fi + fi +} + +CURRMODEM=$1 +COMMPORT=$2 + +OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "sierrainfo.gcom" "$CURRMODEM") + +OX=$(echo $OX | tr 'a-z' 'A-Z') + +CSQ=$(echo $OX | grep -o "+CSQ: [0-9]\{1,2\}" | grep -o "[0-9]\{1,2\}") +if [ -z "$CSQ" ] || [ "$CSQ" = "99" ]; then + CSQ="-" + CSQ_PER="-" + CSQ_RSSI="-" +else + CSQ_PER=$(($CSQ * 100/31))"%" + CSQ_RSSI=$((2 * CSQ - 113))" dBm" +fi + +MODTYPE="-" +NETMODE="-" +LBAND="-" +PCI="-" + +LTEINFO=$(echo $OX | grep -o "!LTEINFO: .\+ INTRAFREQ:" | tr " " ",") +LTEINFO=$(echo "$LTEINFO" | grep -o "[0-9]\{1,6\}\,[0-9]\{3\}\,.\+") +if [ -n "$LTEINFO" ]; then + PCI=$(echo $LTEINFO | cut -d, -f10 | grep -o "[0-9]\{1,3\}") + if [ -z "$PCI" ]; then + PCI="-" + fi +fi + +SINR=$(echo $OX | grep -o "SINR (.B): [-.0-9]\{1,5\}" | tr '\n' ' ' | cut -d' ' -f3) +if [ -n "$SINR" ]; then + SINR5=$(echo $OX | grep -o "NR5G SINR (.B): [-]*[.0-9]\{1,5\}" | cut -d' ' -f4) + if [ -n "$SINR5" ]; then + SINR=$SINR" dB, "$SINR5 + fi + SINR=$SINR" dB" +else + SINR="-" +fi +TEMP=$(echo $OX | grep -o "TEMPERATURE: [-.0-9]\+ " | grep -o "[-.0-9]\+" | tr '\n' ' ') +if [ -n "$TEMP" ]; then + TEMP=$(printf "$(echo $TEMP | cut -d' ' -f2)\xc2\xb0C") +else + TEMP="unknown" +fi + +RAT=$(echo $OX | grep -o "SYSTEM MODE: [^ ]\{3,10\}" | cut -d' ' -f3) + +MODE=$RAT +case $RAT in + "WCDMA") + MODE=$(echo $OX | grep -o " \*CNTI: 0,[^ ]\+" | cut -d, -f2) + if [ -z "$MODE" ] || [ "$MODE" = "NONE" ]; then + MODE=$RAT + fi + CHANNEL=$(echo $OX | grep -o "WCDMA CHANNEL: [0-9]\{3,5\}" | cut -d' ' -f3) + if [ -n "$CHANNEL" ]; then + LOCKCHAN=$(echo $OX | grep -o "!UMTSCHAN? ENABLE: 01 CHANNEL: [0-9]\{3,5\}") + if [ -n "$LOCKCHAN" ]; then + LOCKCHAN=$(echo $LOCKCHAN | grep -o "CHANNEL: [0-9]\+" | grep -o "[0-9]\+") + CHANNEL=$CHANNEL" (Soft locked to $LOCKCHAN)" + fi + else + CHANNEL="-" + fi + ECIO=$(echo $OX | grep -o "EC/IO: [+-]\?[.0-9]\+") + ECIO=$(echo "$ECIO") + ECIO1=$(echo "$ECIO" | cut -d' ' -f4) + ECIO=$(echo "$ECIO" | cut -d' ' -f2) + RSCP=$(echo $OX | grep -o "RSCP: -[.0-9]\+") + RSCP=$(echo "$RSCP") + RSCP1=$(echo "$RSCP" | cut -d' ' -f4) + RSCP=$(echo "$RSCP" | cut -d' ' -f2) + ;; + "LTE") + LBAND=$(echo $OX | grep -o "LTE BAND: B[0-9]\+ LTE BW: [.012345]\+ MHZ" | grep -o "[.0-9]\+") + LBAND=$(printf "B%d (Bandwidth %s MHz)" $LBAND) + CHANNEL=$(echo $OX | grep -o "LTE RX CHAN: [0-9]\{1,6\}" | grep -o "[0-9]\+") + SLBAND=$(echo $OX | grep -o " ACTIVE LTE SCELL BAND:[ ]*B[0-9]\+ LTE SCELL BW:[ ]*[.012345]\+ MHZ") + if [ -n "$SLBAND" ]; then + SLBAND=$(echo $SLBAND | grep -o "[.0-9]\+") + SLBAND=$(printf "
                                                                        B%d (CA, Bandwidth %s MHz)" $SLBAND) + LBAND=$LBAND$SLBAND + XTRACHAN=$(echo $OX | grep -o " LTE SCELL CHAN:[0-9]\+" | grep -o "[0-9]\{2,6\}") + CHANNEL=$CHANNEL", "$XTRACHAN + fi + SSCLIST=$(echo $OX | grep -o "LTE S[CS]C[0-9] STATE:[ ]\?ACTIVE" | grep -o "[0-9]") + for SSCVAL in $(echo "$SSCLIST"); do + SSCx="S[CS]C"$SSCVAL + read_ssc + done + if [ -n "$LTEINFO" ]; then + RSCP=$(echo $LTEINFO | cut -d, -f12 | grep -o "[-][.0-9]\{2,5\}") + ECIO=$(echo $LTEINFO | cut -d, -f11 | grep -o "[-.0-9]\{1,5\}") + fi + if [ -z "$RSCP" ]; then + RSCP=$(echo $OX | grep -o "PCC RXM RSRP: -[0-9]\{2,3\} " | cut -d' ' -f4) + fi + if [ -n "$RSCP" ]; then + RSCP1=$(echo $OX | grep -o "PCC RXD RSRP: -[0-9]\{2,3\} " | cut -d' ' -f4) + if [ -z "$RSCP1" ]; then + RSCP1=$(echo $OX | grep -o "PCC RXD RSSI: -[0-9]\+ RSRP (DBM): -[0-9]\{2,3\} " | cut -d' ' -f7) + fi + else + RSCP=$(echo $OX | grep -o "RSRP (DBM): -[0-9]\{2,3\} " | tr '\n' ' ' | cut -d' ' -f3) + fi + if [ -z "$ECIO" ]; then + ECIO=$(echo $OX | grep -o "RSRQ (DB): [-.0-9]\{1,5\} " | cut -d' ' -f3) + fi + ;; + "ENDC") + MODE="LTE/NR EN-DC" + LBAND=$(echo $OX | grep -o "LTE BAND: B[0-9]\+ LTE BW: [.012345]\+ MHZ" | grep -o "[.0-9]\+") + LBAND=$(printf "B%d (Bandwidth %s MHz)" $LBAND) + CHANNEL=$(echo $OX | grep -o "LTE RX CHAN: [0-9]\{1,6\}" | grep -o "[0-9]\+") + NBAND=$(echo $OX | grep -o "NR5G BAND: N[0-9]\+ NR5G BW: [0-9]\+ MHZ") + NBAND=$(echo "$NBAND" | cut -d' ' -f3)" "$(echo "$NBAND" | cut -d' ' -f6) + if [ "$NBAND" != " " ]; then + NBAND=$(echo $NBAND | grep -o "[.0-9]\+") + NBAND=$(printf "
                                                                        n%d (Bandwidth %s MHz)" $NBAND) + LBAND=$LBAND$NBAND + NCHAN=$(echo $OX | grep -o "NR5G RX CHAN: [0-9]\{6\}" | cut -d' ' -f4) + CHANNEL=$CHANNEL", "$NCHAN + fi + SSCLIST=$(echo $OX | grep -o "LTE S[CS]C[0-9] STATE:[ ]\?ACTIVE" | grep -o "[0-9]") + for SSCVAL in $(echo "$SSCLIST"); do + SSCx="S[CS]C"$SSCVAL + read_ssc + done + RSCP=$(echo $OX | grep -o "PCC RXM RSRP: -[0-9]\{2,3\} " | cut -d' ' -f4) + RSCP1=$(echo $OX | grep -o "NR5G RSRP (DBM): -[0-9]\{2,3\} " | cut -d' ' -f4) + ECIO=$(echo $OX | grep -o "RSRQ (DB): [-.0-9]\{1,5\} " | tr '\n' ' ' | cut -d' ' -f3) + ECIO1=$(echo $OX | grep -o "NR5G RSRQ (DB): [-.0-9]\{1,5\} " | cut -d' ' -f4) + ;; + "NR5G") + MODE="NR5G-SA" + NBAND=$(echo $OX | grep -o "NR5G BAND: N[0-9]\+ NR5G BW: [0-9]\+ MHZ") + NBAND=$(echo "$NBAND" | cut -d' ' -f3)" "$(echo "$NBAND" | cut -d' ' -f6) + CHANNEL=$(echo $OX | grep -o "NR5G RX CHAN: [0-9]\{1,6\}" | grep -o "[0-9]\+") + RSCP=$(echo $OX | grep -o "PCC RXM RSRP: -[0-9]\{2,3\} " | cut -d' ' -f4) + ECIO=$(echo $OX | grep -o "RSRQ (DB): [-.0-9]\{1,5\} " | cut -d' ' -f3) + ;; +esac + +SELRAT=$(echo $OX | grep -o "!SELRAT:[^0-9]\+[0-9]\{2\}" | grep -o "[0-9]\{2\}") +if [ -n "$SELRAT" ]; then + MODTYPE="2" + case $SELRAT in + "01" ) + NETMODE="5" + ;; + "02" ) + NETMODE="3" + ;; + "06" ) + NETMODE="7" + ;; + * ) + NETMODE="1" + ;; + esac +fi + +CMODE=$(uci -q get modem.modem$CURRMODEM.cmode) + +if [ "$CMODE" = 0 ]; then + NETMODE="10" +fi +if [ -z "$RSCP1" ]; then + RSCP1=" " +fi +if [ -z "$ECIO1" ]; then + ECIO1=" " +fi + +{ + echo 'CSQ="'"$CSQ"'"' + echo 'CSQ_PER="'"$CSQ_PER"'"' + echo 'CSQ_RSSI="'"$CSQ_RSSI"'"' + echo 'ECIO="'"$ECIO"'"' + echo 'RSCP="'"$RSCP"'"' + echo 'ECIO1="'"$ECIO1"'"' + echo 'RSCP1="'"$RSCP1"'"' + echo 'MODE="'"$MODE"'"' + echo 'MODTYPE="'"$MODTYPE"'"' + echo 'NETMODE="'"$NETMODE"'"' + echo 'CHANNEL="'"$CHANNEL"'"' + echo 'LBAND="'"$LBAND"'"' + echo 'PCI="'"$PCI"'"' + echo 'TEMP="'"$TEMP"'"' + echo 'SINR="'"$SINR"'"' +} > /tmp/signal$CURRMODEM.file + +CONNECT=$(uci -q get modem.modem$CURRMODEM.connected) + +if [ "$CONNECT" -eq 0 ]; then + exit 0 +fi + +if [ $CSQ = "-" ]; then + log "$OX" +fi + +ENB="0" +if [ -e /etc/config/failover ]; then + ENB=$(uci get failover.enabled.enabled) +fi + +if [ $ENB = "1" ]; then + exit 0 +fi + +WWANX=$(uci -q get modem.modem$CURRMODEM.interface) +OPER=$(cat /sys/class/net/$WWANX/operstate 2>/dev/null) +rm -f "/tmp/connstat"$CURRMODEM + +if [ ! $OPER ]; then + exit 0 +fi +if echo $OPER | grep -q "unknown"; then + exit 0 +fi + +if echo $OPER | grep -q "down"; then + echo "1" > "/tmp/connstat"$CURRMODEM +fi diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/common/simcomdata.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/common/simcomdata.sh new file mode 100644 index 0000000..e48fdaf --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/common/simcomdata.sh @@ -0,0 +1,172 @@ +#!/bin/sh + +ROOTER=/usr/lib/rooter + +CURRMODEM=$1 +COMMPORT=$2 + +decode_bw() { + BW=$(echo $BW | grep -o "[0-5]\{1\}") + case $BW in + "0") + BW="1.4" ;; + "1") + BW="3" ;; + "2") + BW="5" ;; + "3") + BW="10" ;; + "4") + BW="15" ;; + "5") + BW="20" ;; + esac +} + +OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "simcominfo.gcom" "$CURRMODEM") + +OX=$(echo $OX | tr 'a-z' 'A-Z') + +REGXa="+CPSI:[ ]*LTE,ONLINE,[0-9]\{3\}-[0-9]\{2,3\},0X[0-9A-F]\{1,5\},[0-9]\{3,9\},[0-9]\{1,3\},[-A-Z0-9]\+,[0-9]\{1,6\},[0-5],[0-5],-[0-9]\{1,3\},-[0-9]\{1,4\},[-0-9]\{1,5\},[0-9]\{1,2\}" + +REGXb="+CPSI:[ ]*NR5G[_ANS]*,[0-9]\{1,3\},[0-9]\{6\},-[0-9]\{1,4\},-[0-9]\{1,4\},[-0-9]\{1,4\}" + +REGXc="+CPSI:[ ]*NR5G_SA,ONLINE,[0-9]\{3\}-[0-9]\{2,3\},0X[0-9A-F]\{1,6\},[0-9]\{3,13\},[0-9]\{1,3\},[^,]\+,[0-9]\{6,7\},-[0-9]\{1,4\},-[0-9]\{1,4\},[-0-9]\{1,4\}" + +REGXz="+CMGRMI: CA_SCELL,[0-9]\{2,6\},[^,]\+,[0-9]\{1,3\},[0-5],[^,]\+,[0-9]\{1,3\},[^,]\+,[^,]\+,[^,]\+,[^,]\+,[^,]\+,1" + +CHANNEL="-" +ECIO="-" +RSCP="-" +ECIO1=" " +RSCP1=" " +MODE="-" +NETMODE="-" +LBAND="-" +PCI="-" +CTEMP="-" +MODE="" +SINR="-" + +CSQ=$(echo "$OX" | grep -o "+CSQ: [0-9]\{1,2\}" | grep -o "[0-9]\{1,2\}") +if [ $CSQ = "99" ]; then + CSQ="" +fi +if [ -n "$CSQ" ]; then + CSQ_PER=$(($CSQ * 100/31))"%" + CSQ_RSSI=$((2 * CSQ - 113))" dBm" +else + CSQ="-" + CSQ_PER="-" + CSQ_RSSI="-" +fi + +CPSIa=$(echo "$OX" | grep -o "$REGXa") +if [ -n "$CPSIa" ]; then + CPSIb=$(echo "$OX" | grep -o "$REGXb") + PCI=$(echo $CPSIa | cut -d, -f6) + LBAND=$(echo $CPSIa | cut -d, -f7 | grep -o "[0-9]\{1,3\}") + CHANNEL=$(echo $CPSIa | cut -d, -f8) + BW=$(echo $CPSIa | cut -d, -f9) + decode_bw + BWD=$BW + BW=$(echo $CPSIa | cut -d, -f10) + decode_bw + BWU=$BW + LBAND="B"$LBAND" (Bandwidth $BWD MHz Down | $BWU MHz Up)" + ECIO=$(($(echo $CPSIa | cut -d, -f11) / 10)) + RSCP=$(($(echo $CPSIa | cut -d, -f12) / 10)) + SINR=$((($(echo $CPSIa | cut -d, -f14) * 2) - 20))" dB" + if [ -n "$CPSIb" ]; then + MODE="LTE/NR EN-DC" + PCI=$PCI", "$(echo $CPSIb | cut -d, -f2) + NCHAN=$(echo $CPSIb | cut -d, -f3) + CHANNEL="$CHANNEL, $NCHAN" + NBAND=$("$ROOTER/chan2band.sh" "$NCHAN") + if [ "$NBAND" = "-" ]; then + LBAND=$LBAND"
                                                                        nxx (unknown NR5G band)" + else + LBAND=$LBAND"
                                                                        "$NBAND + fi + RSCP=$RSCP" dBm
                                                                        "$(($(echo $CPSIb | cut -d, -f4) / 10)) + ECIO=$ECIO" dB
                                                                        "$(($(echo $CPSIb | cut -d, -f5) / 10)) + SSINR=$(echo $CPSIb | cut -d, -f6) + if [ $SSINR -lt 255 ]; then + SINR=$SINR"
                                                                        "$((($SSINR / 5) - 20))" dB" + fi + else + MODE="LTE" + fi + CPSIc="" +else + CPSIc=$(echo "$OX" | grep -o "$REGXc") + if [ -n "$CPSIc" ]; then + MODE="NR5G" + PCI=$(echo $CPSIc | cut -d, -f6) + LBAND="n"$(echo $CPSIc | cut -d, -f7 | grep -o "BAND[0-9]\{1,3\}" | grep -o "[0-9]\+") + CHANNEL=$(echo $CPSIc | cut -d, -f8) + RSCP=$(($(echo $CPSIc | cut -d, -f9) / 10)) + ECIO=$(($(echo $CPSIc | cut -d, -f10) / 10)) + if [ "$CSQ_PER" = "-" ]; then + CSQ_PER=$((100 - (($RSCP + 31) * 100/-125)))"%" + fi + SINR=$(($(echo $CPSIc | cut -d, -f11) / 10))" dB" + fi + CPSIb="" +fi + +CAINFO=$(echo "$OX" | grep -o "$REGXz" | tr ' ' ':') +if [ -n "$CAINFO" ]; then + for CASV in $(echo "$CAINFO"); do + LBAND=$LBAND"
                                                                        B"$(echo "$CASV" | cut -d, -f4) + BW=$(echo "$CASV" | cut -d, -f5) + decode_bw + LBAND=$LBAND" (CA, Bandwidth $BW MHz)" + CHANNEL="$CHANNEL, "$(echo "$CASV" | cut -d, -f2) + PCI="$PCI, "$(echo "$CASV" | cut -d, -f7) + done +fi + +CNMP=$(echo "$OX" | grep -o "+CNMP:[ ]*[0-9]\{1,3\}" | grep -o "[0-9]\{1,3\}") +TEMP=$(echo "$OX" | grep -o "+CPMUTEMP:[ ]*[-0-9]\+" | grep -o "[-0-9]\{1,4\}") + +if [ -n "$CNMP" ]; then + case $CNMP in + "2"|"55" ) + NETMODE="1" ;; + "13" ) + NETMODE="3" ;; + "14" ) + NETMODE="5" ;; + "38" ) + NETMODE="7" ;; + "71" ) + NETMODE="9" ;; + "109" ) + NETMODE="8" ;; + * ) + NETMODE="0" ;; + esac +fi +if [ -n "$TEMP" ]; then + TEMP=$(echo $TEMP)$(printf "\xc2\xb0")"C" +fi +MODTYPE="10" + +{ + echo 'CSQ="'"$CSQ"'"' + echo 'CSQ_PER="'"$CSQ_PER"'"' + echo 'CSQ_RSSI="'"$CSQ_RSSI"'"' + echo 'ECIO="'"$ECIO"'"' + echo 'RSCP="'"$RSCP"'"' + echo 'ECIO1="'"$ECIO1"'"' + echo 'RSCP1="'"$RSCP1"'"' + echo 'MODE="'"$MODE"'"' + echo 'MODTYPE="'"$MODTYPE"'"' + echo 'NETMODE="'"$NETMODE"'"' + echo 'CHANNEL="'"$CHANNEL"'"' + echo 'LBAND="'"$LBAND"'"' + echo 'PCI="'"$PCI"'"' + echo 'TEMP="'"$TEMP"'"' + echo 'SINR="'"$SINR"'"' +} > /tmp/signal$CURRMODEM.file diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/common/t77data.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/common/t77data.sh new file mode 100644 index 0000000..5c7ad2e --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/common/t77data.sh @@ -0,0 +1,236 @@ +#!/bin/sh + +ROOTER=/usr/lib/rooter + +log() { + logger -t "T77 Data" "$@" +} + +CURRMODEM=$1 +COMMPORT=$2 + +OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "t77info.gcom" "$CURRMODEM") + +OX=$(echo $OX | tr 'a-z' 'A-Z') +O=$($ROOTER/common/processat.sh "$OX") +O=$(echo $O) + +REGXca="BAND:[0-9]\{1,3\} BW:[0-9.]\+MHZ EARFCN:[0-9]\+ PCI:[0-9]\+ RSRP:[^R]\+RSRQ:[^R]\+RSSI:[^S]\+SNR[^D]\+" +REGXrxd="RX_DIVERSITY:[^(]\+([^)]\+" + +RSRP="" +RSRQ="" +CHANNEL="-" +ECIO="-" +RSCP="-" +ECIO1=" " +RSCP1=" " +MODE="-" +MODTYPE="-" +NETMODE="-" +LBAND="-" +PCI="-" +SINR="-" + +CSQ=$(echo $OX | grep -o "+CSQ: [0-9]\{1,2\}" | grep -o "[0-9]\{1,2\}") +if [ "$CSQ" = "99" ]; then + CSQ="" +fi +if [ -n "$CSQ" ]; then + CSQ_PER=$(($CSQ * 100/31))"%" + CSQ_RSSI=$((2 * CSQ - 113))" dBm" +else + CSQ="-" + CSQ_PER="-" + CSQ_RSSI="-" +fi + +TEMP=$(echo $OX | grep -o "TSENS_TZ_SENSOR[0-9]:[0-9]\{1,3\}") +if [ -n "$TEMP" ]; then + TEMP=${TEMP:17:3} +fi +if [ -z "$TEMP" ]; then + TEMP=$(echo $OX | grep -o "XO_THERM_BUF:[0-9]\{1,3\}") + if [ -n "$TEMP" ]; then + TEMP=${TEMP:13:3} + fi +fi +if [ -z "$TEMP" ]; then + TEMP=$(echo $OX | grep -o "TSENS: [0-9]\{1,3\}C") +fi +if [ -n "$TEMP" ]; then + TEMP=$(echo $TEMP | grep -o "[0-9]\{1,3\}")$(printf "\xc2\xb0")"C" +else + TEMP="-" +fi +TECH=$(echo $O" " | grep -o "+COPS: .,.,[^,]\+,[027]") +TECH="${TECH: -1}" + +if [ -n "$TECH" ]; then + RSSI=$(echo $O | grep -o " RSSI: [^D]\+D" | grep -o "[-0-9\.]\+") + if [ -n "$RSSI" ]; then + CSQ_RSSI=$(echo $RSSI)" dBm" + fi + case $TECH in + "7") + MODE="LTE" + ECIO=$(echo $O | grep -o " RSRQ: [^D]\+D" | grep -o "[-0-9\.]\+") + SINR=$(echo $OX | grep -o "RS-S[I]*NR: [^D]\+D") + SINR=${SINR:8} + SINR=$(echo "$SINR" | grep -o "[-0-9.]\{1,3\}")" dB" + LBAND="B"$(echo $O | grep -o " BAND: [0-9]\+" | grep -o "[0-9]\+") + DEBUGv1=$(echo $O | grep -o "EARFCN(DL/UL):") + DEBUGv2=$(echo $O | grep -o "LTE ENGINEERING") + if [ -n "$DEBUGv1" ]; then + RSCP=$(echo $O | grep -o "[^G] RSRP: [^D]\+D" | grep -o "[-0-9\.]\+") + RSRPlist=$(echo $OX | grep -o "$REGXrxd" | grep -o "\-[.0-9]\{4,5\}" | tr "\n" ",") + if [ -n "$RSRPlist" ]; then + RSCP=$(echo $RSRPlist | cut -d, -f1) + MIMO=$(echo $OX | grep -o "$REGXrxd" | cut -d" " -f2) + if [ "$MIMO" == "3" ]; then + RSCP="(2xMIMO) $RSCP" + fi + for IDX in 2 3 4; do + RSCPval=$(echo $RSRPlist | cut -d, -f$IDX) + if [ -n "$RSCPval" -a "$RSCPval" != "-256.0" ]; then + RSCP="$RSCP dBm, $RSCPval" + fi + done + fi + CHANNEL=$(echo $O | grep -o " EARFCN(DL/UL): [0-9]\+" | grep -o "[0-9]\+") + BWD=$(echo $O | grep -o " BW: [0-9\.]\+ MHZ" | grep -o "[0-9\.]\+") + if [ "$BWD" != "1.4" ]; then + BWD=${BWD/.*} + fi + LBAND=$LBAND" (Bandwidth $BWD MHz)" + PCI=$(echo $OX | grep -o " ENB ID(PCI): [^(]\+([0-9]\{1,3\})" | grep -o "([0-9]\+)" | grep -o "[0-9]\+") + fi + if [ -n "$DEBUGv2" ]; then + RSCP=$(echo $O | grep -o "RSRP: [^D]\+D" | grep -o "[-0-9\.]\+") + CHANNEL=$(echo $O | grep -o " DL CHANNEL: [0-9]\+" | grep -o "[0-9]\+") + PCI=$(echo $OX | grep -o " PCI: [0-9]\{1,3\}" | grep -o "[0-9]\+") + fi + SCC=$(echo $OX | grep -o " SCELL[1-9]:") + if [ -n "$SCC" ]; then + SCCn=$(echo $SCC | grep -o [0-9]) + for SCCx in $(echo "$SCCn"); do + SCCv=$(echo $OX | grep -o "SCELL$SCCx: $REGXca" | tr ' ' ',') + if [ -n "$SCCv" ]; then + SLBV=B$(echo $SCCv | cut -d, -f2 | grep -o "[0-9]\{1,3\}") + SBWV=$(echo $SCCv | cut -d, -f3 | grep -o "[0-9][^M]\+") + if [ "$SBWV" != "1.4" ]; then + SBWV=${SBWV%.*} + fi + LBAND=$LBAND"
                                                                        "$SLBV" (CA, Bandwidth "$SBWV" MHz)" + CHANNEL=$CHANNEL", "$(echo $SCCv | cut -d, -f4 | grep -o "[0-9]\+") + PCI=$PCI", "$(echo $SCCv | cut -d, -f5 | grep -o "[0-9]\+") + RSCP=$RSCP" dBm, "$(echo $SCCv | cut -d, -f6 | grep -o "[-0-9.]\+") + ECIO=$ECIO" dB, "$(echo $SCCv | cut -d, -f7 | grep -o "[-0-9.]\+") + CSQ_RSSI=$CSQ_RSSI", "$(echo $SCCv | cut -d, -f8 | grep -o "[-0-9.]\+")" dBm" + SINR=$SINR", "$(echo $SCCv | cut -d, -f9 | grep -o "[-0-9.]\+")" dB" + fi + done + else + SCC=$(echo $O | grep -o " SCC[1-9][^M]\+MHZ") + if [ -n "$SCC" ]; then + printf '%s\n' "$SCC" | while read SCCX; do + SCCX=$(echo $SCCX | tr " " ",") + SLBV=$(echo $SCCX | cut -d, -f5 | grep -o "B[0-9]\{1,3\}") + SBWV=$(echo $SCCX | cut -d, -f9) + if [ "$SBWV" != "1.4" ]; then + SBWV=${SBWV/.*} + fi + LBAND=$LBAND"
                                                                        "$SLBV" (CA, Bandwidth "$SBWV" MHz)" + echo "$LBAND" > /tmp/lbandvar$CURRMODEM + done + if [ -e /tmp/lbandvar$CURRMODEM ]; then + read LBAND < /tmp/lbandvar$CURRMODEM + rm /tmp/lbandvar$CURRMODEM + fi + fi + fi + ;; + "2") + MODE="WCDMA" + DEBUGv1=$(echo $O | grep -o "RAT:WCDMA") + if [ -n "$DEBUGv1" ]; then + RSCP=$(echo $O | grep -o "RSCP:[^)]\+" | grep -o "[-0-9\.]\+DBM," | grep -o "[^DBM,]\+") + ECIO=$(echo $O | grep -o " ECIO:[^D]\+D" | grep -o "[-0-9\.]\+") + ECIO=$(echo $ECIO) + CHANNEL=$(echo $O | grep -o " CHANNEL (DL): [0-9]\+" | grep -o "[0-9]\+") + LBAND="B"$(echo $O | grep -o " BAND: [0-9]\+" | grep -o "[0-9]\+") + BW=$(echo $O | grep -o " BW: [0-9\.]\+ MHZ" | grep -o "[0-9\.]\+") + BW=$(printf "%.0f" $BW ) + LBAND=$LBAND" (Bandwidth $BW MHz)" + PCI=$(echo $OX | grep -o "PSC:.\?[0-9]\{1,3\}" | grep -o "[0-9]\+") + else + QCSQ=$(echo $O | grep -o "\$QCSQ: -[0-9]\{2,3\},[-0-9]\{1,3\},[-0-9]\{1,3\},") + if [ -n "$QCSQ" ]; then + RSCP=$(echo $QCSQ | cut -d, -f1 | grep -o "[-0-9]*") + ECIO=$(echo $QCSQ | cut -d, -f2) + fi + fi + ;; + *) + MODE="GSM" + ;; + esac +fi + +SCFG=$(echo $OX | grep -o "\^SYSCONFIG: [0-9]\{1,2\}" | grep -o "[0-9]\{1,2\}") +if [ -n "$SCFG" ]; then + case $SCFG in + "13" ) + NETMODE="3" ;; + "14" ) + NETMODE="5" ;; + "17" ) + NETMODE="7" ;; + * ) + NETMODE="1" ;; + esac +fi + +MODTYPE="8" + +{ + echo 'CSQ="'"$CSQ"'"' + echo 'CSQ_PER="'"$CSQ_PER"'"' + echo 'CSQ_RSSI="'"$CSQ_RSSI"'"' + echo 'ECIO="'"$ECIO"'"' + echo 'RSCP="'"$RSCP"'"' + echo 'ECIO1="'"$ECIO1"'"' + echo 'RSCP1="'"$RSCP1"'"' + echo 'MODE="'"$MODE"'"' + echo 'MODTYPE="'"$MODTYPE"'"' + echo 'NETMODE="'"$NETMODE"'"' + echo 'CHANNEL="'"$CHANNEL"'"' + echo 'LBAND="'"$LBAND"'"' + echo 'PCI="'"$PCI"'"' + echo 'TEMP="'"$TEMP"'"' + echo 'SINR="'"$SINR"'"' +} > /tmp/signal$CURRMODEM.file + +CONNECT=$(uci get modem.modem$CURRMODEM.connected) +if [ $CONNECT -eq 0 ]; then + exit 0 +fi + +if [ "$CSQ" = "-" ]; then + log "$OX" +fi + +WWANX=$(uci get modem.modem$CURRMODEM.interface) +OPER=$(cat /sys/class/net/$WWANX/operstate 2>/dev/null) +rm -f "/tmp/connstat"$CURRMODEM + +if [ ! $OPER ]; then + exit 0 +fi +if echo $OPER | grep -q "unknown"; then + exit 0 +fi + +if echo $OPER | grep -q "down"; then + echo "1" > "/tmp/connstat"$CURRMODEM +fi diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/common/telitdata.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/common/telitdata.sh new file mode 100644 index 0000000..8b677f5 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/common/telitdata.sh @@ -0,0 +1,241 @@ +#!/bin/sh + +ROOTER=/usr/lib/rooter + +CURRMODEM=$1 +COMMPORT=$2 + +log() { + logger -t "Telit Data" "$@" +} +decode_bw() { + case $BW in + "0") + BW="1.4" + ;; + "1") + BW="3" + ;; + "2") + BW="5" + ;; + "3") + BW="10" + ;; + "4") + BW="15" + ;; + "5") + BW="20" + ;; + *) + BW="" + ;; + esac +} +decode_band() { + if [ "$SLBV" -lt 134 ]; then + SLBV=$(($SLBV - 119)) + elif [ "$SLBV" -eq 134 ]; then + SLBV="17" + elif [ "$SLBV" -lt 143 ]; then + SLBV=$(($SLBV - 102)) + elif [ "$SLBV" -lt 147 ]; then + SLBV=$(($SLBV - 125)) + elif [ "$SLBV" -lt 149 ]; then + SLBV=$(($SLBV - 123)) + elif [ "$SLBV" -lt 152 ]; then + SLBV=$(($SLBV - 108)) + elif [ "$SLBV" -eq 152 ]; then + SLBV="23" + elif [ "$SLBV" -eq 153 ]; then + SLBV="26" + elif [ "$SLBV" -eq 154 ]; then + SLBV="32" + elif [ "$SLBV" -lt 158 ]; then + SLBV=$(($SLBV - 30)) + elif [ "$SLBV" -lt 161 ]; then + SLBV=$(($SLBV - 130)) + elif [ "$SLBV" -eq 161 ]; then + SLBV="66" + elif [ "$SLBV" -eq 162 ]; then + SLBV="250" + elif [ "$SLBV" -eq 163 ]; then + SLBV="46" + elif [ "$SLBV" -eq 166 ]; then + SLBV="71" + else + SLBV="??" + fi + +} + +idV=$(uci get modem.modem$CURRMODEM.idV) +idP=$(uci get modem.modem$CURRMODEM.idP) + +if [ $idP = 1040 -o $idP = 1041 ]; then + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "telitinfo.gcom" "$CURRMODEM" | tr 'a-z' 'A-Z') +else + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "telitinfoln.gcom" "$CURRMODEM" | tr 'a-z' 'A-Z') +fi + +O=$($ROOTER/common/processat.sh "$OX") +O=$(echo $O) + +RSRP="" +RSRQ="" +CHANNEL="-" +ECIO="-" +RSCP="-" +ECIO1=" " +RSCP1=" " +MODE="-" +MODTYPE="-" +NETMODE="-" +LBAND="-" +TEMP="-" +PCI="-" +SINR="-" + +CSQ=$(echo $O | grep -o "CSQ: [0-9]\+" | grep -o "[0-9]\+") +[ "x$CSQ" = "x" ] && CSQ=-1 + +if [ $CSQ -ge 0 -a $CSQ -le 31 ]; then + CSQ_PER=$(($CSQ * 100/31)) + CSQ_RSSI=$((2 * CSQ - 113)) + CSQX=$CSQ_RSSI + [ $CSQ -eq 0 ] && CSQ_RSSI="<= "$CSQ_RSSI + [ $CSQ -eq 31 ] && CSQ_RSSI=">= "$CSQ_RSSI + CSQ_PER=$CSQ_PER"%" + CSQ_RSSI=$CSQ_RSSI" dBm" +else + CSQ="-" + CSQ_PER="-" + CSQ_RSSI="-" +fi + +TMP=$(echo $O" " | grep -o "#TEMPSENS: .\+ OK " | tr " " ",") +if [ -n "$TMP" ]; then + TEMP=$(echo $TMP | cut -d, -f3)$(printf "\xc2\xb0")"C" +fi + +MODE="-" +WS46=$(echo $O | grep -o "+COPS:.\+AT#RFSTS" | grep -o "+COPS: [0-3],[0-3],\"[^\"].\+\",[027]") +TECH=$(echo $WS46 | cut -d, -f4) +if [ -n "$TECH" ]; then + MODE=$TECH + case $MODE in + "7") + MODE="LTE" + CAINFO=$(echo $OX | grep -o "#CAINFO: 1.\+OK") + SGCELL=$(echo $OX | grep -o "[#^]RFSTS: \"[ 0-9]\{5,7\}\",[0-9]\{1,5\},.\+,\"[0-9]\{15\}\",\"[^\"]*\",[0-3],[0-9]\{1,2\}[,0-9]\{0,4\}") + if [ -n "$SGCELL" ]; then + RSCP=$(echo $SGCELL | cut -d, -f3) + ECIO=$(echo $SGCELL | cut -d, -f5) + RSSI=$(echo $SGCELL | cut -d, -f4) + CSQ_RSSI=$(echo "$RSSI dBm") + CHANNEL=$(echo $SGCELL | cut -d, -f2) + if [ $(echo ${SGCELL:0:1}) = "#" ]; then + LBAND="B"$(echo $SGCELL | cut -d, -f16 | grep -o "[0-9]\{1,2\}") + else + LBAND="B"$(echo $SGCELL | cut -d, -f15) + SSINR=$(echo $SGCELL | cut -d, -f16) + if [ -n "$SSINR" ]; then + SINR=$((($(echo $SSINR) / 5) - 20))" dB" + fi + fi + BW=$(echo $CAINFO | cut -d, -f3) + decode_bw + if [ -n "$BW" ];then + LBAND=$LBAND" (Bandwidth $BW MHz)" + fi + if [ -n "$CAINFO" ]; then + SCCLIST=$(echo $CAINFO | grep -o "1[2-6][0-9],[0-9]\{1,5\},[0-5],[0-9]\{1,3\},-[0-9]\+,-[0-9]\+,-[0-9]\+,[0-9]\{1,3\},2,[0-5],") + if [ -n "$SCCLIST" ]; then + SSINR=$(echo $CAINFO | grep -o "#CAINFO: [^,]\+,[^,]\+,[^,]\+,[^,]\+,[^,]\+,[^,]\+,[^,]\+,[0-9]\{1,3\},") + SINR=$((($(echo $SSINR | cut -d, -f8) / 5) - 20))" dB" + printf '%s\n' "$SCCLIST" | while read SCCVAL; do + PCI=$(echo $SCCVAL | cut -d, -f4) + SLBV=$(echo $SCCVAL | cut -d, -f1) + decode_band + LBAND=$LBAND"
                                                                        B"$SLBV + BW=$(echo $SCCVAL | cut -d, -f3) + decode_bw + LBAND=$LBAND" (CA, Bandwidth $BW MHz)" + SCHV=$(echo $SCCVAL | cut -d, -f2) + CHANNEL=$(echo "$CHANNEL", "$SCHV") + { + echo "$LBAND" + echo "$CHANNEL" + } > /tmp/lbandvar$CURRMODEM + done + fi + fi + if [ -e /tmp/lbandvar$CURRMODEM ]; then + { + read LBAND + read CHANNEL + } < /tmp/lbandvar$CURRMODEM + rm /tmp/lbandvar$CURRMODEM + fi + fi + ;; + 2) + MODE="UMTS" + SGCELL=$(echo $O | grep -o "[#^]RFSTS: \"[ 0-9]\{5,7\}\",[0-9]\{1,5\},.\+,\"[0-9]\{15\}\",") + if [ -n "$SGCELL" ]; then + RSSI=$(echo $SGCELL | cut -d, -f6) + CSQ_RSSI=$(echo "$RSSI dBm") + RSCP=$(echo $SGCELL | cut -d, -f5) + ECIO=$(echo $SGCELL| cut -d, -f4) + CHANNEL=$(echo $SGCELL | cut -d, -f2) + fi + ;; + esac +fi + +NETMODE="1" +MODTYPE="8" + +{ + echo 'CSQ="'"$CSQ"'"' + echo 'CSQ_PER="'"$CSQ_PER"'"' + echo 'CSQ_RSSI="'"$CSQ_RSSI"'"' + echo 'ECIO="'"$ECIO"'"' + echo 'RSCP="'"$RSCP"'"' + echo 'ECIO1="'"$ECIO1"'"' + echo 'RSCP1="'"$RSCP1"'"' + echo 'MODE="'"$MODE"'"' + echo 'MODTYPE="'"$MODTYPE"'"' + echo 'NETMODE="'"$NETMODE"'"' + echo 'CHANNEL="'"$CHANNEL"'"' + echo 'LBAND="'"$LBAND"'"' + echo 'PCI="'"$PCI"'"' + echo 'TEMP="'"$TEMP"'"' + echo 'SINR="'"$SINR"'"' +} > /tmp/signal$CURRMODEM.file + +CONNECT=$(uci get modem.modem$CURRMODEM.connected) + +if [ $CONNECT -eq 0 ]; then + exit 0 +fi + +if [ "$CSQ" = "-" ]; then + log "$OX" +fi + +WWANX=$(uci get modem.modem$CURRMODEM.interface) +OPER=$(cat /sys/class/net/$WWANX/operstate 2>/dev/null) +rm -f "/tmp/connstat"$CURRMODEM + +if [ ! $OPER ]; then + exit 0 +fi +if echo $OPER | grep -q "unknown"; then + exit 0 +fi + +if echo $OPER | grep -q "down"; then + echo "1" > "/tmp/connstat"$CURRMODEM +fi diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/common/ubloxdata.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/common/ubloxdata.sh new file mode 100644 index 0000000..6f9a4ec --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/common/ubloxdata.sh @@ -0,0 +1,250 @@ +#!/bin/sh + +ROOTER=/usr/lib/rooter + +log() { + logger -t "ublox Data" "$@" +} + +CURRMODEM=$1 +COMMPORT=$2 + +get_ublox() { + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "ubloxinfo.gcom" "$CURRMODEM" | tr 'a-z' 'A-Z') +} + +get_ublox + +UCGED=$(echo $OX | grep -o "+UCGED: 2") +if [ -z "$UCGED" ]; then + ATCMDD="AT+UCGED=2" + UCGED=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + get_ublox +fi +OX=$(echo $OX) + +RSRP="" +RSRQ="" +CHANNEL="-" +ECIO="-" +RSCP="-" +ECIO1=" " +RSCP1=" " +MODE="-" +MODTYPE="-" +NETMODE="-" +LBAND="-" +TEMP="-" +PCI="-" +SINR="-" + +CSQ=$(echo $OX | grep -o "+CSQ: .\+ +CESQ" | tr " " ",") +CESQ=$(echo $OX | grep -o "+CESQ: .\+ +URAT" | tr " " ",") +URAT=$(echo $OX | grep -o "+URAT: .\+ +UCGED" | tr " " ",") +UCGED=$(echo $OX" " | grep -o "+UCGED: .\+ OK " | tr " " ",") + +CSQ=$(echo $CSQ | cut -d, -f2) +CSQ=$(echo $CSQ | grep -o "[0-9]\{1,2\}") + +if [ "$CSQ" -eq "99" ]; then + CSQ="" +fi +if [ -n "$CSQ" ]; then + CSQ_PER=$(($CSQ * 100/31))"%" + CSQ_RSSI=$((2 * CSQ - 113))" dBm" +else + CSQ="-" + CSQ_PER="-" + CSQ_RSSI="-" +fi + +RAT=$(echo $UCGED | cut -d, -f3) +case "$RAT" in + "2") + MODE="GSM" + LAC=$(echo $UCGED | cut -d, -f11) + LAC=$(echo $LAC | grep -o "[0-9A-F]\{4\}") + CID=$(echo $UCGED | cut -d, -f9) + CID=$(echo $CID | grep -o "[0-9A-F]\{4\}") + ;; + "3") + MODE="UMTS" + CHANNEL=$(echo $UCGED | cut -d, -f7) + LAC=$(echo $UCGED | cut -d, -f10) + LAC=$(echo $LAC | grep -o "[0-9A-F]\{4\}") + CID=$(echo $UCGED | cut -d, -f9) + CID=$(echo $CID | grep -o "[0-9A-F]\{5,8\}") + RSCP=$(echo $CESQ | cut -d, -f4) + RSCP=$(echo $RSCP | grep -o "[0-9]\{1,3\}") + if [ "$RSCP" -eq "255" ]; then + RSCP="" + fi + if [ -n "$RSCP" ]; then + RSCP=$(($RSCP - 121)) + fi + ECIO=$(echo $CESQ | cut -d, -f5) + ECIO=$(echo $ECIO | grep -o "[0-9]\{1,3\}") + if [ "$ECIO" -eq "255" ]; then + ECIO="" + fi + if [ -n "$ECIO" ]; then + ECIO=$((($ECIO / 2) - 24)) + fi + ;; + "4") + MODE="LTE" + LBAND=$(echo $UCGED | cut -d, -f8) + if [ "$LBAND" -eq "255" ]; then + LBAND="" + fi + BWU=$(echo $UCGED | cut -d, -f9) + BWU=$(echo $BWU | grep -o "[0-9]\{1,3\}") + BWD=$(echo $UCGED | cut -d, -f10) + BWD=$(echo $BWD | grep -o "[0-9]\{1,3\}") + if [ -z "$BWD" ]; then + LBAND="" + fi + if [ -z "$BWU" ]; then + LBAND="" + fi + if [ -z "$LBAND" ]; then + LBAND="-" + else + if [ "$BWU" = "6" ]; then + BWU="1.4" + else + BWU=$(($(echo $BWU) / 5)) + fi + if [ "$BWD" = "6" ]; then + BWD="1.4" + else + BWD=$(($(echo $BWD) / 5)) + fi + LBAND="B"$LBAND" (Bandwidth $BWD MHz Down | $BWU MHz Up)" + fi + LAC=$(echo $UCGED | cut -d, -f11) + LAC=$(echo $LAC | grep -o "[0-9A-F]\{4\}") + CID=$(echo $UCGED | cut -d, -f12) + CID=$(echo $CID | grep -o "[0-9A-F]\{5,8\}") + RSRP=$(echo $CESQ | cut -d, -f7) + RSRP=$(echo $RSRP | grep -o "[0-9]\{1,3\}") + if [ "$RSRP" -eq "255" ]; then + RSRP="" + fi + if [ -n "$RSRP" ]; then + RSRP=$(($RSRP - 141)) + RSCP=$RSRP + fi + RSRQ=$(echo $CESQ | cut -d, -f6) + RSRQ=$(echo $RSRQ | grep -o "[0-9]\{1,3\}") + if [ "$RSRQ" -eq "255" ]; then + RSRQ="" + fi + if [ -n "$RSRQ" ]; then + RSRQ=$((($RSRQ / 2) - 19)) + ECIO=$RSRQ + fi + ;; +esac + +if [ $RAT -eq "2" ]; then + if [ -n "$CID" ]; then + CID_NUM=$(printf "%d" 0x$CID) + CID=$CID" ("$CID_NUM")" + fi +else + CID=$(echo $CID | grep -o "[0-9A-F]\{5,8\}") + if [ -n "$CID" ]; then + LCID=$(printf "%08X" 0x$CID) + LCID_NUM=$(printf "%d" 0x$LCID) + if [ "$RAT" -eq "4" ]; then + RNC=$(printf "${LCID:1:5}") + CID=$(printf "${LCID:6:2}") + else + RNC=$(printf "${LCID:1:3}") + CID=$(printf "${LCID:4:4}") + fi + CID_NUM=$(printf "%d" 0x$CID) + CID=$CID" ("$CID_NUM")" + RNC_NUM=" ("$(printf "%d" 0x$RNC)")" + fi +fi + +if [ -n "$LAC" ]; then + LAC_NUM=$(printf "%d" 0x$LAC) + LAC=$LAC" ("$LAC_NUM")" +else + LAC="-" + LAC_NUM="-" +fi + +URAT1=$(echo $URAT | cut -d, -f2) +URAT2=$(echo $URAT | cut -d, -f3) +if [ -n "$URAT1" ]; then + MODTYPE="5" + case $URAT1 in + "0" ) + NETMODE="3" + ;; + "2" ) + NETMODE="5" + ;; + "3" ) + NETMODE="7" + ;; + * ) + case $URAT2 in + "0" ) + NETMODE="2" + ;; + "2" ) + NETMODE="4" + ;; + "3" ) + NETMODE="1" + ;; + esac + ;; + esac +fi + +echo 'CSQ="'"$CSQ"'"' > /tmp/signal$CURRMODEM.file +echo 'CSQ_PER="'"$CSQ_PER"'"' >> /tmp/signal$CURRMODEM.file +echo 'CSQ_RSSI="'"$CSQ_RSSI"'"' >> /tmp/signal$CURRMODEM.file +echo 'ECIO="'"$ECIO"'"' >> /tmp/signal$CURRMODEM.file +echo 'RSCP="'"$RSCP"'"' >> /tmp/signal$CURRMODEM.file +echo 'ECIO1="'"$ECIO1"'"' >> /tmp/signal$CURRMODEM.file +echo 'RSCP1="'"$RSCP1"'"' >> /tmp/signal$CURRMODEM.file +echo 'MODE="'"$MODE"'"' >> /tmp/signal$CURRMODEM.file +echo 'MODTYPE="'"$MODTYPE"'"' >> /tmp/signal$CURRMODEM.file +echo 'NETMODE="'"$NETMODE"'"' >> /tmp/signal$CURRMODEM.file +echo 'CHANNEL="'"$CHANNEL"'"' >> /tmp/signal$CURRMODEM.file +echo 'LBAND="'"$LBAND"'"' >> /tmp/signal$CURRMODEM.file +echo 'LAC="'"$LAC"'"' >> /tmp/signal$CURRMODEM.file +echo 'LAC_NUM="'""'"' >> /tmp/signal$CURRMODEM.file +echo 'CID="'"$CID"'"' >> /tmp/signal$CURRMODEM.file +echo 'CID_NUM="'""'"' >> /tmp/signal$CURRMODEM.file +echo 'RNC="'"$RNC"'"' >> /tmp/signal$CURRMODEM.file +echo 'RNC_NUM="'"$RNC_NUM"'"' >> /tmp/signal$CURRMODEM.file +echo 'TEMP="'"$TEMP"'"' >> /tmp/signal$CURRMODEM.file +echo 'PCI="'"$PCI"'"' >> /tmp/signal$CURRMODEM.file +echo 'SINR="'"$SINR"'"' >> /tmp/signal$CURRMODEM.file + +if [ "$CSQ" = "-" ]; then + log "$OX" +fi + +WWANX=$(uci get modem.modem$CURRMODEM.interface) +OPER=$(cat /sys/class/net/$WWANX/operstate 2>/dev/null) +rm -f "/tmp/connstat"$CURRMODEM + +if [ ! $OPER ]; then + exit 0 +fi +if echo $OPER | grep -q "unknown"; then + exit 0 +fi + +if echo $OPER | grep -q "down"; then + echo "1" > "/tmp/connstat"$CURRMODEM +fi diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/common/ztedata.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/common/ztedata.sh new file mode 100644 index 0000000..2800901 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/common/ztedata.sh @@ -0,0 +1,193 @@ +#!/bin/sh + +ROOTER=/usr/lib/rooter + +log() { + logger -t "ZTE Data" "$@" +} + +CURRMODEM=$1 +COMMPORT=$2 + +fix_data() { + O=$($ROOTER/common/processat.sh "$OY") +} + +process_csq() { + CSQ=$(echo "$O" | awk -F[,\ ] '/^\+CSQ:/ {print $2}') + [ "x$CSQ" = "x" ] && CSQ=-1 + if [ $CSQ -ge 0 -a $CSQ -le 31 ]; then + CSQ_PER=$(($CSQ * 100/31)) + CSQ_RSSI=$((2 * CSQ - 113)) + CSQX=$CSQ_RSSI + [ $CSQ -eq 0 ] && CSQ_RSSI="<= "$CSQ_RSSI + [ $CSQ -eq 31 ] && CSQ_RSSI=">= "$CSQ_RSSI + CSQ_PER=$CSQ_PER"%" + CSQ_RSSI=$CSQ_RSSI" dBm" + else + CSQ="-" + CSQ_PER="-" + CSQ_RSSI="-" + fi +} + +process_zte() { + ZRSSI=$(echo "$O" | awk -F[,\ ] '/^\+ZRSSI:/ {print $2}') + if [ "x$ZRSSI" != "x" ]; then + TMP_RSSI=$CSQ_RSSI + CSQ_RSSI="-"$ZRSSI" dBm" + ECI=$(echo "$O" | awk -F[,\ ] '/^\+ZRSSI:/ {print $3}') + if [ "x$ECI" != "x" ]; then + ECIO=`expr $ECI / 2` + ECIO="-"$ECIO + RSCP=$(echo "$O" | awk -F[,\ ] '/^\+ZRSSI:/ {print $4}') + if [ "x$RSCP" != "x" ]; then + RSCP=`expr $RSCP / 2` + RSCP="-"$RSCP + else + CSQ_RSSI=$TMP_RSSI + RSCP=$ZRSSI + ECIO=$ECI + fi + else + RSCP=$ZRSSI + CSQ_RSSI=$TMP_RSSI + ECIO=`expr $RSCP - $CSQX` + fi + fi + + MODE="-" + TECH=$(echo "$O" | awk -F[,\ ] '/^\+ZPAS:/ {print $2}' | sed 's/"//g') + if [ "x$TECH" != "x" -a "x$TECH" != "xNo" ]; then + MODE="$TECH" + fi + + ZSNT=$(echo "$O" | awk -F[,\ ] '/^\+ZSNT:/ {print $2}') + if [ "x$ZSNT" != "x" ]; then + MODTYPE="1" + if [ $ZSNT = "0" ]; then + ZSNTX=$(echo "$O" | awk -F[,\ ] '/^\+ZSNT:/ {print $4}') + case $ZSNTX in + "0" ) + NETMODE="1" + ;; + "1" ) + NETMODE="2" + ;; + "2" ) + NETMODE="4" + ;; + "6" ) + NETMODE="6" + ;; + esac + else + case $ZSNT in + "1" ) + NETMODE="3" + ;; + "2" ) + NETMODE="5" + ;; + "6" ) + NETMODE="7" + ;; + esac + fi + fi + + ZCELLINFO=$(echo $O | grep -o "+ZCELLINFO: .\+ OK") + if [ -n "$ZCELLINFO" ]; then + LBAND=$(echo $ZCELLINFO | cut -d, -f3 | grep -o "LTE B[0-9]\{1,2\}") + CHANNEL=$(echo $ZCELLINFO | cut -d, -f4 | grep -o "[0-9]\+") + if [ -n "$LBAND" ]; then + LBAND="B"$(echo $LBAND | grep -o "[0-9]\+") + else + LBAND="-" + CHANNEL="-" + fi + fi + + ZSINR=$(echo $OY | grep -o "+ZSINR: [-0-9]\{1,3\},[0-9],") + if [ -n "$ZSINR" ]; then + ZSINR=${ZSINR:8} + SINR=$(echo $ZSINR | cut -d, -f1)"."$(echo $ZSINR | cut -d, -f2)" dB" + fi + + CMODE=$(uci get modem.modem$CURRMODEM.cmode) + if [ $CMODE = 0 ]; then + NETMODE="10" + fi +} + +CSQ="-" +CSQ_PER="-" +CSQ_RSSI="-" +ECIO="-" +RSCP="-" +ECIO1=" " +RSCP1=" " +MODE="-" +MODETYPE="-" +NETMODE="-" +LBAND="-" +CHANNEL="-" +TEMP="-" +PCI="-" +SINR="-" + +OY=$($ROOTER/gcom/gcom-locked "$COMMPORT" "zteinfo.gcom" "$CURRMODEM") + +fix_data +process_csq +process_zte + +{ + echo 'CSQ="'"$CSQ"'"' > /tmp/signal$CURRMODEM.file + echo 'CSQ_PER="'"$CSQ_PER"'"' + echo 'CSQ_RSSI="'"$CSQ_RSSI"'"' + echo 'ECIO="'"$ECIO"'"' + echo 'RSCP="'"$RSCP"'"' + echo 'ECIO1="'"$ECIO1"'"' + echo 'RSCP1="'"$RSCP1"'"' + echo 'MODE="'"$MODE"'"' + echo 'MODTYPE="'"$MODTYPE"'"' + echo 'NETMODE="'"$NETMODE"'"' + echo 'LBAND="'"$LBAND"'"' + echo 'CHANNEL="'"$CHANNEL"'"' + echo 'TEMP="'"$TEMP"'"' + echo 'PCI="'"$PCI"'"' + echo 'SINR="'"$SINR"'"' +} > /tmp/signal$CURRMODEM.file + +CONNECT=$(uci get modem.modem$CURRMODEM.connected) +if [ $CONNECT -eq 0 ]; then + exit 0 +fi + +if [ $CSQ = "-" ]; then + log "$OY" +fi + +ENB="0" +if [ -e /etc/config/failover ]; then + ENB=$(uci get failover.enabled.enabled) +fi +if [ $ENB = "1" ]; then + exit 0 +fi + +WWANX=$(uci get modem.modem$CURRMODEM.interface) +OPER=$(cat /sys/class/net/$WWANX/operstate 2>/dev/null) +rm -f "/tmp/connstat"$CURRMODEM + +if [ ! $OPER ]; then + exit 0 +fi +if echo $OPER | grep -q "unknown"; then + exit 0 +fi + +if echo $OPER | grep -q "down"; then + echo "1" > "/tmp/connstat"$CURRMODEM +fi diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/bandmask b/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/bandmask new file mode 100644 index 0000000..8051d05 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/bandmask @@ -0,0 +1,483 @@ +#!/bin/sh + +ROOTER=/usr/lib/rooter + +log() { + modlog "Band Mask $CURRMODEM" "$@" +} + +CURRMODEM=$1 +MODTYPE=$2 + +CPORT=$(uci get modem.modem$CURRMODEM.commport) + +sierrabandmask() { + enb=$(uci -q get custom.bandlock.enabled) + ATCMDD='AT!ENTERCND="A710";!BAND?' + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + if [ $enb == "1" ]; then + log " " + log "Sierra Response : $OX" + log " " + fi + OX=$(echo $OX | tr " " '\x0a') + line=$OX + Unk=$(echo $line | grep "Unknown") + if [ "$Unk" ]; then + BND=$(echo $line | cut -d, -f6 | tr " " ",") + if [ $enb == "1" ]; then + log "Unknw : $BND" + fi + L1=$(echo $BND | cut -d, -f11) + GW=$(echo $BND | cut -d, -f10) + L2=$(echo $BND | cut -d, -f13) + else + all=$(echo $line | grep "L Band Mask 2") + if [ "$all" ]; then + BND=$(echo $line | cut -d, -f4 | tr " " ",") + if [ $enb == "1" ]; then + log "EM7511 : $BND" + fi + OK=8 + EOK=$(echo $BND | cut -d, -f$OK) + while [ $EOK != "OK" ]; do + OK=$(( OK + 1 )) + EOK=$(echo $BND | cut -d, -f$OK) + done + if [ $enb == "1" ]; then + log "$OK" + fi + ex1=$(( OK - 5 )) + ex2=$(( OK - 6 )) + ex3=$(( OK - 3 )) + L1=$(echo $BND | cut -d, -f$ex1) + GW=$(echo $BND | cut -d, -f$ex2) + L2=$(echo $BND | cut -d, -f$ex3) + else + BND=$(echo $line | cut -d, -f5 | tr " " ",") + if [ $enb == "1" ]; then + log "$BND" + fi + L1=$(echo $BND | cut -d, -f3) + GW=$(echo $BND | cut -d, -f2) + L2=$(echo $BND | cut -d, -f5) + fi + fi + if [ ! $L2 ]; then + L2="0000000000000000" + fi + if [ $L2 = "OK" ]; then + L2="0000000000000000" + fi + if [ $enb == "1" ]; then + log " " + log "LTE Band Mask : $L2$L1" + log " " + fi + uci set modem.modem$CURRMODEM.GW="$GW" + uci set modem.modem$CURRMODEM.L1="0x$L2$L1" + uci set modem.modem$CURRMODEM.L1X="$L1" + uci set modem.modem$CURRMODEM.L2="$L2" + uci commit modem + ATCMDD='AT!ENTERCND="AWRONG"' + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") +} + +quebandmask() { + enb=$(uci -q get custom.bandlock.enabled) + idP=$(uci get modem.modem$CURRMODEM.idP) + CPORT=$(uci get modem.modem$CURRMODEM.commport) + ATCMDD="AT+CGMM" + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + model=$(echo "$OX" | tr '\n' ' ' | cut -d' ' -f2) + uci set modem.modem$CURRMODEM.model=$model + ATCMDD='AT+QCFG="band"' + EM160=0 + if [ $enb == "1" ]; then + log " " + log "Modem PID : $idP" + log "Modem Model : $model" + log " " + fi + if [ $idP = "0620" -o $idP = "0800" -o $idP = "030b" -o $idP = "0900" -o $idP = "0801" ]; then + EM20=$(echo $model | grep "EM20") + if [ -z "$EM20" ]; then + EM160=1 + ATCMDD='AT+QNWPREFCFG="lte_band"' + fi + fi + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + if [ $enb == "1" ]; then + log " " + log "Quectel Response : $OX" + log " " + fi + L5="" + L6="" + EMT=0 + + if [ $EM160 = $EMT ]; then + qm=$(echo $OX" " | grep "+QCFG:" | tr -d '"' | tr " " ",") + if [ $enb == "1" ]; then + log "$qm" + log " " + fi + L1=$(echo $qm | cut -d, -f5) + GW=$(echo $qm | cut -d, -f4) + L2="0" + else + qm=$(echo $OX" " | grep "+QNWPREFCFG:" | tr -d '"' | tr " " ":" | tr "," ":") + if [ $enb == "1" ]; then + log "$qm" + log " " + fi + bd=5 + msk="" + L1=$(echo $qm | cut -d: -f"$bd") + while [ $L1 != "OK" ] + do + msk=$msk$L1" " + bd=$((bd+1)) + L1=$(echo $qm | cut -d: -f"$bd") + done + L1=$(encodemask $msk) + if [ -z "$L1" ]; then + L1="0" + fi + L2="0" + GW="0" + EMT=0800 + + if [ $idP = $EMT -o $idP = 0900 -o $idP = "0801" ]; then + ATCMDD='AT+QNWPREFCFG="nsa_nr5g_band"' + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + qm=$(echo $OX" " | grep "+QNWPREFCFG:" | tr -d '"' | tr " " ":" | tr "," ":") + if [ $enb == "1" ]; then + log "EM160/RM500 $qm" + fi + bd=5 + msk="" + L5=$(echo $qm | cut -d: -f"$bd") + + while [ $L5 != "OK" ] + do + msk=$msk$L5" " + bd=$((bd+1)) + L5=$(echo $qm | cut -d: -f"$bd") + done + if [ -z "$msk" -o $msk = "0" ]; then + L5="0" + else + L5=$(encodemask $msk) + fi + + ATCMDD='AT+QNWPREFCFG="nr5g_band"' + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + qm=$(echo $OX" " | grep "+QNWPREFCFG:" | tr -d '"' | tr " " ":" | tr "," ":") + if [ $enb == "1" ]; then + log "EM160/RM500 $qm" + fi + bd=5 + msk="" + L6=$(echo $qm | cut -d: -f"$bd") + + while [ $L6 != "OK" ] + do + msk=$msk$L6" " + bd=$((bd+1)) + L6=$(echo $qm | cut -d: -f"$bd") + done + if [ -z "$msk" -o $msk = "0" ]; then + L6="0" + else + L6=$(encodemask $msk) + fi + $ROOTER/luci/celltype.sh $CURRMODEM + netmode=$(uci -q get modem.modem$CURRMODEM.netmode) + NET="0" + if [ -e /etc/qfake ]; then + if [ $netmode = "7" ]; then + NET=8 + fi + else + if [ $netmode = "8" ]; then + NET=8 + fi + if [ $netmode = "9" ]; then + NET=9 + fi + fi + uci set modem.modem$CURRMODEM.NET="$NET" + if [ $NET = "8" -a $L1 = "0" ]; then + if [ $enb == "1" ]; then + log "NSA no LTE" + fi + fi + fi + fi + if [ $enb == "1" ]; then + log " " + log "LTE Band Mask : $L1" + log "5G NSA Band Mask : $L5" + log "5G NA Band Mask : $L6" + log " " + fi + uci set modem.modem$CURRMODEM.GW="$GW" + uci set modem.modem$CURRMODEM.L1="$L1" + uci set modem.modem$CURRMODEM.L2="$L2" + uci set modem.modem$CURRMODEM.L5="$L5" + uci set modem.modem$CURRMODEM.L6="$L6" + uci commit modem +} + +fibomask() { + enb=$(uci -q get custom.bandlock.enabled) + CPORT=$(uci get modem.modem$CURRMODEM.commport) + msk="" + NRsupport=false + ATCMDD='AT+GTACT=?' + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + OX=$(echo $OX | grep -o "+GTACT:[^)]\+") + if [ -n "$OX" ]; then + RATlist=$(echo $OX | grep -o "[0-9]\{2\}") + for RATval in $(echo "$RATlist"); do + if [ $RATval == "14" -o $RATval == "16" -o $RATval == "17" -o $RATval == "20" ]; then + NRsupport=true + fi + done + ATCMDD='AT+GTACT?' + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + OX=$(echo $OX" " | grep "+GTACT:" | tr -d '"' | tr " " ",") + else + ATCMDD='AT+XACT?' + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + OX=$(echo $OX" " | grep "+XACT:" | tr -d '"' | tr " " ",") + if [ -z "$OX" ]; then + ATCMDD="" + OX="No AT command found to read bands" + fi + fi + LTEbands=$(echo "$OX" | grep -o "1[0-9]\{2\}") + NRbands=$(echo "$OX" | grep -o "50[0-9]\{1,3\}") + for bandval in $(echo "$LTEbands"); do + msk=$msk$((bandval-100))" " + done + if [ -n "$msk" ]; then + L1=$(encodemask $msk) + else + L1="0" + fi + msk="" + for bandval in $(echo "$NRbands"); do + msk=$msk${bandval:2}" " + done + if [ $enb == "1" ]; then + log " " + log "Get Current Bands : $ATCMDD" + log "Current Bands : $OX" + log " " + fi + if [ -z "$msk" ]; then + if $NRsupport; then + L5="0x0" + else + L5="" + fi + else + L5="0x"$(encodemask $msk) + fi + if [ -n "$L1$L5" ]; then + if [ $enb == "1" ]; then + log " " + log "LTE Band Mask : $L1" + log "5G Band Mask : $L5" + log " " + fi + uci set modem.modem$CURRMODEM.L1="0x$L1" + uci set modem.modem$CURRMODEM.L5="$L5" + uci commit modem + fi +} + +t77mask() { + enb=$(uci -q get custom.bandlock.enabled) + ATCMDD='AT^SLBAND?' + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + if [ $enb == "1" ]; then + log " " + log "T77 Response : $OX" + log " " + fi + lte=$(echo $OX" " | tr "," ":" | tr " " ",") + if [ $enb == "1" ]; then + log " " + log "T77 Response : $lte" + log " " + fi + qm=$(echo $lte | cut -d, -f5) + log "$qm" + bd=3 + msk="" + L1=$(echo $qm | cut -d: -f"$bd") + while [ $L1 != "OK" ] + do + msk=$msk$L1" " + bd=$((bd+1)) + L1=$(echo $qm | cut -d: -f"$bd") + done + L1=$(encodemask $msk) + if [ -z "$L1" ]; then + L1="0" + fi + if [ $enb == "1" ]; then + log " " + log "LTE Band Mask : $L1" + log " " + fi + uci set modem.modem$CURRMODEM.L1="0x$L1" + uci commit modem +} + +reversebit() { + LX=$1 + length=${#LX} + jx="${LX:2:length-2}" + length=${#jx} + str="" + i=$((length-1)) + while [ $i -ge 0 ] + do + dgt="0x"${jx:$i:1} + DecNum=`printf "%d" $dgt` + Binary= + Number=$DecNum + while [ $DecNum -ne 0 ] + do + Bit=$(expr $DecNum % 2) + Binary=$Bit$Binary + DecNum=$(expr $DecNum / 2) + done + if [ -z $Binary ]; then + Binary="0000" + fi + len=${#Binary} + while [ $len -lt 4 ] + do + Binary="0"$Binary + len=${#Binary} + done + revstr="" + length=${#Binary} + ii=$((length-1)) + while [ $ii -ge 0 ] + do + revstr=$revstr${Binary:$ii:1} + ii=$((ii-1)) + done + str=$str$revstr + i=$((i-1)) + done + revstr=$str"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" +} + +reverse() { + REV="" + BNDD=$1 + strlen=${#BNDD} + i=$((strlen-1)) + while [ $i -ge 0 ] + do + REV=$REV${BNDD:$i:1} + i=$((i-1)) + done +} + +telitbandmask() { + enb=$(uci -q get custom.bandlock.enabled) + ATCMDD='AT#BND?' + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + if [ $enb == "1" ]; then + log " " + log "Telit Response : $OX" + log " " + fi + OX=$(echo $OX | tr " " '\x0a') + line=$OX + bnd=$(echo $line | grep "BND: ") + if [ ! -z "$bnd" ]; then + line=$(echo $bnd | tr " " ',') + if [ $enb == "1" ]; then + log "$line" + fi + BND=$(echo $line | cut -d, -f5) + ext=$(echo $line | cut -d, -f6) + reverse $BND + revs=$REV"0000000000000000" + revs=${revs:0:16} + reverse $revs + EXT="" + if [ "$ext" != "OK" -a "$ext" != "0" ]; then + EXT=$ext + fi + revs=$EXT$REV + if [ $enb == "1" ]; then + log " " + log "LTE Band Mask : $revs" + log " " + fi + ATCMDD='AT#BND=?' + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + OX=$(echo $OX | tr " " '\x0a') + OX=$(echo ${OX//),(/!}) + BND=$(echo $OX"!!" | cut -d! -f3) + extt=$(echo $OX"!!" | cut -d! -f4) + if [ ! -z "$extt" ]; then + extt=$(echo $extt | tr "(" ',') + extt=$(echo $extt | tr ")" ',') + extt=$(echo $extt",," | cut -d, -f1) + fi + BND=$(echo $BND | tr "(" ',') + BND=$(echo $BND | tr ")" ',') + BND=$(echo $BND",," | cut -d, -f1) + reverse $BND + revx=$REV"0000000000000000" + revx=${revx:0:16} + reverse $revx + revx=$extt$REV + revx=${revx:0:18} + reversebit "0x"$revx + revstr=${revstr:0:72} + if [ $enb == "1" ]; then + log " " + log "LTE Bit Mask : $revstr" + log " " + fi + + uci set modem.modem$CURRMODEM.GW="0" + uci set modem.modem$CURRMODEM.L1="0x$revs" + uci set modem.modem$CURRMODEM.L1X="$revstr" + uci set modem.modem$CURRMODEM.LEXT="$extt" + uci set modem.modem$CURRMODEM.L2="0" + uci commit modem + fi +} + +case $MODTYPE in + "0" ) + sierrabandmask + ;; + "1" ) + quebandmask + ;; + "2" ) + fibomask + ;; + "3" ) + t77mask + ;; + "4" ) + telitbandmask + ;; +esac + +$ROOTER/luci/mask.sh diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/conmon.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/conmon.sh new file mode 100644 index 0000000..fece3af --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/conmon.sh @@ -0,0 +1,188 @@ +#!/bin/sh +. /lib/functions.sh + +ROOTER=/usr/lib/rooter +ROOTER_LINK="/tmp/links" + +log() { + modlog "Connection Monitor $CURRMODEM" "$@" +} + +CURRMODEM=$1 + +power_toggle() { + if [ -f "/tmp/gpiopin" ]; then + source /tmp/gpiopin + echo "$GPIOPIN" > /sys/class/gpio/export + if [ $? -eq 0 ]; then + $ROOTER/pwrtoggle.sh 3 + else + $ROOTER/pwrtoggle.sh $CURRMODEM + fi + else + if [ $ACTIVE = 4 ]; then +# GPIO power-toggle not supported so re-bind USB driver, but only if power toggle is configured in connection monitoring + if [ $(uci -q get modem.pinginfo$CURRMODEM.alive) = 4 ]; then + $ROOTER/pwrtoggle.sh $CURRMODEM + fi +# if [ -L /sys/bus/usb/drivers/usb/usb1 ]; then +# if [ $(uci get modem.pinginfo1.alive) = 4 ]; then +# $ROOTER/pwrtoggle.sh 1 +# fi +# fi +# if [ -L /sys/bus/usb/drivers/usb/usb2 ]; then +# if [ $(uci get modem.pinginfo2.alive) = 4 ]; then +# $ROOTER/pwrtoggle.sh 2 +# fi +# fi + fi + fi +} + +do_down() { + echo 'MONSTAT="'"DOWN$1"'"' > /tmp/monstat$CURRMODEM + case $ACTIVE in + "1" ) + log "Modem $CURRMODEM Connection is Down$1" + ;; + "2" ) + log "Modem $CURRMODEM Connection is Down$1" + reboot -f + ;; + "3" ) + log "Modem $CURRMODEM Connection is Down$1" + PROT=$(uci get modem.modem$CURRMODEM.proto) + if [ $PROT -eq "30" ]; then + CPORT=$(uci get modem.modem$CURRMODEM.commport) + ATCMDD="AT+CFUN=4;+CFUN=1,1" + $ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD" + echo "1" > /tmp/modgone + log "Setting Modem Removal flag" + sleep 60 + else + if [ -f $ROOTER_LINK/reconnect$CURRMODEM ]; then + $ROOTER_LINK/reconnect$CURRMODEM $CURRMODEM & + fi + fi + ;; + "4" ) + log "Modem $CURRMODEM Connection is Down$1" + power_toggle + ;; + esac +} + +CURSOR="-" + +log "Start Connection Monitor for Modem $CURRMODEM" + +sleep 30 + +while [ 1 = 1 ]; do + CP=$(uci -q get ping.ping.enable) + if [ $CP = "1" ]; then + echo 'MONSTAT="'"Custom Ping Test"'"' > /tmp/monstat$CURRMODEM + sleep 60 + else + ACTIVE=$(uci get modem.pinginfo$CURRMODEM.alive) + if [ $ACTIVE = "0" ]; then + echo 'MONSTAT="'"Disabled"'"' > /tmp/monstat$CURRMODEM + sleep 60 + else + track_ips= + IFNAME=$(uci get modem.modem$CURRMODEM.interface) + TIMEOUT=$(uci get modem.pinginfo$CURRMODEM.pingwait) + INTERVAL=$(uci get modem.pinginfo$CURRMODEM.pingtime) + RELIAB=$(uci get modem.pinginfo$CURRMODEM.reliability) + DOWN=$(uci get modem.pinginfo$CURRMODEM.down) + UP=$(uci get modem.pinginfo$CURRMODEM.up) + COUNT=$(uci get modem.pinginfo$CURRMODEM.count) + PACKETSIZE=$(uci get modem.pinginfo$CURRMODEM.packetsize) + INTERF=$(uci get modem.modeminfo$CURRMODEM.inter) + + list_track_ips() { + track_ips="$1 $track_ips" + } + + config_load modem + config_list_foreach "pinginfo$CURRMODEM" "trackip" list_track_ips + + if [ -f "/tmp/connstat$CURRMODEM" ]; then + do_down " from Modem" + rm -f /tmp/connstat$CURRMODEM + sleep 20 + else + ENB="0" + if [ -e /etc/config/failover ]; then + ENB=$(uci get failover.enabled.enabled) + fi + if [ $ENB = "1" ]; then + if [ -e /tmp/mdown$CURRMODEM ]; then + do_down " (using Failover)" + else + echo 'MONSTAT="'"Up ($CURSOR) (using Failover)"'"' > /tmp/monstat$CURRMODEM + fi + sleep 20 + else + # check to see if modem iface has an IP address, if not try a reconnect/power toggle + OX=$(ip address show $IFNAME 2>&1) + ip4=$(echo "$OX" | grep 'inet ' | cut -d' ' -f6) + ip6=$(echo "$OX" | grep 'inet6' | grep global | cut -d' ' -f6) + if [ -z "$ip4" -a -z "$ip6" ]; then + do_down " (no IP address)" + fi + + UPDWN="0" + host_up_count=0 + score_up=$UP + score_dwn=$DOWN + lost=0 + while true; do + if [ ! -z "$track_ips" ]; then + for track_ip in $track_ips; do + ping -I $IFNAME -c $COUNT -W $TIMEOUT -s $PACKETSIZE -q $track_ip &> /dev/null + if [ $? -eq 0 ]; then + let host_up_count++ + else + let lost++ + fi + done + if [ $host_up_count -lt $RELIAB ]; then + let score_dwn-- + score_up=$UP + if [ $score_dwn -eq 0 ]; then + UPDWN="1" + break + fi + else + let score_up-- + score_dwn=$DOWN + if [ $score_up -eq 0 ]; then + UPDWN="0" + break + fi + fi + else + UPDWN="0" + exit + fi + host_up_count=0 + sleep $INTERVAL + done + if [ $UPDWN = "1" ]; then + do_down " (using Ping Test)" + else + echo 'MONSTAT="'"UP ($CURSOR) (using Ping Test)"'"' > /tmp/monstat$CURRMODEM + fi + sleep $INTERVAL + + fi + fi + if [ $CURSOR = "-" ]; then + CURSOR="+" + else + CURSOR="-" + fi + fi + fi +done diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/create_connect.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/create_connect.sh new file mode 100644 index 0000000..7561519 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/create_connect.sh @@ -0,0 +1,1360 @@ +#!/bin/sh + +ROOTER=/usr/lib/rooter +ROOTER_LINK="/tmp/links" + +log() { + modlog "Create Connection $CURRMODEM" "$@" +} + +ifname1="ifname" +if [ -e /etc/newstyle ]; then + ifname1="device" +fi + +handle_timeout(){ + local wget_pid="$1" + local count=0 + TIMEOUT=70 + res=1 + if [ -d /proc/${wget_pid} ]; then + res=0 + fi + while [ "$res" = 0 -a $count -lt "$((TIMEOUT))" ]; do + sleep 1 + count=$((count+1)) + res=1 + if [ -d /proc/${wget_pid} ]; then + res=0 + fi + done + + if [ "$res" = 0 ]; then + log "Killing process on timeout" + kill "$wget_pid" 2> /dev/null + res=1 + if [ -d /proc/${wget_pid} ]; then + res=0 + fi + if [ "$res" = 0 ]; then + log "Killing process on timeout" + kill -9 $wget_pid 2> /dev/null + fi + fi +} + +set_dns() { + local pDNS1=$(uci -q get modem.modeminfo$CURRMODEM.dns1) + local pDNS2=$(uci -q get modem.modeminfo$CURRMODEM.dns2) + local pDNS3=$(uci -q get modem.modeminfo$CURRMODEM.dns3) + local pDNS4=$(uci -q get modem.modeminfo$CURRMODEM.dns4) + + local aDNS="$pDNS1 $pDNS2 $pDNS3 $pDNS4" + local bDNS="" + + echo "$aDNS" | grep -o "[[:graph:]]" &>/dev/null + if [ $? = 0 ]; then + log "Using DNS settings from the Connection Profile" + pdns=1 + for DNSV in $(echo "$aDNS"); do + if [ "$DNSV" != "0.0.0.0" ] && [ -z "$(echo "$bDNS" | grep -o "$DNSV")" ]; then + [ -n "$(echo "$DNSV" | grep -o ":")" ] && continue + bDNS="$bDNS $DNSV" + fi + done + + bDNS=$(echo $bDNS) + if [ $DHCP = 1 ]; then + uci set network.wan$INTER.peerdns=0 + uci set network.wan$INTER.dns="$bDNS" + fi + echo "$bDNS" > /tmp/v4dns$INTER + + bDNS="" + for DNSV in $(echo "$aDNS"); do + if [ "$DNSV" != "0:0:0:0:0:0:0:0" ] && [ -z "$(echo "$bDNS" | grep -o "$DNSV")" ]; then + [ -z "$(echo "$DNSV" | grep -o ":")" ] && continue + bDNS="$bDNS $DNSV" + fi + done + echo "$bDNS" > /tmp/v6dns$INTER + else + log "Using Provider assigned DNS" + pdns=0 + rm -f /tmp/v[46]dns$INTER + fi +} + +set_dns2() { + local pDNS1=$(uci -q get modem.modeminfo$CURRMODEM.dns1) + local pDNS2=$(uci -q get modem.modeminfo$CURRMODEM.dns2) + local pDNS3=$(uci -q get modem.modeminfo$CURRMODEM.dns3) + local pDNS4=$(uci -q get modem.modeminfo$CURRMODEM.dns4) + + local _DNS1 _DNS2 _DNS3 _DNS4 aDNS bDNS + + echo "$pDNS1 $pDNS2 $pDNS3 $pDNS4" | grep -o "[[:graph:]]" &>/dev/null + if [ $? = 0 ]; then + log "Using DNS settings from the Connection Profile" + pdns=1 + _DNS1=$pDNS1 + _DNS2=$pDNS2 + _DNS3=$pDNS3 + _DNS4=$pDNS4 + else + log "Using Provider assigned DNS" + pdns=0 + _DNS1=$DNS1 + _DNS2=$DNS2 + _DNS3=$DNS3 + _DNS4=$DNS4 + fi + + aDNS="$_DNS1 $_DNS2 $_DNS3 $_DNS4" + + bDNS="" + for DNSV in $(echo "$aDNS"); do + if [ "$DNSV" != "0.0.0.0" ] && [ "$DNSV" != "0:0:0:0:0:0:0:0" ] && [ -z "$(echo "$bDNS" | grep -o "$DNSV")" ]; then + [ -n "$(echo "$DNSV" | grep -o ":")" ] && [ -z "$ip6" ] && continue + bDNS="$bDNS $DNSV" + fi + done + + bDNS=$(echo $bDNS) + uci set network.wan$INTER.dns="$bDNS" +} + +check_apn() { + IPVAR="IP" + local COMMPORT="/dev/ttyUSB"$CPORT + if [ -e /etc/nocops ]; then + echo "0" > /tmp/block + fi + ATCMDD="AT+CGDCONT=?" + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + + [ "$PDPT" = "0" ] && PDPT="" + for PDP in "$PDPT" IPV4V6; do + if [[ "$(echo $OX | grep -o "$PDP")" ]]; then + IPVAR="$PDP" + break + fi + done + + uci set modem.modem$CURRMODEM.pdptype=$IPVAR + uci commit modem + + log "PDP Type selected in the Connection Profile: \"$PDPT\", active: \"$IPVAR\"" + + if [ "$idV" = "12d1" ]; then + CFUNOFF="0" + else + CFUNOFF="4" + fi + + ATCMDD="AT+CGDCONT?;+CFUN?" + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + CGDCONT2=$(echo $OX | grep "+CGDCONT: 2,") + if [ -z "$CGDCONT2" ]; then + ATCMDD="AT+CGDCONT=2,\"$IPVAR\",\"ims\"" + OXy=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + fi + if `echo $OX | grep "+CGDCONT: $CID,\"$IPVAR\",\"$NAPN\"," 1>/dev/null 2>&1` + then + if [ -z "$(echo $OX | grep -o "+CFUN: 1")" ]; then + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "AT+CFUN=1") + fi + else + ATCMDD="AT+CGDCONT=$CID,\"$IPVAR\",\"$NAPN\"" + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "AT+CFUN=$CFUNOFF") + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "AT+CFUN=1") + sleep 5 + fi + if [ -e /etc/nocops ]; then + rm -f /tmp/block + fi +} + +save_variables() { + echo 'MODSTART="'"$MODSTART"'"' > /tmp/variable.file + echo 'WWAN="'"$WWAN"'"' >> /tmp/variable.file + echo 'USBN="'"$USBN"'"' >> /tmp/variable.file + echo 'ETHN="'"$ETHN"'"' >> /tmp/variable.file + echo 'WDMN="'"$WDMN"'"' >> /tmp/variable.file + echo 'BASEPORT="'"$BASEPORT"'"' >> /tmp/variable.file +} + +chcklog() { + OOX=$1 + CLOG=$(uci -q get modem.modeminfo$CURRMODEM.log) + if [ $CLOG = "1" ]; then + log "$OOX" + fi +} + +get_connect() { + NAPN=$(uci -q get modem.modeminfo$CURRMODEM.apn) + NUSER=$(uci -q get modem.modeminfo$CURRMODEM.user) + NPASS=$(uci -q get modem.modeminfo$CURRMODEM.passw) + NAUTH=$(uci -q get modem.modeminfo$CURRMODEM.auth) + spin=$(uci -q get custom.simpin.pin) # SIM Pin + if [ -z "$spin" ]; then + spin=$(uci -q get modem.modeminfo$CURRMODEM.pincode) # Profile Pin + if [ -z "$spin" ]; then + spin=$(uci -q get profile.simpin.pin) # Default profile Pin + fi + fi + PINC=$spin + uci set modem.modeminfo$CURRMODEM.pincode=$PINC + uci commit modem + PDPT=$(uci -q get modem.modeminfo$CURRMODEM.pdptype) +# +# QMI and MBIM can't handle nil +# + case $PROT in + "2"|"3"|"30"|"88" ) + if [ -z "$NUSER" ]; then + NUSER="NIL" + fi + if [ -z "$NPASS" ]; then + NPASS="NIL" + fi + ;; + esac + + uci set modem.modem$CURRMODEM.apn=$NAPN + uci set modem.modem$CURRMODEM.user=$NUSER + uci set modem.modem$CURRMODEM.passw=$NPASS + uci set modem.modem$CURRMODEM.auth=$NAUTH + uci set modem.modem$CURRMODEM.pin=$PINC + uci commit modem +} + +chksierra() { + SIERRAID=0 + if [ $idV = 1199 ]; then + case $idP in + "68aa"|"68a2"|"68a3"|"68a9"|"68b0"|"68b1" ) + SIERRAID=1 + ;; + "68c0"|"9040"|"9041"|"9051"|"9054"|"9056"|"90d3" ) + SIERRAID=1 + ;; + "9070"|"907b"|"9071"|"9079"|"901c"|"9091"|"901f"|"90b1" ) + SIERRAID=1 + ;; + esac + elif [ $idV = 114f -a $idP = 68a2 ]; then + SIERRAID=1 + elif [ $idV = 413c -a $idP = 81a8 ]; then + SIERRAID=1 + elif [ $idV = 413c -a $idP = 81b6 ]; then + SIERRAID=1 + fi +} + +chktelitmbim() { + TELITMBIM=0 + if [ $idV = 1bc7 -a $idP = 0032 ]; then + TELITMBIM=1 + fi +} + +chkT77() { + T77=0 + if [ $idV = 413c -a $idP = 81d7 ]; then + T77=1 + elif [ $idV = 413c -a $idP = 81d8 ]; then + T77=1 + elif [ $idV = 0489 -a $idP = e0b4 ]; then + T77=1 + elif [ $idV = 0489 -a $idP = e0b5 ]; then + T77=1 + elif [ $idV = 1bc7 -a $idP = 1910 ]; then + T77=1 + fi + if [ $T77 = 1 ]; then + [ -n "$TTYDEVS" ] || T77=0 + fi +} + +chkraw() { + RAW=0 + if [ $idV = 03f0 -a $idP = 0857 ]; then + RAW=1 + elif [ $idV = 1bc7 -a $idP = 1900 ]; then + RAW=1 + elif [ $idV = 1bc7 -a $idP = 1910 ]; then + RAW=1 + elif [ $idV = 19d2 -a $idP = 1432 ]; then + RAW=1 + elif [ $idV = 1e0e -a $idP = 9001 ]; then + RAW=1 + elif [ $idV = 2c7c ]; then + RAW=1 + elif [ $idV = 05c6 -a $idP = 9025 ]; then + [ $MAN = "Telit" ] || RAW=1 + elif [ $idV = 05c6 -a $idP = 90db ]; then + RAW=1 + elif [ $idV = 05c6 -a $idP = f601 ]; then + RAW=1 + elif [ $idV = 2cb7 -a $idP = 0104 ]; then + RAW=1 + elif [ $idV = 413c -a $idP = 81d7 ]; then + RAW=1 + fi +} + +chkreg() { + local OX REGV REGST REGCMD + local COMMPORT="/dev/ttyUSB"$CPORT + ATCMDD="AT+CEREG?;+CREG?" + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + for REGCMD in +CEREG +CREG; do + REGV=$(echo "$OX" | grep -o "$REGCMD: [0-3],[0-9]") + if [ -n "$REGV" ]; then + REGST=$(echo "$REGV" | cut -d, -f2) + case $REGST in + "0" ) + continue + ;; + "1"|"5"|"6"|"7" ) + REGOK=1 + break + ;; + * ) + REGOK=0 + ;; + esac + fi + done +} + +addv6() { + . /lib/functions.sh + . /lib/netifd/netifd-proto.sh + local interface=wan$INTER + local zone="$(fw3 -q network "$interface" 2>/dev/null)" + + log "Adding IPv6 dynamic interface" + json_init + json_add_string name "${interface}_6" + json_add_string ${ifname1} "@$interface" + json_add_string proto "dhcpv6" + json_add_string extendprefix 1 + [ -n "$zone" ] && json_add_string zone "$zone" + [ "$pdns" = 1 ] && json_add_boolean peerdns 0 + [ "$nat46" = 1 ] || json_add_string iface_464xlat 0 + proto_add_dynamic_defaults + json_close_object + ubus call network add_dynamic "$(json_dump)" +} + +get_tty() { +# $1 is bInterfaceNumber value + local IFNUM OX + IFNUM=$1 + for TTYD in $(echo "$TTYDEVS"); do + if [ ! "$ACM" = 1 ]; then + OX=$(cat /sys/class/tty/$TTYD/../../../bInterfaceNumber | grep "$IFNUM") + else + OX=$(cat /sys/class/tty/$TTYD/../../bInterfaceNumber | grep "$IFNUM") + fi + if [ $? = 0 ]; then + CPORT=$(echo $TTYD | grep -o "[[:digit:]]\+") + break + else + CPORT="" + fi + done +} + +get_tty_fix() { +# $1 is fixed ttyUSB or ttyACM port number + local POS + POS=`expr 1 + $1` + CPORT=$(echo "$TTYDEVS" | cut -d' ' -f"$POS" | grep -o "[[:digit:]]\+") +} + +get_tty_ncm() { + local IFPROT OX + PROTS="12 62 02 2" # PC UI interface bInterfaceProtocol value + for IFPROT in $PROTS; do + for TTYD in $(echo "$TTYDEVS"); do + OX=$(cat /sys/class/tty/$TTYD/../../../bInterfaceProtocol | grep -w "$IFPROT") + if [ $? = 0 ]; then + CPORT=$(echo $TTYD | grep -o "[[:digit:]]\+") + break 2 + else + CPORT="" + fi + done + done +} + +mbimcport() { + lua $ROOTER/common/modemchk.lua "$idV" "$idP" "$CPORT" "$CPORT" + source /tmp/parmpass + uci set modem.modem$CURRMODEM.commport=$CPORT + uci set modem.modem$CURRMODEM.proto="30" + log "MBIM Comm Port : /dev/ttyUSB$CPORT" +} + +CURRMODEM=$1 +RECON=$2 +SIERRAID=0 + +MAN=$(uci -q get modem.modem$CURRMODEM.manuf) +MOD=$(uci -q get modem.modem$CURRMODEM.model) +PROT=$(uci -q get modem.modem$CURRMODEM.proto) +idV=$(uci -q get modem.modem$CURRMODEM.idV) +idP=$(uci -q get modem.modem$CURRMODEM.idP) + +if [ ! -z "$RECON" ]; then + $ROOTER/signal/status.sh $CURRMODEM "$MAN $MOD" "ReConnecting" + uci set modem.modem$CURRMODEM.active=1 + uci set modem.modem$CURRMODEM.connected=0 + uci commit modem + INTER=$(uci -q get modem.modeminfo$CURRMODEM.inter) + jkillall getsignal$CURRMODEM + rm -f $ROOTER_LINK/getsignal$CURRMODEM + jkillall con_monitor$CURRMODEM + rm -f $ROOTER_LINK/con_monitor$CURRMODEM + jkillall mbim_monitor$CURRMODEM + rm -f $ROOTER_LINK/mbim_monitor$CURRMODEM + ifdown wan$INTER + CPORT=$(uci -q get modem.modem$CURRMODEM.commport) + WWANX=$(uci -q get modem.modem$CURRMODEM.wwan) + WDMNX=$(uci -q get modem.modem$CURRMODEM.wdm) + if [ "$RECON" = "1" ]; then + $ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "reset.gcom" "$CURRMODEM" + fi +else + + DELAY=$(uci -q get modem.modem$CURRMODEM.delay) + if [ -z "$DELAY" ]; then + DELAY=5 + fi + +rm -f /tmp/usbwait + +MATCH="$(uci get modem.modem$CURRMODEM.maxcontrol | cut -d/ -f3- | xargs dirname)" + +case $PROT in + # Sierra Direct-IP data interface + + "1" ) + OX="$(for a in /sys/class/net/*; do readlink $a; done | grep "$MATCH")" + ifname=$(basename $OX) + WWANX=$(echo $ifname | grep -o "[[:digit:]]") + log "Modem $CURRMODEM Sierra Direct-IP Device : $ifname" + + uci set modem.modem$CURRMODEM.wwan=$WWANX + uci set modem.modem$CURRMODEM.interface=$ifname + uci commit modem + ;; + + # QMI, NCM and MBIM use cdc-wdm + + "2"|"3"|"30"|"4"|"6"|"7" ) + OX="$(for a in /sys/class/usbmisc/*; do readlink $a; done | grep "$MATCH")" + devname=$(basename $OX) + log "Modem $CURRMODEM WDM Device : $devname" + WDMNX=$(echo $devname | grep -o "[[:digit:]]") + ifname="$(ls /sys/class/usbmisc/$devname/device/net/)" + WWANX=$(echo $ifname | grep -o "[[:digit:]]") + + uci set modem.modem$CURRMODEM.wdm=$WDMNX + uci set modem.modem$CURRMODEM.wwan=$WWANX + uci set modem.modem$CURRMODEM.interface=$ifname + uci commit modem + ;; +esac + +OX=$(for a in /sys/class/tty/*; do readlink $a; done | grep "$MATCH" | tr '\n' ' ' | xargs -r -n1 basename) +TTYDEVS=$(echo "$OX" | grep -o ttyUSB[0-9]) +if [ $? -ne 0 ]; then + TTYDEVS=$(echo "$OX" | grep -o ttyACM[0-9]) + [ $? -eq 0 ] && ACM=1 +fi +TTYDEVS=$(echo "$TTYDEVS" | tr '\n' ' ') +TTYDEVS=$(echo $TTYDEVS) +if [ -n "$TTYDEVS" ]; then + log Modem $CURRMODEM is a parent of $TTYDEVS +else + log "No Comm Ports" +fi + +get_tty_fix 0 +if [ -n "$CPORT" ]; then + uci set modem.modem$CURRMODEM.baseport=$CPORT +else + uci set modem.modem$CURRMODEM.baseport="" +fi +uci commit modem.modem$CURRMODEM + + case $PROT in +# +# Sierra Direct-IP modem comm port +# + "1" ) + log "Start Direct-IP Connection" + get_tty 03 + lua $ROOTER/common/modemchk.lua "$idV" "$idP" "$CPORT" "$CPORT" + source /tmp/parmpass + log "Sierra Comm Port : /dev/ttyUSB$CPORT" + ;; +# +# QMI modem comm port +# + "2"|"88" ) + log "Start QMI (RMNET) Connection" + sleep $DELAY + + chksierra + if [ $SIERRAID -eq 1 ]; then + get_tty 03 + elif [ $idV = 1bc7 ]; then + get_tty 03 + else + if [ $idV = 2c7c ]; then + QUEIF2="0121 0125 0306 0296 0512 0620 0800 030b 0801 0900" + if [[ $(echo "$QUEIF2" | grep -o -i "$idP") ]]; then + TPORT=2 + fi + elif [ $idV = 05c6 -a $idP = 9025 ]; then + [ $MAN = "Telit" ] || TPORT=2 + elif [ $idV = 1e0e -a $idP = 9001 ]; then + TPORT=2 + else + TPORT=1 + fi + get_tty_fix $TPORT + fi + + lua $ROOTER/common/modemchk.lua "$idV" "$idP" "$CPORT" "$CPORT" + source /tmp/parmpass + + log "Modem $CURRMODEM QMI (RMNET) Comm Port : /dev/ttyUSB$CPORT" + chkraw + ;; + "3"|"30" ) + log "Start MBIM Connection" + sleep $DELAY + + chksierra + if [ $SIERRAID -eq 1 ]; then + SIERRAIF2='1199:90b1' + if [[ $(echo $SIERRAIF2 | grep -o -i "$idV:$idP") ]]; then + IFNUM=02 + else + IFNUM=03 + fi + get_tty $IFNUM + if [ -z "$CPORT" ]; then + if [ $idP = "90d3" ]; then + get_tty_fix 0 + lua $ROOTER/common/modemchk.lua "$idV" "$idP" "$CPORT" "$CPORT" + source /tmp/parmpass + uci set modem.modem$CURRMODEM.commport=$CPORT + if [ -n "$CPORT" ]; then + uci set modem.modem$CURRMODEM.proto="30" + fi + log "Modem $CURRMODEM MBIM Comm Port : /dev/ttyUSB$CPORT" + else + uci set modem.modem$CURRMODEM.commport="" + uci set modem.modem$CURRMODEM.proto="3" + log "No MBIM Comm Port" + fi + else + mbimcport + fi + else + chktelitmbim + if [ $TELITMBIM -eq 1 ]; then + get_tty 00 + lua $ROOTER/common/modemchk.lua "$idV" "$idP" "$CPORT" "$CPORT" + source /tmp/parmpass + ACMPORT=$CPORT + CPORT=9$ACMPORT + ln -fs /dev/ttyACM$ACMPORT /dev/ttyUSB$CPORT + uci set modem.modem$CURRMODEM.commport=$CPORT + if [ -n "$CPORT" ]; then + uci set modem.modem$CURRMODEM.proto="30" + fi + log "Modem $CURRMODEM MBIM Comm Port : /dev/ttyUSB$CPORT" + else + chkT77 + if [ $T77 -eq 1 ]; then + get_tty 02 + mbimcport + else + case $idV in + "2c7c"|"05c6" ) + get_tty_fix 2 + mbimcport + ;; + "03f0" ) + get_tty 02 + mbimcport + ;; + "1bc7" ) + if [ "$idP" = "1041" ]; then + get_tty 07 + else + get_tty 02 + fi + mbimcport + ;; + "2cb7" ) + get_tty_fix 0 + lua $ROOTER/common/modemchk.lua "$idV" "$idP" "$CPORT" "$CPORT" + source /tmp/parmpass + ACMPORT=$CPORT + CPORT="8$ACMPORT" + ln -fs /dev/ttyACM$ACMPORT /dev/ttyUSB$CPORT + + uci set modem.modem$CURRMODEM.commport=$CPORT + uci set modem.modem$CURRMODEM.proto="30" + log "Modem $CURRMODEM MBIM Comm Port : /dev/ttyUSB$CPORT" + ;; + * ) + uci set modem.modem$CURRMODEM.commport="" + log "No MBIM Comm Port" + ;; + esac + fi + fi + fi + uci commit modem + ;; +# +# Huawei NCM +# + "4"|"6"|"7"|"24"|"26"|"27" ) + if [ "$idV" = "2c7c" -a "$idP" = "0900" ]; then + ATCMDD='AT+QCFG="usbnet",2' + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB2" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + ATCMDD='AT+CFUN=1,1' + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB2" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + reboot -f + fi + log "Start NCM Connection" + sleep $DELAY + + get_tty_ncm + lua $ROOTER/common/modemchk.lua "$idV" "$idP" "$CPORT" "$CPORT" + source /tmp/parmpass + + log "NCM Comm Port : /dev/ttyUSB$CPORT" + ;; + "28" ) + log "Start Fibocom NCM Connection" + get_tty_fix 2 + lua $ROOTER/common/modemchk.lua "$idV" "$idP" "$CPORT" "$CPORT" + source /tmp/parmpass + ACMPORT=$CPORT + CPORT="8$ACMPORT" + ln -fs /dev/ttyACM$ACMPORT /dev/ttyUSB$CPORT + log "Modem $CURRMODEM Fibocom NCM Comm Port : /dev/ttyUSB$CPORT" + ;; + esac + + uci set modem.modem$CURRMODEM.commport=$CPORT + uci commit modem + +fi +if [ $PROT = "3" ]; then +# May have got changed to 30 above + PROT=$(uci -q get modem.modem$CURRMODEM.proto) +fi +if [ -z "$idV" ]; then + idV=$(uci -q get modem.modem$CURRMODEM.idV) +fi +QUECTEL=false +if [ "$idV" = "2c7c" ]; then + QUECTEL=true +elif [ "$idV" = "05c6" ]; then + QUELST="9090,9003,9215" + if [[ $(echo "$QUELST" | grep -o "$idP") ]]; then + QUECTEL=true + fi +fi + +if [ -e $ROOTER/connect/preconnect.sh ]; then + if [ "$RECON" != "2"|"88" ]; then + $ROOTER/connect/preconnect.sh $CURRMODEM + fi +fi + +if $QUECTEL; then + if [ "$RECON" != "2"|"88" ]; then + ATCMDD="AT+CNMI?" + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + if `echo $OX | grep -o "+CNMI: [0-3],2," >/dev/null 2>&1`; then + ATCMDD="AT+CNMI=0,0,0,0,0" + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + fi + ATCMDD="AT+QINDCFG=\"smsincoming\"" + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + if `echo $OX | grep -o ",1" >/dev/null 2>&1`; then + ATCMDD="AT+QINDCFG=\"smsincoming\",0,1" + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + fi + ATCMDD="AT+QINDCFG=\"all\"" + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + if `echo $OX | grep -o ",1" >/dev/null 2>&1`; then + ATCMDD="AT+QINDCFG=\"all\",0,1" + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + fi + log "Quectel Unsolicited Responses Disabled" + fi + $ROOTER/connect/bandmask $CURRMODEM 1 + clck=$(uci -q get custom.bandlock.cenable$CURRMODEM) + if [ $clck = "1" ]; then + ear=$(uci -q get custom.bandlock.earfcn$CURRMODEM) + pc=$(uci -q get custom.bandlock.pci$CURRMODEM) + ear1=$(uci -q get custom.bandlock.earfcn1$CURRMODEM) + pc1=$(uci -q get custom.bandlock.pci1$CURRMODEM) + ear2=$(uci -q get custom.bandlock.earfcn2$CURRMODEM) + pc2=$(uci -q get custom.bandlock.pci2$CURRMODEM) + ear3=$(uci -q get custom.bandlock.earfcn3$CURRMODEM) + pc3=$(uci -q get custom.bandlock.pci3$CURRMODEM) + cnt=1 + earcnt=$ear","$pc + if [ $ear1 != "0" -a $pc1 != "0" ]; then + earcnt=$earcnt","$ear1","$pc1 + let cnt=cnt+1 + fi + if [ $ear2 != "0" -a $pc2 != "0" ]; then + earcnt=$earcnt","$ear2","$pc2 + let cnt=cnt+1 + fi + if [ $ear3 != "0" -a $pc3 != "0" ]; then + earcnt=$earcnt","$ear3","$pc3 + let cnt=cnt+1 + fi + earcnt=$cnt","$earcnt + ATCMDD="at+qnwlock=\"common/4g\"" + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + log "$OX" + if `echo $OX | grep "ERROR" 1>/dev/null 2>&1` + then + ATCMDD="at+qnwlock=\"common/lte\",2,$ear,$pc" + else + ATCMDD=$ATCMDD","$earcnt + fi + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + log "Cell Lock $OX" + sleep 10 + fi +fi +$ROOTER/luci/celltype.sh $CURRMODEM +if [ $SIERRAID -eq 1 ]; then + $ROOTER/connect/bandmask $CURRMODEM 0 + $ROOTER/luci/celltype.sh $CURRMODEM +fi +if [ $idV = "2dee" ]; then + ATC="AT^MODE=0" + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATC") +fi +if [ $idV = "2cb7" -o $idV = "8087" ]; then + $ROOTER/connect/bandmask $CURRMODEM 2 +fi + +chkT77 +if [ $T77 -eq 1 ]; then + $ROOTER/connect/bandmask $CURRMODEM 3 +fi + +if [ $idV = "1bc7" ]; then + if [ $idP = "1040" -o $idP = "1041" ]; then + $ROOTER/connect/bandmask $CURRMODEM 4 + fi +fi + +CHKPORT=$(uci -q get modem.modem$CURRMODEM.commport) +if [ -n "$CHKPORT" ]; then + $ROOTER/common/gettype.sh $CURRMODEM + $ROOTER/connect/get_profile.sh $CURRMODEM + if [ -e $ROOTER/simlock.sh ]; then + $ROOTER/simlock.sh $CURRMODEM + fi + + if [ -e /tmp/simpin$CURRMODEM ]; then + log " SIM Error" + exit 0 + fi + if [ -e /usr/lib/gps/gps.sh ]; then + /usr/lib/gps/gps.sh $CURRMODEM & + fi + INTER=$(uci -q get modem.modeminfo$CURRMODEM.inter) + [ $INTER = 3 ] && log "Modem $CURRMODEM disabled in Connection Profile" && exit 1 + $ROOTER/sms/check_sms.sh $CURRMODEM & + get_connect + if [ -z "$INTER" ]; then + INTER=$CURRMODEM + else + if [ $INTER = 0 ]; then + INTER=$CURRMODEM + fi + fi + log "Profile for Modem $CURRMODEM sets interface to WAN$INTER" + OTHER=1 + if [ $CURRMODEM = 1 ]; then + OTHER=2 + fi + EMPTY=$(uci -q get modem.modem$OTHER.empty) + if [ $EMPTY = 0 ]; then + OINTER=$(uci -q get modem.modem$OTHER.inter) + if [ ! -z "$OINTER" ]; then + if [ $INTER = $OINTER ]; then + INTER=1 + if [ $OINTER = 1 ]; then + INTER=2 + fi + log "Switched Modem $CURRMODEM to WAN$INTER as Modem $OTHER is using WAN$OINTER" + fi + fi + fi + uci set modem.modem$CURRMODEM.inter=$INTER + uci commit modem + log "Modem $CURRMODEM is using WAN$INTER" + + CID=$(uci -q get modem.modeminfo$CURRMODEM.context) + [ -z "$CID" ] && CID=1 + + DHCP=1 + if [ $PROT = 28 ]; then + DHCP=0 + elif [ $PROT = 2 -a $idV = 05c6 -a $idP = 9025 ]; then + [ $MAN = "Telit" ] || DHCP=0 + fi + NODHCP=$(uci -q get modem.modeminfo$CURRMODEM.nodhcp) + if [ $idV = "2c7c" -a $idP = "0801" ]; then + NODHCP="1" + fi + if [ "$NODHCP" = "1" ]; then + DHCP=0 + log "Using QMI without DHCP" + fi + + if [ $DHCP = 1 ]; then + uci delete network.wan$INTER + uci set network.wan$INTER=interface + uci set network.wan$INTER.proto=dhcp + uci set network.wan$INTER.${ifname1}=$ifname + uci set network.wan$INTER._orig_bridge=false + uci set network.wan$INTER.metric=$INTER"0" + set_dns + uci commit network + else + set_dns + fi + + ttl=$(uci -q get modem.modeminfo$CURRMODEM.ttl) + if [ -z "$ttl" ]; then + ttl="0" + fi + $ROOTER/connect/handlettl.sh $CURRMODEM "$ttl" & + + if [ -e $ROOTER/changedevice.sh ]; then + $ROOTER/changedevice.sh $ifname + fi + + autoapn=$(uci -q get profile.disable.autoapn) + imsi=$(uci -q get modem.modem$CURRMODEM.imsi) + mcc6=${imsi:0:6} + mcc5=${imsi:0:5} + apd=0 + if [ -e /usr/lib/autoapn/apn.data ]; then + apd=1 + fi + if [ "$autoapn" = "1" -a $apd -eq 1 ]; then + isplist=$(grep -F "$mcc6" '/usr/lib/autoapn/apn.data') + if [ -z "$isplist" ]; then + isplist=$(grep -F "$mcc5" '/usr/lib/autoapn/apn.data') + if [ -z "$isplist" ]; then + isplist="000000,$NAPN,Default,$NPASS,$CID,$NUSER,$NAUTH" + fi + fi + else + isplist="000000,$NAPN,Default,$NPASS,$CID,$NUSER,$NAUTH" + fi + + uci set modem.modeminfo$CURRMODEM.isplist="$isplist" + uci commit modem + + if [ $idV = 12d1 ]; then + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "curc.gcom" "$CURRMODEM") + log "Huawei Unsolicited Responses Disabled" + ATCMDD="AT^USSDMODE=0" + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + fi + FORCE=$(uci -q get modem.modeminfo$CURRMODEM.ppp) + if [ -n "$FORCE" ]; then + if [ $FORCE = 1 ]; then + log "Forcing PPP mode" + case $idV in + "12d1" ) + retval=10 + ;; + * ) + retval=11 + ;; + esac + uci set modem.modem$CURRMODEM.proto=$retval + rm -f $ROOTER_LINK/create_proto$CURRMODEM + log "Forced Protcol Value : $retval" + log "Connecting a PPP Modem" + ln -fs $ROOTER/ppp/create_ppp.sh $ROOTER_LINK/create_proto$CURRMODEM + $ROOTER_LINK/create_proto$CURRMODEM $CURRMODEM & + exit 0 + fi + fi +fi + +if $QUECTEL; then + ATCMDD="AT+QINDCFG=\"all\",1" + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") +fi + +modis=$(uci -q get basic.basic.modem) +if [ ! -z $modis ]; then + if [ $modis = "0" ]; then + log "Modem Disabled" + exit 0 + fi +fi + +for isp in $isplist +do + NAPN=$(echo $isp | cut -d, -f2) + NPASS=$(echo $isp | cut -d, -f4) + CID=$(echo $isp | cut -d, -f5) + NUSER=$(echo $isp | cut -d, -f6) + NAUTH=$(echo $isp | cut -d, -f7) + if [ "$NPASS" = "nil" ]; then + NPASS="NIL" + fi + if [ "$NUSER" = "nil" ]; then + NUSER="NIL" + fi + if [ "$NAUTH" = "nil" ]; then + NAUTH="0" + fi + export SETAPN=$NAPN + export SETUSER=$NUSER + export SETPASS=$NPASS + export SETAUTH=$NAUTH + export PINCODE=$PINC + + uci set modem.modem$CURRMODEM.apn=$NAPN + uci set modem.modem$CURRMODEM.user=$NUSER + uci set modem.modem$CURRMODEM.passw=$NPASS + uci set modem.modem$CURRMODEM.auth=$NAUTH + uci set modem.modem$CURRMODEM.pin=$PINC + uci commit modem + + concount=1 + while [ "$concount" -lt 3 ]; do + case $PROT in + "1" ) + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "auto.gcom" "$CURRMODEM") + chcklog "$OX" + M7=$(echo "$OX" | sed -e "s/SCPROF:/SCPROF: /;s! ! !g") + AU=$(echo "$M7" | awk -F[,\ ] '/^\!SCPROF:/ {print $4}') + if [ $AU = "1" ]; then + AUTO="1" + log "Autoconnect is Enabled" + else + AUTO="0" + log "Autoconnect is not Enabled" + fi + ;; + esac + uci set modem.modem$CURRMODEM.auto=$AUTO + uci commit modem + + case $PROT in + # + # Check provider Lock + # + "1"|"2"|"4"|"6"|"7"|"24"|"26"|"27"|"30"|"28"|"88" ) + $ROOTER/common/lockchk.sh $CURRMODEM + ;; + * ) + log "No Provider Lock Done" + ;; + esac + + case $PROT in + # + # Sierra and NCM uses separate Pincode setting + # + "1"|"4"|"6"|"7"|"24"|"26"|"27"|"28" ) + if [ -n "$PINC" ]; then + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "setpin.gcom" "$CURRMODEM") + chcklog "$OX" + ERROR="ERROR" + if `echo $OX | grep "$ERROR" 1>/dev/null 2>&1` + then + log "Modem $CURRMODEM Failed to Unlock SIM Pin" + $ROOTER/signal/status.sh $CURRMODEM "$MAN $MOD" "Failed to Connect : Pin Locked" + exit 0 + fi + fi + ;; + * ) + log "Pincode in script" + ;; + esac + $ROOTER/log/logger "Attempting to Connect Modem #$CURRMODEM" + log "Attempting to Connect Modem $CURRMODEM" + + if [ -e $ROOTER/modem-led.sh ]; then + $ROOTER/modem-led.sh $CURRMODEM 2 + fi + + BRK=0 + case $PROT in + # + # Sierra connect script + # + "1" ) + if [ $AUTO = "0" ]; then + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "connect-directip.gcom" "$CURRMODEM") + chcklog "$OX" + ERROR="ERROR" + if `echo $OX | grep "$ERROR" 1>/dev/null 2>&1` + then + BRK=1 + $ROOTER/signal/status.sh $CURRMODEM "$MAN $MOD" "Failed to Connect : Retrying" + fi + M7=$(echo "$OX" | sed -e "s/SCACT:/SCACT: /;s! ! !g") + SCACT="!SCACT: 1,1" + if `echo ${M7} | grep "$SCACT" 1>/dev/null 2>&1` + then + BRK=0 + ifup wan$INTER + sleep 20 + else + BRK=1 + $ROOTER/signal/status.sh $CURRMODEM "$MAN $MOD" "Failed to Connect : Retrying" + fi + else + ifup wan$INTER + sleep 20 + fi + ;; + # + # QMI connect script + # + "2" ) + check_apn + $ROOTER/qmi/connectqmi.sh $CURRMODEM cdc-wdm$WDMNX $NAUTH $NAPN $NUSER $NPASS $RAW $DHCP $PINC + if [ $? = 0 ]; then + ifup wan$INTER + [ -f /tmp/ipv6supp$INTER ] && addv6 + else + exit 0 + fi + ;; + # + # NCM connect script + # + "4"|"6"|"7"|"24"|"26"|"27" ) + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "ati") + E5372=$(echo $OX | grep "E5372") + R215=$(echo $OX | grep "R215") + E5787=$(echo $OX | grep "E5787") + check_apn + if [ -n "$E5372" -o -n "$R215" -o -n "$E5787" ]; then + ifup wan$INTER + BRK=0 + else + OX=$($ROOTER/gcom/gcom-locked "/dev/cdc-wdm$WDMNX" "connect-ncm.gcom" "$CURRMODEM") + chcklog "$OX" + ERROR="ERROR" + if `echo $OX | grep "$ERROR" 1>/dev/null 2>&1` + then + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "connect-ncm.gcom" "$CURRMODEM") + chcklog "$OX" + fi + ERROR="ERROR" + if `echo $OX | grep "$ERROR" 1>/dev/null 2>&1` + then + BRK=1 + $ROOTER/signal/status.sh $CURRMODEM "$MAN $MOD" "Failed to Connect : Retrying" + else + ifup wan$INTER + sleep 25 + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "cgpaddr.gcom" "$CURRMODEM") + chcklog "$OX" + OX=$($ROOTER/common/processat.sh "$OX") + STATUS=$(echo "$OX" | awk -F[,\ ] '/^\^SYSINFOEX:/ {print $2}' | sed 's/"//g') + DOMAIN=$(echo "$OX" | awk -F[,\ ] '/^\^SYSINFOEX:/ {print $3}' | sed 's/"//g') + if [ "x$STATUS" = "x" ]; then + STATUS=$(echo "$OX" | awk -F[,\ ] '/^\^SYSINFO:/ {print $2}') + DOMAIN=$(echo "$OX" | awk -F[,\ ] '/^\^SYSINFO:/ {print $3}') + fi + CGPADDR="+CGPADDR:" + if `echo $OX | grep "$CGPADDR" 1>/dev/null 2>&1` + then + if [ $STATUS = "2" ]; then + if [ $DOMAIN = "1" ]; then + BRK=0 + else + if [ $DOMAIN = "2" ]; then + BRK=0 + else + if [ $DOMAIN = "3" ]; then + BRK=0 + else + BRK=1 + $ROOTER/signal/status.sh $CURRMODEM "$MAN $MOD" "Network Error : Retrying" + fi + fi + fi + else + BRK=1 + $ROOTER/signal/status.sh $CURRMODEM "$MAN $MOD" "Network Error : Retrying" + fi + else + BRK=1 + $ROOTER/signal/status.sh $CURRMODEM "$MAN $MOD" "No IP Address : Retrying" + fi + fi + fi + [ $BRK = 0 ] && addv6 + ;; + # + # Fibocom NCM connect + # + "28" ) + OX="$(for a in /sys/class/net/*; do readlink $a; done | grep "$MATCH" | grep ".6/net/")" + ifname=$(basename $OX) + log "Modem $CURRMODEM Fibocom NCM Data Port : $ifname" + COMMPORT="/dev/ttyUSB"$CPORT + ATCMDD="AT+CGACT=0,$CID" + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + check_apn + ATCMDD="AT+CGPIAF=1,0,0,0;+XDNS=$CID,1;+XDNS=$CID,2" + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + ATCMDD="AT+CGACT=1,$CID" + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + ERROR="ERROR" + if [ -e /tmp/simerr$CURRMODEM ]; then + SIMFAIL=1 + log "SIM card error" + else + chkreg + [ "$REGOK" != 1 ] && log "Subscriber registration failed" + fi + if [ "$SIMFAIL" = 1 -o "$REGOK" != 1 ]; then + BRK=1 + $ROOTER/signal/status.sh $CURRMODEM "$MAN $MOD" "Failed to Connect : Retrying" + elif `echo "$OX" | grep -q "$ERROR"`; then + BRK=1 + $ROOTER/signal/status.sh $CURRMODEM "$MAN $MOD" "Failed to Connect : Retrying" + else + ATCMDD="AT+CGCONTRDP=$CID" + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + if `echo "$OX" | grep -q "$ERROR"`; then + log "Failed to get IP information for context $CID" + BRK=1 + $ROOTER/signal/status.sh $CURRMODEM "$MAN $MOD" "Failed to get IP information : Retrying" + else + OX=$(echo "${OX//[\" ]/}") + ip=$(echo $OX | cut -d, -f4 | grep -o "[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}") + ip=$(echo $ip | cut -d' ' -f1) + DNS1=$(echo $OX | cut -d, -f6) + DNS2=$(echo $OX | cut -d, -f7) + OX6=$(echo $OX | grep -o "+CGCONTRDP:$CID,[0-9]\+,[^,]\+,[0-9A-F]\{1,4\}:[0-9A-F]\{1,4\}.\+") + ip6=$(echo $OX6 | grep -o "[0-9A-F]\{1,4\}:[0-9A-F]\{1,4\}:[0-9A-F]\{1,4\}:[0-9A-F]\{1,4\}:[0-9A-F]\{1,4\}:[0-9A-F]\{1,4\}:[0-9A-F]\{1,4\}:[0-9A-F]\{1,4\}") + ip6=$(echo $ip6 | cut -d' ' -f1) + DNS3=$(echo "$OX6" | cut -d, -f6) + DNS4=$(echo "$OX6" | cut -d, -f7) + + log "IP address(es): $ip $ip6" + log "DNS servers 1&2: $DNS1 $DNS2" + log "DNS servers 3&4: $DNS3 $DNS4" + + if [[ $(echo "$ip6" | grep -o "^[23]") ]]; then + # Global unicast IP acquired + v6cap=1 + elif [[ $(echo "$ip6" | grep -o "^[0-9a-fA-F]\{1,4\}:") ]]; then + # non-routable address + v6cap=2 + else + v6cap=0 + fi + + if [ -n "$ip6" -a -z "$ip" ]; then + log "Running IPv6-only mode" + nat46=1 + fi + + ATCMDD="AT+XDATACHANNEL=1,1,\"/USBCDC/2\",\"/USBHS/NCM/0\",2,$CID" + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + RDNS=$(uci -q get network.wan$INTER.dns) + + log "Applying IP settings to wan$INTER" + uci delete network.wan$INTER + uci set network.wan$INTER=interface + uci set network.wan$INTER.proto=static + uci set network.wan$INTER.${ifname1}=$ifname + uci set network.wan$INTER.metric=$INTER"0" + if [ -n "$ip" ]; then + uci set network.wan$INTER.ipaddr=$ip/32 + uci set network.wan$INTER.gateway='0.0.0.0' + fi + if [ "$v6cap" -gt 0 ]; then + uci set network.wan$INTER.ip6addr=$ip6/128 + fi + + if [ -n "$RDNS" ]; then + uci set network.wan$INTER.dns="$RDNS" + else + set_dns2 + fi + + uci commit network + uci set modem.modem$CURRMODEM.interface=$ifname + uci commit modem + ip link set dev $ifname arp off + ATCMDD="AT+CGDATA=\"M-RAW_IP\",$CID" + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "raw-ip.gcom" "$CURRMODEM" "$ATCMDD") + RESP=$(echo $OX | sed "s/AT+CGDATA=\"M-RAW_IP\",$CID //") + log "Final Modem $CURRMODEM result code is \"$RESP\"" + if [ "$RESP" = "OK CONNECT" ]; then + ifup wan$INTER + if [ -e /sys/class/net/$ifname/cdc_ncm/tx_timer_usecs ]; then + echo "0" > /sys/class/net/$ifname/cdc_ncm/tx_timer_usecs + fi + [ $v6cap = 2 ] && addv6 + sleep 2 + BRK=0 + else + BRK=1 + $ROOTER/signal/status.sh $CURRMODEM "$MAN $MOD" "Failed to Connect : Retrying" + fi + fi + fi + ;; + # + # MBIM connect script + # + "3"|"30" ) + if [ -n "$CPORT" ]; then + check_apn + fi + log "Using Netifd Method" + uci delete network.wan$INTER + uci set network.wan$INTER=interface + uci set network.wan$INTER.proto=mbim + uci set network.wan$INTER.device=/dev/cdc-wdm$WDMNX + uci set network.wan$INTER.metric=$INTER"0" + uci set network.wan$INTER.currmodem=$CURRMODEM + uci -q commit network + rm -f /tmp/usbwait + ifup wan$INTER + MIFACE=$(uci -q get modem.modem$CURRMODEM.interface) + if [ -e /sys/class/net/$MIFACE/cdc_ncm/tx_timer_usecs ]; then + echo "0" > /sys/class/net/$MIFACE/cdc_ncm/tx_timer_usecs + fi + exit 0 + ;; + esac + + if [ $BRK = 1 ]; then + ATCMDD="AT+COPS=0" + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + $ROOTER/log/logger "Retry Connection with Modem #$CURRMODEM" + log "Retry Connection" + sleep 10 + concount=$((concount+1)) + else + $ROOTER/log/logger "Modem #$CURRMODEM Connected" + log "Modem $CURRMODEM Connected" + break + fi + done + if [ $BRK = 0 ]; then + break + fi +done + +if [ $BRK = 1 ]; then + exit 0 +fi + +if [ -e $ROOTER/modem-led.sh ]; then + $ROOTER/modem-led.sh $CURRMODEM 3 +fi + +case $PROT in +# +# Sierra, NCM and QMI use modemsignal.sh and reconnect.sh +# + "1"|"2"|"4"|"6"|"7"|"24"|"26"|"27"|"28"|"88" ) + ln -fs $ROOTER/signal/modemsignal.sh $ROOTER_LINK/getsignal$CURRMODEM + ln -fs $ROOTER/connect/reconnect.sh $ROOTER_LINK/reconnect$CURRMODEM + # send custom AT startup command + if [ $(uci -q get modem.modeminfo$CURRMODEM.at) -eq "1" ]; then + ATCMDD=$(uci -q get modem.modeminfo$CURRMODEM.atc) + if [ ! -z "$ATCMDD" ]; then + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + OX=$($ROOTER/common/processat.sh "$OX") + ERROR="ERROR" + if `echo $OX | grep "$ERROR" 1>/dev/null 2>&1` + then + log "Error sending custom AT command: $ATCMDD with result: $OX" + else + log "Sent custom AT command: $ATCMDD with result: $OX" + fi + fi + fi + ;; +esac + + $ROOTER_LINK/getsignal$CURRMODEM $CURRMODEM $PROT & + ln -fs $ROOTER/connect/conmon.sh $ROOTER_LINK/con_monitor$CURRMODEM + $ROOTER_LINK/con_monitor$CURRMODEM $CURRMODEM & + uci set modem.modem$CURRMODEM.connected=1 + uci commit modem + + if [ -e $ROOTER/connect/postconnect.sh ]; then + $ROOTER/connect/postconnect.sh $CURRMODEM + fi + + if [ -e /etc/bandlock ]; then + M1='AT+COPS=?' + export TIMEOUT="120" + #OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$M1") + export TIMEOUT="5" + fi + + if [ -e $ROOTER/timezone.sh ]; then + TZ=$(uci -q get modem.modeminfo$CURRMODEM.tzone) + if [ "$TZ" = "1" ]; then + log "Set TimeZone" + $ROOTER/timezone.sh & + fi + fi + + CLB=$(uci -q get modem.modeminfo$CURRMODEM.lb) + if [ -e /etc/config/mwan3 ]; then + ENB=$(uci -q get mwan3.wan$INTER.enabled) + if [ ! -z "$ENB" ]; then + if [ $CLB = "1" ]; then + uci set mwan3.wan$INTER.enabled=1 + else + uci set mwan3.wan$INTER.enabled=0 + fi + uci commit mwan3 + /usr/sbin/mwan3 restart + fi + fi + diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/create_hostless.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/create_hostless.sh new file mode 100644 index 0000000..192dcba --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/create_hostless.sh @@ -0,0 +1,666 @@ +#!/bin/sh + +ROOTER=/usr/lib/rooter +ROOTER_LINK="/tmp/links" + +log() { + modlog "Create Hostless Connection $CURRMODEM" "$@" +} + +ifname1="ifname" +if [ -e /etc/newstyle ]; then + ifname1="device" +fi + +handle_timeout(){ + local wget_pid="$1" + local count=0 + ps | grep -v grep | grep $wget_pid + res="$?" + while [ "$res" = 0 -a $count -lt "$((TIMEOUT))" ]; do + sleep 1 + count=$((count+1)) + ps | grep -v grep | grep $wget_pid + res="$?" + done + + if [ "$res" = 0 ]; then + log "Killing process on timeout" + kill "$wget_pid" 2> /dev/null + ps | grep -v grep | grep $wget_pid + res="$?" + if [ "$res" = 0 ]; then + log "Killing process on timeout" + kill -9 $wget_pid 2> /dev/null + fi + fi +} + +check_apn() { + IPVAR="IP" + local COMMPORT="/dev/ttyUSB"$CPORT + if [ -e /etc/nocops ]; then + echo "0" > /tmp/block + fi + ATCMDD="AT+CGDCONT=?" + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + + [ "$PDPT" = "0" ] && PDPT="" + for PDP in "$PDPT" IPV4V6; do + if [[ "$(echo $OX | grep -o "$PDP")" ]]; then + IPVAR="$PDP" + break + fi + done + + uci set modem.modem$CURRMODEM.pdptype=$IPVAR + uci commit modem + + log "PDP Type selected in the Connection Profile: \"$PDPT\", active: \"$IPVAR\"" + + if [ "$idV" = "12d1" ]; then + CFUNOFF="0" + else + CFUNOFF="4" + fi + ATCMDD="AT+CGDCONT?;+CFUN?" + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + CGDCONT2=$(echo $OX | grep "+CGDCONT: 2,") + if [ -z "$CGDCONT2" ]; then + ATCMDD="AT+CGDCONT=2,\"$IPVAR\",\"ims\"" + OXy=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + fi + CGDCONT=$(echo $OX | grep -o "$CID,[^,]\+,[^,]\+,[^,]\+,0,0,1") + IPCG=$(echo $CGDCONT | cut -d, -f4) + if [ "$CGDCONT" == "$CID,\"$IPVAR\",\"$NAPN\",$IPCG,0,0,1" ]; then + if [ -z "$(echo $OX | grep -o "+CFUN: 1")" ]; then + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "AT+CFUN=1") + fi + else + ATCMDD="AT+CGDCONT=$CID,\"$IPVAR\",\"$NAPN\",,0,0,1" + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "AT+CFUN=$CFUNOFF") + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "AT+CFUN=1") + sleep 5 + fi +} + +set_dns() { + local pDNS1=$(uci -q get modem.modeminfo$CURRMODEM.dns1) + local pDNS2=$(uci -q get modem.modeminfo$CURRMODEM.dns2) + local pDNS3=$(uci -q get modem.modeminfo$CURRMODEM.dns3) + local pDNS4=$(uci -q get modem.modeminfo$CURRMODEM.dns4) + + local aDNS="$pDNS1 $pDNS2 $pDNS3 $pDNS4" + local bDNS="" + + echo "$aDNS" | grep -o "[[:graph:]]" &>/dev/null + if [ $? = 0 ]; then + log "Using DNS settings from the Connection Profile" + pdns=1 + for DNSV in $(echo "$aDNS"); do + if [ "$DNSV" != "0.0.0.0" ] && [ -z "$(echo "$bDNS" | grep -o "$DNSV")" ]; then + [ -n "$(echo "$DNSV" | grep -o ":")" ] && continue + bDNS="$bDNS $DNSV" + fi + done + + bDNS=$(echo $bDNS) + uci set network.wan$INTER.peerdns=0 + uci set network.wan$INTER.dns="$bDNS" + echo "$bDNS" > /tmp/v4dns$INTER + + bDNS="" + for DNSV in $(echo "$aDNS"); do + if [ "$DNSV" != "0:0:0:0:0:0:0:0" ] && [ -z "$(echo "$bDNS" | grep -o "$DNSV")" ]; then + [ -z "$(echo "$DNSV" | grep -o ":")" ] && continue + bDNS="$bDNS $DNSV" + fi + done + echo "$bDNS" > /tmp/v6dns$INTER + else + log "Using Hostless Modem as a DNS relay" + pdns=0 + rm -f /tmp/v[46]dns$INTER + fi +} + +set_network() { + uci delete network.wan$INTER + uci set network.wan$INTER=interface + uci set network.wan$INTER.proto=dhcp + uci set network.wan$INTER.${ifname1}=$1 + uci set network.wan$INTER.metric=$INTER"0" + set_dns + uci commit network + sleep 5 +} + +save_variables() { + echo 'MODSTART="'"$MODSTART"'"' > /tmp/variable.file + echo 'WWAN="'"$WWAN"'"' >> /tmp/variable.file + echo 'USBN="'"$USBN"'"' >> /tmp/variable.file + echo 'ETHN="'"$ETHN"'"' >> /tmp/variable.file + echo 'WDMN="'"$WDMN"'"' >> /tmp/variable.file + echo 'BASEPORT="'"$BASEPORT"'"' >> /tmp/variable.file +} + +chcklog() { + OOX=$1 + CLOG=$(uci -q get modem.modeminfo$CURRMODEM.log) + if [ $CLOG = "1" ]; then + log "$OOX" + fi +} + +get_connect() { + NAPN=$(uci -q get modem.modeminfo$CURRMODEM.apn) + PDPT=$(uci -q get modem.modeminfo$CURRMODEM.pdptype) + uci set modem.modem$CURRMODEM.apn="$NAPN" + uci commit modem +} + +get_tty_fix() { +# $1 is fixed ttyUSB or ttyACM port number + local POS + POS=`expr 1 + $1` + CPORT=$(echo "$TTYDEVS" | cut -d' ' -f"$POS" | grep -o "[[:digit:]]\+") +} + +get_ip() { + ATCMDD="AT+CGPIAF=1,1,1,0;+CGPADDR" + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + OX=$(echo "$OX" | grep "^+CGPADDR: $CID," | cut -d'"' -f2) + ip4=$(echo $OX | cut -d, -f1 | grep "\.") + ip6=$(echo $OX | cut -d, -f2 | grep ":") + log "IP address(es) obtained: $ip4 $ip6" +} + +check_ip() { + if [[ $(echo "$ip6" | grep -o "^[23]") ]]; then + # Global unicast IP acquired + v6cap=1 + elif [[ $(echo "$ip6" | grep -o "^[0-9a-fA-F]\{1,4\}:") ]]; then + # non-routable address + v6cap=2 + else + v6cap=0 + fi + + if [ -n "$ip6" -a -z "$ip4" ]; then + log "Running IPv6-only mode" + nat46=1 + fi +} + +addv6() { + . /lib/functions.sh + . /lib/netifd/netifd-proto.sh + local interface=wan$INTER + local zone="$(fw3 -q network "$interface" 2>/dev/null)" + + log "Adding IPv6 dynamic interface" + json_init + json_add_string name "${interface}_6" + json_add_string ${ifname1} "@$interface" + json_add_string proto "dhcpv6" + json_add_string extendprefix 1 + [ -n "$zone" ] && json_add_string zone "$zone" + [ "$pdns" = 1 ] && json_add_boolean peerdns 0 + [ "$nat46" = 1 ] || json_add_string iface_464xlat 0 + proto_add_dynamic_defaults + json_close_object + ubus call network add_dynamic "$(json_dump)" +} + +CURRMODEM=$1 + +MAN=$(uci -q get modem.modem$CURRMODEM.manuf) +MOD=$(uci -q get modem.modem$CURRMODEM.model) +$ROOTER/signal/status.sh $CURRMODEM "$MAN $MOD" "Connecting" +$ROOTER/log/logger "Attempting to Connect Modem #$CURRMODEM ($MAN $MOD)" + +BASEP=$(uci -q get modem.modem$CURRMODEM.baseport) +idV=$(uci -q get modem.modem$CURRMODEM.idV) +idP=$(uci -q get modem.modem$CURRMODEM.idP) +log " " +log "Hostless ID $idV:$idP" +log " " + +MATCH="$(uci -q get modem.modem$CURRMODEM.maxcontrol | cut -d/ -f3- | xargs dirname)" +OX=$(for a in /sys/class/tty/*; do readlink $a; done | grep "$MATCH" | tr '\n' ' ' | xargs -r -n1 basename) +TTYDEVS=$(echo "$OX" | grep -o ttyUSB[0-9]) +if [ $? -ne 0 ]; then + TTYDEVS=$(echo "$OX" | grep -o ttyACM[0-9]) + [ $? -eq 0 ] && ACM=1 +fi +TTYDEVS=$(echo "$TTYDEVS" | tr '\n' ' ') +TTYDEVS=$(echo $TTYDEVS) +if [ -n "$TTYDEVS" ]; then + log Modem $CURRMODEM is a parent of $TTYDEVS +else + log "No ECM Comm Port" +fi + +if [ $idV = 1546 -a $idP = 1146 ]; then + SP=1 +elif [ $idV = 19d2 -a $idP = 1476 ]; then + SP=2 +elif [ $idV = 1410 -a $idP = 9022 ]; then + SP=3 +elif [ $idV = 1410 -a $idP = 9032 ]; then + SP=3 +elif [ $idV = 2cb7 -o $idV = 1508 ]; then + sleep 5 + log "Fibocom ECM" + SP=4 +elif [ $idV = 2c7c ]; then + SP=5 +elif [ $idV = 12d1 -a $idP = 15c1 ]; then + SP=6 +elif [ $idV = 2cd2 ]; then + log "MikroTik R11e ECM" + SP=7 +else + SP=0 +fi + +log " " +log "Modem Type $SP" +log " " +if [ $SP -gt 0 ]; then + if [ $SP -eq 3 ]; then + PORTN=0 + elif [ $SP -eq 4 ]; then + PORTN=2 + elif [ $SP -eq 5 ]; then + [ $idP = 6026 ] && PORTN=1 || PORTN=2 + elif [ $SP -eq 6 ]; then + PORTN=2 + elif [ $SP -eq 7 ]; then + PORTN=0 + else + PORTN=1 + fi + get_tty_fix $PORTN + lua $ROOTER/common/modemchk.lua "$idV" "$idP" "$CPORT" "$CPORT" + source /tmp/parmpass + + if [ "$ACM" = 1 ]; then + ACMPORT=$CPORT + CPORT="7$ACMPORT" + ln -fs /dev/ttyACM$ACMPORT /dev/ttyUSB$CPORT + fi + + log "Modem $CURRMODEM ECM Comm Port : /dev/ttyUSB$CPORT" + uci set modem.modem$CURRMODEM.commport=$CPORT + uci commit modem + + $ROOTER/sms/check_sms.sh $CURRMODEM & + + if [ -e $ROOTER/connect/preconnect.sh ]; then + $ROOTER/connect/preconnect.sh $CURRMODEM + fi + + if [ $SP = 5 ]; then + clck=$(uci -q get custom.bandlock.cenable$CURRMODEM) + if [ "$clck" = "1" ]; then + ear=$(uci -q get custom.bandlock.earfcn$CURRMODEM) + pc=$(uci -q get custom.bandlock.pci$CURRMODEM) + ear1=$(uci -q get custom.bandlock.earfcn1$CURRMODEM) + pc1=$(uci -q get custom.bandlock.pci1$CURRMODEM) + ear2=$(uci -q get custom.bandlock.earfcn2$CURRMODEM) + pc2=$(uci -q get custom.bandlock.pci2$CURRMODEM) + ear3=$(uci -q get custom.bandlock.earfcn3$CURRMODEM) + pc3=$(uci -q get custom.bandlock.pci3$CURRMODEM) + cnt=1 + earcnt=$ear","$pc + if [ "$ear1" != "0" -a $pc1 != "0" ]; then + earcnt=$earcnt","$ear1","$pc1 + let cnt=cnt+1 + fi + if [ "$ear2" != "0" -a $pc2 != "0" ]; then + earcnt=$earcnt","$ear2","$pc2 + let cnt=cnt+1 + fi + if [ "$ear3" != "0" -a $pc3 != "0" ]; then + earcnt=$earcnt","$ear3","$pc3 + let cnt=cnt+1 + fi + earcnt=$cnt","$earcnt + ATCMDD="at+qnwlock=\"common/4g\"" + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + log "$OX" + if `echo $OX | grep "ERROR" 1>/dev/null 2>&1` + then + ATCMDD="at+qnwlock=\"common/lte\",2,$ear,$pc" + else + ATCMDD=$ATCMDD","$earcnt + fi + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + log "Cell Lock $OX" + sleep 10 + fi + fi + + $ROOTER/connect/bandmask $CURRMODEM 1 + uci commit modem + + if [ $SP = 4 ]; then + if [ -e /etc/interwave ]; then + idP=$(uci -q get modem.modem$CURRMODEM.idP) + idPP=${idP:1:1} + if [ "$idPP" = "1" ]; then + ATC="AT+GTRAT=17" + else + ATC="AT+XACT=4,2" + fi + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATC") + fi + $ROOTER/connect/bandmask $CURRMODEM 2 + uci commit modem + fi +fi +$ROOTER/common/gettype.sh $CURRMODEM +$ROOTER/connect/get_profile.sh $CURRMODEM +if [ -e $ROOTER/simlock.sh ]; then + $ROOTER/simlock.sh $CURRMODEM +fi + +if [ -e /tmp/simpin$CURRMODEM ]; then + log " SIM Error" + exit 0 +fi +if [ -e /usr/lib/gps/gps.sh ]; then + /usr/lib/gps/gps.sh $CURRMODEM & +fi + +INTER=$(uci -q get modem.modeminfo$CURRMODEM.inter) +if [ -z "$INTER" ]; then + INTER=$CURRMODEM +else + if [ "$INTER" = 0 ]; then + INTER=$CURRMODEM + fi +fi +log "Profile for Modem $CURRMODEM sets interface to WAN$INTER" +OTHER=1 +if [ $CURRMODEM = 1 ]; then + OTHER=2 +fi +EMPTY=$(uci -q get modem.modem$OTHER.empty) +if [ "$EMPTY" = 0 ]; then + OINTER=$(uci -q get modem.modem$OTHER.inter) + if [ ! -z "$OINTER" ]; then + if [ $INTER = $OINTER ]; then + INTER=1 + if [ "$OINTER" = 1 ]; then + INTER=2 + fi + log "Switched Modem $CURRMODEM to WAN$INTER as Modem $OTHER is using WAN$OINTER" + fi + fi +fi +uci set modem.modem$CURRMODEM.inter=$INTER +uci commit modem +log "Modem $CURRMODEM is using WAN$INTER" + +CID=$(uci -q get modem.modeminfo$CURRMODEM.context) +[ -z "$CID" ] && CID=1 + +log "Checking Network Interface" +ifname="$(if [ "$MATCH" ]; then for a in /sys/class/net/*; do readlink $a; done | grep "$MATCH"; fi | xargs -r basename)" + +if [ "$ifname" ]; then + log "Modem $CURRMODEM ECM Data Port : $ifname" + set_network "$ifname" + uci set modem.modem$CURRMODEM.interface=$ifname + if [ -e $ROOTER/changedevice.sh ]; then + $ROOTER/changedevice.sh $ifname + fi +else + log "Modem $CURRMODEM - No ECM Data Port found" +fi +uci commit modem + +ttl=$(uci -q get modem.modeminfo$CURRMODEM.ttl) +if [ -z "$ttl" ]; then + ttl="0" +fi +hostless=$(uci -q get modem.modeminfo$CURRMODEM.hostless) +if [ "$ttl" != "0" -a "$ttl" != "1" -a "$ttl" != "TTL-INC 1" -a "$hostless" = "1" ]; then + let "ttl=$ttl+1" +fi +$ROOTER/connect/handlettl.sh $CURRMODEM "$ttl" + +if [ $SP -eq 2 ]; then + get_connect + export SETAPN=$NAPN + BRK=1 + + while [ $BRK -eq 1 ]; do + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "connect-zecm.gcom" "$CURRMODEM") + chcklog "$OX" + ERROR="ERROR" + if `echo ${OX} | grep "${ERROR}" 1>/dev/null 2>&1` + then + $ROOTER/signal/status.sh $CURRMODEM "$MAN $MOD" "Failed to Connect : Retrying" + else + BRK=0 + fi + done +fi + +if [ $SP -eq 4 ]; then + get_connect + export SETAPN=$NAPN + BRK=1 + + while [ $BRK -eq 1 ]; do + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "connect-fecm.gcom" "$CURRMODEM") + chcklog "$OX" + log " " + log "Fibocom Connect : $OX" + log " " + ERROR="ERROR" + if `echo ${OX} | grep "${ERROR}" 1>/dev/null 2>&1` + then + $ROOTER/signal/status.sh $CURRMODEM "$MAN $MOD" "Failed to Connect : Retrying" + else + BRK=0 + get_ip + fi + done +fi + +if [ $SP = 5 ]; then + get_connect + if [ -n "$NAPN" ]; then + $ROOTER/common/lockchk.sh $CURRMODEM + if [ $idP = 6026 ]; then + IPN=1 + case "$PDPT" in + "IPV6" ) + IPN=2 + ;; + "IPV4V6" ) + IPN=3 + ;; + esac + ATCMDD="AT+QICSGP=$CID,$IPN,\"$NAPN\"" + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + ATCMDD="AT+QNETDEVCTL=2,$CID,1" + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + else + check_apn + fi + fi + ATCMDD="AT+CNMI?" + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + if `echo $OX | grep -o "+CNMI: [0-3],2," >/dev/null 2>&1`; then + ATCMDD="AT+CNMI=0,0,0,0,0" + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + fi + ATCMDD="AT+QINDCFG=\"smsincoming\"" + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + if `echo $OX | grep -o ",1" >/dev/null 2>&1`; then + ATCMDD="AT+QINDCFG=\"smsincoming\",0,1" + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + fi + ATCMDD="AT+QINDCFG=\"all\"" + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + if `echo $OX | grep -o ",1" >/dev/null 2>&1`; then + ATCMDD="AT+QINDCFG=\"all\",0,1" + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + fi + log "Quectel Unsolicited Responses Disabled" + $ROOTER/luci/celltype.sh $CURRMODEM + ATCMDD="AT+QINDCFG=\"all\",1" + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + + get_ip + if [ -n "$ip6" ]; then + check_ip + if [ "$v6cap" -gt 0 ]; then + addv6 + fi + fi +fi + +if [ $SP -eq 6 ]; then + get_connect + export SETAPN=$NAPN + BRK=1 + + while [ $BRK -eq 1 ]; do + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "connect-ncm.gcom" "$CURRMODEM") + chcklog "$OX" + ERROR="ERROR" + if `echo ${OX} | grep "${ERROR}" 1>/dev/null 2>&1` + then + $ROOTER/signal/status.sh $CURRMODEM "$MAN $MOD" "Failed to Connect : Retrying" + else + BRK=0 + fi + done +fi + +if [ $SP -eq 7 ]; then + get_connect + export SETAPN=$NAPN + BRK=1 + + if [ -n "$NAPN" ]; then + check_apn + fi + + while [ $BRK -eq 1 ]; do + ATCMDD="AT\$ECMCALL=1" + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + chcklog "$OX" + ERROR="ERROR" + if `echo ${OX} | grep "${ERROR}" 1>/dev/null 2>&1` + then + $ROOTER/signal/status.sh $CURRMODEM "$MAN $MOD" "Failed to Connect : Retrying" + else + BRK=0 + get_ip + if [ -n "$ip6" ]; then + check_ip + if [ "$v6cap" -gt 0 ]; then + addv6 + fi + fi + fi + done +fi + +rm -f /tmp/usbwait + +ifup wan$INTER +while `ifstatus wan$INTER | grep -q '"up": false\|"pending": true'`; do + sleep 1 +done +wan_ip=$(expr "`ifstatus wan$INTER | grep '"nexthop":'`" : '.*"nexthop": "\(.*\)"') +if [ $? -ne 0 ] ; then + wan_ip=192.168.0.1 +fi +uci set modem.modem$CURRMODEM.ip=$wan_ip +uci commit modem + +$ROOTER/log/logger "HostlessModem #$CURRMODEM Connected with IP $wan_ip" + +PROT=5 + +if [ $SP -gt 1 ]; then + ln -s $ROOTER/signal/modemsignal.sh $ROOTER_LINK/getsignal$CURRMODEM + $ROOTER_LINK/getsignal$CURRMODEM $CURRMODEM $PROT & +else + VENDOR=$(uci -q get modem.modem$CURRMODEM.idV) + case $VENDOR in + "19d2" ) + TIMEOUT=3 + wget -O /tmp/connect.file http://$wan_ip/goform/goform_set_cmd_process?goformId=CONNECT_NETWORK & + handle_timeout "$!" + ln -s $ROOTER/signal/ztehostless.sh $ROOTER_LINK/getsignal$CURRMODEM + $ROOTER_LINK/getsignal$CURRMODEM $CURRMODEM $PROT & + ;; + "12d1" ) + log "Huawei Hostless" + ln -s $ROOTER/signal/huaweihostless.sh $ROOTER_LINK/getsignal$CURRMODEM + $ROOTER_LINK/getsignal$CURRMODEM $CURRMODEM $PROT & + ;; + * ) + log "Other Hostless" + ln -s $ROOTER/signal/otherhostless.sh $ROOTER_LINK/getsignal$CURRMODEM + $ROOTER_LINK/getsignal$CURRMODEM $CURRMODEM $PROT & + ;; +esac +fi + +ln -s $ROOTER/connect/conmon.sh $ROOTER_LINK/con_monitor$CURRMODEM +$ROOTER_LINK/con_monitor$CURRMODEM $CURRMODEM & +uci set modem.modem$CURRMODEM.connected=1 +uci commit modem + +if [ $SP -gt 0 ]; then + if [ -e $ROOTER/connect/postconnect.sh ]; then + $ROOTER/connect/postconnect.sh $CURRMODEM + fi + if [ $(uci -q get modem.modeminfo$CURRMODEM.at) -eq "1" ]; then + ATCMDD=$(uci -q get modem.modeminfo$CURRMODEM.atc) + if [ -n "$ATCMDD" ]; then + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + OX=$($ROOTER/common/processat.sh "$OX") + ERROR="ERROR" + if `echo $OX | grep "$ERROR" 1>/dev/null 2>&1` + then + log "Error sending custom AT command: $ATCMDD with result: $OX" + else + log "Sent custom AT command: $ATCMDD with result: $OX" + fi + fi + fi + + if [ -e $ROOTER/timezone.sh ]; then + TZ=$(uci -q get modem.modeminfo$CURRMODEM.tzone) + if [ "$TZ" = "1" ]; then + log "Set TimeZone" + $ROOTER/timezone.sh & + fi + fi +fi + +CLB=$(uci -q get modem.modeminfo$CURRMODEM.lb) +if [ -e /etc/config/mwan3 ]; then + ENB=$(uci -q get mwan3.wan$INTER.enabled) + if [ ! -z "$ENB" ]; then + if [ "$CLB" = "1" ]; then + uci set mwan3.wan$INTER.enabled=1 + else + uci set mwan3.wan$INTER.enabled=0 + fi + uci commit mwan3 + /usr/sbin/mwan3 restart + fi +fi diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/create_iphone.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/create_iphone.sh new file mode 100644 index 0000000..fe87a5c --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/create_iphone.sh @@ -0,0 +1,222 @@ +#!/bin/sh + +ROOTER=/usr/lib/rooter +ROOTER_LINK="/tmp/links" + +log() { + modlog "Create iPhone Connection $CURRMODEM" "$@" +} + + +ifname1="ifname" +if [ -e /etc/newstyle ]; then + ifname1="device" +fi + +handle_timeout(){ + local wget_pid="$1" + local count=0 + ps | grep -v grep | grep $wget_pid + res="$?" + while [ "$res" = 0 -a $count -lt "$((TIMEOUT))" ]; do + sleep 1 + count=$((count+1)) + ps | grep -v grep | grep $wget_pid + res="$?" + done + + if [ "$res" = 0 ]; then + log "Killing process on timeout" + kill "$wget_pid" 2> /dev/null + ps | grep -v grep | grep $wget_pid + res="$?" + if [ "$res" = 0 ]; then + log "Killing process on timeout" + kill -9 $wget_pid 2> /dev/null + fi + fi +} + +set_dns() { + local pDNS1=$(uci -q get modem.modeminfo$CURRMODEM.dns1) + local pDNS2=$(uci -q get modem.modeminfo$CURRMODEM.dns2) + local pDNS3=$(uci -q get modem.modeminfo$CURRMODEM.dns3) + local pDNS4=$(uci -q get modem.modeminfo$CURRMODEM.dns4) + + local aDNS="$pDNS1 $pDNS2 $pDNS3 $pDNS4" + local bDNS="" + + echo "$aDNS" | grep -o "[[:graph:]]" &>/dev/null + if [ $? = 0 ]; then + log "Using DNS settings from the Connection Profile" + pdns=1 + for DNSV in $(echo "$aDNS"); do + if [ "$DNSV" != "0.0.0.0" ] && [ -z "$(echo "$bDNS" | grep -o "$DNSV")" ]; then + [ -n "$(echo "$DNSV" | grep -o ":")" ] && continue + bDNS="$bDNS $DNSV" + fi + done + + bDNS=$(echo $bDNS) + uci set network.wan$INTER.peerdns=0 + uci set network.wan$INTER.dns="$bDNS" + echo "$bDNS" > /tmp/v4dns$INTER + + bDNS="" + for DNSV in $(echo "$aDNS"); do + if [ "$DNSV" != "0:0:0:0:0:0:0:0" ] && [ -z "$(echo "$bDNS" | grep -o "$DNSV")" ]; then + [ -z "$(echo "$DNSV" | grep -o ":")" ] && continue + bDNS="$bDNS $DNSV" + fi + done + echo "$bDNS" > /tmp/v6dns$INTER + else + log "Using Hostless Modem as a DNS" + pdns=0 + rm -f /tmp/v[46]dns$INTER + fi +} + +set_network() { + uci delete network.wan$INTER + uci set network.wan$INTER=interface + uci set network.wan$INTER.proto=dhcp + uci set network.wan$INTER.${ifname1}=$1 + uci set network.wan$INTER.metric=$INTER"0" + set_dns + uci commit network + sleep 5 +} + +save_variables() { + echo 'MODSTART="'"$MODSTART"'"' > /tmp/variable.file + echo 'WWAN="'"$WWAN"'"' >> /tmp/variable.file + echo 'USBN="'"$USBN"'"' >> /tmp/variable.file + echo 'ETHN="'"$ETHN"'"' >> /tmp/variable.file + echo 'WDMN="'"$WDMN"'"' >> /tmp/variable.file + echo 'BASEPORT="'"$BASEPORT"'"' >> /tmp/variable.file +} + +chcklog() { + OOX=$1 + CLOG=$(uci -q get modem.modeminfo$CURRMODEM.log) + if [ $CLOG = "1" ]; then + log "$OOX" + fi +} + + +CURRMODEM=$1 + +MAN=$(uci get modem.modem$CURRMODEM.manuf) +MOD=$(uci get modem.modem$CURRMODEM.model) +$ROOTER/signal/status.sh $CURRMODEM "$MAN $MOD" "Connecting" +$ROOTER/log/logger "Attempting to Connect Modem #$CURRMODEM ($MAN $MOD)" + +BASEP=$(uci -q get modem.modem$CURRMODEM.baseport) +idV=$(uci get modem.modem$CURRMODEM.idV) +idP=$(uci get modem.modem$CURRMODEM.idP) + +$ROOTER/connect/get_profile.sh $CURRMODEM + +INTER=$(uci get modem.modeminfo$CURRMODEM.inter) +if [ -z $INTER ]; then + INTER=$CURRMODEM +else + if [ $INTER = 0 ]; then + INTER=$CURRMODEM + fi +fi +log "Profile for Modem $CURRMODEM sets interface to WAN$INTER" +OTHER=1 +if [ $CURRMODEM = 1 ]; then + OTHER=2 +fi +EMPTY=$(uci get modem.modem$OTHER.empty) +if [ $EMPTY = 0 ]; then + OINTER=$(uci get modem.modem$OTHER.inter) + if [ ! -z $OINTER ]; then + if [ $INTER = $OINTER ]; then + INTER=1 + if [ $OINTER = 1 ]; then + INTER=2 + fi + log "Switched Modem $CURRMODEM to WAN$INTER as Modem $OTHER is using WAN$OINTER" + fi + fi +fi +uci set modem.modem$CURRMODEM.inter=$INTER +uci commit modem +log "Modem $CURRMODEM is using WAN$INTER" + +log "Checking Network Interface" +MATCH="$(uci get modem.modem$CURRMODEM.maxcontrol | cut -d/ -f3- | xargs dirname)" +ifname="$(if [ "$MATCH" ]; then for a in /sys/class/net/*; do readlink $a; done | grep "$MATCH"; fi | xargs -r basename)" + +if [ "$ifname" ]; then + log "Modem $CURRMODEM - iPhone - Data Port : $ifname" + set_network "$ifname" + uci set modem.modem$CURRMODEM.interface=$ifname +else + log "Modem $CURRMODEM - No iPhone Data Port found" +fi +uci commit modem + +rm -f /tmp/usbwait + +ifup wan$INTER +while `ifstatus wan$INTER | grep -q '"up": false\|"pending": true'`; do + sleep 1 +done +wan_ip=$(expr "`ifstatus wan$INTER | grep '"nexthop":'`" : '.*"nexthop": "\(.*\)"') +if [ $? -ne 0 ] ; then + wan_ip=192.168.0.1 +fi +uci set modem.modem$CURRMODEM.ip=$wan_ip +uci commit modem + +log "saving Trusted locks" +for file in `ls /var/lib/lockdown | grep -v SystemConfiguration.plist`; +do + if [ ! -f "/etc/lockdown/locks/$file" ];then + cp /var/lib/lockdown/$file /etc/lockdown/locks/ + else + new_md5=`md5sum /var/lib/lockdown/$file | awk -F" " '{print $1}'` + old_md5=`md5sum /etc/lockdown/locks/$file | awk -F" " '{print $1}'` + if [ "$new_md5" != "$old_md5" ];then + cp /var/lib/lockdown/$file /etc/lockdown/locks/ + fi + fi +done + +$ROOTER/log/logger "iPhone #$CURRMODEM Connected with IP $wan_ip" + +ln -s $ROOTER/signal/otherhostless.sh $ROOTER_LINK/getsignal$CURRMODEM +$ROOTER_LINK/getsignal$CURRMODEM $CURRMODEM $PROT & + +ln -s $ROOTER/connect/conmon.sh $ROOTER_LINK/con_monitor$CURRMODEM +$ROOTER_LINK/con_monitor$CURRMODEM $CURRMODEM & +uci set modem.modem$CURRMODEM.connected=1 +uci commit modem + +if [ -e $ROOTER/timezone.sh ]; then + TZ=$(uci -q get modem.modeminfo$CURRMODEM.tzone) + if [ "$TZ" = "1" ]; then + log "Set TimeZone" + $ROOTER/timezone.sh & + fi +fi + +CLB=$(uci -q get modem.modeminfo$CURRMODEM.lb) +if [ -e /etc/config/mwan3 ]; then + ENB=$(uci -q get mwan3.wan$INTER.enabled) + if [ ! -z $ENB ]; then + if [ $CLB = "1" ]; then + uci set mwan3.wan$INTER.enabled=1 + else + uci set mwan3.wan$INTER.enabled=0 + fi + uci commit mwan3 + /usr/sbin/mwan3 restart + fi +fi diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/disablemw3.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/disablemw3.sh new file mode 100644 index 0000000..9cef8b9 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/disablemw3.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +ROOTER=/usr/lib/rooter + +CURRMODEM=$1 + +if [ -e /etc/config/mwan3 ]; then + INTER=$(uci get modem.modeminfo$CURRMODEM.inter) + ENB=$(uci get mwan3.wan$INTER.enabled) + if [ ! -z $ENB ]; then + uci set mwan3.wan$INTER.enabled=0 + uci commit mwan3 + fi +fi \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/disconnect.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/disconnect.sh new file mode 100644 index 0000000..bde1749 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/disconnect.sh @@ -0,0 +1,73 @@ +#!/bin/sh + +ROOTER=/usr/lib/rooter +ROOTER_LINK="/tmp/links" +TIMEOUT=10 + +log() { + modlog "Disconnect Modem $CURRMODEM" "$@" +} + +handle_timeout(){ + local wget_pid="$1" + local count=0 + res=1 + if [ -d /proc/${wget_pid} ]; then + res=0 + fi + while [ "$res" = 0 -a $count -lt "$((TIMEOUT))" ]; do + sleep 1 + count=$((count+1)) + res=1 + if [ -d /proc/${wget_pid} ]; then + res=0 + fi + done + + if [ "$res" = 0 ]; then + log "Killing process on timeout" + kill "$wget_pid" 2> /dev/null + res=1 + if [ -d /proc/${wget_pid} ]; then + res=0 + fi + if [ "$res" = 0 ]; then + log "Killing process on timeout" + kill -9 $wget_pid 2> /dev/null + fi + fi +} + +CURRMODEM=$(uci get modem.general.miscnum) +uci set modem.modem$CURRMODEM.connected=0 +uci commit modem +INTER=$(uci get modem.modeminfo$CURRMODEM.inter) + +jkillall getsignal$CURRMODEM +rm -f $ROOTER_LINK/getsignal$CURRMODEM +jkillall con_monitor$CURRMODEM +rm -f $ROOTER_LINK/con_monitor$CURRMODEM +ifdown wan$INTER + +MAN=$(uci get modem.modem$CURRMODEM.manuf) +MOD=$(uci get modem.modem$CURRMODEM.model) +$ROOTER/signal/status.sh $CURRMODEM "$MAN $MOD" "Disconnected" + +PROT=$(uci get modem.modem$CURRMODEM.proto) +CPORT=$(uci get modem.modem$CURRMODEM.commport) + +case $PROT in +"30" ) + ATCMDD="AT+CFUN=0" + $ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD" + ;; +"3" ) + WDMNX=$(uci get modem.modem$CURRMODEM.wdm) + umbim -n -t 3 -d /dev/cdc-wdm$WDMNX disconnect + ;; +* ) + $ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "reset.gcom" "$CURRMODEM" + ;; +esac + +$ROOTER/log/logger "Modem #$CURRMODEM was Manually Disconnected" diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/get_profile.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/get_profile.sh new file mode 100644 index 0000000..89c5194 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/get_profile.sh @@ -0,0 +1,423 @@ +#!/bin/sh + +. /lib/functions.sh + +ROOTER=/usr/lib/rooter +ROOTER_LINK="/tmp/links" + +log() { + modlog "Get Profile $CURRMODEM" "$@" +} + +CURRMODEM=$1 + +MODEL=$(uci get modem.modem$CURRMODEM.model) +MANUF=$(uci get modem.modem$CURRMODEM.manuf) +idV=$(uci get modem.modem$CURRMODEM.idV) +idP=$(uci get modem.modem$CURRMODEM.idP) +IMEI=$(uci get modem.modem$CURRMODEM.imei) +IMSI=$(uci -q get modem.modem$CURRMODEM.imsi) +ICCID=$(uci get modem.modem$CURRMODEM.iccid) + +log "Modem $CURRMODEM is $MANUF $MODEL" + +rm -f /tmp/profile$CURRMODEM + +if [ "$IMSI" = "Unknown" ]; then + log "Warning: IMSI cannot be read - SIM card missing or locked?" + touch /tmp/simerr$CURRMODEM +else + rm -f /tmp/simerr$CURRMODEM +fi + +MATCH=0 + +do_custom() { + local config=$1 + local select name enabled select1 + local model + local imsi + local vid + local pid + + if [ $MATCH -eq 0 ]; then + config_get select $1 select + config_get name $1 name + config_get enabled $1 enabled + if [ -z "$enabled" ]; then + enabled=1 + fi + if [ -z "$name" ]; then + name="Not Named" + fi + if [ $enabled -eq 1 ]; then + case $select in + "0" ) + config_get vid $1 vid + config_get pid $1 pid + if [ $idV = $vid -a $idP = $pid ]; then + MATCH=1 + log "Modem ID Profile - "$name"" + fi + ;; + "1" ) + config_get imei $1 imei + case $IMEI in + "$imei"*) + MATCH=1 + log "SIM IMEI Profile - "$name"" + ;; + esac + ;; + "2" ) + config_get model $1 model + if [ "$MODEL" == "$model" ]; then + MATCH=1 + log "Modem Model Profile - "$name"" + fi + ;; + "3" ) + config_get imsi $1 imsi + case $IMSI in + "$imsi"*) + MATCH=1 + log "SIM IMSI Profile - "$name"" + ;; + esac + ;; + "4" ) + config_get iccid $1 iccid + case $ICCID in + "$iccid"*) + MATCH=1 + log "SIM ICCID Profile - "$name"" + ;; + esac + ;; + esac + if [ $MATCH = 1 ]; then + config_get select1 $1 select1 + if [ $select1 -ne 10 ]; then + MATCH=0 + case $select1 in + "0" ) + config_get vid1 $1 vid1 + config_get pid1 $1 pid1 + if [ $idV = $vid1 -a $idP = $pid1 ]; then + MATCH=1 + log "Modem ID Profile - "$name"" + fi + ;; + "1" ) + config_get imei1 $1 imei1 + case $IMEI in + "$imei"*) + MATCH=1 + log "SIM IMEI Profile - "$name"" + ;; + esac + ;; + "2" ) + config_get model1 $1 model1 + if [ "$MODEL" == "$model1" ]; then + MATCH=1 + log "Modem Model Profile - "$name"" + fi + ;; + "3" ) + config_get imsi1 $1 imsi1 + case $IMSI in + "$imsi1"*) + MATCH=1 + log "SIM IMSI Profile - "$name"" + ;; + esac + ;; + "4" ) + config_get iccid1 $1 iccid1 + case $ICCID in + "$iccid1"*) + MATCH=1 + log "SIM ICCID Profile - "$name"" + ;; + esac + ;; + esac + fi + if [ $MATCH = 1 ]; then + local apn user passw pincode auth ppp delay lock mcc mnc + local dns1 dns2 dns3 dns4 log lb at atc + config_get apn $1 apn + dapn=$(echo "$apn" | grep "|") + if [ -z $dapn ]; then + apn2="" + else + fapn=$apn"|" + fapn=$(echo $fapn" " | tr "|" ",") + apn=$(echo $fapn | cut -d, -f1) + apn2=$(echo $fapn | cut -d, -f2) + fi + uci set modem.modeminfo$CURRMODEM.apn=$apn + uci set modem.modeminfo$CURRMODEM.apn2=$apn2 + config_get mtu $1 mtu + uci set modem.modeminfo$CURRMODEM.mtu=$mtu + config_get context $1 context + uci set modem.modeminfo$CURRMODEM.context=$context + config_get user $1 user + uci set modem.modeminfo$CURRMODEM.user=$user + config_get passw $1 passw + uci set modem.modeminfo$CURRMODEM.passw=$passw + config_get pincode $1 pincode + uci set modem.modeminfo$CURRMODEM.pincode=$pincode + config_get auth $1 auth + uci set modem.modeminfo$CURRMODEM.auth=$auth + config_get ppp $1 ppp + uci set modem.modeminfo$CURRMODEM.ppp=$ppp + config_get inter $1 inter + uci set modem.modeminfo$CURRMODEM.inter=$inter + config_get delay $1 delay + uci set modem.modeminfo$CURRMODEM.delay=$delay + config_get lock $1 lock + uci set modem.modeminfo$CURRMODEM.lock=$lock + config_get mcc $1 mcc + uci set modem.modeminfo$CURRMODEM.mcc=$mcc + config_get mnc $1 mnc + uci set modem.modeminfo$CURRMODEM.mnc=$mnc + config_get dns1 $1 dns1 + uci set modem.modeminfo$CURRMODEM.dns1=$dns1 + config_get dns2 $1 dns2 + uci set modem.modeminfo$CURRMODEM.dns2=$dns2 + config_get dns3 $1 dns3 + uci set modem.modeminfo$CURRMODEM.dns3=$dns3 + config_get dns4 $1 dns4 + uci set modem.modeminfo$CURRMODEM.dns4=$dns4 + config_get log $1 log + uci set modem.modeminfo$CURRMODEM.log=$log + config_get lb $1 lb + uci set modem.modeminfo$CURRMODEM.lb=$lb + config_get at $1 at + uci set modem.modeminfo$CURRMODEM.at=$at + config_get atc $1 atc + uci set modem.modeminfo$CURRMODEM.atc=$atc + config_get tzone $1 tzone + uci set modem.modeminfo$CURRMODEM.tzone=$tzone + config_get nodhcp $1 nodhcp + uci set modem.modeminfo$CURRMODEM.nodhcp=$nodhcp + config_get pdptype $1 pdptype + if [ $pdptype = "0" ]; then + pdptype="" + fi + uci set modem.modeminfo$CURRMODEM.pdptype=$pdptype + config_get ttl $1 ttl + if [ -z "$ttl" ]; then + ttl="0" + fi + uci set modem.modeminfo$CURRMODEM.ttl="$ttl" + config_get hostless $1 hostless + if [ -z "$hostless" ]; then + hostless="0" + fi + uci set modem.modeminfo$CURRMODEM.hostless="$hostless" + config_get bwday $1 bwday + if [ -z $bwday ]; then + bwday="0" + fi + uci set modem.modeminfo$CURRMODEM.bwday=$bwday + config_get phone $1 phone + if [ -z $phone ]; then + phone="0" + fi + uci set modem.modeminfo$CURRMODEM.bwphone=$phone + config_get bwdelay $1 bwdelay + if [ -z $bwdelay ]; then + bwdelay="0" + fi + uci set modem.modeminfo$CURRMODEM.bwdelay=$bwdelay + + [ -n "$apn" ] || log "This profile has no APN configured !!!" + + config_get alive $1 alive + uci delete modem.pinginfo$CURRMODEM + uci set modem.pinginfo$CURRMODEM=pinfo$CURRMODEM + uci set modem.pinginfo$CURRMODEM.alive=$alive + if [ $alive -ne 0 ]; then + local reliability count pingtime pingwait packetsize down up + + handle_trackip() { + local value="$1" + uci add_list modem.pinginfo$CURRMODEM.trackip=$value + } + config_list_foreach "$config" trackip handle_trackip + TIP=$(uci get modem.pinginfo$CURRMODEM.trackip) + if [ -z "$TIP" ]; then + uci add_list modem.pinginfo$CURRMODEM.trackip="1.1.1.1" + fi + config_get reliability $1 reliability + uci set modem.pinginfo$CURRMODEM.reliability=$reliability + config_get count $1 count + uci set modem.pinginfo$CURRMODEM.count=$count + config_get pingtime $1 pingtime + uci set modem.pinginfo$CURRMODEM.pingtime=$pingtime + config_get pingwait $1 pingwait + uci set modem.pinginfo$CURRMODEM.pingwait=$pingwait + config_get packetsize $1 packetsize + uci set modem.pinginfo$CURRMODEM.packetsize=$packetsize + config_get down $1 down + uci set modem.pinginfo$CURRMODEM.down=$down + config_get up $1 up + uci set modem.pinginfo$CURRMODEM.up=$up + fi + + uci commit modem + fi + fi + fi + fi +} + +autoapn=$(uci -q get profile.disable.autoapn) +apd=0 +if [ -e /usr/lib/autoapn/apn.data ]; then + apd=1 +fi + +if [ $autoapn = "1" -a $apd -eq 1 ]; then + MATCH=0 +else + autod=$(uci -q get profile.disable.enabled) + if [ $autod = "1" ]; then + MATCH=0 + else + config_load profile + config_foreach do_custom custom + fi +fi + +if [ $MATCH = 0 ]; then + if [ $autod = "1" ]; then + if [ -e /etc/config/isp ]; then + MATCH=1 + fi + fi + if [ $MATCH = 1 ]; then + isp=$(uci -q get isp.general.current) + apn=$(uci -q get isp.$isp.apn) + apn2="" + else + apn=$(uci -q get profile.default.apn) + dapn=$(echo "$apn" | grep "|") + if [ -z $dapn ]; then + apn2="" + else + fapn=$apn"|" + fapn=$(echo $fapn" " | tr "|" ",") + apn=$(echo $fapn | cut -d, -f1) + apn2=$(echo $fapn | cut -d, -f2) + fi + fi + uci set modem.modeminfo$CURRMODEM.apn=$apn + uci set modem.modeminfo$CURRMODEM.apn2=$apn2 + if [ -n "$ICCID" ]; then + iccid="891490" + case $ICCID in + "$iccid"*) + uci set modem.modeminfo$CURRMODEM.apn2="" + uci set modem.modeminfo$CURRMODEM.apn="internet.freedommobile.ca" + ;; + esac + fi + + uci set modem.modeminfo$CURRMODEM.user=$(uci -q get profile.default.user) + uci set modem.modeminfo$CURRMODEM.passw=$(uci -q get profile.default.passw) + uci set modem.modeminfo$CURRMODEM.pincode=$(uci -q get profile.default.pincode) + uci set modem.modeminfo$CURRMODEM.context=$(uci -q get profile.default.context) + uci set modem.modeminfo$CURRMODEM.auth=$(uci get profile.default.auth) + uci set modem.modeminfo$CURRMODEM.ppp=$(uci get profile.default.ppp) + uci set modem.modeminfo$CURRMODEM.inter=0 + uci set modem.modeminfo$CURRMODEM.delay=$(uci get profile.default.delay) + uci set modem.modeminfo$CURRMODEM.lock=$(uci get profile.default.lock) + uci set modem.modeminfo$CURRMODEM.mcc=$(uci -q get profile.default.mcc) + uci set modem.modeminfo$CURRMODEM.mnc=$(uci -q get profile.default.mnc) + uci set modem.modeminfo$CURRMODEM.dns1=$(uci -q get profile.default.dns1) + uci set modem.modeminfo$CURRMODEM.dns2=$(uci -q get profile.default.dns2) + uci set modem.modeminfo$CURRMODEM.dns3=$(uci -q get profile.default.dns3) + uci set modem.modeminfo$CURRMODEM.dns4=$(uci -q get profile.default.dns4) + uci set modem.modeminfo$CURRMODEM.log=$(uci get profile.default.log) + uci set modem.modeminfo$CURRMODEM.lb=$(uci get profile.default.lb) + uci set modem.modeminfo$CURRMODEM.at=$(uci -q get profile.default.at) + uci set modem.modeminfo$CURRMODEM.atc=$(uci -q get profile.default.atc) + uci set modem.modeminfo$CURRMODEM.tzone=$(uci -q get profile.default.tzone) + uci set modem.modeminfo$CURRMODEM.mtu=$(uci -q get profile.default.mtu) + uci set modem.modeminfo$CURRMODEM.nodhcp=$(uci -q get profile.default.nodhcp) + pdp=$(uci -q get profile.default.pdptype) + if [ $pdp = "0" ]; then + pdp="" + fi + uci set modem.modeminfo$CURRMODEM.pdptype=$pdp + ttl=$(uci -q get profile.default.ttl) + if [ -z "$ttl" ]; then + ttl="0" + fi + uci set modem.modeminfo$CURRMODEM.ttl="$ttl" + hostless=$(uci -q get profile.default.hostless) + if [ -z "$hostless" ]; then + hostless="0" + fi + uci set modem.modeminfo$CURRMODEM.hostless="$hostless" + bwday=$(uci -q get profile.default.bwday) + if [ -z $bwday ]; then + bwday="0" + fi + uci set modem.modeminfo$CURRMODEM.bwday=$bwday + phone=$(uci -q get profile.default.phone) + if [ -z $phone ]; then + phone="0" + fi + uci set modem.modeminfo$CURRMODEM.bwphone=$phone + bwdelay=$(uci -q get profile.default.bwdelay) + if [ -z $bwdelay ]; then + bwdelay="0" + fi + uci set modem.modeminfo$CURRMODEM.bwdelay=$bwdelay + + alive=$(uci get profile.default.alive) + uci delete modem.pinginfo$CURRMODEM + uci set modem.pinginfo$CURRMODEM=pinfo$CURRMODEM + uci set modem.pinginfo$CURRMODEM.alive=$alive + if [ $alive -ne 0 ]; then + + handle_trackip1() { + local value="$1" + uci add_list modem.pinginfo$CURRMODEM.trackip=$value + } + config_list_foreach "default" trackip handle_trackip1 + TIP=$(uci get modem.pinginfo$CURRMODEM.trackip) + if [ -z "$TIP" ]; then + uci add_list modem.pinginfo$CURRMODEM.trackip="1.1.1.1" + fi + uci set modem.pinginfo$CURRMODEM.reliability=$(uci get profile.default.reliability) + uci set modem.pinginfo$CURRMODEM.count=$(uci get profile.default.count) + uci set modem.pinginfo$CURRMODEM.pingtime=$(uci get profile.default.pingtime) + uci set modem.pinginfo$CURRMODEM.pingwait=$(uci get profile.default.pingwait) + uci set modem.pinginfo$CURRMODEM.packetsize=$(uci get profile.default.packetsize) + uci set modem.pinginfo$CURRMODEM.down=$(uci get profile.default.down) + uci set modem.pinginfo$CURRMODEM.up=$(uci get profile.default.up) + fi + + uci commit modem + if [ "$autoapn" = "1" -a $apd -eq 1 ]; then + log "Automatic APN Used" + else + log "Default Profile Used" + [ -n "$(uci -q get profile.default.apn)" ] || log "Default profile has no APN configured" + fi +fi + +if [ ! -e /etc/config/isp ]; then + if [ "$autoapn" != "1" -a $apd -eq 1 ]; then + APN=$(uci -q get modem.modeminfo$CURRMODEM.apn) + log "APN of profile used is $APN" + fi +fi + +touch /tmp/profile$CURRMODEM diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/handlettl.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/handlettl.sh new file mode 100644 index 0000000..fe216c6 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/handlettl.sh @@ -0,0 +1,106 @@ +#!/bin/sh + +log() { + modlog "TTL Settings $CURRMODEM" "$@" +} + +delTTL() { + FLG="0" + exst=$(cat /etc/ttl.user | grep "#startTTL$CURRMODEM") + if [ ! -z "$exst" ]; then + cp /etc/ttl.user /etc/ttl.user.bk + sed -i -e "s!iptables -t mangle -I POSTROUTING -o $IFACE!iptables -t mangle -D POSTROUTING -o $IFACE!g" /etc/ttl.user.bk + sed -i -e "s!iptables -t mangle -I PREROUTING -i $IFACE!iptables -t mangle -D PREROUTING -i $IFACE!g" /etc/ttl.user.bk + sed -i -e "s!ip6tables -t mangle -I POSTROUTING -o $IFACE!iptables -t mangle -D POSTROUTING -o $IFACE!g" /etc/ttl.user.bk + sed -i -e "s!ip6tables -t mangle -I PREROUTING -i $IFACE!iptables -t mangle -D PREROUTING -i $IFACE!g" /etc/ttl.user.bk + + rm -f /tmp/ttl.user + run=0 + while IFS= read -r line; do + if [ $run = "0" ]; then + sttl=$line + stx=$(echo "$sttl" | grep "#startTTL$CURRMODEM") + if [ ! -z $stx ]; then + run=1 + fi + else + sttl=$line + stx=$(echo "$sttl" | grep "#endTTL$CURRMODEM") + if [ ! -z $stx ]; then + chmod 777 /tmp/ttl.user + /tmp/ttl.user + break + fi + echo "$sttl" >> /tmp/ttl.user + fi + done < /etc/ttl.user.bk + cp /etc/ttl.user /etc/ttl.user.bk + + sed /"#startTTL$CURRMODEM"/,/"#endTTL$CURRMODEM"/d /etc/ttl.user.bk > /etc/ttl.user + FLG="1" + fi +} + +CURRMODEM=$1 +TTL="$2" +if [ $CURRMODEM = "0" ]; then + IFACE="wan" +else + IFACE=$(uci -q get modem.modem$CURRMODEM.interface) +fi + +if [ "$TTL" = "0" ]; then + ENB=$(uci -q get ttl.ttl.enabled) + if [ $ENB = "1" ]; then + TTL=$(uci -q get ttl.ttl.value) + if [ -z "$TTL" ]; then + TTL=65 + fi + else + delTTL + log "Deleting TTL on interface $IFACE" + exit 0 + fi +fi + +if [ "$TTL" = "1" ]; then + delTTL + log "Deleting TTL on interface $IFACE" + exit 0 +fi + +delTTL +VALUE="$TTL" +echo "#startTTL$CURRMODEM" >> /etc/ttl.user +log "Setting TTL $VALUE on interface $IFACE" +if [ "$TTL" = "TTL-INC 1" ]; then + TTL="0" +fi + +if [ $VALUE = "0" ]; then + echo "iptables -t mangle -I POSTROUTING -o $IFACE -j TTL --ttl-inc 1" >> /etc/ttl.user + echo "iptables -t mangle -I PREROUTING -i $IFACE -j TTL --ttl-inc 1" >> /etc/ttl.user + iptables -t mangle -I POSTROUTING -o $IFACE -j TTL --ttl-inc 1 + iptables -t mangle -I PREROUTING -i $IFACE -j TTL --ttl-inc 1 + if [ -e /usr/sbin/ip6tables ]; then + echo "ip6tables -t mangle -I POSTROUTING -o $IFACE -j HL --hl-inc 1" >> /etc/ttl.user + echo "ip6tables -t mangle -I PREROUTING -i $IFACE -j HL --hl-inc 1" >> /etc/ttl.user + ip6tables -t mangle -I POSTROUTING -o $IFACE -j HL --hl-inc 1 + ip6tables -t mangle -I PREROUTING -i $IFACE -j HL --hl-inc 1 + fi +else + echo "iptables -t mangle -I POSTROUTING -o $IFACE -j TTL --ttl-set $VALUE" >> /etc/ttl.user + echo "iptables -t mangle -I PREROUTING -i $IFACE -j TTL --ttl-set $VALUE" >> /etc/ttl.user + iptables -t mangle -I POSTROUTING -o $IFACE -j TTL --ttl-set $VALUE + iptables -t mangle -I PREROUTING -i $IFACE -j TTL --ttl-set $VALUE + if [ -e /usr/sbin/ip6tables ]; then + echo "ip6tables -t mangle -I POSTROUTING -o $IFACE -j HL --hl-set $VALUE" >> /etc/ttl.user + echo "ip6tables -t mangle -I PREROUTING -i $IFACE -j HL --hl-set $VALUE" >> /etc/ttl.user + ip6tables -t mangle -I POSTROUTING -o $IFACE -j HL --hl-set $VALUE + ip6tables -t mangle -I PREROUTING -i $IFACE -j HL --hl-set $VALUE + fi +fi +echo "#endTTL$CURRMODEM" >> /etc/ttl.user + + + diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/postconnect.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/postconnect.sh new file mode 100644 index 0000000..12ec93e --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/postconnect.sh @@ -0,0 +1,19 @@ +#!/bin/sh + +ROOTER=/usr/lib/rooter +ROOTER_LINK="/tmp/links" + +log() { + modlog "PostConnect $CURRMODEM" "$@" +} + +CURRMODEM=$1 +idV=$(uci -q get modem.modem$CURRMODEM.idV) +idP=$(uci -q get modem.modem$CURRMODEM.idP) +CPORT=$(uci get modem.modem$CURRMODEM.commport) + +log "Running PostConnect script" + +if [ -e /usr/lib/scan/emailchk.sh ]; then + /usr/lib/scan/emailchk.sh & +fi \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/preconnect.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/preconnect.sh new file mode 100644 index 0000000..92bef6f --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/preconnect.sh @@ -0,0 +1,15 @@ +#!/bin/sh + +ROOTER=/usr/lib/rooter +ROOTER_LINK="/tmp/links" + +log() { + modlog "PreConnect $CURRMODEM" "$@" +} + +CURRMODEM=$1 +idV=$(uci -q get modem.modem$CURRMODEM.idV) +idP=$(uci -q get modem.modem$CURRMODEM.idP) +CPORT=$(uci get modem.modem$CURRMODEM.commport) + +log "Running PreConnect script" \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/reconnect-ppp.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/reconnect-ppp.sh new file mode 100644 index 0000000..26e6ccf --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/reconnect-ppp.sh @@ -0,0 +1,59 @@ +#!/bin/sh + +ROOTER=/usr/lib/rooter +ROOTER_LINK="/tmp/links" + +log() { + logger -t "Reconnect Modem" "$@" +} + +CURRMODEM=$1 +uci set modem.modem$CURRMODEM.connected=0 +uci commit modem + +INTER=$(uci get modem.modeminfo$CURRMODEM.inter) + +jkillall getsignal$CURRMODEM +rm -f $ROOTER_LINK/getsignal$CURRMODEM +jkillall con_monitor$CURRMODEM +rm -f $ROOTER_LINK/con_monitor$CURRMODEM +ifdown wan$INTER +MAN=$(uci get modem.modem$CURRMODEM.manuf) +MOD=$(uci get modem.modem$CURRMODEM.model) +$ROOTER/signal/status.sh $CURRMODEM "$MAN $MOD" "Reconnecting" +PROT=$(uci get modem.modem$CURRMODEM.proto) + +CPORT=$(uci get modem.modem$CURRMODEM.commport) + +SEVR=$(uci get modem.modem$CURRMODEM.service) + +if [ $SEVR = 0 ]; then + COUNTER=1 + while [ $COUNTER -lt 6 ]; do + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "reset.gcom" "$CURRMODEM") + ERROR="ERROR" + if `echo ${OX} | grep "${ERROR}" 1>/dev/null 2>&1` + then + log "Retry Reset" + sleep 3 + let COUNTER=COUNTER+1 + else + log "Modem Reset" + sleep 3 + $ROOTER/common/lockchk.sh $CURRMODEM + break + fi + done + if [ $COUNTER -lt 6 ]; then + ifup wan$INTER + else + log "Reset Failed for Modem $CURRMODEM" + $ROOTER/signal/status.sh $CURRMODEM "$MAN $MOD" "Failed to Reset" + fi +else + ifup wan$INTER +fi + + + + diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/reconnect.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/reconnect.sh new file mode 100644 index 0000000..98ba291 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/reconnect.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +ROOTER_LINK="/tmp/links" + +log() { + modlog "Reconnect Modem $CURRMODEM" "$@" +} + +CURRMODEM=$1 +log "Re-starting Connection for Modem $CURRMODEM" +$ROOTER_LINK/create_proto$CURRMODEM $CURRMODEM 1 + diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/customname.lua b/rooter/ext-rooter-basic/files/usr/lib/rooter/customname.lua new file mode 100644 index 0000000..464217d --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/customname.lua @@ -0,0 +1,17 @@ +#!/usr/bin/lua + +mfile = "/tmp/sysinfo/model" +nfile="/etc/custom" +local file = io.open(nfile, "r") +if file == nil then + return +end +linex = file:read("*line") +file:close() +file = io.open(mfile, "w") +if file == nil then + return +end + +file:write(linex,"\n") +file:close() \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/auto.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/auto.gcom new file mode 100644 index 0000000..73544d9 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/auto.gcom @@ -0,0 +1,31 @@ +opengt + set com 115200n81 + set comecho off + set senddelay 0.05 + waitquiet 1 0.2 + +:start +let $g=$env("TIMEOUT") +if $g = "" let f=25 +else let f = val($g) + +send "AT!SCPROF?1^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s +:continue +exit 0 + +:getresult +get 1 "^m" $s +let x=len($s) +if x=0 let $s="^mTIMEOUT ERROR" +else print $s +if $s="^jOK" return +if $mid($s,0,6)="^jERROR" return +if $mid($s,0,8)="^jCOMMAND" return +if $mid($s,0,11)="^j+CME ERROR" return +if time()>t return +goto getresult + print $s + return diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/baseinfo.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/baseinfo.gcom new file mode 100644 index 0000000..84149d6 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/baseinfo.gcom @@ -0,0 +1,33 @@ +opengt + set com 115200n81 + set comecho off + set senddelay 0.02 + waitquiet 1 0.2 + +let $g=$env("TIMEOUT") +if $g = "" let f=25 +else let f = val($g) + +send "ATI^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT+CGEQNEG=1^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + + exit 0 + +:getresult +get 1 "^m" $s +let x=len($s) +if x=0 let $s="^mTIMEOUT ERROR" +else print $s +if $s="^jOK" return +if $mid($s,0,6)="^jERROR" return +if $mid($s,0,8)="^jCOMMAND" return +if $mid($s,0,11)="^j+CME ERROR" return +if time()>t return +goto getresult diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/cellinfo.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/cellinfo.gcom new file mode 100644 index 0000000..6ced05d --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/cellinfo.gcom @@ -0,0 +1,50 @@ +opengt + set com 115200n81 + set comecho off + set senddelay 0.02 + waitquiet 0.2 0.2 + +let $g=$env("TIMEOUT") +if $g = "" let f=25 +else let f = val($g) + +send "AT+CREG=2;+CREG?;+CREG=0^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT+CEREG=2;+CEREG?;+CEREG=0^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT+C5GREG=2;+C5GREG?;+C5GREG=0^m" +let t=time()+f +gosub noerror +if $s="^mTIMEOUT ERROR" print $s + + exit 0 + +:getresult +get 1 "^m" $s +let x=len($s) +if x=0 let $s="^mTIMEOUT ERROR" +else print $s +if $s="^jOK" return +if $mid($s,0,6)="^jERROR" return +if $mid($s,0,8)="^jCOMMAND" return +if $mid($s,0,11)="^j+CME ERROR" return +if time()>t return +goto getresult + +:noerror +get 1 "^m" $s +if $mid($s,0,6)="^jERROR" return +let x=len($s) +if x=0 let $s="^mTIMEOUT ERROR" +else print $s +if $s="^jOK" return +if $mid($s,0,8)="^jCOMMAND" return +if $mid($s,0,11)="^j+CME ERROR" return +if time()>t return +goto noerror diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/cellinfo0.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/cellinfo0.gcom new file mode 100644 index 0000000..4a72dd0 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/cellinfo0.gcom @@ -0,0 +1,45 @@ +opengt + set com 115200n81 + set comecho off + set senddelay 0.02 + waitquiet 0.2 0.2 + +let $g=$env("TIMEOUT") +if $g = "" let f=25 +else let f = val($g) + +send "AT+COPS=3,0;+COPS?^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT+COPS=3,2;+COPS?^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + + exit 0 + +:getresult +get 1 "^m" $s +let x=len($s) +if x=0 let $s="^mTIMEOUT ERROR" +else print $s +if $s="^jOK" return +if $mid($s,0,6)="^jERROR" return +if $mid($s,0,8)="^jCOMMAND" return +if $mid($s,0,11)="^j+CME ERROR" return +if time()>t return +goto getresult + +:noerror +get 1 "^m" $s +if $mid($s,0,6)="^jERROR" return +let x=len($s) +if x=0 let $s="^mTIMEOUT ERROR" +else print $s +if $s="^jOK" return +if $mid($s,0,8)="^jCOMMAND" return +if $mid($s,0,11)="^j+CME ERROR" return +if time()>t return +goto noerror diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/cgpaddr.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/cgpaddr.gcom new file mode 100644 index 0000000..126aef6 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/cgpaddr.gcom @@ -0,0 +1,46 @@ +opengt + set com 115200n81 + set comecho off + set senddelay 0.05 + waitquiet 1 0.2 + +:start +let $g=$env("TIMEOUT") +if $g = "" let f=25 +else let f = val($g) + +send "AT+CGPADDR=1^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT\^SYSINFOEX^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT\^SYSINFO^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT\^NDISSTATQRY?^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + + +:continue + exit 0 + +:getresult +get 1 "^m" $s +let x=len($s) +if x=0 let $s="^mTIMEOUT ERROR" +else print $s +if $s="^jOK" return +if $mid($s,0,6)="^jERROR" return +if $mid($s,0,8)="^jCOMMAND" return +if $mid($s,0,11)="^j+CME ERROR" return +if time()>t return +goto getresult diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/connect-directip.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/connect-directip.gcom new file mode 100644 index 0000000..00bc9e4 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/connect-directip.gcom @@ -0,0 +1,64 @@ +opengt + set com 115200n81 + set comecho off + set senddelay 0.05 + waitquiet 1 0.2 + +:start +let $g=$env("TIMEOUT") +if $g = "" let f=25 +else let f = val($g) + +send "AT!SCACT=0,1^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT!SCDFTPROF=1^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +let $x=$env("SETAPN") +let $y=$env("SETUSER") +let $z=$env("SETPASS") +let $a=$env("SETAUTH") +send "AT+CGDCONT=1,\"IP\",\"" +send $x +send "\"^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT$QCPDPP=1," +send $a +if $a="0" send "^m" +else send ",\"" send $z send "\",\"" send $y send "\"^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT!SCACT=1,1^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT!SCACT?^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +:continue + exit 0 + +:getresult +get 1 "^m" $s +let x=len($s) +if x=0 let $s="^mTIMEOUT ERROR" +else print $s +if $s="^jOK" return +if $mid($s,0,6)="^jERROR" return +if $mid($s,0,8)="^jCOMMAND" return +if $mid($s,0,11)="^j+CME ERROR" return +if time()>t return +goto getresult diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/connect-fecm.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/connect-fecm.gcom new file mode 100644 index 0000000..653f601 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/connect-fecm.gcom @@ -0,0 +1,45 @@ +opengt + set com 115200n81 + set comecho off + set senddelay 0.05 + waitquiet 1 0.2 + +:start +let $g=$env("TIMEOUT") +if $g = "" let f=25 +else let f = val($g) + +send "AT+GTRNDIS=0,1" +send "^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +let $x=$env("SETAPN") +send "AT+CGDCONT=1,\"IP\",\"" +send $x +send "\"^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT+GTRNDIS=1,1" +send "^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +:continue + exit 0 + +:getresult +get 1 "^m" $s +let x=len($s) +if x=0 let $s="^mTIMEOUT ERROR" +else print $s +if $s="^jOK" return +if $mid($s,0,6)="^jERROR" return +if $mid($s,0,8)="^jCOMMAND" return +if $mid($s,0,11)="^j+CME ERROR" return +if time()>t return +goto getresult diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/connect-ncm.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/connect-ncm.gcom new file mode 100644 index 0000000..1fd4893 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/connect-ncm.gcom @@ -0,0 +1,48 @@ +opengt + set com 115200n81 + set comecho off + set senddelay 0.05 + waitquiet 1 0.2 + +:start +let $g=$env("TIMEOUT") +if $g = "" let f=25 +else let f = val($g) + +send "AT^^NDISDUP=1,0^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +let $x=$env("SETAPN") +let $y=$env("SETUSER") +let $z=$env("SETPASS") +let $a=$env("SETAUTH") +send "AT^^NDISDUP=1,1,\"" +send $x +if $a="0" send "\"^m" +else send "\",\"" send $y send "\",\"" send $z send "\"," send $a send "^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT\^NDISSTATQRY?^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +:continue + exit 0 + +:getresult +get 1 "^m" $s +let x=len($s) +if x=0 let $s="^mTIMEOUT ERROR" +else print $s +if $s="^jOK" return +if $mid($s,0,6)="^jERROR" return +if $mid($s,0,8)="^jCOMMAND" return +if $mid($s,0,11)="^j+CME ERROR" return +if time()>t return +goto getresult + diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/connect-ppp.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/connect-ppp.gcom new file mode 100644 index 0000000..fadf2d8 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/connect-ppp.gcom @@ -0,0 +1,36 @@ +opengt + set com 115200n81 + set comecho off + set senddelay 0.05 + waitquiet 1 0.2 + +:start +let $g=$env("TIMEOUT") +if $g = "" let f=25 +else let f = val($g) + +let $y=$env("SETUSER") +let $z=$env("SETPASS") +let $a=$env("SETAUTH") +send "AT$QCPDPP=1," +send $a +if $a="0" send "^m" +else send ",\"" send $z send "\",\"" send $y send "\"^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +:continue + exit 0 + +:getresult +get 1 "^m" $s +let x=len($s) +if x=0 let $s="^mTIMEOUT ERROR" +else print $s +if $s="^jOK" return +if $mid($s,0,6)="^jERROR" return +if $mid($s,0,8)="^jCOMMAND" return +if $mid($s,0,11)="^j+CME ERROR" return +if time()>t return +goto getresult diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/connect-zecm.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/connect-zecm.gcom new file mode 100644 index 0000000..fd14d94 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/connect-zecm.gcom @@ -0,0 +1,45 @@ +opengt + set com 115200n81 + set comecho off + set senddelay 0.05 + waitquiet 1 0.2 + +:start +let $g=$env("TIMEOUT") +if $g = "" let f=25 +else let f = val($g) + +send "AT+ZECMCALL=0" +send "^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +let $x=$env("SETAPN") +send "AT+CGDCONT=1,\"IP\",\"" +send $x +send "\"^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT+ZECMCALL=1" +send "^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +:continue + exit 0 + +:getresult +get 1 "^m" $s +let x=len($s) +if x=0 let $s="^mTIMEOUT ERROR" +else print $s +if $s="^jOK" return +if $mid($s,0,6)="^jERROR" return +if $mid($s,0,8)="^jCOMMAND" return +if $mid($s,0,11)="^j+CME ERROR" return +if time()>t return +goto getresult diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/curc.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/curc.gcom new file mode 100644 index 0000000..59f79da --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/curc.gcom @@ -0,0 +1,31 @@ +opengt + set com 115200n81 + set comecho off + set senddelay 0.05 + waitquiet 1 0.2 + +:start +let $g=$env("TIMEOUT") +if $g = "" let f=25 +else let f = val($g) + +send "AT\^CURC=0^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +:continue + exit 0 + +:getresult +get 1 "^m" $s +let x=len($s) +if x=0 let $s="^mTIMEOUT ERROR" +else print $s +if $s="^jOK" return +if $mid($s,0,6)="^jERROR" return +if $mid($s,0,8)="^jCOMMAND" return +if $mid($s,0,11)="^j+CME ERROR" return +if time()>t return +goto getresult + diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/fibocominfo.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/fibocominfo.gcom new file mode 100644 index 0000000..72126b5 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/fibocominfo.gcom @@ -0,0 +1,65 @@ +opengt +set com 115200n81 +set comecho off +set senddelay 0.02 +waitquiet 0.2 0.2 + +let $g=$env("TIMEOUT") +if $g = "" let f=25 +else let f = val($g) + +send "AT+CSQ^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT+GTCCINFO?^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s +if $s="^jERROR" goto gtrat + +send "AT+COPN^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +:gtrat +send "AT+GTRAT?^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT+GTCAINFO?^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT+XACT?^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT+XMCI=1;+XLEC?^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT+MTSM=1^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +exit 0 + +:getresult +get 1 "^m" $s +let x=len($s) +if x=0 let $s="^mTIMEOUT ERROR" +else print $s +if $s="^jOK" return +if $mid($s,0,6)="^jERROR" return +if $mid($s,0,8)="^jCOMMAND" return +if $mid($s,0,11)="^j+CME ERROR" return +if time()>t return +goto getresult diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/gcom-locked b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/gcom-locked new file mode 100644 index 0000000..ff816e2 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/gcom-locked @@ -0,0 +1,41 @@ +#!/bin/sh + +log() { + logger -t "gcom-locked " "$@" +} + +ROOTER_GCOM="/usr/lib/rooter/gcom/" + + +PORT=$1 +GCOM=$2 +CURRMODEM=$3 +ATC=$4 + +LOCKDIR="/tmp/lockgcom$CURRMODEM" +PIDFILE="${LOCKDIR}/PID" + +while [ 1 -lt 6 ]; do + if mkdir "${LOCKDIR}" &>/dev/null; then + echo "$$" > "${PIDFILE}" + if [ ! -z "$ATC" ]; then + export ATCMD="$ATC" + fi + OX=$(gcom -d $PORT -s $ROOTER_GCOM$GCOM 2>/dev/null) + if [ ! -e /tmp/block ]; then + /usr/lib/rooter/log/at-logger "$PORT $OX" + fi + break + else + OTHERPID="$(cat "${PIDFILE}" 2>/dev/null)" + if [ $? = 0 ]; then + if ! kill -0 $OTHERPID &>/dev/null; then + rm -rf "${LOCKDIR}" + fi + fi + sleep 1 + fi +done + +rm -rf "${LOCKDIR}" +echo "$OX" \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/gettype.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/gettype.gcom new file mode 100644 index 0000000..77d733b --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/gettype.gcom @@ -0,0 +1,43 @@ +opengt + set com 115200n81 + set comecho off + set senddelay 0.02 + waitquiet 0.2 0.2 + +let $g=$env("TIMEOUT") +if $g = "" let f=25 +else let f = val($g) + +send "AT+CFUN=1^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "ATI^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT+CNUM^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT+CPBR=?^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + + exit 0 + +:getresult +get 1 "^m" $s +let x=len($s) +if x=0 let $s="^mTIMEOUT ERROR" +else print $s +if $s="^jOK" return +if $mid($s,0,6)="^jERROR" return +if $mid($s,0,8)="^jCOMMAND" return +if $mid($s,0,11)="^j+CME ERROR" return +if time()>t return +goto getresult diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/huaweiinfo.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/huaweiinfo.gcom new file mode 100644 index 0000000..cd9a091 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/huaweiinfo.gcom @@ -0,0 +1,74 @@ +opengt + set com 115200n81 + set comecho off + set senddelay 0.02 + waitquiet 0.2 0.2 + +let $g=$env("TIMEOUT") +if $g = "" let f=25 +else let f = val($g) + +send "AT+CSQ^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT\^CSNR?^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT\^HCSQ?^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT\^SYSINFOEX^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT\^SYSCFGEX?^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT\^SYSCFG?^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT\^SYSINFO^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT\^HFREQINFO?^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT\^LTERSRP?^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT\^CHIPTEMP?^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + + exit 0 + +:getresult +get 1 "^m" $s +let x=len($s) +if x=0 let $s="^mTIMEOUT ERROR" +else print $s +if $s="^jOK" return +if $mid($s,0,6)="^jERROR" return +if $mid($s,0,8)="^jCOMMAND" return +if $mid($s,0,11)="^j+CME ERROR" return +if time()>t return +goto getresult + diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/lock-prov.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/lock-prov.gcom new file mode 100644 index 0000000..332890a --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/lock-prov.gcom @@ -0,0 +1,38 @@ +opengt + set com 115200n81 + set comecho off + set senddelay 0.05 + waitquiet 1 0.2 + +:start +let $g=$env("TIMEOUT") +if $g = "" let f=25 +else let f = val($g) + +send "AT+COPS=0^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +let $x=$env("MCCMNC") +send "AT+COPS=1,2,\"" +send $x +send "\",2^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +:continue + exit 0 + +:getresult +get 1 "^m" $s +let x=len($s) +if x=0 let $s="^mTIMEOUT ERROR" +else print $s +if $s="^jOK" return +if $mid($s,0,6)="^jERROR" return +if $mid($s,0,8)="^jCOMMAND" return +if $mid($s,0,11)="^j+CME ERROR" return +if time()>t return +goto getresult diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/mdm9215info.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/mdm9215info.gcom new file mode 100644 index 0000000..a647dac --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/mdm9215info.gcom @@ -0,0 +1,43 @@ +opengt + set com 115200n81 + set comecho off + set senddelay 0.02 + waitquiet 0.2 0.2 + +let $g=$env("TIMEOUT") +if $g = "" let f=25 +else let f = val($g) + +send "AT+CSQ^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT+COPS?^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT$QCSQ^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT$QCSYSMODE?^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + + exit 0 + +:getresult +get 1 "^m" $s +let x=len($s) +if x=0 let $s="^mTIMEOUT ERROR" +else print $s +if $s="^jOK" return +if $mid($s,0,6)="^jERROR" return +if $mid($s,0,8)="^jCOMMAND" return +if $mid($s,0,11)="^j+CME ERROR" return +if time()>t return +goto getresult diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/meiginfo.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/meiginfo.gcom new file mode 100644 index 0000000..556874f --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/meiginfo.gcom @@ -0,0 +1,69 @@ +opengt + set com 115200n81 + set comecho off + set senddelay 0.02 + waitquiet 0.2 0.2 + +let $g=$env("TIMEOUT") +if $g = "" let f=25 +else let f = val($g) + +send "AT+CSQ^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT+PSRAT^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +if $s="^jERROR" goto newmodel + +send "AT+MODODR?^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT+CELLINFO^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT+SGCELLINFO^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +exit 0 + +:newmodel + +send "AT\^SYSCFGEX?^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT+SGCELLINFOEX^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT+CELLINFO=3^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +exit 0 + +:getresult +get 1 "^m" $s +let x=len($s) +if x=0 let $s="^mTIMEOUT ERROR" +else print $s +if $s="^jOK" return +if $mid($s,0,6)="^jERROR" return +if $mid($s,0,8)="^jCOMMAND" return +if $mid($s,0,11)="^j+CME ERROR" return +if time()>t return +goto getresult diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/novatelinfo.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/novatelinfo.gcom new file mode 100644 index 0000000..e1a58e8 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/novatelinfo.gcom @@ -0,0 +1,48 @@ +opengt + set com 115200n81 + set comecho off + set senddelay 0.02 + waitquiet 0.2 0.2 + +let $g=$env("TIMEOUT") +if $g = "" let f=25 +else let f = val($g) + +send "AT+CSQ^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT$NWRAT?^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT$NWDEGC^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT+VZWRSRP?^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT+VZWRSRQ?^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + + exit 0 + +:getresult +get 1 "^m" $s +let x=len($s) +if x=0 let $s="^mTIMEOUT ERROR" +else print $s +if $s="^jOK" return +if $mid($s,0,6)="^jERROR" return +if $mid($s,0,8)="^jCOMMAND" return +if $mid($s,0,11)="^j+CME ERROR" return +if time()>t return +goto getresult diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/otherinfo.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/otherinfo.gcom new file mode 100644 index 0000000..6f851cd --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/otherinfo.gcom @@ -0,0 +1,28 @@ +opengt + set com 115200n81 + set comecho off + set senddelay 0.02 + waitquiet 0.2 0.2 + +let $g=$env("TIMEOUT") +if $g = "" let f=25 +else let f = val($g) + +send "AT+CSQ^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + + exit 0 + +:getresult +get 1 "^m" $s +let x=len($s) +if x=0 let $s="^mTIMEOUT ERROR" +else print $s +if $s="^jOK" return +if $mid($s,0,6)="^jERROR" return +if $mid($s,0,8)="^jCOMMAND" return +if $mid($s,0,11)="^j+CME ERROR" return +if time()>t return +goto getresult diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/quantainfo.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/quantainfo.gcom new file mode 100644 index 0000000..2ae0303 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/quantainfo.gcom @@ -0,0 +1,38 @@ +opengt + set com 115200n81 + set comecho off + set senddelay 0.02 + waitquiet 0.2 0.2 + +let $g=$env("TIMEOUT") +if $g = "" let f=25 +else let f = val($g) + +send "AT+CSQ^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT*QRFINFO?^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT\^QCNCFG?^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + + exit 0 + +:getresult +get 1 "^m" $s +let x=len($s) +if x=0 let $s="^mTIMEOUT ERROR" +else print $s +if $s="^jOK" return +if $mid($s,0,6)="^jERROR" return +if $mid($s,0,8)="^jCOMMAND" return +if $mid($s,0,11)="^j+CME ERROR" return +if time()>t return +goto getresult diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/quectelinfo.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/quectelinfo.gcom new file mode 100644 index 0000000..286acb9 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/quectelinfo.gcom @@ -0,0 +1,76 @@ +opengt +set com 115200n81 +set comecho off +set senddelay 0.02 +waitquiet 0.2 0.2 + +let $g=$env("TIMEOUT") +if $g = "" let f=25 +else let f = val($g) + +send "AT+CSQ^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT+QENG=\"servingcell\"^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT+QRSRP^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT+QCAINFO^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT+QCFG=\"nwscanmode\"^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s +if $s="^jERROR" goto qnwpref +goto temp + +:qnwpref +send "AT+QNWPREFCFG=\"mode_pref\"^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +:temp +send "AT+QTEMP^m" +let t=time()+1 +gosub gettemp + +send "AT+QENG=\"neighbourcell\"^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +exit 0 + +:getresult +get 1 "^m" $s +let x=len($s) +if x=0 let $s="^mTIMEOUT ERROR" +else print $s +if $s="^jOK" return +if $mid($s,0,6)="^jERROR" return +if $mid($s,0,8)="^jCOMMAND" return +if $mid($s,0,11)="^j+CME ERROR" return +if time()>t return +goto getresult + +:gettemp +get 1 "^m" $s +let x=len($s) +if x>0 print $s +if $mid($s,0,6)="^jERROR" return +if $mid($s,0,8)="^jCOMMAND" return +if $mid($s,0,11)="^j+CME ERROR" return +if time()>t return +goto gettemp diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/raw-ip.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/raw-ip.gcom new file mode 100644 index 0000000..cbdbf3e --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/raw-ip.gcom @@ -0,0 +1,31 @@ +opengt + set com 115200n81 + set comecho off + set senddelay 0.05 + waitquiet 1 0.2 + +:start +let $g=$env("TIMEOUT") +if $g = "" let f=25 +else let f = val($g) + +let $x=$env("ATCMD") +send $x +send "^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +:continue + exit 0 + +:getresult +get 1 "^m" $s +let x=len($s) +if x=0 let $s="^mTIMEOUT ERROR" +else print $s +if $s="^jCONNECT" return +if $mid($s,0,6)="^jERROR" return +if $mid($s,0,11)="^j+CME ERROR" return +if time()>t return +goto getresult diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/reset.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/reset.gcom new file mode 100644 index 0000000..09e46f5 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/reset.gcom @@ -0,0 +1,25 @@ +opengt + set com 115200n81 + set comecho off + set senddelay 0.05 + waitquiet 1 0.2 + +//send "ate0^m" +//waitquiet 1 0.2 +send "AT+COPS=2;+CFUN=4^m" +waitfor 5 "OK" +sleep 5 +send "AT+CFUN?^m" +waitfor 5 "+CME ERROR:","+CFUN:" +if % = 0 goto cme_err +get 2 " " $s +if $left($s,1) = "1" goto end +sleep 5 +send "AT+CFUN=1^m" +waitquiet 1 0.2 +exit 0 + +:cme_err +print "+CME ERROR" +:end +exit 0 diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/run-at.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/run-at.gcom new file mode 100644 index 0000000..b40dd6e --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/run-at.gcom @@ -0,0 +1,31 @@ +opengt + set com 115200n81 + set comecho off + set senddelay 0.05 + waitquiet 1 0.2 + +:start +let $g=$env("TIMEOUT") +if $g="" let f=25 +else let f=val($g) + +let $x=$env("ATCMD") +send $x +send "^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s +:continue +exit 0 + +:getresult +get 1 "^m" $s +let x=len($s) +if x=0 let $s="^mTIMEOUT ERROR" +else print $s +if $s="^jOK" return +if $mid($s,0,6)="^jERROR" return +if $mid($s,0,8)="^jCOMMAND" return +if $mid($s,0,11)="^j+CME ERROR" return +if time()>t return +goto getresult diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/sendsms-at.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/sendsms-at.gcom new file mode 100644 index 0000000..7203af5 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/sendsms-at.gcom @@ -0,0 +1,45 @@ +opengt + set com 115200n81 + set comecho off + set senddelay 0.05 + waitquiet 1 0.2 + +:start + +let $x=$env("ATCMD") +let $j=$left($x,1) +if $j = "0" let $j=$mid($x,1,2) +else let $j=$left($x,3) +let $r=$mid($x,4,4) +let k=len($x)-9 +let $p=$right($x,k) +send "AT+CMGF=0^m" +waitfor 2 "OK" +send "AT+CMGS=" +send $j +send "^m" +waitfor 3 ">" +send $p +send "^z" +waitfor 20 "+CMGS:" + +if % = 0 gosub sentsub +else gosub failsub + +get 1 "" $s + +:continue + exit 0 + +:sentsub +get 2 "^m^j" $s +let $c=$s +print "SMS sent, reference: "+$c +let $c='echo "SMS sent, reference: "'+$c+' > /tmp/smssendstatus'+$r +system $c +return + +:failsub +system 'echo "SMS sending failed" > /tmp/smssendstatus'+$r +print "SMS sending failed" +return diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/setapn.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/setapn.gcom new file mode 100644 index 0000000..9b29c50 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/setapn.gcom @@ -0,0 +1,45 @@ +opengt + set com 115200n81 + set comecho off + set senddelay 0.05 + waitquiet 1 0.2 + +:start +let $g=$env("TIMEOUT") +if $g = "" let f=25 +else let f = val($g) + +let $x=$env("SETAPN") +let $y=$env("SETUSER") +let $z=$env("SETPASS") +let $a=$env("SETAUTH") +send "AT+CGDCONT=1,\"IP\",\"" +send $x +send "\"^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT$QCPDPP=1," +send $a +if $a="0" send "^m" +else send ",\"" send $z send "\",\"" send $y send "\"^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +:continue + exit 0 + +:getresult +get 1 "^m" $s +let x=len($s) +if x=0 let $s="^mTIMEOUT ERROR" +else print $s +if $s="^jOK" return +if $mid($s,0,6)="^jERROR" return +if $mid($s,0,8)="^jCOMMAND" return +if $mid($s,0,11)="^j+CME ERROR" return +if time()>t return +goto getresult + diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/setpin.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/setpin.gcom new file mode 100644 index 0000000..9084557 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/setpin.gcom @@ -0,0 +1,53 @@ +# set pin code from evnironment "$PINCODE" +opengt + set com 115200n81 + set senddelay 0.05 + waitquiet 3 0.5 + flash 0.1 + + let c=0 +:start + send "AT+CPIN?^m" + waitfor 15 "SIM PUK","SIM PIN","READY","ERROR","ERR" + if % = -1 goto timeout + if % = 0 goto ready + if % = 1 goto setpin + if % = 2 goto ready + if % = 3 goto checkrepeat + if % = 4 goto checkrepeat + +:checkrepeat + inc c + if c>3 goto pinerror + waitquiet 12 0.5 + goto start + +:timeout + print "ERROR" + exit 1 + +:ready + goto continue + exit 0 + +:setpin + # check if output was "SIM PIN2", that's ok. + waitfor 1 "2" + if % = 0 goto ready + + send "AT+CPIN=\"" + send $env("PINCODE") + send "\"^m" + + waitfor 20 "OK","ERR" + if % = -1 goto pinerror + if % = 0 goto continue + if % = 1 goto pinerror + +:pinerror + print "ERROR" + exit 1 + +:continue + print "OK" + exit 0 diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/sierrainfo.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/sierrainfo.gcom new file mode 100644 index 0000000..e24780c --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/sierrainfo.gcom @@ -0,0 +1,68 @@ +opengt + set com 115200n81 + set comecho off + set senddelay 0.02 + waitquiet 0.2 0.2 + +let $g=$env("TIMEOUT") +if $g = "" let f=25 +else let f = val($g) + +send "AT+CSQ;+CESQ^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT*CNTI=0^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT!SELRAT?^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT+ECIO?^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT+RSCP?^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT!UMTSCHAN?^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT!LTEINFO?^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT!GSTATUS?^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT!PCTEMP?^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + + exit 0 + +:getresult +get 1 "^m" $s +let x=len($s) +if x=0 let $s="^mTIMEOUT ERROR" +else print $s +if $s="^jOK" return +if $mid($s,0,6)="^jERROR" return +if $mid($s,0,8)="^jCOMMAND" return +if $mid($s,0,11)="^j+CME ERROR" return +if time()>t return +goto getresult diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/simcominfo.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/simcominfo.gcom new file mode 100644 index 0000000..50e45c9 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/simcominfo.gcom @@ -0,0 +1,48 @@ +opengt +set com 115200n81 +set comecho off +set senddelay 0.02 +waitquiet 0.2 0.2 + +let $g=$env("TIMEOUT") +if $g = "" let f=25 +else let f = val($g) + +send "AT+CSQ^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT+CPSI?^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT+CNMP?^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT+CMGRMI=4^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT+CPMUTEMP^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +exit 0 + +:getresult +get 1 "^m" $s +let x=len($s) +if x=0 let $s="^mTIMEOUT ERROR" +else print $s +if $s="^jOK" return +if $mid($s,0,6)="^jERROR" return +if $mid($s,0,8)="^jCOMMAND" return +if $mid($s,0,11)="^j+CME ERROR" return +if time()>t return +goto getresult diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/smschk.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/smschk.gcom new file mode 100644 index 0000000..f5d9e82 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/smschk.gcom @@ -0,0 +1,36 @@ +opengt + set com 115200n81 + set comecho off + set senddelay 0.05 + waitquiet 1 0.2 + +:start +let $g=$env("TIMEOUT") +if $g = "" let f=25 +else let f = val($g) + +send "AT+CMGS=?;+CMGL=?;+CMGR=?^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send 'AT+CPMS="SM","SM","SM"^m' +waitfor 5 "OK" + +send 'AT+CGSMS=2^m' +waitfor 5 "OK" + +:continue + exit 0 + +:getresult +get 1 "^m" $s +let x=len($s) +if x=0 let $s="^mTIMEOUT ERROR" +else print $s +if $s="^jOK" return +if $mid($s,0,6)="^jERROR" return +if $mid($s,0,8)="^jCOMMAND" return +if $mid($s,0,11)="^j+CME ERROR" return +if time()>t return +goto getresult diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/smswrite.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/smswrite.gcom new file mode 100644 index 0000000..a65bb3c --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/smswrite.gcom @@ -0,0 +1,39 @@ +opengt + set com 115200n81 + set comecho off + set senddelay 0.05 + waitquiet 1 0.2 + +:start + +let $x=$env("ATCMD") +let $j=$left($x,1) +if $j = "0" let $j=$mid($x,1,2) +else let $j=$left($x,3) +let $d=$mid($x,4,2) +let $t=$mid($x,7,1) +let k=len($x)-9 +let $p=$right($x,k) +send "AT+CMGF=0^m" +waitfor 2 "OK" +send 'AT+CPMS="SM"' +send ',"' +send $d +send '"^m' +waitfor 2 "OK" +send "AT+CMGW=" +send $j +send "," +send $t +send "^m" +waitfor 3 ">" +send $p +send "^z" +waitfor 25 "+CMGW:" +if % = 0 print "+CMGW:" +else print "AT+CMGW - TIMEOUT" +get 1 "" $s +print $s + +:continue + exit 0 diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/t77info.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/t77info.gcom new file mode 100644 index 0000000..f47d378 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/t77info.gcom @@ -0,0 +1,70 @@ +opengt + set com 115200n81 + set comecho off + set senddelay 0.02 + waitquiet 0.2 0.2 + +let $g=$env("TIMEOUT") +if $g = "" let f=25 +else let f = val($g) + +send "AT+CSQ^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT+COPS?^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT\^CA_INFO?^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT\^DEBUG?^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT$DEBUG?^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT\^SYSCONFIG?^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT$QCSQ^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT+TEMP?^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +if $s!="^jERROR" exit 0 + +send "AT\^TEMP?^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + + exit 0 + +:getresult +get 1 "^m" $s +let x=len($s) +if x=0 let $s="^mTIMEOUT ERROR" +else print $s +if $s="^jOK" return +if $mid($s,0,6)="^jERROR" return +if $mid($s,0,8)="^jCOMMAND" return +if $mid($s,0,11)="^j+CME ERROR" return +if time()>t return +goto getresult diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/telitinfo.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/telitinfo.gcom new file mode 100644 index 0000000..5eaff94 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/telitinfo.gcom @@ -0,0 +1,48 @@ +opengt + set com 115200n81 + set comecho off + set senddelay 0.02 + waitquiet 0.2 0.2 + +let $g=$env("TIMEOUT") +if $g = "" let f=25 +else let f = val($g) + +send "AT+CSQ^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT#TEMPSENS=2^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT+COPS?^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT#RFSTS^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT#CAINFO?^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + + exit 0 + +:getresult +get 1 "^m" $s +let x=len($s) +if x=0 let $s="^mTIMEOUT ERROR" +else print $s +if $s="^jOK" return +if $mid($s,0,6)="^jERROR" return +if $mid($s,0,8)="^jCOMMAND" return +if $mid($s,0,11)="^j+CME ERROR" return +if time()>t return +goto getresult diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/telitinfoln.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/telitinfoln.gcom new file mode 100644 index 0000000..eb9bcbd --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/telitinfoln.gcom @@ -0,0 +1,43 @@ +opengt + set com 115200n81 + set comecho off + set senddelay 0.02 + waitquiet 0.2 0.2 + +let $g=$env("TIMEOUT") +if $g = "" let f=25 +else let f = val($g) + +send "AT+CSQ^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT+COPS?^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT^RFSTS?^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT#CAINFO?^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + + exit 0 + +:getresult +get 1 "^m" $s +let x=len($s) +if x=0 let $s="^mTIMEOUT ERROR" +else print $s +if $s="^jOK" return +if $mid($s,0,6)="^jERROR" return +if $mid($s,0,8)="^jCOMMAND" return +if $mid($s,0,11)="^j+CME ERROR" return +if time()>t return +goto getresult diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/ubloxinfo.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/ubloxinfo.gcom new file mode 100644 index 0000000..9ebe9dc --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/ubloxinfo.gcom @@ -0,0 +1,43 @@ +opengt + set com 115200n81 + set comecho off + set senddelay 0.02 + waitquiet 0.2 0.2 + +let $g=$env("TIMEOUT") +if $g = "" let f=25 +else let f = val($g) + +send "AT+CSQ^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT+CESQ^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT+URAT?^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT+UCGED?^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + + exit 0 + +:getresult +get 1 "^m" $s +let x=len($s) +if x=0 let $s="^mTIMEOUT ERROR" +else print $s +if $s="^jOK" return +if $mid($s,0,6)="^jERROR" return +if $mid($s,0,8)="^jCOMMAND" return +if $mid($s,0,11)="^j+CME ERROR" return +if time()>t return +goto getresult diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/ussd.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/ussd.gcom new file mode 100644 index 0000000..254da89 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/ussd.gcom @@ -0,0 +1,29 @@ +opengt + set com 115200n81 + set comecho off + set senddelay 0.05 + waitquiet 1 0.2 +:start +let f=20 +let $x=$env("ATCMD") +send $x+"^m" +waitfor 2 "OK" +let t=time()+f +let $s="" +gosub getresult +let x=len($s) +if x<2 let $s="^mUSSD TIMEOUT ERROR" +print $s +:continue +exit 0 +:getresult +get 1 "^m" $u +let x=len($u) +let $v=$s +if x>0 let $s=$v+$u +if $right(" "+$s,4) = '",15' return +if $right(" "+$s,4) = '",72' return +if $right(" "+$s,4) = '",68' return +if $mid($s,0,30)="^j+CME ERROR:" return +if time()>t return +goto getresult diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/zteinfo.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/zteinfo.gcom new file mode 100644 index 0000000..013447c --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/zteinfo.gcom @@ -0,0 +1,58 @@ +opengt + set com 115200n81 + set comecho off + set senddelay 0.02 + waitquiet 0.2 0.2 + +let $g=$env("TIMEOUT") +if $g = "" let f=25 +else let f = val($g) + +send "AT+CSQ^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT+ZPAS?^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT+ZRSSI^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT+ZRSSI?^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT+ZSINR^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT+ZSNT?^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + +send "AT+ZCELLINFO?^m" +let t=time()+f +gosub getresult +if $s="^mTIMEOUT ERROR" print $s + + exit 0 + +:getresult +get 1 "^m" $s +let x=len($s) +if x=0 let $s="^mTIMEOUT ERROR" +else print $s +if $s="^jOK" return +if $mid($s,0,6)="^jERROR" return +if $mid($s,0,8)="^jCOMMAND" return +if $mid($s,0,11)="^j+CME ERROR" return +if time()>t return +goto getresult diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gpio-set.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/gpio-set.sh new file mode 100644 index 0000000..9ec628e --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/gpio-set.sh @@ -0,0 +1,23 @@ +#!/bin/sh + +GPIO=$1 # name or number (without "gpio" prefix) +VAL=$2 # 0 or 1 +WAIT=$3 # delay in seconds, optional + +log() { + modlog "GPIO Set" "$@" +} + + +[ -n "$WAIT" ] && sleep $WAIT + +if `echo "$GPIO" | grep -q "^[0-9]*$"`; then + GPIO=gpio$GPIO +fi + +if [ -w /sys/class/gpio/$GPIO/value ]; then + echo "$VAL" > /sys/class/gpio/$GPIO/value + log "GPIO $GPIO has been set to $VAL" +else + log "GPIO $GPIO is not writable" +fi diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gpiomodel.lua b/rooter/ext-rooter-basic/files/usr/lib/rooter/gpiomodel.lua new file mode 100644 index 0000000..fe63096 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/gpiomodel.lua @@ -0,0 +1,221 @@ +#!/usr/bin/lua + +mfile = "/tmp/sysinfo/model" +echo = 1 +model = {} +gpio = {} +gpio2 = {} +gpio3 = {} +gpio4 = {} +gpioname = {} +gpioname2 = {} +gpioname3 = {} +gpioname4 = {} + +pin = nil +pin2 = nil + +model[1] = "10u" +gpio[1] = 18 +model[2] = "11u" +gpio[2] = 8 +model[3] = "13u" +gpio[3] = 18 +model[4] = "mr3020" +gpio[4] = 8 +model[5] = "3040" +gpio[5] = 18 +model[6] = "3220" +gpio[6] = 6 +model[7] = "3420" +gpio[7] = 6 +model[8] = "wdr3500" +gpio[8] = 12 +gpioname[8] = "tp-link:power:usb" +model[9] = "wdr3600" +gpio[9] = 22 +gpioname[9] = "tp-link:power:usb1" +gpio2[9] = 21 +gpioname2[9] = "tp-link:power:usb2" +model[10] = "wdr4300" +gpio[10] = 22 +gpioname[10] = "tp-link:power:usb1" +gpio2[10] = 21 +gpioname2[10] = "tp-link:power:usb2" +model[11] = "wdr4310" +gpio[11] = 22 +gpioname2[11] = "tp-link:power:usb2" +gpioname[11] = "tp-link:power:usb1" +gpio2[11] = 21 +model[12] = "wdr4900" +gpio[12] = 10 +model[13] = "703n" +gpio[13] = 8 +model[14] = "710n" +gpio[14] = 8 +model[15] = "720" +gpio[15] = 8 +model[16] = "842" +gpio[16] = 6 +gpioname[16] = "tp-link:power:usb" +model[17] = "1043" +gpio[17] = 21 +gpioname[17] = "tp-link:power:usb" +model[18] = "4530" +gpio[18] = 22 +model[19] = "archer" +gpio[19] = 22 +gpio2[19] = 21 +gpioname2[19] = "tp-link:power:usb2" +gpioname[19] = "tp-link:power:usb1" +model[20] = "ar150" +gpio[20] = 6 +model[21] = "domino" +gpio[21] = 6 +model[22] = "300a" +gpio[22] = 0 +model[23] = "mt300n" +gpio[23] = 0 +model[24] = "ar750s" +gpio[24] = 7 +model[25] = "oolite" +gpio[25] = 18 +model[26] = "7800" +gpio[26] = 15 +gpio2[26] = 16 +model[27] = "m11g" +gpio[27] = 9 +gpioname[27] = "gpio9" +model[28] = "m33g" +gpio[28] = 9 +gpio2[28] = 10 +gpio3[28] = 11 +gpio4[28] = 12 +gpioname[28] = "pcie0_power" +gpioname2[28] = "pcie1_power" +gpioname3[28] = "pcie2_power" +gpioname4[28] = "usb_power" +model[29] = "rbsxtr" +gpio[29] = 13 +model[30] = "ap147" +gpio[30] = 13 +model[31] = "gigamod" +gpio[31] = 16 +gpioname[31] = "power_usb" +model[32] = "turbomod" +gpio[32] = 17 +gpioname[32] = "power_usb" +model[33] = "mk01" +gpio[33] = 6 + +numodel = 33 + +local file = io.open(mfile, "r") +if file == nil then + return +end + +name = nil +name2 = nil +line = file:read("*line") +file:close() +line = line:lower() + +for i=1,numodel do + start, ends = line:find(model[i]) + if start ~= nil then + if model[i] == "3420" then + start, ends = line:find("v1") + if start ~= nil then + pin = gpio[i] + pin2 = nil + else + pin = 4 + pin2 = nil + end + elseif model[i] == "3220" then + start, ends = line:find("v1") + if start ~= nil then + pin = gpio[i] + pin2 = nil + else + pin = 8 + pin2 = nil + end + elseif model[i] == "1043" then + start, ends = line:find("v2") + if start ~= nil then + pin = gpio[i] + pin2 = nil + name = gpioname[i] + name2 = nil + end + elseif model[i] == "842" then + start, ends = line:find("v3") + if start == nil then + start, ends = line:find("v2") + if start == nil then + pin = gpio[i] + pin2 = gpio2[i] + name = gpioname[i] + name2 = gpioname2[i] + else + pin = 4 + pin2 = nil + name = gpioname[i] + name2 = nil + end + end + elseif model[i] == "archer" then + start, ends = line:find("c20") + if start == nil then + pin = gpio[i] + pin2 = gpio2[i] + name = gpioname[i] + name2 = gpioname2[i] + end + elseif model[i] == "mt300n" then + start, ends = line:find("v2") + if start ~= nil then + pin = 11 + pin2 = nil + name = "usb" + name2 = nil + else + pin = gpio[i] + pin2 = nil + name = gpioname[i] + name2 = nil + end + else + pin = gpio[i] + pin2 = gpio2[i] + name = gpioname[i] + name2 = gpioname2[i] + end + break + end +end + +if pin ~= nil then + local tfile = io.open("/tmp/gpiopin", "w") + if pin2 ~= nil then + tfile:write("GPIOPIN=\"", pin, "\"\n") + tfile:write("GPIOPIN2=\"", pin2, "\"") + else + tfile:write("GPIOPIN=\"", pin, "\"") + end + tfile:close() +end +if name ~= nil then + local tfile = io.open("/tmp/gpioname", "w") + if name2 ~= nil then + tfile:write("GPIONAME=\"", name, "\"\n") + tfile:write("GPIONAME2=\"", name2, "\"") + else + tfile:write("GPIONAME=\"", name, "\"") + end + tfile:close() +else + os.remove("/tmp/gpioname") +end diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/idown.lua b/rooter/ext-rooter-basic/files/usr/lib/rooter/idown.lua new file mode 100644 index 0000000..cda3061 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/idown.lua @@ -0,0 +1,22 @@ +#!/usr/bin/lua + +cmd = arg[1] +interface = arg[2] + +function trim(s) + return (s:gsub("^%s*(.-)%s*$", "%1")) +end + +if interface ~= "wan" and interface ~= "wwan" then + s, e = interface:find("wan") + if s ~= nil then + mnum = trim(interface:sub(e+1)) + if cmd == "1" then + os.execute("/usr/lib/rooter/connect/disablemw3.sh " .. mnum) + line = "echo \"0\" > /tmp/mdown" .. mnum + else + line = "rm -f /tmp/mdown" .. mnum + end + os.execute(line) + end +end \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/initialize.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/initialize.sh new file mode 100644 index 0000000..194a78c --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/initialize.sh @@ -0,0 +1,295 @@ +#!/bin/sh +. /lib/functions.sh + +ROOTER=/usr/lib/rooter +ROOTER_LINK="/tmp/links" + +CODENAME="ROOter " +if [ -f "/etc/codename" ]; then + source /etc/codename +fi + +# +# Set the maximum number of modems supported +# +MAX_MODEMS=2 +MODCNT=$MAX_MODEMS + +log() { + modlog "ROOter Initialize" "$@" +} + +do_zone() { + local config=$1 + local name + local network + + config_get name $1 name + config_get network $1 network + newnet=$network + if [ $name = wan ]; then + WAN1=$(echo $network | grep "wan1") + if [ -z $WAN1 ]; then + COUNTER=1 + while [ $COUNTER -le $MODCNT ]; do + newnet="$newnet wan$COUNTER" + let COUNTER=COUNTER+1 + done + uci_set firewall "$config" network "$newnet" + uci_commit firewall + /etc/init.d/firewall restart + fi + fi +} + +firstboot() { + HO=$(uci get system.@system[-1].hostname) + if [ $HO = "OpenWrt" ]; then + uci set system.@system[-1].hostname="OpenWrt" + echo "OpenWrt" > /proc/sys/kernel/hostname + fi + if [ $HO = "LEDE" ]; then + uci set system.@system[-1].hostname="LEDE" + echo "LEDE" > /proc/sys/kernel/hostname + fi + uci set system.@system[-1].cronloglevel="9" + uci commit system + + AP=$(uci -q get profile.default.apn) + if [ -z "$AP" ]; then + uci set profile.default.apn="internet" + uci commit profile + fi + + log "ROOter First Boot finalized" + + config_load firewall + config_foreach do_zone zone + + source /etc/openwrt_release + if [ $DISTRIB_RELEASE = "SNAPSHOT" ]; then + DISTRIB_RELEASE="21.02.2" + fi + tone=$(echo "$DISTRIB_RELEASE" | grep "21.02") +} + +if [ -e /tmp/installing ]; then + exit 0 +fi + + +log " Initializing Rooter" + +sed -i -e 's|/etc/savevar|#removed line|g' /etc/rc.local + +[ -f "/etc/firstboot" ] || { + firstboot +} + +mkdir -p $ROOTER_LINK + +uci delete modem.Version +uci set modem.Version=version +uci set modem.Version.ver=$CODENAME +uci commit modem + +source /etc/openwrt_release +rm -f /etc/openwrt_release +if [ $DISTRIB_RELEASE = "SNAPSHOT" ]; then + DISTRIB_RELEASE="21.02.2" +fi +if [ -e /etc/custom ]; then + lua $ROOTER/customname.lua + DISTRIB_DESCRIPTION=$(uci get modem.Version.ver) + DISTRIB_REVISION=" " +else + DISTRIB_DESCRIPTION=$(uci get modem.Version.ver)" ( "$DISTRIB_ID" "$DISTRIB_RELEASE" )" + DISTRIB_REVISION=" " +fi +echo "$(uci get modem.Version.ver)" > /etc/revision +echo 'DISTRIB_ID="'"$DISTRIB_ID"'"' >> /etc/openwrt_release +echo 'DISTRIB_RELEASE="'"$DISTRIB_RELEASE"'"' >> /etc/openwrt_release +echo 'DISTRIB_REVISION="'"$DISTRIB_REVISION"'"' >> /etc/openwrt_release +echo 'DISTRIB_CODENAME="'"$DISTRIB_CODENAME"'"' >> /etc/openwrt_release +echo 'DISTRIB_TARGET="'"$DISTRIB_TARGET"'"' >> /etc/openwrt_release +echo 'DISTRIB_DESCRIPTION="'"$DISTRIB_DESCRIPTION"'"' >> /etc/openwrt_release + +MODSTART=1 +WWAN=0 +USBN=0 +ETHN=1 +BASEPORT=0 +WDMN=0 +if + ifconfig eth1 &>/dev/null +then + if [ -e "/sys/class/net/eth1/device/bInterfaceProtocol" ]; then + ETHN=1 + else + ETHN=2 + fi +fi + +echo 'MODSTART="'"$MODSTART"'"' > /tmp/variable.file +echo 'WWAN="'"$WWAN"'"' >> /tmp/variable.file +echo 'USBN="'"$USBN"'"' >> /tmp/variable.file +echo 'ETHN="'"$ETHN"'"' >> /tmp/variable.file +echo 'WDMN="'"$WDMN"'"' >> /tmp/variable.file +echo 'BASEPORT="'"$BASEPORT"'"' >> /tmp/variable.file + +echo 'MODCNTX="'"$MODCNT"'"' > /tmp/modcnt +uci set modem.general.max=$MODCNT +uci set modem.general.modemnum=1 +uci set modem.general.smsnum=1 +uci set modem.general.miscnum=1 + +OPING=$(uci -q get modem.ping.alive) +if [ ! -z $OPING ]; then + uci delete modem.ping +fi + +ifname1="ifname" +if [ -n "$tone" -o -e /etc/newstyle ]; then + ifname1="device" +fi + +COUNTER=1 +while [ $COUNTER -le $MODCNT ]; do + uci delete modem.modem$COUNTER + uci set modem.modem$COUNTER=modem + uci set modem.modem$COUNTER.empty=1 + + IPEX=$(uci get modem.pinginfo$COUNTER.alive) + if [ -z $IPEX ]; then + uci set modem.pinginfo$COUNTER=pinfo$COUNTER + uci set modem.pinginfo$COUNTER.alive="0" + fi + + INEX=$(uci get modem.modeminfo$COUNTER) + if [ -z $INEX ]; then + uci set modem.modeminfo$COUNTER=minfo$COUNTER + fi + + rm -f $ROOTER_LINK/getsignal$COUNTER + rm -f $ROOTER_LINK/reconnect$COUNTER + rm -f $ROOTER_LINK/create_proto$COUNTER + $ROOTER/signal/status.sh $COUNTER "No Modem Present" + + uci -q delete network.wan$COUNTER + uci set network.wan$COUNTER=interface + uci set network.wan$COUNTER.proto=dhcp + uci set network.wan$COUNTER.metric=$COUNTER"0" + uci set network.wan$COUNTER.${ifname1}="wan"$COUNTER + + if [ -e /etc/config/mwan3 ]; then + ENB=$(uci -q get mwan3.wan$COUNTER.enabled) + if [ ! -z $ENB ]; then + uci set mwan3.wan$COUNTER.enabled=0 + fi + fi + + if [ -e /etc/config/failover ]; then + uci delete failover.Modem$COUNTER + uci set failover.Modem$COUNTER=member + fi + + let COUNTER=COUNTER+1 +done + +if [ -e /etc/config/failover ]; then + uci delete failover.Wan + EXX=$(uci get network.wan) + if [ ! -z $EXX ]; then + uci set failover.Wan=member + fi + uci delete failover.Hotspot + uci set failover.Hotspot=member + uci commit failover + ENB=$(uci get failover.enabled.enabled) + if [ $ENB = "1" ]; then + if [ -e $ROOTER/connect/failover.sh ]; then + log "Starting Failover System" + $ROOTER/connect/failover.sh & + fi + fi +fi + +PRO=$(uci -q get network.wan.proto) +if [ ! -z $PRO ]; then + uci set network.wan.metric="1" +fi + +SM=$(uci get modem.sms) +if [ -z $SM ]; then + uci set modem.sms="sms" + uci set modem.sms.menable="0" + uci set modem.sms.slots="0" +fi + +uci commit modem +uci commit network +if [ -e /etc/config/mwan3 ]; then + uci commit mwan3 +fi + +if [ -e $ROOTER/removeipv6.sh ]; then + $ROOTER/removeipv6.sh +fi + +if [ -e /etc/hotplug.d/10-motion ]; then + rm -f /etc/hotplug.d/10-motion +fi +if [ -e /etc/hotplug.d/20-mjpg-streamer ]; then + rm -f /etc/hotplug.d/20-mjpg-streamer +fi +if [ -e /etc/hotplug.d/50-printer ]; then + rm -f /etc/hotplug.d/50-printer +fi +if [ -e $ROOTER/special.sh ]; then + $ROOTER/special.sh +fi + +lua $ROOTER/gpiomodel.lua + +HO=$(uci get system.@system[-1].hostname) +if [ $HO = "OpenWrt" ]; then + uci set system.@system[-1].hostname="OpenWrt" + uci commit system +fi + +if [ -e /usr/lib/lua/luci/model/cbi/admin_system/cronnew.lua ]; then + mv -f /usr/lib/lua/luci/model/cbi/admin_system/cronnew.lua /usr/lib/lua/luci/model/cbi/admin_system/crontab.lua +fi + + +if [ -f "/etc/firstboot" ]; then + echo 'FIRSTBOOT="'"1"'"' > /etc/firstboot +else + echo 'FIRSTBOOT="'"0"'"' > /etc/firstboot + echo 'BOOTTIME="'"$(date +%s)"'"' > /tmp/boottime +fi + +# +# Added modems to various drivers +# +#source /etc/flash +#if [ "$FLASH" = "4" ]; then +#fi +#echo "413c 81b6" > /sys/bus/usb-serial/drivers/option1/new_id +echo "1546 1146" > /sys/bus/usb-serial/drivers/option1/new_id +echo "106c 3718" > /sys/bus/usb-serial/drivers/option1/new_id +#echo "1199 9091" > /sys/bus/usb-serial/drivers/option1/new_id + +# end of bootup +echo "0" > /tmp/bootend.file + +/etc/init.d/dnsmasq restart + +chown -R root:root /etc/dropbear/ +chmod 700 /etc/dropbear/ +chmod 644 /etc/dropbear/authorized_keys 2>/dev/null + +if [ ! -z $tone ]; then + [ -e /etc/newstyle ] || touch /etc/newstyle + #reboot -f +fi diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/log/at-logger b/rooter/ext-rooter-basic/files/usr/lib/rooter/log/at-logger new file mode 100644 index 0000000..ca7d6e6 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/log/at-logger @@ -0,0 +1,12 @@ +#!/bin/sh + +ROOTER=/usr/lib/rooter + +TEXT=$1 +DATE=$(date +%c) + +echo " " >> /tmp/atlog +echo "$DATE : $TEXT" >> /tmp/atlog +lua $ROOTER/log/rotate.lua /tmp/atlog /tmp/attlog +mv /tmp/attlog /tmp/atlog + diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/log/logger b/rooter/ext-rooter-basic/files/usr/lib/rooter/log/logger new file mode 100644 index 0000000..e78b574 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/log/logger @@ -0,0 +1,17 @@ +#!/bin/sh + +ROOTER=/usr/lib/rooter + +TEXT=$1 +DATE=$(date +%c) + +wc -l $ROOTER/log/connect.log > /tmp/linecnt +read lcnt fle < /tmp/linecnt +rm -f /tmp/linecnt +if [ $lcnt -ge 20 ]; then + start=$((lcnt-1)) + tail +$start $ROOTER/log/connect.log > /tmp/connect.log + mv /tmp/connect.log $ROOTER/log/connect.log +fi + +echo "$DATE : $TEXT" >> $ROOTER/log/connect.log diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/log/modlogger.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/log/modlogger.sh new file mode 100644 index 0000000..fde69f7 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/log/modlogger.sh @@ -0,0 +1,26 @@ +#!/bin/sh + +ROOTER=/usr/lib/rooter + +TEXT=$1 +DATE=$(date +%c) + +modlog="/tmp/modlog.log" +tmplog="/tmp/tmodlog" + +echo "$DATE : $TEXT" >> $modlog +lua $ROOTER/log/mrotate.lua $modlog $tmplog +mv $tmplog $modlog + +exit 0 + +wc -l $modlog > /tmp/linecnt +read lcnt fle < /tmp/linecnt +rm -f /tmp/linecnt +if [ $lcnt -ge 200 ]; then + start=$((lcnt-1)) + tail +$start modlog > $tmplog + mv $tmplog $modlog +fi + +echo "$DATE : $TEXT" >> $modlog diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/log/mrotate.lua b/rooter/ext-rooter-basic/files/usr/lib/rooter/log/mrotate.lua new file mode 100644 index 0000000..0a5317d --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/log/mrotate.lua @@ -0,0 +1,39 @@ +#!/usr/bin/lua + +local uci = require "luci.model.uci".cursor() + +logfile = {} +infile = arg[1] +outfile = arg[2] + +i=0 +ifile = io.open(infile, "r") +if ifile == nil then + return +end +repeat + local line = ifile:read("*line") + if line == nil then + break + end + if string.len(line) > 1 then + i = i + 1 + logfile[i] = line + end +until 1==0 +ifile:close() + +maxs = 195 + +if i < maxs then + j = 1 +else + j = i - maxs - 1 +end +ofile = io.open(outfile, "w") +for k=j,i do + if logfile[k] ~= nil then + ofile:write(logfile[k] .. "\n") + end +end +ofile:close() \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/log/rotate.lua b/rooter/ext-rooter-basic/files/usr/lib/rooter/log/rotate.lua new file mode 100644 index 0000000..f866446 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/log/rotate.lua @@ -0,0 +1,43 @@ +#!/usr/bin/lua + +local uci = require "luci.model.uci".cursor() + +logfile = {} +infile = arg[1] +outfile = arg[2] + +i=0 +ifile = io.open(infile, "r") +if ifile == nil then + return +end +repeat + local line = ifile:read("*line") + if line == nil then + break + end + if string.len(line) > 1 then + i = i + 1 + logfile[i] = line + end +until 1==0 +ifile:close() + +bff = uci:get("variable", "info", "buffersize") +if bff == nil then + maxs = 50 +else + maxs = tonumber(bff) +end +if i < maxs then + j = 1 +else + j = i - maxs - 1 +end +ofile = io.open(outfile, "w") +for k=j,i do + if logfile[k] ~= nil then + ofile:write(logfile[k] .. "\n") + end +end +ofile:close() \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/logprint.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/logprint.sh new file mode 100644 index 0000000..779337f --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/logprint.sh @@ -0,0 +1,5 @@ +#!/bin/sh +# + +modlog "Log Print " "$1 $2 $3 $4 $5 $6" +exit 0 diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/atcmd.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/atcmd.sh new file mode 100644 index 0000000..efda95d --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/atcmd.sh @@ -0,0 +1,21 @@ +#!/bin/sh + +ROOTER=/usr/lib/rooter +ATCMDD=$1 + +CURRMODEM=$(uci get modem.general.miscnum) +COMMPORT="/dev/ttyUSB"$(uci get modem.modem$CURRMODEM.commport) + +M2=$(echo "$ATCMDD" | sed -e "s#~#\"#g") +COPS="+cops=?" +QOPS="+qops?" +M3=$(echo "$M2" | awk '{print tolower($0)}') +if `echo ${M3} | grep "${COPS}" 1>/dev/null 2>&1`; then + export TIMEOUT="120" +elif `echo ${M3} | grep "${QOPS}" 1>/dev/null 2>&1`; then + export TIMEOUT="120" +else + export TIMEOUT="5" +fi +OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$M2") +echo "$OX" > /tmp/result$CURRMODEM.at diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/celltype.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/celltype.sh new file mode 100644 index 0000000..d1b3fb1 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/celltype.sh @@ -0,0 +1,495 @@ +#!/bin/sh + +ROOTER=/usr/lib/rooter + +log() { + modlog "Cell type $CURRMODEM" "$@" +} + +zte_type() { + ATCMDD="AT+ZSNT?" + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + OX=$($ROOTER/common/processat.sh "$OX") + ZSNT=$(echo "$OX" | awk -F[,\ ] '/^\+ZSNT:/ {print $2}') + if [ "x$ZSNT" != "x" ]; then + NETMODE="-" + if [ $ZSNT = "0" ]; then + ZSNTX=$(echo "$OX" | awk -F[,\ ] '/^\+ZSNT:/ {print $4}') + case $ZSNTX in + "0" ) + NETMODE="1" + ;; + "1" ) + NETMODE="2" + ;; + "2" ) + NETMODE="4" + ;; + "6" ) + NETMODE="6" + ;; + esac + else + case $ZSNT in + "1" ) + NETMODE="3" + ;; + "2" ) + NETMODE="5" + ;; + "6" ) + NETMODE="7" + ;; + esac + fi + fi + uci set modem.modem$CURRMODEM.modemtype="1" + uci set modem.modem$CURRMODEM.netmode=$NETMODE + uci commit modem +} + +sierra_type() { + ATCMDD="AT!SELRAT?" + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + SELRAT=$(echo $OX | grep -o "!SELRAT:[^0-9]\+[0-9]\{2\}" | grep -o "[0-9]\{2\}") + if [ -n "$SELRAT" ]; then + case $SELRAT in + "01" ) + NETMODE="5" + ;; + "02" ) + NETMODE="3" + ;; + "06" ) + NETMODE="7" + ;; + * ) + NETMODE="1" + ;; + esac + fi + uci set modem.modem$CURRMODEM.modemtype="2" + uci set modem.modem$CURRMODEM.netmode=$NETMODE + uci commit modem +} + +huawei_type() { + ATCMDD="AT^SYSCFGEX?" + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + OX=$($ROOTER/common/processat.sh "$OX") + SYSCFG=$(echo "$OX" | awk -F[,\"] '/^\^SYSCFGEX:/ {print $2}') + if [ "x$SYSCFG" != "x" ]; then + NETMODE="-" + case $SYSCFG in + "00" ) + NETMODE="1" + ;; + "01" ) + NETMODE="3" + ;; + "02" ) + NETMODE="5" + ;; + "03" ) + NETMODE="7" + ;; + * ) + ACQ=${SYSCFG:0:2} + case $ACQ in + "01" ) + NETMODE="2" + ;; + "02" ) + NETMODE="4" + ;; + "03" ) + NETMODE="6" + ;; + esac + ;; + esac + uci set modem.modem$CURRMODEM.modemtype="3" + else + ATCMDD="AT^SYSCFG?" + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + OX=$($ROOTER/common/processat.sh "$OX") + SYSCFG=$(echo "$OX" | awk -F[,\ ] '/^\^SYSCFG:/ {print $2}') + if [ "x$SYSCFG" != "x" ]; then + NETMODE="-" + case $SYSCFG in + "7" ) + NETMODE="1" + ;; + "13" ) + NETMODE="3" + ;; + "14" ) + NETMODE="5" + ;; + * ) + SYSCFG=$(echo "$OX" | awk -F[,\ ] '/^\^SYSCFG:/ {print $3}') + case $SYSCFG in + "0" ) + NETMODE="1" + ;; + "1" ) + NETMODE="2" + ;; + "2" ) + NETMODE="4" + ;; + esac + ;; + esac + uci set modem.modem$CURRMODEM.modemtype="4" + fi + fi + uci set modem.modem$CURRMODEM.netmode=$NETMODE + uci commit modem +} + +ublox_type() { + ATCMDD="AT+URAT?" + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + URAT=$(echo $OX" " | grep -o "+URAT: .\+ OK " | tr " " ",") + URAT1=$(echo $URAT | cut -d, -f2) + URAT2=$(echo $URAT | cut -d, -f3) + if [ -n "$URAT1" ]; then + NETMODE="-" + case $URAT1 in + "0" ) + NETMODE="3" + ;; + "2" ) + NETMODE="5" + ;; + "3" ) + NETMODE="7" + ;; + * ) + case $URAT2 in + "0" ) + NETMODE="2" + ;; + "2" ) + NETMODE="4" + ;; + "3" ) + NETMODE="1" + ;; + esac + ;; + esac + uci set modem.modem$CURRMODEM.modemtype="5" + fi + uci set modem.modem$CURRMODEM.netmode=$NETMODE + uci commit modem +} + +quectel_type() { + idVidP=$idV":"$idP + ATCMDD="AT+CGMM" + model=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + EM20=$(echo "$model" | grep "EM20") + if [ $EM20 ]; then + idVidP=$idV":"$idP"0" + fi + if [ "$idVidP" == "2c7c:0800" -o "$idVidP" == "2c7c:0620" -o "$idVidP" == "2c7c:030b" -o "$idVidP" == "2c7c:0801" -o "$idVidP" == "2c7c:0900" ]; then + ATCMDD="AT+QNWPREFCFG=\"mode_pref\"" + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + QNSM=$(echo $OX | grep -o ",[AUTOLENR5GWCDM:]\+" | tr ',' ' ') + QNSM=$(echo $QNSM) + if [ -n "$QNSM" ]; then + case $QNSM in + "AUTO" ) + NETMODE="1" + ;; + "LTE" ) + NETMODE="7" + ;; + "LTE:NR5G" ) + NETMODE="8" + ;; + "NR5G" ) + NETMODE="9" + ;; + "WCDMA" ) + NETMODE="5" + ;; + esac + uci set modem.modem$CURRMODEM.modemtype="6" + fi + else + ATCMDD="AT+QCFG=\"nwscanmode\"" + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + QNSM=$(echo $OX | grep -o "+QCFG: \"nwscanmode\",[0-9]" | grep -o "[0-9]") + if [ -n "$QNSM" ]; then + case $QNSM in + "0" ) + NETMODE="1" + ;; + "1" ) + NETMODE="3" + ;; + "2"|"5" ) + NETMODE="5" + ;; + "3" ) + NETMODE="7" + ;; + esac + uci set modem.modem$CURRMODEM.modemtype="6" + fi + fi + uci set modem.modem$CURRMODEM.netmode=$NETMODE + uci commit modem +} + +meig_type() { + if [ $idV == "2dee" ]; then + ATCMDD="AT^SYSCFGEX?" + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + RATs=$(echo "$OX" | grep -o "\^SYSCFGEX: \"[0-9]\{2,6\}\"" | grep -o "[0-9]\{2,6\}") + if [ -n "$RATs" ]; then + case $RATs in + "02" ) + NETMODE="5" ;; + "03" ) + NETMODE="7" ;; + "04" ) + NETMODE="9" ;; + "0203" | "0204" | "020304" | "020403" ) + NETMODE="4" ;; + "0304" | "0302" | "030402" | "030204" ) + NETMODE="6" ;; + "0403" ) + NETMODE="8" ;; + * ) + NETMODE="1" ;; + esac + fi + else + ATCMDD="AT+MODODR?" + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + MODODR=$(echo $OX | grep -o "[0-9]") + if [ -n "$MODODR" ]; then + case $MODODR in + "1"|"8" ) + NETMODE="5" ;; + "2" ) + NETMODE="1" ;; + "3" ) + NETMODE="3" ;; + "5" ) + NETMODE="7" ;; + esac + fi + fi + uci set modem.modem$CURRMODEM.modemtype="7" + uci set modem.modem$CURRMODEM.netmode=$NETMODE + uci commit modem +} + +telit_type() { + ATCMDD="AT^SYSCONFIG?" + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + SCFG=$(echo $OX | grep -o "\^SYSCONFIG: [0-9]\{1,2\}" | grep -o "[0-9]\{1,2\}") + if [ -n "$SCFG" ]; then + PREF=$(echo $OX | grep -o "\^SYSCONFIG: 2,[0-9]" | grep -o ",[0-9]") + case $SCFG in + "13" ) + NETMODE="3" ;; + "14" ) + NETMODE="5" ;; + "17" ) + NETMODE="7" ;; + * ) + NETMODE="1" ;; + esac + uci set modem.modem$CURRMODEM.modemtype="8" + fi + uci set modem.modem$CURRMODEM.netmode=$NETMODE + uci commit modem +} + +fibocom_type() { + NETMODE="" + idPP=${idP:1:1} + if [ "$idPP" = "1" ]; then + ATCMDD="AT+GTRAT?" + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + MRAT=$(echo $OX | grep -o "+GTRAT: [0-9]\{1,2\}" | grep -o "[0-9]\{1,2\}") + if [ -n "$MRAT" ]; then + case $MRAT in + "2" ) + NETMODE="5" ;; + "3" ) + NETMODE="7" ;; + "14" ) + NETMODE="9" ;; + "17" ) + NETMODE="8" ;; + * ) + NETMODE="1" ;; + esac + fi + else + ATCMDD="AT+XACT?" + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + XACT=$(echo $OX | grep -o "+XACT: [0-9]" | grep -o "[0-9]") + if [ -n "$XACT" ]; then + PREF=$(echo $OX | grep -o "+XACT: [0-9],[0-9]" | grep -o ",[0-9]") + case $XACT in + "1" ) + NETMODE="5" ;; + "2" ) + NETMODE="7" ;; + "4" ) + if [ "$PREF" = ",1" ]; then + NETMODE="4" + else + NETMODE="6" + fi ;; + * ) + NETMODE="6" ;; + esac + + fi + fi + uci set modem.modem$CURRMODEM.modemtype="9" + uci set modem.modem$CURRMODEM.netmode=$NETMODE + uci commit modem +} + +simcom_type() { + ATCMDD="AT+CNMP?" + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + CNMP=$(echo "$OX" | grep -o "+CNMP:[ ]*[0-9]\{1,3\}" | grep -o "[0-9]\{1,3\}") + if [ -n "$CNMP" ]; then + case $CNMP in + "2"|"55" ) + NETMODE="1" ;; + "13" ) + NETMODE="3" ;; + "14" ) + NETMODE="5" ;; + "38" ) + NETMODE="7" ;; + "71" ) + NETMODE="9" ;; + "109" ) + NETMODE="8" ;; + * ) + NETMODE="0" ;; + esac + fi + uci set modem.modem$CURRMODEM.modemtype="10" + uci set modem.modem$CURRMODEM.netmode=$NETMODE + uci commit modem +} + +quanta_type() { + ATCMDD="AT^QCNCFG?" + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + TECH=$(echo $OX | grep -o "\^QCNCFG: \"[0123]\{2\}\"" | grep -o "[0123]\{2\}") + case $TECH in + "02") + NETMODE="5" + ;; + "03") + NETMODE="7" + ;; + *) + NETMODE="1" + ;; + esac + uci set modem.modem$CURRMODEM.modemtype="11" + uci set modem.modem$CURRMODEM.netmode=$NETMODE + uci commit modem +} + +CURRMODEM=$1 +COMMPORT="/dev/ttyUSB"$(uci get modem.modem$CURRMODEM.commport) + +idV=$(uci get modem.modem$CURRMODEM.idV) +idP=$(uci -q get modem.modem$CURRMODEM.idP) +NETMODE="-" + +# This case statement should be kept in sync with: $ROOTER/signal/modemsignal.sh +case $idV in +"1199"|"0f3d" ) + sierra_type + ;; +"19d2" ) + if [ $idP = 1432 ]; then + telit_type + else + zte_type + fi + ;; +"12d1" ) + huawei_type + ;; +"2c7c" ) + quectel_type + ;; +"2cb7"|"1508"|"8087" ) + fibocom_type + ;; +"2dee" ) + meig_type + ;; +"05c6" ) + case $idP in + "f601" ) + meig_type + ;; + "5042" ) + telit_type + ;; + "9090"|"9003"|"9215" ) + quectel_type + ;; + "90db" ) + simcom_type + ;; + * ) + : + ;; + esac + ;; +"1bc7" ) + telit_type + ;; +"1410" ) + : + ;; +"413c" ) + case $idP in + "81d7"|"81d8" ) + telit_type + ;; + * ) + sierra_type + ;; + esac + ;; +"0489" |"03f0" ) + telit_type + ;; +"1e0e" ) + simcom_type + ;; +"8087" ) + if [ $idP = "095a" ]; then + fibocom_type + fi + ;; +"0408" ) + quanta_type + ;; +* ) + : + ;; +esac +exit diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em060-2xbands b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em060-2xbands new file mode 100644 index 0000000..aa600ca --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em060-2xbands @@ -0,0 +1,29 @@ +2 2 +2 5 +2 12 +2 13 +2 39 +4 4 +4 5 +4 12 +4 13 +4 29 +5 5 +5 7 +5 25 +5 30 +5 66 +7 7 +7 12 +7 26 +12 12 +12 25 +12 30 +12 66 +13 66 +25 25 +25 26 +30 29 +66 29 +66 66 +41 41 diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em12-2xbands b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em12-2xbands new file mode 100644 index 0000000..307919e --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em12-2xbands @@ -0,0 +1,46 @@ +1 3 +1 5 +1 18 +1 19 +1 20 +1 26 +2 2 +2 4 +2 5 +2 12 +2 13 +2 17 +2 29 +2 30 +2 66 +3 3 +3 5 +2 7 +3 8 +3 19 +3 20 +3 28 +4 4 +4 5 +4 12 +4 13 +4 17 +4 19 +4 30 +5 7 +5 30 +5 66 +7 7 +7 20 +7 28 +12 30 +13 66 +19 21 +20 32 +29 30 +38 38 +39 39 +39 41 +40 40 +41 41 +66 66 \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em12-3xbands b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em12-3xbands new file mode 100644 index 0000000..43f7600 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em12-3xbands @@ -0,0 +1,43 @@ +1 3 5 +1 3 7 +1 3 8 +1 3 19 +1 3 20 +1 3 28 +1 7 20 +2 4 5 +2 4 13 +2 5 30 +2 12 30 +2 29 30 +3 7 20 +3 7 28 +3 7 8 +4 5 30 +4 12 30 +4 29 30 +5 66 2 +13 66 2 +66 12 30 +66 29 30 +66 5 30 +2 14 66 +2 2 5 +2 2 13 +3 3 7 +3 7 7 +3 3 20 +3 3 28 +3 3 1 +4 4 5 +4 4 13 +7 7 28 +5 66 66 +13 66 66 +66 66 2 +14 66 66 +39 39 41 +39 41 41 +40 40 40 +41 41 41 +66 66 66 \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em20-2xbands b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em20-2xbands new file mode 100644 index 0000000..74a2677 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em20-2xbands @@ -0,0 +1,50 @@ +1 3 +1 5 +1 18 +1 19 +1 20 +1 26 +2 2 +2 4 +2 5 +2 12 +2 13 +2 14 +2 17 +2 29 +2 30 +2 66 +3 3 +3 5 +2 7 +3 8 +3 19 +3 20 +3 28 +4 4 +4 5 +4 12 +4 13 +4 17 +4 19 +4 30 +5 7 +5 30 +5 66 +7 7 +7 20 +7 28 +12 30 +13 66 +14 30 +14 66 +29 30 +38 38 +39 39 +39 41 +40 40 +41 41 +66 5 +66 12 +66 29 +66 30 \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em20-3xbands b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em20-3xbands new file mode 100644 index 0000000..701af64 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em20-3xbands @@ -0,0 +1,41 @@ +1 3 5 +1 3 7 +1 3 19 +1 3 20 +1 3 28 +1 7 20 +2 4 5 +2 4 13 +2 5 30 +2 12 30 +2 29 30 +3 7 20 +3 7 28 +3 7 8 +4 5 30 +4 12 30 +4 29 30 +5 66 2 +13 66 2 +66 12 30 +66 29 30 +66 5 30 +2 14 66 +2 2 5 +2 2 13 +3 3 7 +3 7 7 +3 3 20 +3 3 28 +4 4 5 +4 4 13 +7 7 28 +5 66 66 +13 66 66 +39 39 41 +39 41 41 +40 40 40 +41 41 41 +66 66 2 +14 66 66 +66 66 66 \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em20-4xbands b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em20-4xbands new file mode 100644 index 0000000..5489ad5 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em20-4xbands @@ -0,0 +1,8 @@ +1 1 3 28 0 +1 3 40 40 0 +1 3 7 7 0 +1 3 3 7 7 +1 3 3 40 40 +1 3 7 7 28 +2 13 66 66 0 +3 3 7 7 28 \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em7411-2xbands b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em7411-2xbands new file mode 100644 index 0000000..4667685 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em7411-2xbands @@ -0,0 +1,29 @@ +2 2 +2 5 +2 7 +2 12 +2 13 +2 14 +2 71 +4 4 +4 5 +4 7 +4 12 +4 13 +4 71 +5 5 +5 66 +7 7 +7 12 +12 66 +13 66 +14 66 +25 25 +25 26 +26 41 +41 41 +42 42 +43 43 +48 48 +66 66 +66 71 \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em7411-3xbands b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em7411-3xbands new file mode 100644 index 0000000..a50f0f9 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em7411-3xbands @@ -0,0 +1,8 @@ +2 2 2 +7 7 7 +12 12 12 +41 41 41 +42 42 42 +43 43 43 +48 48 48 +66 66 66 \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em7511-2xbands b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em7511-2xbands new file mode 100644 index 0000000..ea770ac --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em7511-2xbands @@ -0,0 +1,60 @@ +1 3 +1 5 +1 7 +1 8 +1 18 +1 19 +1 20 +1 26 +1 41 +1 42 +2 2 +2 4 +2 5 +2 12 +2 13 +2 28 +2 29 +2 30 +2 46 +2 66 +3 3 +3 5 +3 7 +3 8 +3 19 +3 20 +3 28 +3 41 +3 42 +4 4 +4 5 +4 7 +4 12 +4 13 +4 28 +4 29 +4 30 +4 46 +5 5 +5 7 +5 30 +5 46 +5 66 +7 7 +7 20 +7 28 +12 30 +12 66 +13 46 +13 66 +19 42 +20 32 +28 42 +29 30 +29 66 +30 66 +41 41 +41 42 +42 42 +48 48 \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em7511-3xbands b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em7511-3xbands new file mode 100644 index 0000000..f64b670 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em7511-3xbands @@ -0,0 +1,55 @@ +1 3 5 +1 3 7 +1 3 8 +1 3 19 +1 3 20 +1 3 28 +1 5 7 +1 7 20 +1 7 7 +1 42 42 +2 2 5 +2 2 12 +2 2 13 +2 4 5 +2 4 7 +2 4 12 +2 4 13 +2 4 29 +2 5 30 +2 5 66 +2 7 7 +2 7 12 +2 12 30 +2 13 66 +2 29 30 +2 66 66 +3 3 5 +3 3 7 +3 7 7 +3 7 20 +3 7 28 +3 41 42 +3 41 41 +3 42 42 +4 4 5 +4 4 12 +4 4 13 +4 4 30 +4 5 30 +4 7 7 +4 7 12 +4 12 30 +4 29 30 +5 30 66 +5 66 66 +7 7 28 +12 30 66 +13 66 66 +19 42 42 +29 30 66 +41 42 42 +41 41 42 +41 41 41 +48 48 48 +66 66 66 \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em7565-2xbands b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em7565-2xbands new file mode 100644 index 0000000..3ff2f85 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em7565-2xbands @@ -0,0 +1,14 @@ +1 18 +1 26 +1 41 +2 2 +2 28 +2 46 +4 28 +4 46 +5 5 +5 46 +20 32 +41 41 +42 42 +48 48 \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em7565-3xbands b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em7565-3xbands new file mode 100644 index 0000000..61b39c8 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em7565-3xbands @@ -0,0 +1,51 @@ +1 3 5 +1 3 7 +1 3 8 +1 3 19 +1 3 20 +1 3 28 +1 42 42 +2 2 5 +2 2 12 +2 2 13 +2 4 5 +2 4 7 +2 4 12 +2 4 13 +2 4 29 +2 5 30 +2 5 66 +2 7 7 +2 7 12 +2 12 30 +2 13 66 +2 29 30 +2 66 66 +3 3 5 +3 3 7 +3 3 20 +3 3 28 +3 7 7 +3 7 20 +3 7 28 +3 41 42 +3 41 41 +3 42 42 +4 4 5 +4 4 12 +4 4 13 +4 4 30 +4 7 7 +4 7 12 +4 12 30 +4 29 30 +5 30 66 +5 66 66 +7 7 28 +12 30 66 +13 66 66 +29 30 66 +41 42 41 +41 41 42 +48 48 48 +66 66 66 \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/ep06a-bands b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/ep06a-bands new file mode 100644 index 0000000..e9565cd --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/ep06a-bands @@ -0,0 +1,27 @@ +2 2 +5 5 +2 12 +2 13 +2 29 +4 4 +4 5 +4 12 +4 13 +4 29 +7 5 +7 7 +7 12 +7 26 +25 5 +25 12 +25 25 +25 26 +30 5 +30 12 +30 29 +41 41 +66 5 +66 12 +66 13 +66 29 +66 66 \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/ep06e-bands b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/ep06e-bands new file mode 100644 index 0000000..0937585 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/ep06e-bands @@ -0,0 +1,32 @@ +1 5 +1 8 +1 20 +1 28 +1 1 +3 5 +3 7 +3 8 +3 20 +3 28 +3 3 +5 38 +5 40 +5 41 +7 5 +7 8 +7 20 +7 28 +7 7 +8 38 +8 40 +8 41 +20 32 +20 38 +20 40 +20 41 +28 38 +28 40 +28 41 +38 38 +40 40 +41 41 diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/l850-2xbands b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/l850-2xbands new file mode 100644 index 0000000..540bd0a --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/l850-2xbands @@ -0,0 +1,35 @@ +1 3 +1 5 +1 18 +1 19 +1 20 +1 21 +1 26 +2 4 +2 5 +2 12 +2 13 +2 17 +2 29 +2 30 +2 66 +3 5 +3 7 +3 8 +3 19 +3 20 +3 28 +4 5 +4 12 +4 13 +4 17 +4 29 +4 30 +5 7 +5 30 +5 66 +7 20 +7 28 +12 30 +13 66 +29 30 \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/l850-3xbands b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/l850-3xbands new file mode 100644 index 0000000..29632c3 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/l850-3xbands @@ -0,0 +1,27 @@ +1 3 7 +1 3 19 +1 3 20 +1 19 21 +2 4 5 +2 4 13 +2 5 30 +2 12 30 +2 29 30 +3 7 20 +3 7 28 +4 5 30 +4 12 30 +4 29 30 +5 66 2 +13 66 2 +2 2 5 +2 2 13 +3 3 7 +3 7 7 +3 3 20 +4 4 5 +4 4 13 +5 66 66 +13 66 66 +66 66 2 +66 66 66 \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/lock.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/lock.sh new file mode 100644 index 0000000..f9d8ff5 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/lock.sh @@ -0,0 +1,394 @@ +#!/bin/sh + +ROOTER=/usr/lib/rooter +ROOTER_LINK="/tmp/links" + +log() { + modlog "Lock Band $CURRMODEM" "$@" +} + +RESTART="1" + +ifname1="ifname" +if [ -e /etc/newstyle ]; then + ifname1="device" +fi + +fibdecode() { + j=$1 + tdec=$2 + mod=$3 + length=${#j} + jx=$j + length=${#jx} + + str="" + i=$((length-1)) + while [ $i -ge 0 ] + do + dgt="0x"${jx:$i:1} + DecNum=`printf "%d" $dgt` + Binary= + Number=$DecNum + while [ $DecNum -ne 0 ] + do + Bit=$(expr $DecNum % 2) + Binary=$Bit$Binary + DecNum=$(expr $DecNum / 2) + done + if [ -z $Binary ]; then + Binary="0000" + fi + len=${#Binary} + while [ $len -lt 4 ] + do + Binary="0"$Binary + len=${#Binary} + done + revstr="" + length=${#Binary} + ii=$((length-1)) + while [ $ii -ge 0 ] + do + revstr=$revstr${Binary:$ii:1} + ii=$((ii-1)) + done + str=$str$revstr + i=$((i-1)) + done + + len=${#str} + ii=0 + lst="" + sep="," + hun=101 + if [ $mod = "1" ]; then + sep=":" + hun=1 + fi + if [ $mod = "2" ]; then + sep="," + hun=1 + fi + while [ $ii -lt $len ] + do + bnd=${str:$ii:1} + if [ $bnd -eq 1 ]; then + if [ $tdec -eq 1 ]; then + jj=$((ii+hun)) + else + if [ $ii -lt 9 ]; then + jj=$((ii+501)) + else + jj=$((ii+5001)) + fi + fi + if [ -z "$lst" ]; then + lst=$jj + else + lst=$lst$sep$jj + fi + fi + ii=$((ii+1)) + done + if [ -z $lst ]; then + lst="0" + fi +} + +encode() { + maskz=$1 + length=${#maskz} + i=0 + ii=1 + lst="" + ij=$((length-1)) + while [ $i -le $ij ] + do + dgt=${maskz:$i:1} + if [ $dgt == "1" ]; then + lst=$lst$ii" " + fi + i=$((i+1)) + ii=$((ii+1)) + done + maskz=$(encodemask $lst) + maskz=$(echo $maskz | sed 's/^0*//') +} + +maskx=$1 +mask64=$(echo "$maskx""," | cut -c1-64 | cut -d, -f1) +maskl2=$(echo ${maskx:64}"," | cut -d, -f1) +maskc=$(echo "$maskx" | grep ",") +if [ ! -z "$maskc" ]; then + mask=$(echo $maskx"," | cut -d, -f1) + mask5g=$(echo $maskx"," | cut -d, -f2) + mask5gsa=$(echo $maskx"," | cut -d, -f3) +else + mask=$maskx + mask5g="" + mask5gsa="" +fi + +#log "$mask" +#log "$mask5g" +#log "$mask5gsa" + +encode $mask +mask=$maskz +encode $mask5g +mask5g=$maskz +encode $mask5gsa +mask5gsa=$maskz +encode $mask64 +mask64=$maskz +encode $maskl2 +if [ -z $maskz ]; then + maskl2="0" +else + maskl2=$maskz +fi +if [ -z $mask64 ]; then + mask64="0" +fi + +if [ -z "$2" ]; then + CURRMODEM=$(uci get modem.general.miscnum) +else + CURRMODEM=1 +fi +COMMPORT="/dev/ttyUSB"$(uci get modem.modem$CURRMODEM.commport) +CPORT=$(uci -q get modem.modem$CURRMODEM.commport) +model=$(uci get modem.modem$CURRMODEM.model) +uVid=$(uci get modem.modem$CURRMODEM.uVid) +uPid=$(uci get modem.modem$CURRMODEM.uPid) +GW=$(uci -q get modem.modem$CURRMODEM.GW) + +export TIMEOUT="5" +case $uVid in + "2c7c" ) + MODT="1" + if [ -z "$2" ]; then + RESTART="1" + fi + M5="" + M2='AT+QCFG="band",0,'$mask',0,1' + if [ $uPid = 0620 ]; then + EM20=$(echo $model | grep "EM20") + if [ -z "$EM20" ]; then #EM160 + if [ ! -z $mask ]; then + fibdecode $mask 1 1 + else + lst="0" + fi + M2='AT+QNWPREFCFG="lte_band",'$lst + else # Fake EM160 RM500 + if [ -e /etc/qfake ]; then + if [ ! -z $mask ]; then + fibdecode $mask 1 1 + else + lst="0" + fi + M2F='AT+QNWPREFCFG="lte_band",'$lst + if [ ! -z $mask5g ]; then + fibdecode $mask5g 1 1 + else + lst="0" + fi + M5F='AT+QNWPREFCFG="nsa_nr5g_band",'$lst + NET=$(uci -q get modem.modem$CURRMODEM.netmode) + if [ $NET = "9" ]; then + M5F='AT+QNWPREFCFG="nr5g_band",'$lst + fi + log " " + log "Fake LTE Locking Cmd : $M2F" + log "Fake 5G Locking Cmd : $M5F" + log " " + #rm -f /tmp/bmask + exit 0 + fi + fi + fi + if [ $uPid = 030b ]; then + if [ ! -z $mask ]; then + fibdecode $mask 1 1 + else + lst="0" + fi + M2='AT+QNWPREFCFG="lte_band",'$lst + fi + if [ $uPid = 0306 ]; then + RESTART="1" + fi + if [ $uPid = 0800 -o $uPid = 0900 -o $uPid = 0801 ]; then + if [ ! -z "$mask" ]; then + fibdecode $mask 1 1 + else + lst="0" + fi + M2='AT+QNWPREFCFG="lte_band",'$lst + if [ ! -z "$mask5g" ]; then + fibdecode $mask5g 1 1 + else + lst="0" + fi + M5='AT+QNWPREFCFG="nsa_nr5g_band",'$lst + if [ ! -z "$mask5gsa" ]; then + fibdecode $mask5gsa 1 1 + else + lst="0" + fi + M6='AT+QNWPREFCFG="nr5g_band",'$lst + fi + log " " + log "Locking Cmd : $M2" + log "Locking Cmd : $M5" + log "Locking Cmd : $M6" + log " " + + ATCMDD="AT" + NOCFUN=$uVid + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$M2") + if [ ! -z "$M5" ]; then + OX5=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$M5") + fi + if [ ! -z "$M6" ]; then + OX6=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$M6") + fi + log "Locking Cmd Response : $OX" + log "Locking Cmd Response : $OX5" + log "Locking Cmd Response : $OX6" + log " " + if [ $RESTART = "1" ]; then + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + sleep 10 + fi + ;; + "1199" ) + MODT="0" + M1='AT!ENTERCND="A710"' + if [ -z $mask64 ]; then + mask64="0" + fi + case $uPid in + + "68c0"|"9041"|"901f" ) # MC7354 EM/MC7355 + M2='AT!BAND=11,"Test",0,'$mask64,0 + ;; + "9070"|"9071"|"9078"|"9079"|"907a"|"907b" ) # EM/MC7455 + M2='AT!BAND=11,"Test",0,'$mask64,0 + if [ -e /etc/fake ]; then + M2='AT!BAND=11,"Test",0,'$mask64','$maskl2',0,0,0' + fi + ;; + "9090"|"9091"|"90b1" ) + M2='AT!BAND=11,"Test",0,'$mask64','$maskl2',0,0,0' + ;; + esac + log "$M2" + if [ -e /etc/fake ]; then + exit 0 + fi + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$M1") + log "$OX" + ATCMDD="AT+CFUN=1,1" + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$M2") + log "$OX" + M2='AT!BAND=00;!BAND=11' + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$M2") + log "$OX" + if [ $RESTART = "1" ]; then + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + ATCMDD='AT!ENTERCND="AWRONG"' + fi + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + ;; + "8087"|"2cb7" ) + MODT="2" + FM150="" + if [ $uVid = 2cb7 ]; then + FM150=$(echo $model | grep "FM150") + if [ -z $FM150 ]; then + COMM="XACT" + else + COMM="GTACT" + fi + else + COMM="XACT" + fi + ATCMDD='AT+'$COMM'?' + log " " + log " Get Current Bands : $ATCMDD" + log " " + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + log " " + log " Get Current Bands Response : $OX" + log " " + + lte="" + if [ ! -z $mask ]; then + fibdecode $mask 1 0 + lte=","$lst + fi + L1="4,2,1" + lst="" + if [ ! -z $FM150 ]; then + L1="17,6," + if [ ! -z $mask5g ]; then + fibdecode $mask5g 5 0 + lst=","$lst + else + L1="4,3," + fi + fi + ATCMDD="AT+""$COMM"="$L1$lte$lst" + log " " + log "Lock Command : $ATCMDD" + log " " + + #exit 0 + + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + log " " + log "Lock Response : $OX" + log " " + if [ $RESTART = "1" ]; then + ATCMDD="AT+CFUN=1,1" + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + fi + ;; + "413c" ) + MODT="3" + case $uPid in + + "81d7"|"81d8"|"e0b4" |"e0b5"|"1910") + if [ ! -z $mask ]; then + fibdecode $mask 1 2 + ATCMDD="AT^SLBAND=LTE,2,""$lst" + log "$ATCMDD" + else + exit 0 + fi + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + log " " + log "Lock Response : $OX" + log " " + if [ $RESTART = "1" ]; then + ATCMDD="AT+CFUN=1,1" + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + fi + ;; + esac + ;; + * ) + exit 0 + ;; +esac + +if [ $RESTART = "0" ]; then + /usr/lib/rooter/connect/bandmask $CURRMODEM $MODT + exit 0 +fi +rm -f /tmp/bmask +/usr/lib/rooter/luci/restart.sh $CURRMODEM +exit 0 diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/luaops.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/luaops.sh new file mode 100644 index 0000000..b05855f --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/luaops.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +COMMAND=$1 +FILE=$2 + +if [ $COMMAND = delete ]; then + rm -f $FILE +fi \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/mask.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/mask.sh new file mode 100644 index 0000000..5c92692 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/mask.sh @@ -0,0 +1,332 @@ +#!/bin/sh + +ROOTER=/usr/lib/rooter + +log() { + modlog "BandMasking $CURRMODEM" "$@" +} + +# +# remove for band locking +# +enb=$(uci -q get custom.bandlock.enabled) +if [ $enb == "0" ]; then + exit 0 +fi + +reverse() { + LX=$1 + length=${#LX} + jx="${LX:2:length-2}" + length=${#jx} + str="" + i=$((length-1)) + while [ $i -ge 0 ] + do + dgt="0x"${jx:$i:1} + DecNum=`printf "%d" $dgt` + Binary= + Number=$DecNum + while [ $DecNum -ne 0 ] + do + Bit=$(expr $DecNum % 2) + Binary=$Bit$Binary + DecNum=$(expr $DecNum / 2) + done + if [ -z $Binary ]; then + Binary="0000" + fi + len=${#Binary} + while [ $len -lt 4 ] + do + Binary="0"$Binary + len=${#Binary} + done + revstr="" + length=${#Binary} + ii=$((length-1)) + while [ $ii -ge 0 ] + do + revstr=$revstr${Binary:$ii:1} + ii=$((ii-1)) + done + str=$str$revstr + i=$((i-1)) + done + revstr=$str"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" +} + +rm -f /tmp/bmask +CURRMODEM=$(uci get modem.general.miscnum) +CPORT="/dev/ttyUSB"$(uci get modem.modem$CURRMODEM.commport) +uVid=$(uci get modem.modem$CURRMODEM.uVid) +uPid=$(uci get modem.modem$CURRMODEM.uPid) +ATCMDD="AT+CGMM" +model=$($ROOTER/gcom/gcom-locked "$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") +L1=$(uci -q get modem.modem$CURRMODEM.L1) +L5=$(uci -q get modem.modem$CURRMODEM.L5) +L6=$(uci -q get modem.modem$CURRMODEM.L6) + +if [ ! $L1 ]; then + exit 0 +fi + +CA3="" +M5="x" +M6="x" +case $uVid in + "2c7c" ) + case $uPid in + "0125" ) # EC25 + #EUX EC25EUXGAR B1/B3/B7/B8/B20/B28A/B38/B40/B41 + #EU EC25EUGAR B1/B3/B7/B8/B20/B28A/B38/B40/B41 + #EC EC25ECGAR + #E EC25EFAR B1/B3/B5/B7/B8/B20/B38/B40/B41 + #AU EC25AUGCR + #AF-FD EC25AFFDR B2/B4/B5/B12/B13/B14/B66/B71 + #AF EC25AFFAR B2/B4/B5/B12/B13/B14/B66/B71 + #A EC25AFAR + CA="" + M1='ATI' + OX=$($ROOTER/gcom/gcom-locked "$CPORT" "run-at.gcom" "$CURRMODEM" "$M1") + REV=$(echo $OX" " | grep -o "Revision: .\+ OK " | tr " " ",") + MODL=$(echo $REV | cut -d, -f2) + EC25AF=$(echo $MODL | grep "EC25AFF") + if [ ! -z "$EC25AF" ]; then # EC25-AF + M2='01011000000111000000000000000000000000000000000000000000000000000100001' + else + EC25AF=$(echo $MODL | grep "EC25E") + if [ ! -z "$EC25AF" ]; then # EC25-E + M2='1010101100000000000100000000000000000101100' + else + EC25AF=$(echo $MODL | grep "EC25AU") + if [ ! -z "$EC25AF" ]; then # EC25-AU + M2='111110110000000000000000000100000000000100' + else # EC25-A + M2='01010000000100' + fi + fi + fi + ;; + "0306" ) # EP06-A + M1='AT+GMR' + OX=$($ROOTER/gcom/gcom-locked "$CPORT" "run-at.gcom" "$CURRMODEM" "$M1") + EP06E=$(echo $OX | grep "EP06E") + if [ ! -z "$EP06E" ]; then # EP06E + M2='101010110000000000010000000100010000010110' + CA="ep06e-bands" + else # EP06A + M2='010110100001100010000000110011000000000010000000000000000000000001' + CA="ep06a-bands" + fi + ;; + "030b" ) # EM060 + M2='111110110001110001110000110111000100011111100101000000000000000001000010' + CA="em060-2xbands" + CA3="" + ;; + "0512" ) # EM12-G + EM12=$(echo $model | grep "EG18") + if [ -z "$EM12" ]; then + M2='111110111001110011111000110111010000011110000000000000000000000001' + CA="em12-2xbands" + CA3="em12-3xbands" + else # EG18 + EM12=$(echo $model | grep "EA") + if [ -z "$EM12" ]; then # NA + M2='01011001000111001000000011001100000000001000000000000000000000000000001000010' + else # EA + M2='101010110000000000010000000100000000010110' + fi + CA="" + CA3="" + fi + ;; + "0620" ) # EM20-G + EM20=$(echo $model | grep "EM20") + if [ ! -z "$EM20" ]; then + M2='111110110001110011110000110111000000011111100101000000000000000001' + CA="em20-2xbands" + CA3="em20-3xbands" + CA4="em20-4xbands" + if [ -e /etc/qfake ]; then + M2='1111101100011100011100001101110101000111111000010000000000000000010000100' + M5='0000000000000000000000000000000000000100100000000000000000000000000000000000111' + M6='1110101100010000000100001001000000000101100000010000000000000000010000100000111' + $ROOTER/luci/celltype.sh $CURRMODEM + NET=$(uci -q get modem.modem$CURRMODEM.netmode) + if [ $NET != "7" ]; then + M5=$M6 # SA mode + L5=$L6 + fi + CA="" + CA3="" + CA4="" + fi + + else + M2='111110110001110011110000110111010000011111100101000000000000000001' + CA="em20-2xbands" + CA3="em20-3xbands" + CA4="em20-4xbands" + fi + ;; + "0801" ) #RM520 + GL=$(echo $model | grep "GL") + if [ ! -z "$GL" ]; then #RM520N-GL + M2='1111101100011100111100001101110101000111111001010000000000000000010000100' + M5='11101011000111000101000011011100000001011000000100000000000000000100011000111110' + M6=$M5 + CA="" + CA3="" + else #RM520N-EU + M2='1010101100000000000100000001000100000101111001000000000000000000000000100' + M5='101010110000000000010000000100000000010110000000000000000000000000000010001111' + M6=$M5 + CA="" + CA3="" + fi + ;; + "0900" ) + M2='111010110000000000010000000100000100011110' + M5='1000000000000000000000000001000000000000100000000000000000000000000000000000111' + M6=$M5 + CA="" + CA3="" + ;; + "0800") # RM500 + f2=$(echo $model | grep "500") + if [ -z "$f2" ]; then #RM502/505/510 + M2='1111101100011100011100001101110101000111111001010000000000000000010000100' + M5='1110101100010100000100001001000000000101100000010000000000000000010000100000111' + M6=$M5 + else + GL=$(echo $model | grep "GL") + if [ ! -z "$GL" ]; then #RM500-GL + M2='1111101100011100111100001101110101000111111001010000000000000000010000100' + M5='0000000000000000000000000000000000000000100000000000000000000000000000000000111' + M6='1110101100010000000100001001000000000101100000010000000000000000010000100000111' + else # RM500-AE + M2='1111101100011100011100001101110101000111111001010000000000000000010000100' + M5='11101011000100000001000010010000000001011000000100000000000000000100001000001110' + M6=$M5 + fi + fi + CA="" + CA3="" + ;; + esac + ;; + "1199" ) + case $uPid in + "68a2" ) # MC7700 + M2='1001000000000000100000000' + CA="" + ;; + "68c0"|"9041"|"901f" ) # MC7354 EM/MC7355 + M2='0101100000001000100000001' + CA="" + ;; + "9070"|"9071"|"9078"|"9079"|"907a"|"907b" ) # EM/MC7455 + M2='11111011000110000001000011000100000000001' + if [ -e /etc/fake ]; then + M2='1111101100011100011100000100110100000000110001010000000000000000010' + fi + CA="mc7455-bands" + ;; + "9090"|"9091"|"90b1" ) + EM7565=$(echo "$model" | grep "7565") + if [ ! -z "$EM7565" ]; then # EM7565 + M2='111110111001100001110000010111010000000011100101000000000000000001' + CA="em7565-2xbands" + CA3="em7565-3xbands" + else + EM7511=$(echo "$model" | grep "7511") + if [ ! -z "$EM7511" ]; then # EM7511 + M2='1111101100011100011100000100110100000000110001010000000000000000010' + CA="em7511-2xbands" + CA3="em7511-3xbands" + else # EM7411 + M2='0101101000011100000000001100000000000000111000010000000000000000010000100' + CA="em7411-2xbands" + CA3="em7411-3xbands" + fi + fi + ;; + esac + ;; + "8087" ) + M2='111110110001100011110000010111000000011110000000000000000000000001' + CA="l850-2xbands" + CA3="l850-3xbands" + ;; + "2cb7" ) + FM150=$(echo "$model" | grep "FM150") + if [ -z "$FM150" ]; then + M2='111110110001100011110000010111000000011110000000000000000000000001' + CA="l850-2xbands" + CA3="l850-3xbands" + else + M2='01011000000100000000000010001100000000000000000000000000000000000100001' + M5='00001000000100000000000000000000000000001000000000000000000000000100001' + CA="" + CA3="" + fi + ;; + "413c" ) + case $uPid in + + "81d7"|"81d8"|"e0b4" |"e0b5"|"1910") + M2='11111011000111001111000011011101000001111110010100000000000000000100' + CA="" + CA3="" + ;; + esac + ;; + "1bc7" ) + case $uPid in + + "1040"|"1041") + L1X=$(uci -q get modem.modem$CURRMODEM.L1X) + M2=$L1X + CA="" + CA3="" + ;; + esac + ;; + * ) + exit 0 + ;; +esac + +reverse $L1 +echo $revstr > /tmp/bmask1 +if [ ! -z $L5 ]; then + reverse $L5 +else + revstr="x" +fi +echo $revstr >> /tmp/bmask1 +if [ ! -z $L6 ]; then + reverse $L6 +else + revstr="x" +fi +echo $revstr >> /tmp/bmask1 +echo $M2 >> /tmp/bmask1 +echo $M5 >> /tmp/bmask1 +if [ -z "$M6" ]; then + M6="x" +fi +echo $M6 >> /tmp/bmask1 +if [ $CA ]; then + echo $CA >> /tmp/bmask1 + if [ $CA3 ]; then + echo $CA3 >> /tmp/bmask1 + if [ $CA4 ]; then + echo $CA4 >> /tmp/bmask1 + fi + fi +fi +mv /tmp/bmask1 /tmp/bmask + diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/mc7455-bands b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/mc7455-bands new file mode 100644 index 0000000..3114071 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/mc7455-bands @@ -0,0 +1,14 @@ +1 8 +2 2 +2 5 +2 12 +2 13 +3 7 +3 20 +4 4 +4 5 +4 12 +4 13 +7 7 +7 20 +41 41 \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/modechge.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/modechge.sh new file mode 100644 index 0000000..7c5ec76 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/modechge.sh @@ -0,0 +1,276 @@ +#!/bin/sh + +ROOTER=/usr/lib/rooter + +MODEMTYPE=$1 +NETMODE=$2 + +# log() { + modlog "ModeChange $CURRMODEM" "$@" +# } + +CURRMODEM=$(uci get modem.general.modemnum) +uci set modem.modem$CURRMODEM.cmode="0" +uci set modem.modem$CURRMODEM.netmode="10" +uci commit modem + +MODEMTYPE=$(uci get modem.modem$CURRMODEM.modemtype) +COMMPORT="/dev/ttyUSB"$(uci get modem.modem$CURRMODEM.commport) + +# ZTE +if [ $MODEMTYPE -eq 1 ]; then + case $NETMODE in + 1*) + ATC="AT+ZSNT=0,0,0" ;; + 2*) + ATC="AT+ZSNT=0,0,1" ;; + 3*) + ATC="AT+ZSNT=1,0,0" ;; + 4*) + ATC="AT+ZSNT=0,0,2" ;; + 5*) + ATC="AT+ZSNT=2,0,0" ;; + 6*) + ATC="AT+ZSNT=0,0,6" ;; + 7*) + ATC="AT+ZSNT=6,0,0" ;; + esac + ATC=$ATC";+ZBANDI=0" +fi + +# Sierra +if [ $MODEMTYPE -eq 2 ]; then + case $NETMODE in + "3" ) + ATC="AT!SELRAT=2" ;; + "5" ) + ATC="AT!SELRAT=1" ;; + "7" ) + ATC="AT!SELRAT=6" ;; + * ) + ATC="AT!SELRAT=0" ;; + esac +fi + +# Huawei LTE +if [ $MODEMTYPE -eq 3 ]; then + case $NETMODE in + 1*) + ATC="AT^SYSCFGEX=\"00\",40000000,2,4,40000000,," ;; + 2*) + ATC="AT^SYSCFGEX=\"010203\",40000000,2,4,40000000,," ;; + 3*) + ATC="AT^SYSCFGEX=\"01\",40000000,2,4,40000000,," ;; + 4*) + ATC="AT^SYSCFGEX=\"020301\",40000000,2,4,40000000,," ;; + 5*) + ATC="AT^SYSCFGEX=\"02\",40000000,2,4,40000000,," ;; + 6*) + ATC="AT^SYSCFGEX=\"030201\",40000000,2,4,40000000,," ;; + 7*) + ATC="AT^SYSCFGEX=\"03\",40000000,2,4,40000000,," ;; + esac +fi + +# Huawei legacy +if [ $MODEMTYPE -eq 4 ]; then + case $NETMODE in + 1*) + ATC="AT^SYSCFG=2,0,40000000,2,4" ;; + 2*) + ATC="AT^SYSCFG=2,1,40000000,2,4" ;; + 3*) + ATC="AT^SYSCFG=13,1,40000000,2,4" ;; + 4*) + ATC="AT^SYSCFG=2,2,40000000,2,4" ;; + 5*) + ATC="AT^SYSCFG=14,2,40000000,2,4" ;; + esac +fi + +# ublox +if [ $MODEMTYPE -eq 5 ]; then + case $NETMODE in + 1*) + ATC="AT+CFUN=4;+URAT=4,3;+CFUN=1,1" ;; + 2*) + ATC="AT+CFUN=4;+URAT=4,0;+CFUN=1,1" ;; + 3*) + ATC="AT+CFUN=4;+URAT=0;+CFUN=1,1" ;; + 4*) + ATC="AT+CFUN=4;+URAT=4,2;+CFUN=1,1" ;; + 5*) + ATC="AT+CFUN=4;+URAT=2;+CFUN=1,1" ;; + 6*) + ATC="AT+CFUN=4;+URAT=4,3;+CFUN=1,1" ;; + 7*) + ATC="AT+CFUN=4;+URAT=4,3;+CFUN=1,1" ;; + esac +fi + +# Quectel +if [ $MODEMTYPE -eq 6 ]; then + CURRMODEM=$(uci -q get modem.general.modemnum) + idV=$(uci -q get modem.modem$CURRMODEM.idV) + idP=$(uci -q get modem.modem$CURRMODEM.idP) + ATCMDD="AT+CGMM" + model=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + EM20=$(echo "$model" | grep "EM20") + if [ $EM20 ]; then + idP="0" + fi + NEWFMT=false + if [ "$idV" = "2c7c" ]; then + if [ "$idP" = "0800" -o "$idP" = "0620" -o "$idP" = "030b" -o "$idP" = "0801" -o "$idP" = "0900" ]; then + NEWFMT=true + fi + fi + case $NETMODE in + "3") + ATC="AT+QCFG=\"nwscanmode\",1" ;; + "5") + if $NEWFMT; then + ATC="AT+QNWPREFCFG=\"mode_pref\",WCDMA" + else + ATC="AT+QCFG=\"nwscanmode\",2" + fi + ;; + "7") + if $NEWFMT; then + ATC="AT+QNWPREFCFG=\"mode_pref\",LTE" + else + ATC="AT+QCFG=\"nwscanmode\",3" + fi + ;; + "8") + ATC="AT+QNWPREFCFG=\"mode_pref\",LTE:NR5G" ;; + "9") + ATC="AT+QNWPREFCFG=\"mode_pref\",NR5G" ;; + *) + if $NEWFMT; then + ATC="AT+QNWPREFCFG=\"mode_pref\",AUTO" + else + ATC="AT+QCFG=\"nwscanmode\",0" + fi + ;; + esac +fi + +# MEIG +if [ $MODEMTYPE -eq 7 ]; then + CURRMODEM=$(uci -q get modem.general.modemnum) + idV=$(uci -q get modem.modem$CURRMODEM.idV) + if [ $idV == "2dee" ]; then + case $NETMODE in + "4") + ATC="AT^SYSCFGEX=\"020304\"" ;; + "5") + ATC="AT^SYSCFGEX=\"02\"" ;; + "6") + ATC="AT^SYSCFGEX=\"030402\"" ;; + "7") + ATC="AT^SYSCFGEX=\"03\"" ;; + "8") + ATC="AT^SYSCFGEX=\"0403\"" ;; + "9") + ATC="AT^SYSCFGEX=\"04\"" ;; + *) + ATC="AT^SYSCFGEX=\"00\"" ;; + esac + else + case $NETMODE in + "3") + ATC="AT+MODODR=3" ;; + "5") + ATC="AT+MODODR=1" ;; + "7") + ATC="AT+MODODR=5" ;; + *) + ATC="AT+MODODR=2" ;; + esac + fi +fi + +# Telit, Foxconn, etc. +if [ $MODEMTYPE -eq 8 ]; then + case $NETMODE in + "3" ) + ATC="AT\$QCNSP=1,0,0" ;; + "5" ) + ATC="AT\$QCNSP=2,0,0" ;; + "7" ) + ATC="AT\$QCNSP=6,0,0" ;; + * ) + ATC="AT\$QCNSP=0,0,0" ;; + esac +fi + +# Fibocom +if [ $MODEMTYPE -eq 9 ]; then + CURRMODEM=$(uci -q get modem.general.modemnum) + idV=$(uci -q get modem.modem$CURRMODEM.idV) + idP=$(uci -q get modem.modem$CURRMODEM.idP) + idPP=${idP:1:1} + if [ "$idPP" = "1" ]; then + case $NETMODE in + "7") + ATC="AT+GTRAT=3" ;; + "8") + ATC="AT+GTRAT=17" ;; + "9") + ATC="AT+GTRAT=14" ;; + *) + ATC="AT+GTRAT=10" ;; + esac + else + case $NETMODE in + "4") + ATC="AT+XACT=4,1" ;; + "5") + ATC="AT+XACT=1" ;; + "7") + ATC="AT+XACT=2" ;; + *) + ATC="AT+XACT=4,2" ;; + esac + fi +fi + +# SIMCom +if [ $MODEMTYPE -eq 10 ]; then + case $NETMODE in + "3") + ATC="AT+CNMP=13" ;; + "5") + ATC="AT+CNMP=14" ;; + "7") + ATC="AT+CNMP=38" ;; + "8") + ATC="AT+CNMP=109" ;; + "9") + ATC="AT+CNMP=71" ;; + *) + ATC="AT+CNMP=1" ;; + esac +fi + +# Quanta, Megafon +if [ $MODEMTYPE -eq 11 ]; then + case $NETMODE in + "5") + ATC="AT^QCNCFG=02" ;; + "7") + ATC="AT^QCNCFG=03" ;; + *) + ATC="AT^QCNCFG=00" ;; + esac +fi + +ATCMDD="$ATC" +OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + +$ROOTER/luci/celltype.sh $CURRMODEM +uci set modem.modem$CURRMODEM.cmode="1" +uci commit modem + +$ROOTER/luci/restart.sh $CURRMODEM diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/modemchge.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/modemchge.sh new file mode 100644 index 0000000..a0fd3e9 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/modemchge.sh @@ -0,0 +1,46 @@ +#!/bin/sh + +TYPE=$1 +DIREC=$2 +source /tmp/modcnt +MODCNT=$MODCNTX + +case $TYPE in +"modem" ) + MODENUM=$(uci get modem.general.modemnum) + ;; +"sms" ) + MODENUM=$(uci get modem.general.smsnum) + ;; +"misc" ) + MODENUM=$(uci get modem.general.miscnum) + ;; +esac + +if [ $DIREC -eq 1 ]; then + let MODENUM=MODENUM+1 + if [ $MODENUM -gt $MODCNT ]; then + MODENUM=1 + fi +else + if [ $MODENUM -eq 1 ]; then + MODENUM=$MODCNT + else + let MODENUM=MODENUM-1 + fi +fi +case $TYPE in +"modem" ) + uci set modem.general.modemnum=$MODENUM + ;; +"sms" ) + uci set modem.general.smsnum=$MODENUM + ;; +"misc" ) + uci set modem.general.miscnum=$MODENUM + uci commit modem + /usr/lib/rooter/luci/mask.sh + ;; +esac +uci commit modem + diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/portchge.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/portchge.sh new file mode 100644 index 0000000..928b60d --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/portchge.sh @@ -0,0 +1,28 @@ +#!/bin/sh + +DIR=$1 + +log() { + modlog "Port change $CURRMODEM" "$@" +} + + +CURRMODEM=$(uci get modem.general.modemnum) +BASEP=$(uci get modem.modem$CURRMODEM.baseport) +MAXP=$(uci get modem.modem$CURRMODEM.maxport) +PORT=$(uci get modem.modem$CURRMODEM.commport) + +log "$DIR" + +if [ $DIR = "up" ]; then + if [ $PORT -lt $MAXP ]; then + PORT=`expr $PORT + 1` + echo 'PORT="'"$PORT"'"' > /tmp/port$CURRMODEM.file + fi +else + if [ $PORT -gt $BASEP ]; then + PORT=`expr $PORT - 1` + echo 'PORT="'"$PORT"'"' > /tmp/port$CURRMODEM.file + fi +fi + diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/protochnge.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/protochnge.sh new file mode 100644 index 0000000..d6d8ff8 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/protochnge.sh @@ -0,0 +1,155 @@ +#!/bin/sh + +ROOTER=/usr/lib/rooter + +NEWMOD=$1 + + log() { + modlog "ProtoChange $CURRMODEM" "$@" + } + +ifname1="ifname" +if [ -e /etc/newstyle ]; then + ifname1="device" +fi + + change_bconf() { + local devname=$1 + local conf=$2 + local mode=$3 + local unconf=0 + log "Switching Modem at $devname to $mode by selecting Cfg# $conf" + echo $unconf >/sys/bus/usb/devices/$devname/bConfigurationValue + sleep 1 + echo $conf >/sys/bus/usb/devices/$devname/bConfigurationValue +} + + chkT77() { + T77=0 + if [ $idV = 413c -a $idP = 81d7 ]; then + T77=1 + elif [ $idV = 413c -a $idP = 81d8 ]; then + T77=1 + elif [ $idV = 0489 -a $idP = e0b4 ]; then + T77=1 + elif [ $idV = 0489 -a $idP = e0b5 ]; then + T77=1 + elif [ $idV = 1bc7 -a $idP = 1910 ]; then + T77=1 + fi +} + + chksierra() { + SIERRAID=0 + if [ $idV = 1199 ]; then + case $idP in + "68aa"|"68a2"|"68a3"|"68a9"|"68b0"|"68b1" ) + SIERRAID=1 + ;; + "68c0"|"9040"|"9041"|"9051"|"9054"|"9056"|"90d3" ) + SIERRAID=1 + ;; + "9070"|"907b"|"9071"|"9079"|"901c"|"9091"|"901f"|"90b1" ) + SIERRAID=1 + ;; + esac + elif [ $idV = 114f -a $idP = 68a2 ]; then + SIERRAID=1 + elif [ $idV = 413c -a $idP = 81a8 ]; then + SIERRAID=1 + elif [ $idV = 413c -a $idP = 81b6 ]; then + SIERRAID=1 + fi +} + +chkquectel() { + QUECTEL=false + if [ "$idV" = "2c7c" ]; then + QUECTEL=true + elif [ "$idV" = "05c6" ]; then + QUELST="9090,9003,9215" + if [[ $(echo "$QUELST" | grep -o "$idP") ]]; then + QUECTEL=true + fi + fi +} + +log "Protocol Change to $NEWMOD" + +CURRMODEM=$(uci get modem.general.modemnum) +CPORT=$(uci get modem.modem$CURRMODEM.commport) +idV=$(uci get modem.modem$CURRMODEM.uVid) +idP=$(uci get modem.modem$CURRMODEM.uPid) + +chkquectel +if $QUECTEL; then + case $NEWMOD in + "1" ) + ATCMDD='AT+QCFG="usbnet",0' + ;; + "2" ) + ATCMDD='AT+QCFG="usbnet",2' + ;; + "3" ) + ATCMDD='AT+QCFG="usbnet",1' + ;; + esac + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") +fi + + chksierra + if [ $SIERRAID -eq 1 ]; then + ATCMDD='AT!ENTERCND="A710"' + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + + case $idP in + "68c0"|"9041"|"901f" ) # MC7354 EM/MC7355 + case $NEWMOD in + "1" ) + ATCMDD='at!UDUSBCOMP=6' + ;; + "2" ) + ATCMDD='at!UDUSBCOMP=8' + ;; + esac + ;; + "9070"|"9071"|"9078"|"9079"|"907a"|"907b" ) # EM/MC7455 + case $NEWMOD in + "1" ) + ATCMDD='at!usbcomp=1,1,10d' + ;; + "2" ) + ATCMDD='at!usbcomp=1,1,1009' + ;; + esac + ;; + "9090"|"9091"|"90b1" ) # EM7565 + case $NEWMOD in + "1" ) + ATCMDD='at!usbcomp=1,3,10d' + ;; + "2" ) + ATCMDD='AT!USBCOMP=1,3,1009' + ;; + esac + ;; + esac + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + ATCMDD='AT!ENTERCND="AWRONG"' + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + fi + + chkT77 + if [ $T77 = "1" ]; then + DEVICE=$(uci get modem.modem$CURRMODEM.device) + if [ $NEWMOD = "1" ]; then + change_bconf $DEVICE 1 QMI + else + change_bconf $DEVICE 2 MBIM + fi + log "T77 $NEWMOD $DEVICE" + fi +sleep 5 + +/usr/lib/rooter/luci/restart.sh $CURRMODEM + diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/restart.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/restart.sh new file mode 100644 index 0000000..dbbe377 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/restart.sh @@ -0,0 +1,53 @@ +#!/bin/sh + +ROOTER=/usr/lib/rooter +ROOTER_LINK="/tmp/links" + +log() { + modlog "Modem Restart/Diisconnect $CURRMODEM" "$@" +} + +ifname1="ifname" +if [ -e /etc/newstyle ]; then + ifname1="device" +fi + +CURRMODEM=$1 +CPORT=$(uci -q get modem.modem$CURRMODEM.commport) +INTER=$(uci get modem.modeminfo$CURRMODEM.inter) + +if [ ! -z "$2" ]; then # disconnect + uci set modem.modem$CURRMODEM.connected=0 + uci commit modem + jkillall getsignal$CURRMODEM + rm -f $ROOTER_LINK/getsignal$CURRMODEM + jkillall con_monitor$CURRMODEM + rm -f $ROOTER_LINK/con_monitor$CURRMODEM + ifdown wan$INTER + $ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "reset.gcom" "$CURRMODEM" +else # restart + uVid=$(uci get modem.modem$CURRMODEM.uVid) + uPid=$(uci get modem.modem$CURRMODEM.uPid) + #if [ $uVid != "2c7c" ]; then + if [ ! -z "$CPORT" ]; then + ATCMDD="AT+CFUN=1,1" + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + fi + log "Hard modem reset done" + #fi + ifdown wan$INTER + uci delete network.wan$CURRMODEM + uci set network.wan$CURRMODEM=interface + uci set network.wan$CURRMODEM.proto=dhcp + uci set network.wan$CURRMODEM.${ifname1}="wan"$CURRMODEM + uci set network.wan$CURRMODEM.metric=$CURRMODEM"0" + uci commit network + /etc/init.d/network reload + echo "1" > /tmp/modgone + log "Hard USB reset done" + + PORT="usb$CURRMODEM" + echo $PORT > /sys/bus/usb/drivers/usb/unbind + sleep 35 + echo $PORT > /sys/bus/usb/drivers/usb/bind +fi diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/scancmd.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/scancmd.sh new file mode 100644 index 0000000..dc6e96d --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/scancmd.sh @@ -0,0 +1,412 @@ +#!/bin/sh + +ROOTER=/usr/lib/rooter + +log() { + modlog "Scan Command $CURRMODEM" "$@" +} + +fibdecode() { + j=$1 + tdec=$2 + mod=$3 + length=${#j} + jx=$j + length=${#jx} + + str="" + i=$((length-1)) + while [ $i -ge 0 ] + do + dgt="0x"${jx:$i:1} + DecNum=`printf "%d" $dgt` + Binary= + Number=$DecNum + while [ $DecNum -ne 0 ] + do + Bit=$(expr $DecNum % 2) + Binary=$Bit$Binary + DecNum=$(expr $DecNum / 2) + done + if [ -z $Binary ]; then + Binary="0000" + fi + len=${#Binary} + while [ $len -lt 4 ] + do + Binary="0"$Binary + len=${#Binary} + done + revstr="" + length=${#Binary} + ii=$((length-1)) + while [ $ii -ge 0 ] + do + revstr=$revstr${Binary:$ii:1} + ii=$((ii-1)) + done + str=$str$revstr + i=$((i-1)) + done + len=${#str} + ii=0 + lst="" + sep="," + hun=101 + if [ $mod = "1" ]; then + sep=":" + hun=1 + fi + while [ $ii -lt $len ] + do + bnd=${str:$ii:1} + if [ $bnd -eq 1 ]; then + if [ $tdec -eq 1 ]; then + jj=$((ii+hun)) + else + if [ $ii -lt 9 ]; then + jj=$((ii+501)) + else + jj=$((ii+5001)) + fi + fi + if [ -z $lst ]; then + lst=$jj + else + lst=$lst$sep$jj + fi + fi + ii=$((ii+1)) + done +} + +CURRMODEM=$(uci get modem.general.miscnum) +COMMPORT="/dev/ttyUSB"$(uci get modem.modem$CURRMODEM.commport) +uVid=$(uci get modem.modem$CURRMODEM.uVid) +uPid=$(uci get modem.modem$CURRMODEM.uPid) +model=$(uci get modem.modem$CURRMODEM.model) +ACTIVE=$(uci get modem.pinginfo$CURRMODEM.alive) +uci set modem.pinginfo$CURRMODEM.alive='0' +uci commit modem +L1=$(uci get modem.modem$CURRMODEM.L1) +length=${#L1} +L1="${L1:2:length-2}" +L1=$(echo $L1 | sed 's/^0*//') +L2=$(uci get modem.modem$CURRMODEM.L2) +L1X=$(uci get modem.modem$CURRMODEM.L1X) +if [ -z $L1X ]; then + L1X="0" +fi + +case $uVid in + "2c7c" ) + M2='AT+QENG="neighbourcell"' + M5="" + case $uPid in + "0125" ) # EC25-A + EC25=$(echo $model | grep "EC25-AF") + if [ ! -z $EC25 ]; then + MX='400000000000003818' + else + MX='81a' + fi + M4='AT+QCFG="band",0,'$MX',0' + ;; + "0306" ) + M1='AT+GMR' + OX=$($ROOTER/gcom/gcom-locked "$CPORT" "run-at.gcom" "$CURRMODEM" "$M1") + EP06E=$(echo $OX | grep "EP06E") + if [ ! -z $EP06E ]; then # EP06E + M3='1a080800d5' + else # EP06-A + M3="2000001003300185A" + fi + M4='AT+QCFG="band",0,'$M3',0' + ;; + "030b" ) # EM060 + M3="420000A7E23B0E38DF" + M4='AT+QCFG="band",0,'$M3',0' + ;; + "0512" ) # EM12-G + EM12=$(echo $model | grep "EG18") + if [ -z "$EM12" ]; then + M3="2000001E0BB1F39DF" + else # EG18 + EM12=$(echo $model | grep "EA") + if [ -z "$EM12" ]; then # NA + M3="4200000100330138A" + else # EA + M3="1A0080800C5" + fi + fi + M4='AT+QCFG="band",0,'$M3',0' + ;; + "0620" ) # EM20-G + EM20=$(echo $model | grep "EM20") + if [ ! -z $EM20 ]; then # EM20 + M3="20000A7E03B0F38DF" + M4='AT+QCFG="band",0,'$M3',0' + if [ -e /etc/qfake ]; then + mask="42000087E2BB0F38DF" + fibdecode $mask 1 1 + M4F='AT+QNWPREFCFG="lte_band",'$lst + log "Fake RM500 $M4F" + fi + + else # EM160 + mask="20000A7E0BB0F38DF" + fibdecode $mask 1 1 + M4='AT+QNWPREFCFG="lte_band",'$lst + fi + ;; + "0800"|"0900"|"0801" ) + + ;; + * ) + M3="AT" + M4='AT+QCFG="band",0,'$M3',0' + ;; + esac + + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$M4") + log "$OX" + if [ ! -z $M5 ]; then + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$M5") + log "$OX" + fi + sleep 5 + ;; + "1199" ) + M2='AT!LTEINFO?' + case $uPid in + + "68c0"|"9041"|"901f" ) # MC7354 EM/MC7355 + M3="101101A" + M3X="0" + M4='AT!BAND=11,"Test",0,'$M3,$M3X + ;; + "9070"|"9071"|"9078"|"9079"|"907a"|"907b" ) # EM/MC7455 + M3="100030818DF" + M3X="0" + M4='AT!BAND=11,"Test",0,'$M3,$M3X + if [ -e /etc/fake ]; then + M4='AT!BAND=11,"Test",0,A300BA0E38DF,2,0,0,0' + fi + ;; + "9090"|"9091"|"90b1" ) # EM7565 + EM7565=$(echo "$model" | grep "7565") + if [ ! -z $EM7565 ]; then + M3="A300BA0E38DF" + M3X="2" + M4='AT!BAND=11,"Test",0,'$M3","$M3X",0,0,0" + else + EM7511=$(echo "$model" | grep "7511") + if [ ! -z $EM7511 ]; then # EM7511 + M3="A300BA0E38DF" + M3X="2" + M4='AT!BAND=11,"Test",0,'$M3","$M3X",0,0,0" + else + M3="87000300385A" + M3X="42" + M4='AT!BAND=11,"Test",0,'$M3","$M3X",0,0,0" + fi + fi + + ;; + * ) + M3="AT" + ;; + esac + log "Set full : $M4" + if [ -e /etc/fake ]; then + M4='AT!BAND=11,"Test",0,'$M3,$M3X + fi + M1='AT!ENTERCND="A710"' + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$M1") + log "$OX" + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$M4") + log "$OX" + M4='AT!BAND=00;!BAND=11' + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$M4") + log "$OX" + ATCMDD='AT!ENTERCND="AWRONG"' + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + ;; + "8087"|"2cb7" ) + rm -f /tmp/scan + echo "Cell Scanner Start ..." > /tmp/scan + echo " " >> /tmp/scan + if [ -e /tmp/scan$CURRMODEM ]; then + SCX=$(cat /tmp/scan$CURRMODEM) + echo "$SCX" >> /tmp/scan + else + echo "No Neighbouring cells were found" >> /tmp/scan + fi + echo " " >> /tmp/scan + echo "Done" >> /tmp/scan + exit 0 + ;; + * ) + rm -f /tmp/scanx + echo "Scan for Neighbouring cells not supported" >> /tmp/scan + uci set modem.pinginfo$CURRMODEM.alive=$ALIVE + uci commit modem + exit 0 + ;; +esac + +export TIMEOUT="10" +OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$M2") +OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$M2") +log "$OX" +ERR=$(echo "$OX" | grep "ERROR") +if [ ! -z $ERR ]; then + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$M2") + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$M2") + log "$OX" +fi +if [ ! -z $ERR ]; then + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$M2") + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$M2") + log "$OX" +fi +log "$OX" +echo "$OX" > /tmp/scanx +rm -f /tmp/scan +echo "Cell Scanner Start ..." > /tmp/scan +echo " " >> /tmp/scan +flg=0 +while IFS= read -r line +do + case $uVid in + "2c7c" ) + qm=$(echo $line" " | grep "+QENG:" | tr -d '"' | tr " " ",") + if [ "$qm" ]; then + INT=$(echo $qm | cut -d, -f3) + BND=$(echo $qm | cut -d, -f5) + PCI=$(echo $qm | cut -d, -f6) + RSSI=$(echo $qm | cut -d, -f9) + BAND=$(/usr/bin/chan2band.sh $BND) + if [ "$INT" = "intra" ]; then + echo "Band : $BAND Signal : $RSSI (dBm) EARFCN : $BND PCI : $PCI (current)" >> /tmp/scan + else + echo "Band : $BAND Signal : $RSSI (dBm) EARFCN : $BND PCI : $PCI" >> /tmp/scan + fi + flg=1 + fi + ;; + "1199" ) + qm=$(echo $line" " | grep "Serving:" | tr -d '"' | tr " " ",") + if [ "$qm" ]; then + read -r line + qm=$(echo $line" " | tr -d '"' | tr " " ",") + BND=$(echo $qm | cut -d, -f1) + PCI=$(echo $qm | cut -d, -f10) + BAND=$(/usr/bin/chan2band.sh $BND) + RSSI=$(echo $qm | cut -d, -f13) + echo "Band : $BAND Signal : $RSSI (dBm) EARFCN : $BND PCI : $PCI (current)" >> /tmp/scan + flg=1 + else + qm=$(echo $line" " | grep "InterFreq:" | tr -d '"' | tr " " ",") + log "$line" + if [ "$qm" ]; then + while [ 1 = 1 ] + do + read -r line + log "$line" + qm="" + qm=$(echo $line" " | grep ":" | tr -d '"' | tr " " ",") + if [ "$qm" ]; then + break + fi + qm=$(echo $line" " | grep "OK" | tr -d '"' | tr " " ",") + if [ "$qm" ]; then + break + fi + qm=$(echo $line" " | tr -d '"' | tr " " ",") + if [ "$qm" = "," ]; then + break + fi + BND=$(echo $qm | cut -d, -f1) + PCI=$(echo $qm | cut -d, -f10) + BAND=$(/usr/bin/chan2band.sh $BND) + RSSI=$(echo $qm | cut -d, -f8) + echo "Band : $BAND Signal : $RSSI (dBm) EARFCN : $BND PCI : $PCI" >> /tmp/scan + flg=1 + done + break + fi + fi + ;; + * ) + + ;; + esac +done < /tmp/scanx + +rm -f /tmp/scanx +if [ $flg -eq 0 ]; then + echo "No Neighbouring cells were found" >> /tmp/scan +fi +echo " " >> /tmp/scan +echo "Done" >> /tmp/scan + +case $uVid in + "2c7c" ) + if [ $uPid != "0800" ]; then + if [ $uPid = 0620 -o $uPid = "0800" -o $uPid = "030b" ]; then + EM20=$(echo $model | grep "EM20") + if [ ! -z $EM20 ]; then # EM20 + M2='AT+QCFG="band",0,'$L1',0' + if [ -e /etc/fake ]; then + fibdecode $L1 1 1 + M2F='AT+QNWPREFCFG="lte_band",'$lst + log "Fake EM160 Band Set "$M2F + fi + else + fibdecode $L1 1 1 + M2='AT+QNWPREFCFG="lte_band",'$lst + fi + else + M4='AT+QCFG="band",0,'$L1',0' + fi + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$M4") + log "$OX" + fi + ;; + "1199" ) + M1='AT!ENTERCND="A710"' + case $uPid in + + "68c0"|"9041"|"901f" ) # MC7354 EM/MC7355 + M4='AT!BAND=11,"Test",0,'$L1X,0 + ;; + "9070"|"9071"|"9078"|"9079"|"907a"|"907b" ) # EM/MC7455 + M4='AT!BAND=11,"Test",0,'$L1X,0 + if [ -e /etc/fake ]; then + M4='AT!BAND=11,"Test",0,'$L1X','$L2',0,0,0' + fi + ;; + "9090"|"9091"|"90b1" ) + M4='AT!BAND=11,"Test",0,'$L1X','$L2',0,0,0' + ;; + esac + log "Set back : $M4" + if [ -e /etc/fake ]; then + M4='AT!BAND=11,"Test",0,00000100030818DF,0' + fi + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$M1") + log "$OX" + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$M4") + log "$OX" + M4='AT!BAND=00;!BAND=11' + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$M4") + log "$OX" + ATCMDD='AT!ENTERCND="AWRONG"' + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + ;; +esac +uci set modem.pinginfo$CURRMODEM.alive=$ACTIVE +uci commit modem + +log "Finished Scan" diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/setcell.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/setcell.sh new file mode 100644 index 0000000..8eadd81 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/setcell.sh @@ -0,0 +1,72 @@ +#!/bin/sh + +ROOTER=/usr/lib/rooter + +log() { + modlog "Lock Cell $CURRMODEM" "$@" +} + +dat="$1" + +CURRMODEM=$(uci -q get modem.general.miscnum) + +dat1=$(echo $dat | tr "|" ",") +dat2=$(echo $dat1 | cut -d, -f1) +if [ $dat2 = "0" ]; then + uci set custom.bandlock.cenable$CURRMODEM='0' +else + ear=$(echo $dat1 | cut -d, -f2) + pc=$(echo $dat1 | cut -d, -f3) + ear1=$(echo $dat1 | cut -d, -f4) + pc1=$(echo $dat1 | cut -d, -f5) + ear2=$(echo $dat1 | cut -d, -f6) + pc2=$(echo $dat1 | cut -d, -f7) + ear3=$(echo $dat1 | cut -d, -f8) + pc3=$(echo $dat1 | cut -d, -f9) + uci set custom.bandlock.cenable$CURRMODEM='1' + uci set custom.bandlock.earfcn$CURRMODEM=$ear + uci set custom.bandlock.pci$CURRMODEM=$pc + uci set custom.bandlock.earfcn1$CURRMODEM=$ear1 + uci set custom.bandlock.pci1$CURRMODEM=$pc1 + uci set custom.bandlock.earfcn2$CURRMODEM=$ear2 + uci set custom.bandlock.pci2$CURRMODEM=$pc2 + uci set custom.bandlock.earfcn3$CURRMODEM=$ear3 + uci set custom.bandlock.pci3$CURRMODEM=$pc3 +fi +uci commit custom + +ifname1="ifname" +if [ -e /etc/newstyle ]; then + ifname1="device" +fi + + +CURRMODEM=$(uci get modem.general.miscnum) +COMMPORT="/dev/ttyUSB"$(uci get modem.modem$CURRMODEM.commport) +CPORT=$(uci -q get modem.modem$CURRMODEM.commport) + +ATCMDD="at+qnwlock=\"common/4g\"" +OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") +if `echo $OX | grep "ERROR" 1>/dev/null 2>&1` +then + ATCMDD="at+qnwlock=\"common/lte\",0" +else + ATCMDD=$ATCMDD",0" +fi +OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") +log "$OX" +sleep 5 +ATCMDD="AT+CFUN=1,1" +OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") +log "Hard modem reset done on /dev/ttyUSB$CPORT to reload drivers" +ifdown wan$CURRMODEM +uci delete network.wan$CURRMODEM +uci set network.wan$CURRMODEM=interface +uci set network.wan$CURRMODEM.proto=dhcp +uci set network.wan$CURRMODEM.${ifname1}="wan"$CURRMODEM +uci set network.wan$CURRMODEM.metric=$CURRMODEM"0" +uci commit network +/etc/init.d/network reload +ifdown wan$CURRMODEM +echo "1" > /tmp/modgone +log "Setting Modem Removal flag (1)" diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/wifiradio.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/wifiradio.sh new file mode 100644 index 0000000..1f791a0 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/wifiradio.sh @@ -0,0 +1,15 @@ +#!/bin/sh +. /lib/functions.sh + +config_cb() { + local type="$1" + local name="$2" + if [ ! -z $type ]; then + if [ $type = "wifi-device" ]; then + echo $name >> /tmp/wifi-device + fi + fi +} + +rm -f /tmp/wifi-device +config_load wireless diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/mbimfind.lua b/rooter/ext-rooter-basic/files/usr/lib/rooter/mbimfind.lua new file mode 100644 index 0000000..7e7e67b --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/mbimfind.lua @@ -0,0 +1,92 @@ +#!/usr/bin/lua + +drv = {} +idV = arg[1] +idP = arg[2] + +retval = 0 +echo = 0 + +printf = function(s,...) + if pflag ~= 0 then + io.write(s:format(...)) + local ss = s:format(...) + if echo == 1 then + os.execute("/usr/lib/rooter/logprint.sh " .. ss) + end + end +end + +function trim(s) + return (s:gsub("^%s*(.-)%s*$", "%1")) +end + +-- MAIN +-- C: #Ifs= 3 Cfg#= 3 Atr=a0 MxPwr=500mA + +Cfgs = 1 +local i=0 +local file = io.open("/tmp/prembim", "r") +repeat + local line = file:read("*line") + if line == nil then + break + end + if string.len(line) > 5 then + s, e = line:find("D:") + if s ~= nil then + cs, ce = line:find("#Cfgs= ") + Cfgs = trim(line:sub(ce+1)) + --printf("Cfgs = %s\n", Cfgs) + end + + s, e = line:find("Vendor=") + if s ~= nil then + cs, ce = line:find(" ", e) + m_idV = trim(line:sub(e+1, cs-1)) + s, e = line:find("ProdID=") + cs, ce = line:find(" ", e) + m_idP = trim(line:sub(e+1, cs-1)) + --printf("%s %s\n", m_idV, m_idP) + if m_idV == idV and m_idP == idP then + if Cfgs == "1" then + break + end + Inter = 0 + repeat + line = file:read("*line") + if line == nil then + break + end + if string.len(line) > 5 then + s, e = line:find("C:") + if s ~= nil then + s, e = line:find("Cfg#= ") + cs, ce = line:find(" ", e+1) + Inter = trim(line:sub(e+1, cs)) + --printf("Inter = %s\n", Inter) + end + s, e = line:find("T:") + if s ~= nil then + break + end + s, e = line:find("Cls=02") + if s ~= nil then + s, e = line:find("Sub=0e Prot=00 Driver=") + if s ~= nil then + retval=tonumber(Inter) + --printf("retval = %d\n", retval) + break + end + end + end + until 1==0 + break + end + end + end +until 1==0 +file:close() + + +os.exit(retval) \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/modeswitch.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/modeswitch.sh new file mode 100644 index 0000000..5d9735e --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/modeswitch.sh @@ -0,0 +1,616 @@ +#!/bin/sh +. /lib/functions/procd.sh + +MODCNT=6 + +ROOTER=/usr/lib/rooter +ROOTER_LINK="/tmp/links" + +modeswitch="/usr/bin/usb_modeswitch" + +log() { + modlog "usb-modeswitch $CURRMODEM" "$@" +} + +sanitize() { + sed -e 's/[[:space:]]\+$//; s/[[:space:]]\+/_/g' "$@" +} + +find_usb_attrs() { + local usb_dir="/sys$DEVPATH" + [ -f "$usb_dir/idVendor" ] || usb_dir="${usb_dir%/*}" + + uVid=$(cat "$usb_dir/idVendor") + uPid=$(cat "$usb_dir/idProduct") + uMa=$(sanitize "$usb_dir/manufacturer") + uPr=$(sanitize "$usb_dir/product") + uSe=$(sanitize "$usb_dir/serial") +} + +display_top() { + log "*****************************************************************" + log "*" +} + +display_bottom() { + log "*****************************************************************" +} + + +display() { + local line1=$1 + log "* $line1" + log "*" +} + +# +# Save Interface variables +# +save_variables() { + echo 'MODSTART="'"$MODSTART"'"' > /tmp/variable.file + echo 'WWAN="'"$WWAN"'"' >> /tmp/variable.file + echo 'USBN="'"$USBN"'"' >> /tmp/variable.file + echo 'ETHN="'"$ETHN"'"' >> /tmp/variable.file + echo 'WDMN="'"$WDMN"'"' >> /tmp/variable.file + echo 'BASEPORT="'"$BASEPORT"'"' >> /tmp/variable.file +} +# +# delay until ROOter Initialization done +# +bootdelay() { + if [ ! -f /tmp/bootend.file ]; then + log "Delay for boot up" + sleep 10 + while [ ! -f /tmp/bootend.file ]; do + sleep 1 + done + sleep 10 + fi +} + +# +# return modem number based on port number +# 0 is not found +# +find_device() { + DEVN=$1 + COUNTER=1 + while [ $COUNTER -le $MODCNT ]; do + EMPTY=$(uci get modem.modem$COUNTER.empty) + if [ $EMPTY -eq 0 ]; then + DEVS=$(uci get modem.modem$COUNTER.device) + if [ $DEVN = $DEVS ]; then + retresult=$COUNTER + return + fi + fi + let COUNTER=COUNTER+1 + done + retresult=0 +} + +# +# check if all modems are inactive or empty +# delete all if nothing active +# +check_all_empty() { + COUNTER=1 + while [ $COUNTER -le $MODCNT ]; do + EMPTY=$(uci get modem.modem$COUNTER.empty) + if [ $EMPTY -eq 0 ]; then + ACTIVE=$(uci get modem.modem$COUNTER.active) + if [ $ACTIVE -eq 1 ]; then + return + fi + fi + let COUNTER=COUNTER+1 + done + COUNTER=1 + while [ $COUNTER -le $MODCNT ]; do + uci delete modem.modem$COUNTER + uci set modem.modem$COUNTER=modem + uci set modem.modem$COUNTER.empty=1 + let COUNTER=COUNTER+1 + done + uci set modem.general.modemnum=1 + uci commit modem + MODSTART=1 + WWAN=0 + USBN=0 + ETHN=1 + WDMN=0 + BASEPORT=0 + if + ifconfig eth1 + then + if [ -e "/sys/class/net/eth1/device/bInterfaceProtocol" ]; then + ETHN=1 + else + ETHN=2 + fi + fi + save_variables + display_top; display "No Modems present"; display_bottom +} + +change_bconf() { + local devname=$1 + local conf=$2 + local mode=$3 + local unconf=0 + log "Switching Modem at $DEVICENAME to $mode by selecting Cfg# $bestcfg" + echo $unconf >/sys/bus/usb/devices/$devname/bConfigurationValue + sleep 1 + echo $conf >/sys/bus/usb/devices/$devname/bConfigurationValue +} + + +# +# Add Modem and connect +# +if [ "$ACTION" = add ]; then + bootdelay + CNTR=0 + while [ -e /tmp/modgone ]; do + sleep 1 + CNTR=`expr $CNTR + 1` + if [ $CNTR -gt 10 ]; then + rm -f /tmp/modgone + break + fi + done + find_usb_attrs + + if echo $DEVICENAME | grep -q ":" ; then + exit 0 + fi + + if [ -z $uMa ]; then + log "Ignoring Unnamed Hub" + exit 0 + fi + + UPR=${uPr} + CT=`echo $UPR | tr '[A-Z]' '[a-z]'` + if echo $CT | grep -q "hub" ; then + log "Ignoring Named Hub" + exit 0 + fi + + if [ $uVid = 1d6b ]; then + log "Ignoring Linux Hub" + exit 0 + fi + +# +# Ignore Ethernet adapters +# + if [ $uVid = 13b1 -a $uPid = 0041 ]; then + exit 0 + elif [ $uVid = 2357 -a $uPid = 0601 ]; then + exit 0 + elif [ $uVid = 0b95 -a $uPid = 772b ]; then + exit 0 + elif [ $uVid = 0b95 -a $uPid = 1790 ]; then + exit 0 + elif [ $uVid = 0bda -a $uPid = 8152 ]; then + exit 0 + fi + + bNumConfs=$(cat /sys/bus/usb/devices/$DEVICENAME/bNumConfigurations) + bNumIfs=$(cat /sys/bus/usb/devices/$DEVICENAME/bNumInterfaces) + + # Uncomment the next line to ignore USB-Serial adapters and similar single-port devices + # if [ $bNumConfs = 1 -a $bNumIfs = 1 ] && exit 0 + + cat /sys/kernel/debug/usb/devices > /tmp/wdrv + lua $ROOTER/protofind.lua $uVid $uPid 0 + retval=$? + + if [ -e /etc/config/mjpg-streamer ]; then + if [ $retval -eq 99 ]; then + log "Start MJPEG Streamer $DEVICENAME" + /etc/init.d/mjpg-streamer start + uci delete mjpg-streamer.camera + uci set mjpg-streamer.camera=mjpg-stream + uci set mjpg-streamer.camera.idv=$DEVICENAME + uci commit mjpg-streamer + exit 0 + fi + fi + if [ -e /etc/config/p910nd ]; then + if [ $retval -eq 98 ]; then + # Check if lp device is plugged in and p910nd is not already started + log "USB Printer device plugged in, starting p910nd" + /etc/init.d/p910nd start + uci delete p910nd.printer + uci set p910nd.printer=printer + uci set p910nd.printer.idv=$DEVICENAME + uci commit p910nd + exit 0 + fi + fi + if [ $retval -eq 97 ]; then + if grep "$uVid:$uPid" /etc/usb-mode.json > /dev/null ; then + log "Modem found" + else + log "Found USB Storage" + exit 0 + fi + fi + + DELAY=1 + if [ -f /tmp/usbwait ]; then + log "Delay for previous modem" + while [ -f /tmp/usbwait ]; do + sleep 1 + let DELAY=$DELAY+1 + if [ $DELAY -gt 15 ]; then + break + fi + done + fi + echo "1" > /tmp/usbwait + + source /tmp/variable.file + source /tmp/modcnt + MODCNT=$MODCNTX + + reinsert=0 + find_device $DEVICENAME + if [ $retresult -gt 0 ]; then + ACTIVE=$(uci get modem.modem$retresult.active) + if [ $ACTIVE = 1 ]; then + rm -f /tmp/usbwait + exit 0 + else + IDP=$(uci get modem.modem$retresult.uPid) + IDV=$(uci get modem.modem$retresult.uVid) + if [ $uVid = $IDV -a $uPid = $IDP ]; then + reinsert=1 + CURRMODEM=$retresult + MODSTART=$retresult + WWANX=$(uci get modem.modem$CURRMODEM.wwan) + if [ -n "$WWANX" ]; then + WWAN=$WWANX + save_variables + fi + WDMNX=$(uci get modem.modem$CURRMODEM.wdm) + if [ -n "$WDMNX" ]; then + WDMN=$WDMNX + save_variables + fi + else + display_top; display "Reinsert of different Modem not allowed"; display_bottom + rm -f /tmp/usbwait + exit 0 + fi + fi + fi + + log "Add : $DEVICENAME: Manufacturer=${uMa:-?} Product=${uPr:-?} Serial=${uSe:-?} $uVid $uPid" + + if [ $MODSTART -gt $MODCNT ]; then + display_top; display "Exceeded Maximun Number of Modems"; display_bottom + exit 0 + fi + + if [ $reinsert = 0 ]; then + CURRMODEM=$MODSTART + fi + + FILEN=$uVid:$uPid + display_top; display "Start of Modem Detection and Connection Information" + display "Product=${uPr:-?} $uVid $uPid"; display_bottom + cat /sys/kernel/debug/usb/devices > /tmp/prembim + lua $ROOTER/mbimfind.lua $uVid $uPid + retval=$? + rm -f /tmp/prembim + if [ ! -e /sbin/umbim ]; then + retval=0 + fi + + while : ; do + bConfig=$(cat /sys/bus/usb/devices/$DEVICENAME/bConfigurationValue) + if [ -n "$bConfig" -a -n "$bNumConfs" ]; then + log "Found Modem at $DEVICENAME in Cfg#= $bConfig from $bNumConfs available" + break + else + sleep 1 + fi + done + + FORCEQMI='03f0:0857 1bc7:1900' + if echo $FORCEQMI | grep -q -i "$FILEN"; then + bestcfg=1 + if [ $bConfig -ne $bestcfg ]; then + change_bconf $DEVICENAME $bestcfg QMI + fi + else + if [ $retval -ne 0 ]; then + display_top; display "Found MBIM Modem at $DEVICENAME with Config of $retval"; display_bottom + if [ $FILEN = "12d1:15c1" ]; then + bestcfg=2 + if [ $bConfig -ne $bestcfg ]; then + change_bconf $DEVICENAME $bestcfg ECM + fi + elif [ $FILEN = "413c:81d7" -o $FILEN = "05c6:9025" ]; then + bestcfg=1 + case $bNumConfs in + "3" ) + change_bconf $DEVICENAME $bestcfg QMI + ;; + "2" ) + if [ $bNumIfs -lt 4 ]; then + change_bconf $DEVICENAME $bestcfg QMI + fi + ;; + esac + elif [ $FILEN = "03f0:9d1d" -a $bNumConfs -eq 3 ]; then + bestcfg=1 + change_bconf $DEVICENAME $bestcfg QMI + else + if [ $bConfig -ne $retval ]; then + change_bconf $DEVICENAME $retval MBIM + fi + fi + else + if grep "$FILEN" /etc/usb-mode.json > /dev/null ; then + procd_open_service "usbmode" + procd_open_instance + procd_set_param command "/sbin/usbmode" -s + procd_close_instance + procd_close_service + else + display_top; display "Device at $DEVICENAME does not have a switch data file"; display_bottom + fi + fi + fi + sleep 10 + usb_dir="/sys$DEVPATH" + idV="$(sanitize "$usb_dir/idVendor")" + idP="$(sanitize "$usb_dir/idProduct")" + display_top; display "Modem at $DEVICENAME switched to : $idV:$idP"; display_bottom + + if [ $idV = 2357 -a $idP = 9000 ]; then + sleep 10 + fi + + cat /sys/kernel/debug/usb/devices > /tmp/wdrv + lua $ROOTER/protofind.lua $idV $idP 1 + retval=$? + if [ $idV = 8087 -a $idP = 095a ]; then + retval=28 + fi + if [ $idV = 2cb7 -a $idP = 000b ]; then + retval=28 + fi + display_top; display "ProtoFind returns : $retval"; display_bottom + rm -f /tmp/wdrv + + if [ $reinsert = 0 ]; then + BASEP=$BASEPORT + if [ -f /tmp/drv ]; then + source /tmp/drv + BASEPORT=`expr $PORTN + $BASEPORT` + fi + fi + rm -f /tmp/drv + + if [ $retval -ne 0 ]; then + log "Found Modem $CURRMODEM" + if [ $reinsert = 0 ]; then + uci set modem.modem$CURRMODEM.empty=0 + uci set modem.modem$CURRMODEM.uVid=$uVid + uci set modem.modem$CURRMODEM.uPid=$uPid + uci set modem.modem$CURRMODEM.idV=$idV + uci set modem.modem$CURRMODEM.idP=$idP + uci set modem.modem$CURRMODEM.device=$DEVICENAME + uci set modem.modem$CURRMODEM.baseport=$BASEP + uci set modem.modem$CURRMODEM.maxport=$BASEPORT + uci set modem.modem$CURRMODEM.proto=$retval + uci set modem.modem$CURRMODEM.maxcontrol=/sys$DEVPATH/descriptors + find_usb_attrs + uci set modem.modem$CURRMODEM.manuf=$uMa + uci set modem.modem$CURRMODEM.model=$uPr + uci set modem.modem$CURRMODEM.serial=$uSe + uci set modem.modem$CURRMODEM.celltype="-" + fi + uci set modem.modem$CURRMODEM.active=1 + uci set modem.modem$CURRMODEM.connected=0 + uci commit modem + if [ -e $ROOTER/modem-led.sh ]; then + $ROOTER/modem-led.sh $CURRMODEM 1 + fi + fi + + if [ $reinsert = 0 -a $retval != 0 ]; then + MODSTART=`expr $MODSTART + 1` + save_variables + fi + +# +# Handle specific modem models +# + case $retval in + "0" ) + # + # ubox GPS module + # + if [ $idV = 1546 ]; then + if echo $uPr | grep -q "GPS"; then + SYMLINK="gps0" + BASEX=`expr 1 + $BASEP` + ln -s /dev/ttyUSB$BASEX /dev/${SYMLINK} + display_top ; display "Hotplug Symlink from /dev/ttyUSB$BASEX to /dev/${SYMLINK} created" + display_bottom + fi + fi + rm -f /tmp/usbwait + exit 0 + ;; + "1" ) + log "Connecting a Sierra Modem" + ln -s $ROOTER/connect/create_connect.sh $ROOTER_LINK/create_proto$CURRMODEM + $ROOTER_LINK/create_proto$CURRMODEM $CURRMODEM & + ;; + "2" ) + log "Connecting a QMI Modem" + ln -s $ROOTER/connect/create_connect.sh $ROOTER_LINK/create_proto$CURRMODEM + $ROOTER_LINK/create_proto$CURRMODEM $CURRMODEM & + ;; + "88" ) + log "Connecting a Quectel Rmnet Modem" + ln -s $ROOTER/connect/create_connect.sh $ROOTER_LINK/create_proto$CURRMODEM + $ROOTER_LINK/create_proto$CURRMODEM $CURRMODEM & + ;; + + "3" ) + log "Connecting a MBIM Modem" + ln -s $ROOTER/connect/create_connect.sh $ROOTER_LINK/create_proto$CURRMODEM + $ROOTER_LINK/create_proto$CURRMODEM $CURRMODEM & + ;; + "6"|"4"|"7"|"24"|"26"|"27" ) + log "Connecting a Huawei NCM Modem" + ln -s $ROOTER/connect/create_connect.sh $ROOTER_LINK/create_proto$CURRMODEM + $ROOTER_LINK/create_proto$CURRMODEM $CURRMODEM & + ;; + "28" ) + log "Connecting a Fibocom NCM Modem" + ln -s $ROOTER/connect/create_connect.sh $ROOTER_LINK/create_proto$CURRMODEM + $ROOTER_LINK/create_proto$CURRMODEM $CURRMODEM & + ;; + "5" ) + log "Connecting a Hostless Modem or Phone" + ln -s $ROOTER/connect/create_hostless.sh $ROOTER_LINK/create_proto$CURRMODEM + $ROOTER_LINK/create_proto$CURRMODEM $CURRMODEM & + ;; + "10"|"11"|"12"|"13"|"14"|"15"|"16" ) + log "Connecting a PPP Modem" + ln -s $ROOTER/ppp/create_ppp.sh $ROOTER_LINK/create_proto$CURRMODEM + $ROOTER_LINK/create_proto$CURRMODEM $CURRMODEM + ;; + "9" ) + log "Connecting an iPhone" + ln -s $ROOTER/connect/create_iphone.sh $ROOTER_LINK/create_proto$CURRMODEM + $ROOTER_LINK/create_proto$CURRMODEM $CURRMODEM + ;; + esac + +fi + +# +# Remove Modem +# +if [ "$ACTION" = remove ]; then + find_usb_attrs + + if echo $DEVICENAME | grep -q ":" ; then + exit 0 + fi + find_device $DEVICENAME + if [ $retresult -gt 0 ]; then + IDP=$(uci get modem.modem$retresult.idP) + IDV=$(uci get modem.modem$retresult.idV) + if [ $uVid = $IDV ]; then + exit 0 + else + INTER=$(uci get modem.modem$retresult.inter) + if [ -z $INTER ]; then + INTER=$retresult + fi + if [ -e $ROOTER/modem-led.sh ]; then + $ROOTER/modem-led.sh $retresult 0 + fi + uci set modem.modem$retresult.active=0 + uci set modem.modem$retresult.connected=0 + uci commit modem + if [ -e /etc/config/mwan3 ]; then + ENB=$(uci get mwan3.wan$retresult.enabled) + if [ ! -z $ENB ]; then + uci set mwan3.wan$INTER.enabled=0 + uci commit mwan3 + fi + fi + SMS=$(uci get modem.modem$CURRMODEM.sms) + if [ $SMS = 1 ]; then + if [ -e /usr/lib/sms/stopsms ]; then + /usr/lib/sms/stopsms $CURRMODEM + fi + fi + ifdown wan$INTER + uci delete network.wan$INTER + uci set network.wan$INTER=interface + uci set network.wan$INTER.proto=dhcp + ifname1="ifname" + if [ -e /etc/newstyle ]; then + ifname1="device" + fi + uci set network.wan$INTER.${ifname1}=" " + uci set network.wan$INTER.metric=$INTER"0" + uci commit network + /etc/init.d/network reload + ifdown wan$INTER + PID=$(ps |grep "getsignal$retresult" | grep -v grep |head -n 1 | awk '{print $1}') + kill -9 $PID + rm -f $ROOTER_LINK/getsignal$retresult + PID=$(ps |grep "reconnect$retresult" | grep -v grep |head -n 1 | awk '{print $1}') + kill -9 $PID + rm -f $ROOTER_LINK/reconnect$retresult + PID=$(ps |grep "create_proto$retresult" | grep -v grep |head -n 1 | awk '{print $1}') + kill -9 $PID + rm -f $ROOTER_LINK/create_proto$retresult + PID=$(ps |grep "processsms$retresult" | grep -v grep |head -n 1 | awk '{print $1}') + kill -9 $PID + rm -f $ROOTER_LINK/processsms$retresult + PID=$(ps |grep "con_monitor$retresult" | grep -v grep |head -n 1 | awk '{print $1}') + kill -9 $PID + rm -f $ROOTER_LINK/con_monitor$retresult + PID=$(ps |grep "mbim_monitor$retresult" | grep -v grep |head -n 1 | awk '{print $1}') + kill -9 $PID + rm -f $ROOTER_LINK/mbim_monitor$retresult + if [ -e /usr/lib/gps/gpskill.sh ]; then + /usr/lib/gps/gpskill.sh $retresult + fi + $ROOTER/signal/status.sh $retresult "No Modem Present" + $ROOTER/log/logger "Disconnect (Removed) Modem #$retresult" + display_top; display "Remove : $DEVICENAME : Modem $retresult"; display_bottom + check_all_empty + rm -f /tmp/usbwait + rm -f /tmp/mdown$retresult + rm -f /tmp/msimdata$retresult + rm -f /tmp/msimnum$retresult + rm -f /tmp/modgone + rm -f /tmp/bmask + rm -f /tmp/simpin$retresult + fi + else + IDV=$(uci get mjpg-streamer.camera.idv) + if [ ! -z $IDV ]; then + if [ $DEVICENAME = $IDV ]; then + uci delete mjpg-streamer.camera + uci commit mjpg-streamer + /etc/init.d/mjpg-streamer stop + log "Stop MJPEG-Streamer" + fi + fi + IDV=$(uci get p910nd.printer.idv) + if [ ! -z $IDV ]; then + if [ $DEVICENAME = $IDV ]; then + uci delete p910nd.printer + uci commit p910nd + if [ ! -d /sys$DEVPATH/*/lp0 -a -f /var/run/p9100d.pid ]; then + log "USB Printer device unplugged, stopping p910nd" + /etc/init.d/p910nd stop + # p910nd does not seem to remove .pid file when stopped, removing it manually + rm /var/run/p9100d.pid + fi + fi + fi + fi +fi + +if [ "$ACTION" = "motion" ]; then + logger webcam motion event +fi + diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/ncmfind.lua b/rooter/ext-rooter-basic/files/usr/lib/rooter/ncmfind.lua new file mode 100644 index 0000000..3e39cb3 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/ncmfind.lua @@ -0,0 +1,63 @@ +#!/usr/bin/lua + +drv = {} +idV = arg[1] +idP = arg[2] + +printf = function(s,...) + io.write(s:format(...)) +end + +function trim(s) + return (s:gsub("^%s*(.-)%s*$", "%1")) +end + +local Inter=0 +local file = io.open("/tmp/wdrv", "r") +repeat + local line = file:read("*line") + if line == nil then + break + end + if string.len(line) > 5 then + s, e = line:find("Vendor=") + if s ~= nil then + cs, ce = line:find(" ", e) + m_idV = trim(line:sub(e+1, cs-1)) + s, e = line:find("ProdID=") + cs, ce = line:find(" ", e) + m_idP = trim(line:sub(e+1, cs-1)) + if m_idV == idV and m_idP == idP then + repeat + line = file:read("*line") + if line == nil then + break + end + if string.len(line) > 5 then + s, e = line:find("Prot=") + if s ~= nil then + cs, ce = line:find(" ", e+1) + proto = trim(line:sub(e+1, cs)) + if proto == "2" or proto == "02" or proto == "12" or proto == "32" or proto == "42" or proto == "62" or proto == "72" then + break + else + s, e = line:find("=option") + if s ~= nil then + Inter = Inter + 1 + end + end + end + s, e = line:find("T:") + if s ~= nil then + break + end + end + until 1==0 + break + end + end + end +until 1==0 +file:close() + +os.exit(Inter) \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/nitz2sys.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/nitz2sys.sh new file mode 100644 index 0000000..1a00770 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/nitz2sys.sh @@ -0,0 +1,29 @@ +#!/bin/sh + +log() { + logger -t "NITZ set time" "$@" +} + +CURRMODEM=$(uci -q get modem.general.modemnum) +COMMPORT="/dev/ttyUSB"$(uci -q get modem.modem$CURRMODEM.commport) +ROOTER=/usr/lib/rooter + +ATCMDD="AT+CTZU?;+CCLK?" +OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") +OX=$OX +SUCCESS=1 +NITZstat=$(echo "$OX" | grep "+CTZU: 1") +if [ -n "$NITZstat" ]; then + DTG=$(echo "$OX" | grep -o "+CCLK:.*" | cut -d\" -f2) + DTGyymmdd=$(echo "$DTG" | cut -d, -f1 | tr '/' '-') + DTGhhmmss=$(echo "$DTG" | cut -d, -f2) + DTGhhmmss=${DTGhhmmss:0:8} + DTGtz=$(echo "$DTG" | grep -o "[-+][0-9]\{1,2\}") + if [ -n "$DTGtz" ]; then + DTGif=$(date +%s -u -s "$DTGyymmdd $DTGhhmmss") + OX=$(date -s @$DTGif) + log "$OX" + SUCCESS=0 + fi +fi +exit $SUCCESS diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/portchge.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/portchge.sh new file mode 100644 index 0000000..968f039 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/portchge.sh @@ -0,0 +1,28 @@ +#!/bin/sh + +DIR=$1 + +log() { + logger -t "port change" "$@" +} + + +CURRMODEM=$(uci get modem.general.modemnum) +BASEP=$(uci get modem.modem$CURRMODEM.baseport) +MAXP=$(uci get modem.modem$CURRMODEM.maxport) +PORT=$(uci get modem.modem$CURRMODEM.commport) + +log "$DIR" + +if [ $DIR = "up" ]; then + if [ $PORT -lt $MAXP ]; then + PORT=`expr $PORT + 1` + echo 'PORT="'"$PORT"'"' > /tmp/port$CURRMODEM.file + fi +else + if [ $PORT -gt $BASEP ]; then + PORT=`expr $PORT - 1` + echo 'PORT="'"$PORT"'"' > /tmp/port$CURRMODEM.file + fi +fi + diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/ppp/create_ppp.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/ppp/create_ppp.sh new file mode 100644 index 0000000..e018901 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/ppp/create_ppp.sh @@ -0,0 +1,247 @@ +#!/bin/sh + +ROOTER=/usr/lib/rooter +ROOTER_LINK="/tmp/links" + +log() { + modlog "Create Connection $CURRMODEM" "$@" +} + +ifname1="ifname" +if [ -e /etc/newstyle ]; then + ifname1="device" +fi + +set_dns() { + local pDNS1=$(uci -q get modem.modeminfo$CURRMODEM.dns1) + local pDNS2=$(uci -q get modem.modeminfo$CURRMODEM.dns2) + local pDNS3=$(uci -q get modem.modeminfo$CURRMODEM.dns3) + local pDNS4=$(uci -q get modem.modeminfo$CURRMODEM.dns4) + + local aDNS="$pDNS1 $pDNS2 $pDNS3 $pDNS4" + local bDNS="" + + echo "$aDNS" | grep -o "[[:graph:]]" &>/dev/null + if [ $? = 0 ]; then + log "Using DNS settings from the Connection Profile" + pdns=1 + for DNSV in $(echo "$aDNS"); do + if [ "$DNSV" != "0.0.0.0" ] && [ -z "$(echo "$bDNS" | grep -o "$DNSV")" ]; then + [ -n "$(echo "$DNSV" | grep -o ":")" ] && continue + bDNS="$bDNS $DNSV" + fi + done + + bDNS=$(echo $bDNS) + if [ $DHCP = 1 ]; then + uci set network.wan$INTER.peerdns=0 + uci set network.wan$INTER.dns="$bDNS" + fi + echo "$bDNS" > /tmp/v4dns$INTER + + bDNS="" + for DNSV in $(echo "$aDNS"); do + if [ "$DNSV" != "0:0:0:0:0:0:0:0" ] && [ -z "$(echo "$bDNS" | grep -o "$DNSV")" ]; then + [ -z "$(echo "$DNSV" | grep -o ":")" ] && continue + bDNS="$bDNS $DNSV" + fi + done + echo "$bDNS" > /tmp/v6dns$INTER + else + log "Using Provider assigned DNS" + pdns=0 + rm -f /tmp/v[46]dns$INTER + fi +} + +save_variables() { + echo 'MODSTART="'"$MODSTART"'"' > /tmp/variable.file + echo 'WWAN="'"$WWAN"'"' >> /tmp/variable.file + echo 'USBN="'"$USBN"'"' >> /tmp/variable.file + echo 'ETHN="'"$ETHN"'"' >> /tmp/variable.file + echo 'WDMN="'"$WDMN"'"' >> /tmp/variable.file + echo 'BASEPORT="'"$BASEPORT"'"' >> /tmp/variable.file +} + +get_connect() { + NAPN=$(uci get modem.modeminfo$CURRMODEM.apn) + NUSER=$(uci get modem.modeminfo$CURRMODEM.user) + NPASS=$(uci get modem.modeminfo$CURRMODEM.passw) + NAUTH=$(uci get modem.modeminfo$CURRMODEM.auth) + PINC=$(uci get modem.modeminfo$CURRMODEM.pincode) + + uci set modem.modem$CURRMODEM.apn=$NAPN + uci set modem.modem$CURRMODEM.user=$NUSER + uci set modem.modem$CURRMODEM.pass=$NPASS + uci set modem.modem$CURRMODEM.auth=$NAUTH + uci set modem.modem$CURRMODEM.pin=$PINC + uci commit modem +} + +CURRMODEM=$1 +source /tmp/variable.file + +MAN=$(uci get modem.modem$CURRMODEM.manuf) +MOD=$(uci get modem.modem$CURRMODEM.model) +BASEP=$(uci get modem.modem$CURRMODEM.baseport) +$ROOTER/signal/status.sh $CURRMODEM "$MAN $MOD" "Connecting" +PROT=$(uci get modem.modem$CURRMODEM.proto) + +DELAY=$(uci get modem.modem$CURRMODEM.delay) +if [ -z $DELAY ]; then + DELAY=5 +fi + +idV=$(uci get modem.modem$CURRMODEM.idV) +idP=$(uci get modem.modem$CURRMODEM.idP) + +cat /sys/kernel/debug/usb/devices > /tmp/cdma +lua $ROOTER/cdmafind.lua $idV $idP +retval=$? +rm -f /tmp/cdma +if [ $retval -eq 1 ]; then + log "Found CDMA modem" +fi + +case $PROT in +"10" ) + if [ $retval -eq 0 ]; then + DP=0 + CP=2 + else + DP=0 + CP=0 + fi + ;; +"11"|"12" ) + if [ $retval -eq 0 ]; then + DP=2 + CP=1 + else + DP=0 + CP=0 + fi + ;; +"13" ) + if [ $retval -eq 0 ]; then + DP=4 + CP=3 + else + DP=0 + CP=0 + fi + ;; +"14" ) + if [ $retval -eq 0 ]; then + DP=3 + CP=2 + else + DP=0 + CP=0 + fi + ;; +"15" ) + if [ $retval -eq 0 ]; then + DP=1 + CP=2 + else + DP=0 + CP=0 + fi + ;; +"16" ) + if [ $retval -eq 0 ]; then + DP=2 + CP=0 + ln -s /dev/ttyACM$CP /dev/ttyUSB$CP + ln -s /dev/ttyACM$DP /dev/ttyUSB$DP + else + DP=0 + CP=0 + fi + ;; +esac +$ROOTER/common/modemchk.lua "$idV" "$idP" "$DP" "$CP" +source /tmp/parmpass + +CPORT=`expr $CPORT + $BASEP` +DPORT=`expr $DPORT + $BASEP` +uci set modem.modem$CURRMODEM.commport=$CPORT +uci set modem.modem$CURRMODEM.dataport=$DPORT +uci set modem.modem$CURRMODEM.service=$retval +uci commit modem + +$ROOTER/common/gettype.sh $CURRMODEM +$ROOTER/connect/get_profile.sh $CURRMODEM +get_connect + +INTER=$(uci get modem.modeminfo$CURRMODEM.inter) +if [ -z $INTER ]; then + INTER=$CURRMODEM +else + if [ $INTER = 0 ]; then + INTER=$CURRMODEM + fi +fi +log "Profile for Modem $CURRMODEM sets interface to WAN$INTER" +OTHER=1 +if [ $CURRMODEM = 1 ]; then + OTHER=2 +fi +EMPTY=$(uci get modem.modem$OTHER.empty) +if [ $EMPTY = 0 ]; then + OINTER=$(uci get modem.modem$OTHER.inter) + if [ ! -z $OINTER ]; then + if [ $INTER = $OINTER ]; then + INTER=1 + if [ $OINTER = 1 ]; then + INTER=2 + fi + log "Switched Modem $CURRMODEM to WAN$INTER as Modem $OTHER is using WAN$OINTER" + fi + fi +fi +uci set modem.modem$CURRMODEM.inter=$INTER +uci commit modem +log "Modem $CURRMODEM is using WAN$INTER" +uci delete network.wan$INTER +uci set network.wan$INTER=interface +uci set network.wan$INTER.${ifname1}=3x-wan$INTER +uci set network.wan$INTER.proto=3x +if [ $retval -eq 0 ]; then + uci set network.wan$INTER.service=umts +else + uci set network.wan$INTER.service=cdma +fi +uci set network.wan$INTER.keepalive=10 +uci set network.wan$INTER.device=/dev/ttyUSB$DPORT +uci set network.wan$INTER.apn=$NAPN +uci set network.wan$INTER.username=$NUSER +uci set network.wan$INTER.auth=$NAUTH +uci set network.wan$INTER.password=$NPASS +uci set network.wan$INTER.pincode=$PINC +uci set network.wan$INTER.metric=$CURRMODEM"0" +uci set network.wan$INTER.currmodem=$CURRMODEM +uci set network.wan$INTER.pppd_options="debug noipdefault" +set_dns +uci commit network + +log "PPP Comm Port : /dev/ttyUSB$CPORT" +log "PPP Data Port : /dev/ttyUSB$DPORT" + +if [ $retval -eq 0 ]; then + case $idV in + "1199"|"0f3d"|"413c"|"2c7c"|"05c6" ) + $ROOTER/luci/celltype.sh $CURRMODEM + ;; + esac + $ROOTER/common/lockchk.sh $CURRMODEM + $ROOTER/sms/check_sms.sh $CURRMODEM & +fi + +if [ -e $ROOTER/modem-led.sh ]; then + $ROOTER/modem-led.sh $CURRMODEM 2 +fi + +rm -f /tmp/usbwait +ifup wan$INTER diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/protofind.lua b/rooter/ext-rooter-basic/files/usr/lib/rooter/protofind.lua new file mode 100644 index 0000000..03f9b47 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/protofind.lua @@ -0,0 +1,254 @@ +#!/usr/bin/lua + +drv = {} +idV = arg[1] +idP = arg[2] +pflag = arg[3] +if pflag == nil then + pflag = 1 +end + +special = {} +-- PPP special cases +-- VID PID port # +special[1] = "1bbb" ; special[2] = "0017" ; special[3] = 13 +special[4] = "12d1" ; special[5] = nil ; special[6] = 10 +special[7] = "1546" ; special[8] = "01a6" ; special[9] = 0 +special[10] = "1546" ; special[11] = "01a5" ; special[12] = 0 +special[13] = "1199" ; special[14] = "68a3" ; special[15] = 14 +special[16] = "2001" ; special[17] = "7e35" ; special[18] = 15 + + +retval = 0 +echo = 1 + +printf = function(s,...) + if pflag ~= 0 then + io.write(s:format(...)) + local ss = s:format(...) + if echo == 1 then + os.execute("/usr/lib/rooter/logprint.sh " .. ss) + end + end +end + +function trim(s) + return (s:gsub("^%s*(.-)%s*$", "%1")) +end + +function checkserial() + local got = 0 + j = 1 + repeat + if drv[j] ~= nil then + if drv[j] == "option" or drv[j] == "qcserial" or drv[j] == "usb_serial" or drv[j] == "sierra" then + got = 1 + break + end + j = j + 1 + end + until drv[j] == nil + return got +end + +function countserial() + local got = 0 + j = 1 + repeat + if drv[j] ~= nil then + if drv[j] == "option" or drv[j] == "sierra" or drv[j] == "usb_serial" or drv[j] == "qcserial" then + got = got + 1 + end + j = j + 1 + end + until drv[j] == nil + return got +end + +-- MAIN + +local t = {} + +local i=0 +local file = io.open("/tmp/wdrv", "r") +repeat + local line = file:read("*line") + if line == nil then + break + end + if string.len(line) > 5 then + s, e = line:find("Vendor=") + if s ~= nil then + cs, ce = line:find(" ", e) + m_idV = trim(line:sub(e+1, cs-1)) + s, e = line:find("ProdID=") + cs, ce = line:find(" ", e) + m_idP = trim(line:sub(e+1, cs-1)) + if m_idV == idV and m_idP == idP then + repeat + line = file:read("*line") + if line == nil then + break + end + if string.len(line) > 5 then + s, e = line:find("T:") + if s ~= nil then + break + end + s, e = line:find("Cls=02") + if s ~= nil then + t[i] = trim(line:sub(63)) + i = i + 1 + end + s, e = line:find("Cls=ff") + if s ~= nil then + t[i] = trim(line:sub(63)) + i = i + 1 + end + s, e = line:find("1 Cls=e0") + if s ~= nil then + t[i] = trim(line:sub(63)) + i = i + 1 + end + s, e = line:find("Cls=0a") + if s ~= nil then + t[i] = trim(line:sub(63)) + i = i + 1 + end + s, e = line:find("Cls=0e") + if s ~= nil then + t[i] = trim(line:sub(63)) + i = i + 1 + end + s, e = line:find("Cls=07") + if s ~= nil then + t[i] = trim(line:sub(63)) + i = i + 1 + end + s, e = line:find("Cls=08") + if s ~= nil then + t[i] = trim(line:sub(63)) + i = i + 1 + end + end + until 1==0 + break + end + end + end +until 1==0 +file:close() +if i > 0 then + file = io.open("/tmp/drv", "w") + for j=0,i-1 do + drv[j+1] = t[j] + drver = string.format("%s%d%s%q", "DRIVER", j+1, "=", t[j]) + file:write(drver .. "\n") + end + ports = countserial() + drver = string.format("%s%s%d%s", "PORTN", "=\"", ports, "\"") + file:write(drver .. "\n") + file:close() +end + +i = 1 +repeat + if drv[i] ~= nil then + printf("Driver Name : %d %s\n", i, drv[i]) + i = i + 1 + end +until drv[i] == nil + +i = 1 +repeat + if drv[i] ~= nil then + if drv[i] == "sierra_net" then + retval = 1 + break + end + if drv[i] == "qmi_wwan" then + retval = 2 + break + end + + if drv[i] == "qmi_wwan_q" then + retval = 88 + break + end + + if drv[i] == "cdc_mbim" then + retval = 3 + break + end + if drv[i] == "huawei_cdc_ncm" then + if i == 2 then + retval = 4 + else + if i == 3 then + retval = 6 + else + retval = 7 + end + end + break + end + if drv[i] == "cdc_ncm" then + if i == 2 then + retval = 24 + else + if i == 3 then + retval = 26 + else + retval = 27 + end + end + break + end + if drv[i] == "cdc_ether" or drv[i] == "rndis_host" then + retval = 5 + break + end + if drv[i] == "ipheth" then + retval = 9 + break + end + if drv[i] == "uvcvideo" then + retval = 99 + break + end + if drv[i] == "usblp" then + retval = 98 + break + end + if drv[i] == "usb-storage" then + retval = 97 + end + i = i + 1 + end +until drv[i] == nil + +if retval == 0 then + if checkserial() == 1 then + retval = 88 + k = 1 + vendor = special[k] + while vendor ~= nil do + if idV == vendor then + if special[k+1] == nil then + retval = special[k+2] + break + else + if special[k+1] == idP then + retval = special[k+2] + break + end + end + end + k = k + 3 + vendor = special[k] + end + end +end + +os.exit(retval) + diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/pwrtoggle.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/pwrtoggle.sh new file mode 100644 index 0000000..aaa15c7 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/pwrtoggle.sh @@ -0,0 +1,181 @@ +#!/bin/sh + +ROOTER=/usr/lib/rooter +ROOTER_LINK="/tmp/links" + +log() { + modlog "Power Toggle $CURRMODEM" "$@" +} + +ifname1="ifname" +if [ -e /etc/newstyle ]; then + ifname1="device" +fi + +waitfor() { + CNTR=0 + while [ -e /tmp/modgone ]; do + sleep 1 + CNTR=`expr $CNTR + 1` + if [ $CNTR -gt 35 ]; then + rm -f /tmp/modgone + break + fi + done +} + +rebind() { + CFUNDONE=false + ARG=$1 + CURRMODEM=$(echo "${ARG: -1}") + PROT=$(uci -q get modem.modem$CURRMODEM.proto) + CPORT=$(uci -q get modem.modem$CURRMODEM.commport) + if [ -n "$CPORT" ]; then + VENDOR=$(uci -q get modem.modem$CURRMODEM.idV) + PRODUCT=$(uci -q get modem.modem$CURRMODEM.idP) + # list vendors that do not fully support 3GPP +CFUN + NOCFUN="2c7c" # Quectel will stuck after CFUN, so not using that method at all + case $VENDOR in + "12d1" ) + ATCMDD="AT^RESET" + ;; + "2c7c" ) + ATCMDD="AT" + ;; + * ) + ATCMDD="AT+CFUN=1,1" + ;; + esac + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + if `echo ${OX} | grep "OK" 1>/dev/null 2>&1` && \ + [[ ! `echo $NOCFUN | grep -o "$VENDOR"` ]]; then + CFUNDONE=true + log "Hard modem reset done on /dev/ttyUSB$CPORT to reload drivers" + ifdown wan$CURRMODEM + uci delete network.wan$CURRMODEM + uci set network.wan$CURRMODEM=interface + uci set network.wan$CURRMODEM.proto=dhcp + uci set network.wan$CURRMODEM.${ifname1}="wan"$CURRMODEM + uci set network.wan$CURRMODEM.metric=$CURRMODEM"0" + uci commit network + /etc/init.d/network reload + ifdown wan$CURRMODEM + echo "1" > /tmp/modgone + log "Setting Modem Removal flag (1)" + fi + fi + if ! $CFUNDONE; then + PORT=$1 + log "Re-binding USB driver on $PORT to reset modem" + echo $PORT > /sys/bus/usb/drivers/usb/unbind + sleep 35 + echo $PORT > /sys/bus/usb/drivers/usb/bind + ifdown wan$CURRMODEM + uci delete network.wan$CURRMODEM + uci set network.wan$CURRMODEM=interface + uci set network.wan$CURRMODEM.proto=dhcp + uci set network.wan$CURRMODEM.${ifname1}="wan"$CURRMODEM + uci set network.wan$CURRMODEM.metric=$CURRMODEM"0" + uci commit network + /etc/init.d/network reload + ifdown wan$CURRMODEM + echo "1" > /tmp/modgone + log "Setting Modem Removal flag (2)" + if [[ -n "$CPORT" ]] && [[ ! `echo $NOCFUN | grep -o "$VENDOR"` ]]; then + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + sleep 30 + else + if [ -f $ROOTER_LINK/reconnect$CURRMODEM ]; then + $ROOTER_LINK/reconnect$CURRMODEM $CURRMODEM & + fi + fi + fi +} + +power_toggle() { + MODE=$1 + REBIND=false + if [ -f "/tmp/gpiopin" ]; then + rm -f /tmp/modgone + source /tmp/gpiopin + if [ -f "/tmp/gpioname" ]; then + source /tmp/gpioname + else + echo "$GPIOPIN" > /sys/class/gpio/unexport + echo "$GPIOPIN" > /sys/class/gpio/export + if [ $? -eq 0 ]; then + echo "out" > /sys/class/gpio/gpio$GPIOPIN/direction + if [ $? -ne 0 ]; then + REBIND=true + fi + else + REBIND=true + fi + fi + if ! $REBIND; then + if [ -z $GPIOPIN2 ]; then + if [ -z $GPIONAME ]; then + GPIOT="gpio$GPIOPIN" + else + GPIOT=$GPIONAME + fi + echo 0 > /sys/class/gpio/$GPIOT/value + waitfor + echo 1 > /sys/class/gpio/$GPIOT/value + else + if [ -z $GPIONAME2 ]; then + echo "$GPIOPIN2" > /sys/class/gpio/unexport + echo "$GPIOPIN2" > /sys/class/gpio/export + echo "out" > /sys/class/gpio/gpio$GPIOPIN2/direction + + GPIOT2="gpio$GPIOPIN2" + else + GPIOT2=$GPIONAME2 + fi + if [ -z $GPIONAME ]; then + GPIOT="gpio$GPIOPIN" + else + GPIOT=$GPIONAME + fi + if [ $MODE = 1 ]; then + echo 0 > /sys/class/gpio/$GPIOT/value + waitfor + echo 1 > /sys/class/gpio/$GPIOT/value + fi + if [ $MODE = 2 ]; then + echo 0 > /sys/class/gpio/$GPIOT2/value + waitfor + echo 1 > /sys/class/gpio/$GPIOT2/value + fi + if [ $MODE = 3 ]; then + echo 0 > /sys/class/gpio/$GPIOT/value + echo 0 > /sys/class/gpio/$GPIOT2/value + waitfor + echo 1 > /sys/class/gpio/$GPIOT/value + echo 1 > /sys/class/gpio/$GPIOT2/value + fi + sleep 2 + fi + echo "1" > /tmp/modgone + log "Power Toggle Modem" + log "Setting Modem Removal flag (3)" + fi + else + REBIND=true + fi + if $REBIND; then + # unbind/bind driver from USB to reset modem when power toggle is selected, but not available + if [ $MODE = 1 ]; then + PORT="usb1" + rebind $PORT + fi + if [ $MODE = 2 ]; then + PORT="usb2" + rebind $PORT + fi + echo "1" > /tmp/modgone + log "Setting Modem Removal flag (4)" + fi +} + +power_toggle $1 diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/shutall.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/shutall.sh new file mode 100644 index 0000000..32aabd9 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/shutall.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +ROOTER=/usr/lib/rooter +CURRMODEM=1 +COMMPORT=$(uci get modem.modem$CURRMODEM.commport) +if [ -n "$COMMPORT" ]; then + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$COMMPORT" "run-at.gcom" "$CURRMODEM" "AT+CFUN=0") +fi +CURRMODEM=2 +COMMPORT=$(uci get modem.modem$CURRMODEM.commport) +if [ -n "$COMMPORT" ]; then + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$COMMPORT" "run-at.gcom" "$CURRMODEM" "AT+CFUN=0") +fi +poweroff diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/signal/basedata.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/signal/basedata.sh new file mode 100644 index 0000000..6357516 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/signal/basedata.sh @@ -0,0 +1,79 @@ +#!/bin/sh + +ROOTER=/usr/lib/rooter + +log() { + logger -t "basedata" "$@" +} + +CURRMODEM=$1 +COMMPORT=$2 + +get_base() { + echo "0" > /tmp/block + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "baseinfo.gcom" "$CURRMODEM") + O=$($ROOTER/common/processat.sh "$OX") + rm -f /tmp/block +} + +get_base + +DOWN=$(echo "$O" | awk -F[,] '/\+CGEQNEG:/ {printf "%s", $4}') +if [ "x$DOWN" != "x" ]; then + UP=$(echo "$O" | awk -F[,] '/\+CGEQNEG:/ {printf "%s", $3}') + DOWN=$DOWN" kbps Down | " + UP=$UP" kbps Up" +else + DOWN="-" + UP="-" +fi + +MANUF=$(echo "$O" | awk -F[:] '/Manufacturer:/ { print $2}') +if [ "x$MANUF" = "x" ]; then + MANUF=$(uci get modem.modem$CURRMODEM.manuf) +fi + +MODEL=$(echo "$O" | awk -F[,\ ] '/^\+MODEL:/ {print $2}') +if [ "x$MODEL" != "x" ]; then + MODEL=$(echo "$MODEL" | sed -e 's/"//g') + if [ $MODEL = 0 ]; then + MODEL = "mf820" + fi +else + MODEL=$(uci get modem.modem$CURRMODEM.model) +fi +MODEM=$MANUF" "$MODEL + +pval=$(uci get modem.modem$CURRMODEM.proto) +case $pval in +"1" ) + PROTO="Direct-IP" + ;; +"2" ) + PROTO="QMI" + ;; +"88" ) + PROTO="QUECTEL RMNET" + ;; +"3"|"30" ) + PROTO="MBIM" + ;; +"6"|"4"|"7"|"24"|"26"|"27"|"28" ) + PROTO="NCM" + ;; +"10"|"11"|"12"|"13"|"14"|"15" ) + PROTO="PPP" + ;; +"5" ) + PROTO="Ethernet" + ;; +"9" ) + PROTO="ipheth" + ;; +esac + +echo 'MODEM="'"$MODEM"'"' >> /tmp/base$CURRMODEM.file +echo 'DOWN="'"$DOWN"'"' >> /tmp/base$CURRMODEM.file +echo 'UP="'"$UP"'"' >> /tmp/base$CURRMODEM.file +echo 'PROTO="'"$PROTO"'"' >> /tmp/base$CURRMODEM.file + diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/signal/celldata.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/signal/celldata.sh new file mode 100644 index 0000000..4e163f7 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/signal/celldata.sh @@ -0,0 +1,136 @@ +#!/bin/sh + +ROOTER=/usr/lib/rooter + +CURRMODEM=$1 +COMMPORT=$2 + +if [ -e /etc/nocops ]; then + echo "0" > /tmp/block + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "cellinfo0.gcom" "$CURRMODEM") + rm -f /tmp/block +else + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "cellinfo0.gcom" "$CURRMODEM") +fi +OY=$($ROOTER/gcom/gcom-locked "$COMMPORT" "cellinfo.gcom" "$CURRMODEM") +OXx=$OX + +OX=$(echo $OX | tr 'a-z' 'A-Z') +OY=$(echo $OY | tr 'a-z' 'A-Z') +OX=$OX" "$OY + +COPS="-" +COPS_MCC="-" +COPS_MNC="-" +COPSX=$(echo $OXx | grep -o "+COPS: [01],0,.\+," | cut -d, -f3 | grep -o "[^\"]\+") + +if [ "x$COPSX" != "x" ]; then + COPS=$COPSX +fi + +COPSX=$(echo $OX | grep -o "+COPS: [01],2,.\+," | cut -d, -f3 | grep -o "[^\"]\+") + +if [ "x$COPSX" != "x" ]; then + COPS_MCC=${COPSX:0:3} + COPS_MNC=${COPSX:3:3} + if [ "$COPS" = "-" ]; then + COPS=$(awk -F[\;] '/'$COPS'/ {print $2}' $ROOTER/signal/mccmnc.data) + [ "x$COPS" = "x" ] && COPS="-" + fi +fi + +if [ "$COPS" = "-" ]; then + COPS=$(echo "$O" | awk -F[\"] '/^\+COPS: 0,0/ {print $2}') + if [ "x$COPS" = "x" ]; then + COPS="-" + COPS_MCC="-" + COPS_MNC="-" + fi +fi +COPS_MNC=" "$COPS_MNC + +OX=$(echo "${OX//[ \"]/}") + +CID="" +CID5="" +RAT="" +REGV=$(echo "$OX" | grep -o "+C5GREG:2,[0-9],[A-F0-9]\{2,6\},[A-F0-9]\{5,10\},[0-9]\{1,2\}") +if [ -n "$REGV" ]; then + LAC5=$(echo "$REGV" | cut -d, -f3) + LAC5=$LAC5" ($(printf "%d" 0x$LAC5))" + CID5=$(echo "$REGV" | cut -d, -f4) + CID5L=$(printf "%010X" 0x$CID5) + RNC5=${CID5L:1:6} + RNC5=$RNC5" ($(printf "%d" 0x$RNC5))" + CID5=${CID5L:7:3} + CID5="Short $(printf "%X" 0x$CID5) ($(printf "%d" 0x$CID5)), Long $(printf "%X" 0x$CID5L) ($(printf "%d" 0x$CID5L))" + RAT=$(echo "$REGV" | cut -d, -f5) +fi +REGV=$(echo "$OX" | grep -o "+CEREG:2,[0-9],[A-F0-9]\{2,4\},[A-F0-9]\{5,8\}") +REGFMT="3GPP" +if [ -z "$REGV" ]; then + REGV=$(echo "$OX" | grep -o "+CEREG:2,[0-9],[A-F0-9]\{2,4\},[A-F0-9]\{1,3\},[A-F0-9]\{5,8\}") + REGFMT="SW" +fi +if [ -n "$REGV" ]; then + LAC=$(echo "$REGV" | cut -d, -f3) + LAC=$(printf "%04X" 0x$LAC)" ($(printf "%d" 0x$LAC))" + if [ $REGFMT = "3GPP" ]; then + CID=$(echo "$REGV" | cut -d, -f4) + else + CID=$(echo "$REGV" | cut -d, -f5) + fi + CIDL=$(printf "%08X" 0x$CID) + RNC=${CIDL:1:5} + RNC=$RNC" ($(printf "%d" 0x$RNC))" + CID=${CIDL:6:2} + CID="Short $(printf "%X" 0x$CID) ($(printf "%d" 0x$CID)), Long $(printf "%X" 0x$CIDL) ($(printf "%d" 0x$CIDL))" + +else + REGV=$(echo "$OX" | grep -o "+CREG:2,[0-9],[A-F0-9]\{2,4\},[A-F0-9]\{2,8\}") + if [ -n "$REGV" ]; then + LAC=$(echo "$REGV" | cut -d, -f3) + CID=$(echo "$REGV" | cut -d, -f4) + if [ ${#CID} -gt 4 ]; then + LAC=$(printf "%04X" 0x$LAC)" ($(printf "%d" 0x$LAC))" + CIDL=$(printf "%08X" 0x$CID) + RNC=${CIDL:1:3} + CID=${CIDL:4:4} + CID="Short $(printf "%X" 0x$CID) ($(printf "%d" 0x$CID)), Long $(printf "%X" 0x$CIDL) ($(printf "%d" 0x$CIDL))" + else + LAC="" + fi + else + LAC="" + fi +fi +REGSTAT=$(echo "$REGV" | cut -d, -f2) +if [ "$REGSTAT" == "5" -a "$COPS" != "-" ]; then + COPS_MNC=$COPS_MNC" (Roaming)" +fi +if [ -n "$CID" -a -n "$CID5" ] && [ "$RAT" == "13" -o "$RAT" == "10" ]; then + LAC="4G $LAC, 5G $LAC5" + CID="4G $CID
                                                                        5G $CID5" + RNC="4G $RNC, 5G $RNC5" +elif [ -n "$CID5" ]; then + LAC=$LAC5 + CID=$CID5 + RNC=$RNC5 +fi +if [ -z "$LAC" ]; then + LAC="-" + CID="-" + RNC="-" +fi + +{ + echo 'COPS="'"$COPS"'"' + echo 'COPS_MCC="'"$COPS_MCC"'"' + echo 'COPS_MNC="'"$COPS_MNC"'"' + echo 'LAC="'"$LAC"'"' + echo 'LAC_NUM="'""'"' + echo 'CID="'"$CID"'"' + echo 'CID_NUM="'""'"' + echo 'RNC="'"$RNC"'"' + echo 'RNC_NUM="'""'"' +} > /tmp/cell$CURRMODEM.file diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/signal/celltype.lua b/rooter/ext-rooter-basic/files/usr/lib/rooter/signal/celltype.lua new file mode 100644 index 0000000..62b8ab5 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/signal/celltype.lua @@ -0,0 +1,142 @@ +#!/usr/bin/lua + +modem = arg[1] +numb = arg[2] +echo = 0 + +datalist = {} +celllist = {} + +datalist[1] = "320u" +celllist[1] = 2 +datalist[2] = "330u" +celllist[2] = 2 +datalist[3] = "e3276" +celllist[3] = 3 +datalist[4] = "e398" +celllist[4] = 3 +datalist[5] = "e389" +celllist[5] = 3 +datalist[6] = "e392" +celllist[6] = 3 +datalist[7] = "e397" +celllist[7] = 3 +datalist[8] = "e8278" +celllist[8] = 3 +datalist[9] = "mf820" +celllist[9] = 3 +datalist[10] = "mf821" +celllist[10] = 3 +datalist[11] = "k5005" +celllist[11] = 3 +datalist[12] = "k5007" +celllist[12] = 3 +datalist[13] = "l800" +celllist[13] = 3 +datalist[14] = "e398" +celllist[14] = 3 +datalist[15] = "mf880" +celllist[15] = 3 +datalist[16] = "e3272" +celllist[16] = 3 +datalist[17] = "e3372" +celllist[17] = 3 +datalist[18] = "lte" +celllist[18] = 3 +datalist[19] = "340u" +celllist[19] = 2 +datalist[20] = "mf91d" +celllist[20] = 3 +datalist[21] = "mf825a" +celllist[21] = 3 +datalist[22] = "mf826" +celllist[22] = 3 +datalist[23] = "313u" +celllist[23] = 2 +datalist[24] = "341u" +celllist[24] = 2 +datalist[25] = "em74" +celllist[25] = 2 +datalist[26] = "mc74" +celllist[26] = 2 +datalist[27] = "em75" +celllist[27] = 2 +datalist[28] = "ec2" +celllist[28] = 3 +datalist[29] = "em06" +celllist[29] = 2 +datalist[30] = "ep06" +celllist[30] = 2 +datalist[31] = "slm750" +celllist[31] = 3 +datalist[32] = "bg96" +celllist[32] = 3 +datalist[33] = "em12" +celllist[33] = 2 +datalist[34] = "em20" +celllist[34] = 2 +datalist[35] = "rm5" +celllist[35] = 4 +datalist[36] = "l850" +celllist[36] = 2 +datalist[37] = "l860" +celllist[37] = 2 +datalist[38] = "fm15" +celllist[38] = 4 +datalist[39] = "em18" +celllist[39] = 2 +datalist[40] = "4105" +celllist[40] = 2 +datalist[41] = "em919" +celllist[41] = 4 +datalist[42] = "em16" +celllist[42] = 2 +datalist[43] = "sim820" +celllist[43] = 4 +datalist[44] = "mc73" +celllist[44] = 2 +datalist[45] = "eg25" +celllist[45] = 2 +datalist[46] = "srm8" +celllist[46] = 4 +datalist[47] = "4087" +celllist[47] = 3 +datalist[48] = "rg5" +celllist[48] = 4 +datalist[49] = "eg12" +celllist[49] = 2 +datalist[50] = "eg18" +celllist[50] = 2 +datalist[51] = "megafon" +celllist[51] = 2 +datalist[52] = "ln9" +celllist[52] = 2 + +printf = function(s,...) + if echo == 0 then + io.write(s:format(...)) + else + ss = s:format(...) + os.execute("/usr/lib/rooter/logprint.sh " .. ss) + end +end + +found = 3 +index = 1 +line = datalist[index] +data = string.lower(modem) + +while line ~= nil do + s, e = string.find(data, line) + if s ~= nil then + found = celllist[index] + break + end + index = index + 1 + line = datalist[index] +end + +file = io.open("/tmp/celltype" .. numb, "w") +cell = string.format("%s%s%s%s", "CELL", "=\"", found, "\"") +file:write(cell.. "\n") +file:close() diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/signal/huaweihostless.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/signal/huaweihostless.sh new file mode 100644 index 0000000..aa3fd3f --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/signal/huaweihostless.sh @@ -0,0 +1,205 @@ +#!/bin/sh + +ROOTER=/usr/lib/rooter + +log() { + logger -t "hostless " "$@" +} + +TMPFILE="/tmp/XXXXXX" + +handle_timeout(){ + local wget_pid="$1" + local count=0 + ps | grep -v grep | grep $wget_pid + res="$?" + while [ "$res" = 0 -a $count -lt "$((TIMEOUT))" ]; do + sleep 1 + count=$((count+1)) + ps | grep -v grep | grep $wget_pid + res="$?" + done + + if [ "$res" = 0 ]; then + log "Killing process on timeout" + kill "$wget_pid" 2> /dev/null + ps | grep -v grep | grep $wget_pid + res="$?" + if [ "$res" = 0 ]; then + log "Killing process on timeout" + kill -9 $wget_pid 2> /dev/null + fi + fi +} + +make_status() { + echo "$IP" > /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "$CSQ" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "$MODEM" >> /tmp/status$CURRMODEM.file + echo "$COPS" >> /tmp/status$CURRMODEM.file + echo "$NETWORK" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "$COPS_MCC" >> /tmp/status$CURRMODEM.file + echo "$COPS_MNC" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo " " >> /tmp/status$CURRMODEM.file + echo " " >> /tmp/status$CURRMODEM.file + echo "$MONSTAT" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "$CONN" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "Hostless/Phone" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file +} + +get_signal() { + TIMEOUT=3 + wget http://$IP/api/monitoring/status --load-cookies cookie -O $TMPFILE > /dev/null 2>&1 & + handle_timeout "$!" + local in_CurrentNetworkType="`cat $TMPFILE | grep \"\" | cut -d \">\" -f 2 | cut -d \"<\" -f 1`" + if [ -z $in_CurrentNetworkType ]; then + NETWORK="-" + else + [ "$in_CurrentNetworkType" = "19" ] && NETWORK="LTE" # LTE + [ "$in_CurrentNetworkType" = "9" ] && NETWORK="HSPA+" # HSPA+ + [ "$in_CurrentNetworkType" = "7" ] && NETWORK="HSPA" # HSPA + [ "$in_CurrentNetworkType" = "6" ] && NETWORK="HSUPA" # HSUPA + [ "$in_CurrentNetworkType" = "5" ] && NETWORK="HSDPA" # HSDPA + [ "$in_CurrentNetworkType" = "4" ] && NETWORK="WCDMA" # WCDMA + [ "$in_CurrentNetworkType" = "3" ] && NETWORK="EDGE" # EDGE + [ "$in_CurrentNetworkType" = "2" ] && NETWORK="GPRS" # GPRS + [ "$in_CurrentNetworkType" = "1" ] && NETWORK="GSM" # GSM + fi + SIGNAL="" + local in_SignalStrength="`cat $TMPFILE | grep \"\" | cut -d \">\" -f 2 | cut -d \"<\" -f 1`" + [ "$in_SignalStrength" != "" ] && SIGNAL="$in_SignalStrength" + + if [ "$SIGNAL" = "" ]; then + in_SignalStrength="`cat $TMPFILE | grep \"\" | cut -d \">\" -f 2 | cut -d \"<\" -f 1`" + [ "$in_SignalStrength" != "" ] && SIGNAL="$((in_SignalStrength*20))" + fi + [ -z $SIGNAL ] && SIGNAL=0 + rm -f $TMPFILE +} + +CURRMODEM=$1 +PROTO=$2 +CONN="Modem #"$CURRMODEM + +MANUF=$(uci get modem.modem$CURRMODEM.manuf) +MODEL=$(uci get modem.modem$CURRMODEM.model) +MODEM=$MANUF" "$MODEL +IP=$(uci get modem.modem$CURRMODEM.ip) + +STARTIMEX=$(date +%s) +MONSTAT="Unknown" +rm -f /tmp/monstat$CURRMODEM + +sleep 5 +TIMEOUT=5 +wget -q http://$IP/html/home.html -O nul --save-cookies cookie --keep-session-cookies +sleep 5 +wget http://$IP/api/net/current-plmn -O $TMPFILE --load-cookies cookie > /dev/null 2>&1 & +handle_timeout "$!" + +wget http://$IP/api/device/information -O $TMPFILE --load-cookies cookie > /dev/null 2>&1 & +handle_timeout "$!" +in_mod="`cat $TMPFILE | grep \"\" | cut -d \">\" -f 2 | cut -d \"<\" -f 1`" +if [ "$in_mod" != "" ]; then + MODEM=$MANUF" "$in_mod +fi +IMEI="Unknown" +IMSI="Unknown" +ICCID="Unknown" +CNUM="*" +CNUMx="*" +in_im="`cat $TMPFILE | grep \"\" | cut -d \">\" -f 2 | cut -d \"<\" -f 1`" +if [ "$in_im" != "" ]; then + IMEI=$in_im +fi +in_im="`cat $TMPFILE | grep \"\" | cut -d \">\" -f 2 | cut -d \"<\" -f 1`" +if [ "$in_im" != "" ]; then + IMSI=$in_im +fi +in_im="`cat $TMPFILE | grep \"\" | cut -d \">\" -f 2 | cut -d \"<\" -f 1`" +if [ "$in_im" != "" ]; then + ICCID=$in_im +fi +in_im="`cat $TMPFILE | grep \"\" | cut -d \">\" -f 2 | cut -d \"<\" -f 1`" +if [ "$in_im" != "" ]; then + CNUM=$in_im +fi + + +IDP=$(uci get modem.modem$CURRMODEM.idP) +IDV=$(uci get modem.modem$CURRMODEM.idV) + +echo $IDV" : "$IDP > /tmp/msimdatax$CURRMODEM +echo "$IMEI" >> /tmp/msimdatax$CURRMODEM +echo "$IMSI" >> /tmp/msimdatax$CURRMODEM +echo "$ICCID" >> /tmp/msimdatax$CURRMODEM +echo "1" >> /tmp/msimdatax$CURRMODEM +mv -f /tmp/msimdatax$CURRMODEM /tmp/msimdata$CURRMODEM +echo "$CNUM" > /tmp/msimnumx$CURRMODEM +echo "$CNUMx" >> /tmp/msimnumx$CURRMODEM +mv -f /tmp/msimnumx$CURRMODEM /tmp/msimnum$CURRMODEM + +sleep 20 +TIMEOUT=20 +wget http://$IP/api/net/current-plmn -O $TMPFILE --load-cookies cookie > /dev/null 2>&1 & +handle_timeout "$!" +COPS="" +in_provider="`cat $TMPFILE | grep \"\" | cut -d \">\" -f 2 | cut -d \"<\" -f 1`" +[ "$in_provider" != "" ] && COPS="$in_provider" + +if [ "$COPS" = "" ]; then + COPS="-" + in_provider="`cat $TMPFILE | grep \"\" | cut -d \">\" -f 2 | cut -d \"<\" -f 1`" + [ "$in_provider" != "" ] && COPS="$in_provider)" +fi +COPS_MCC="-" +COPS_MNC="-" +in_mcc="`cat $TMPFILE | grep \"\" | cut -d \">\" -f 2 | cut -d \"<\" -f 1`" +if [ "$in_mcc" != "" ]; then + COPS_MCC=${in_mcc:0:3} + COPS_MNC=${in_mcc:3:3} +fi +COPS_MNC=" "$COPS_MNC +TIMEOUT=5 + +while [ 1 = 1 ]; do + get_signal + CSQ="$SIGNAL" + if [ -e /tmp/monstat$CURRMODEM ]; then + source /tmp/monstat$CURRMODEM + fi + if [ -z $MONSTAT ]; then + MONSTAT="Unknown" + fi + make_status + CURRTIME=$(date +%s) + let ELAPSE=CURRTIME-STARTIMEX + while [ $ELAPSE -lt 10 ]; do + sleep 2 + CURRTIME=$(date +%s) + let ELAPSE=CURRTIME-STARTIMEX + done + STARTIMEX=$CURRTIME +done diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/signal/mccmnc.data b/rooter/ext-rooter-basic/files/usr/lib/rooter/signal/mccmnc.data new file mode 100644 index 0000000..b4cdb19 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/signal/mccmnc.data @@ -0,0 +1,11 @@ +50501;Telstra +50502;Optus +50503;Vodafone +50506;3 +302220;Telus +302610;Bell +302720;Rogers Communication +24004;SWEDEN +24005;Sweden 3G +24008;Telenor SE +51503;Smart \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/signal/modemsignal.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/signal/modemsignal.sh new file mode 100644 index 0000000..bf643ab --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/signal/modemsignal.sh @@ -0,0 +1,287 @@ +#!/bin/sh + +ROOTER=/usr/lib/rooter + +log() { + logger -t "modem signal" "$@" +} + +CURRMODEM=$1 +PROTO=$2 +CONN="Modem #"$CURRMODEM +STARTIME=$(date +%s) +STARTIMEX=$(date +%s) +SMSTIME=0 +COMMPORT="/dev/ttyUSB"$(uci get modem.modem$CURRMODEM.commport) +NUMB=0 +MONSTAT="Unknown" +rm -f /tmp/monstat$CURRMODEM + +make_connect() { + { + echo "Changing Port" + echo "-" + echo "-" + echo "-" + echo "$MODEM" + echo "-" + echo "-" + echo "-" + echo "-" + echo "-" + echo "-" + echo "-" + echo "-" + echo "-" + echo "-" + echo "-" + echo "-" + echo "-" + echo "-" + echo " " + echo " " + echo "-" + echo "-" + echo "-" + echo "$CONN" + echo "-" + echo "-" + echo "-" + echo "-" + echo "-" + echo "-" + echo "-" + echo "-" + echo "-" + echo "-" + } > /tmp/statusx$CURRMODEM.file + mv -f /tmp/statusx$CURRMODEM.file /tmp/status$CURRMODEM.file +} + +make_signal() { + { + if [ -e $ROOTER/provchk.sh ]; then + $ROOTER/provchk.sh $COPS $CURRMODEM + source /tmp/cops$CURRMODEM.file + rm -f /tmp/cops$CURRMODEM.file + fi + echo "$COMMPORT" + echo "$CSQ" + echo "$CSQ_PER" + echo "$CSQ_RSSI" + echo "$MODEM" + echo "$COPS" + echo "$MODE" + echo "$LAC" + echo "$LAC_NUM" + echo "$CID" + echo "$CID_NUM" + echo "$COPS_MCC" + echo "$COPS_MNC" + echo "$RNC" + echo "$RNC_NUM" + echo "$DOWN" + echo "$UP" + echo "$ECIO" + echo "$RSCP" + echo "$ECIO1" + echo "$RSCP1" + echo "$MONSTAT" + echo "$CELL" + echo "$MODTYPE" + echo "$CONN" + echo "$CHANNEL" + echo "$CNUM" + echo "$CNAM" + echo "$LBAND" + echo "$TEMP" + echo "$PROTO" + echo "$PCI" + echo "$SINR" + echo "$LATITUDE" + echo "$LONGITUDE" + } > /tmp/statusx$CURRMODEM.file + mv -f /tmp/statusx$CURRMODEM.file /tmp/status$CURRMODEM.file + if [ -e $ROOTER/modem-led.sh ]; then + $ROOTER/modem-led.sh $CURRMODEM 4 $CSQ + fi +} + +get_basic() { + $ROOTER/signal/basedata.sh $CURRMODEM $COMMPORT + if [ -e /tmp/base$CURRMODEM.file ]; then + source /tmp/base$CURRMODEM.file + rm -f /tmp/base$CURRMODEM.file + fi + $ROOTER/signal/celldata.sh $CURRMODEM $COMMPORT + if [ -e /tmp/cell$CURRMODEM.file ]; then + source /tmp/cell$CURRMODEM.file + rm -f /tmp/cell$CURRMODEM.file + fi + lua $ROOTER/signal/celltype.lua "$MODEM" $CURRMODEM + if [ -e /tmp/celltype$CURRMODEM ]; then + source /tmp/celltype$CURRMODEM + rm -f /tmp/celltype$CURRMODEM + fi +} + +get_basic +while [ 1 = 1 ]; do + get_basic + if [ -e /tmp/port$CURRMODEM.file ]; then + source /tmp/port$CURRMODEM.file + rm -f /tmp/port$CURRMODEM.file + COMMPORT="/dev/ttyUSB"$PORT + uci set modem.modem$CURRMODEM.commport=$PORT + make_connect + get_basic + STARTIME=$(date +%s) + else + CURRTIME=$(date +%s) + let ELAPSE=CURRTIME-STARTIME + if [ $ELAPSE -ge 60 ]; then + STARTIME=$CURRTIME + $ROOTER/signal/celldata.sh $CURRMODEM $COMMPORT + if [ -e /tmp/cell$CURRMODEM.file ]; then + source /tmp/cell$CURRMODEM.file + rm -f /tmp/cell$CURRMODEM.file + fi + fi + if [ -e /tmp/port$CURRMODEM.file ]; then + source /tmp/port$CURRMODEM.file + rm -f /tmp/port$CURRMODEM.file + COMMPORT="/dev/ttyUSB"$PORT + uci set modem.modem$CURRMODEM.commport=$PORT + make_connect + get_basic + STARTIME=$(date +%s) + else + VENDOR=$(uci get modem.modem$CURRMODEM.idV) + PROD=$(uci get modem.modem$CURRMODEM.idP) +# This case statement should be kept in sync with: $ROOTER/luci/celltype.sh + case $VENDOR in + "1199"|"0f3d" ) + $ROOTER/common/sierradata.sh $CURRMODEM $COMMPORT + ;; + "19d2" ) + if [ $PROD = 1432 ]; then + $ROOTER/common/mdm9215data.sh $CURRMODEM $COMMPORT + else + $ROOTER/common/ztedata.sh $CURRMODEM $COMMPORT + fi + ;; + "12d1" ) + $ROOTER/common/huaweidata.sh $CURRMODEM $COMMPORT + ;; + "2c7c" ) + $ROOTER/common/quecteldata.sh $CURRMODEM $COMMPORT + ;; + "2cb7"|"1508" ) + $ROOTER/common/fibocomdata.sh $CURRMODEM $COMMPORT + ;; + "2dee" ) + $ROOTER/common/meigdata.sh $CURRMODEM $COMMPORT + ;; + "05c6" ) + case $PROD in + "f601" ) + $ROOTER/common/meigdata.sh $CURRMODEM $COMMPORT + ;; + "5042" ) + $ROOTER/common/mdm9215data.sh $CURRMODEM $COMMPORT + ;; + "9090"|"9003"|"9215" ) + $ROOTER/common/quecteldata.sh $CURRMODEM $COMMPORT + ;; + "90db" ) + $ROOTER/common/simcomdata.sh $CURRMODEM $COMMPORT + ;; + * ) + $ROOTER/common/otherdata.sh $CURRMODEM $COMMPORT + ;; + esac + ;; + "1bc7" ) + case $PROD in + "1900"|"1901"|"1910"|"1911" ) + $ROOTER/common/t77data.sh $CURRMODEM $COMMPORT + ;; + * ) + $ROOTER/common/telitdata.sh $CURRMODEM $COMMPORT + ;; + esac + ;; + "1410" ) + $ROOTER/common/novateldata.sh $CURRMODEM $COMMPORT + ;; + "413c" ) + case $PROD in + "81d7"|"81d8" ) + $ROOTER/common/t77data.sh $CURRMODEM $COMMPORT + ;; + * ) + $ROOTER/common/sierradata.sh $CURRMODEM $COMMPORT + ;; + esac + ;; + "0489" |"03f0" ) + $ROOTER/common/t77data.sh $CURRMODEM $COMMPORT + ;; + "1e0e" ) + $ROOTER/common/simcomdata.sh $CURRMODEM $COMMPORT + ;; + "8087" ) + if [ $PROD = "095a" ]; then + $ROOTER/common/fibocomdata.sh $CURRMODEM $COMMPORT + fi + ;; + "0408" ) + $ROOTER/common/quantadata.sh $CURRMODEM $COMMPORT + ;; + * ) + $ROOTER/common/otherdata.sh $CURRMODEM $COMMPORT + ;; + esac + CHANNEL="-" + PCI="-" + LBAND="-" + TEMP="-" + SINR="-" + LATITUDE="-" + LONGITUDE="-" + if [ -e /tmp/signal$CURRMODEM.file ]; then + source /tmp/signal$CURRMODEM.file + rm -f /tmp/signal$CURRMODEM.file + fi + if [ -e /tmp/phonenumber$CURRMODEM ]; then + source /tmp/phonenumber$CURRMODEM + rm -f /tmp/phonenumber$CURRMODEM + fi + if [ -e /tmp/gpsdata ]; then + source /tmp/gpsdata + fi + make_signal + uci set modem.modem$CURRMODEM.cmode="1" + uci commit modem + if [ -e /tmp/monstat$CURRMODEM ]; then + source /tmp/monstat$CURRMODEM + fi + if [ -z "$MONSTAT" ]; then + MONSTAT="Unknown" + fi + fi + fi + if [ -e /etc/netspeed ]; then + NETSPEED=60 + else + NETSPEED=10 + fi + CURRTIME=$(date +%s) + let ELAPSE=CURRTIME-STARTIMEX + while [ $ELAPSE -lt $NETSPEED ]; do + sleep 2 + CURRTIME=$(date +%s) + let ELAPSE=CURRTIME-STARTIMEX + done + STARTIMEX=$CURRTIME +done diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/signal/otherhostless.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/signal/otherhostless.sh new file mode 100644 index 0000000..621d626 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/signal/otherhostless.sh @@ -0,0 +1,160 @@ +#!/bin/sh + +ROOTER=/usr/lib/rooter + +log() { + logger -t "hostless " "$@" +} + +get_basic() { + # get basic data here + # + # how it is done with other modems + # + COMMPORT="/dev/ttyUSB"$(uci get modem.modem$CURRMODEM.commport) + $ROOTER/signal/basedata.sh $CURRMODEM $COMMPORT + source /tmp/base$CURRMODEM.file + rm -f /tmp/base$CURRMODEM.file + $ROOTER/signal/celldata.sh $CURRMODEM $COMMPORT + source /tmp/cell$CURRMODEM.file + rm -f /tmp/cell$CURRMODEM.file + lua $ROOTER/signal/celltype.lua "$MODEM" $CURRMODEM + source /tmp/celltype$CURRMODEM + rm -f /tmp/celltype$CURRMODEM +} + +make_signal() { + # get signal data here + # + # how it is done with other modems (Sierra) + # + COMMPORT="/dev/ttyUSB"$(uci get modem.modem$CURRMODEM.commport) + MANUF=$(uci get modem.modem$CURRMODEM.manuf) + MODEL=$(uci get modem.modem$CURRMODEM.model) + MODEM=$MANUF" "$MODEL + $ROOTER/common/ubloxdata.sh $CURRMODEM $COMMPORT + source /tmp/signal$CURRMODEM.file + rm -f /tmp/signal$CURRMODEM.file + echo "$COMMPORT" > /tmp/statusx$CURRMODEM.file + echo "$CSQ" >> /tmp/statusx$CURRMODEM.file + echo "$CSQ_PER" >> /tmp/statusx$CURRMODEM.file + echo "$CSQ_RSSI" >> /tmp/statusx$CURRMODEM.file + echo "$MODEM" >> /tmp/statusx$CURRMODEM.file + echo "$COPS" >> /tmp/statusx$CURRMODEM.file + echo "$MODE" >> /tmp/statusx$CURRMODEM.file + echo "$LAC" >> /tmp/statusx$CURRMODEM.file + echo "$LAC_NUM" >> /tmp/statusx$CURRMODEM.file + echo "$CID" >> /tmp/statusx$CURRMODEM.file + echo "$CID_NUM" >> /tmp/statusx$CURRMODEM.file + echo "$COPS_MCC" >> /tmp/statusx$CURRMODEM.file + echo "$COPS_MNC" >> /tmp/statusx$CURRMODEM.file + echo "$RNC" >> /tmp/statusx$CURRMODEM.file + echo "$RNC_NUM" >> /tmp/statusx$CURRMODEM.file + echo "$DOWN" >> /tmp/statusx$CURRMODEM.file + echo "$UP" >> /tmp/statusx$CURRMODEM.file + echo "$ECIO" >> /tmp/statusx$CURRMODEM.file + echo "$RSCP" >> /tmp/statusx$CURRMODEM.file + echo "$ECIO1" >> /tmp/statusx$CURRMODEM.file + echo "$RSCP1" >> /tmp/statusx$CURRMODEM.file + echo "$MONSTAT" >> /tmp/statusx$CURRMODEM.file + echo "$CELL" >> /tmp/statusx$CURRMODEM.file + echo "$MODTYPE" >> /tmp/statusx$CURRMODEM.file + echo "$CONN" >> /tmp/statusx$CURRMODEM.file + echo "$CHANNEL" >> /tmp/statusx$CURRMODEM.file + echo "$CNUM" >> /tmp/statusx$CURRMODEM.file + echo "$CNAM" >> /tmp/statusx$CURRMODEM.file + echo "$LBAND" >> /tmp/statusx$CURRMODEM.file + echo "$TEMP" >> /tmp/statusx$CURRMODEM.file + echo "$PROTO" >> /tmp/statusx$CURRMODEM.file + echo "$PCI" >> /tmp/statusx$CURRMODEM.file + echo "-" >> /tmp/statusx$CURRMODEM.file + echo "-" >> /tmp/statusx$CURRMODEM.file + mv -f /tmp/statusx$CURRMODEM.file /tmp/status$CURRMODEM.file +} + +CURRMODEM=$1 +PROTO=$2 +CONN="Modem #"$CURRMODEM + +MANUF=$(uci get modem.modem$CURRMODEM.manuf) +MODEL=$(uci get modem.modem$CURRMODEM.model) +MODEM=$MANUF" "$MODEL +IP=$(uci get modem.modem$CURRMODEM.ip) +MONSTAT="Unknown" +rm -f /tmp/monstat$CURRMODEM + +idV=$(uci get modem.modem$CURRMODEM.idV) +idP=$(uci get modem.modem$CURRMODEM.idP) +if [ $idV = 1546 -a $idP = 1146 ]; then + get_basic +fi + + +STARTIMEX=$(date +%s) +MONSTAT="Unknown" +rm -f /tmp/monstat$CURRMODEM + +while [ 1 = 1 ]; do + if [ $idV = 1546 -a $idP = 1146 ]; then +# ublox + make_signal + else + echo "$IP" > /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "$MODEM" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo " " >> /tmp/status$CURRMODEM.file + echo " " >> /tmp/status$CURRMODEM.file + echo "$MONSTAT" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "$CONN" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "Hostless/Phone" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + fi + if [ -e /tmp/monstat$CURRMODEM ]; then + source /tmp/monstat$CURRMODEM + fi + if [ -z $MONSTAT ]; then + MONSTAT="Unknown" + fi + CURRTIME=$(date +%s) + + if [ -e /etc/netspeed ]; then + NETSPEED=60 + else + NETSPEED=10 + fi + + + + let ELAPSE=CURRTIME-STARTIMEX + while [ $ELAPSE -lt $NETSPEED ]; do + sleep 2 + CURRTIME=$(date +%s) + let ELAPSE=CURRTIME-STARTIMEX + done + STARTIMEX=$CURRTIME +done diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/signal/status.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/signal/status.sh new file mode 100644 index 0000000..2b61da8 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/signal/status.sh @@ -0,0 +1,46 @@ +#!/bin/sh + +CURRMODEM=$1 +MSG=$2 +MSG1=$3 +COMMPORT="/dev/ttyUSB"$(uci -q get modem.modem$CURRMODEM.commport) +if [ -z $MSG1 ]; then + MSG1="-" + COMMPORT="-" +fi + +echo "$COMMPORT" > /tmp/status$CURRMODEM.file +echo "-" >> /tmp/status$CURRMODEM.file +echo "-" >> /tmp/status$CURRMODEM.file +echo "-" >> /tmp/status$CURRMODEM.file +echo "$MSG" >> /tmp/status$CURRMODEM.file +echo "$MSG1" >> /tmp/status$CURRMODEM.file +echo "-" >> /tmp/status$CURRMODEM.file +echo "-" >> /tmp/status$CURRMODEM.file +echo "-" >> /tmp/status$CURRMODEM.file +echo "-" >> /tmp/status$CURRMODEM.file +echo "-" >> /tmp/status$CURRMODEM.file +echo "-" >> /tmp/status$CURRMODEM.file +echo "-" >> /tmp/status$CURRMODEM.file +echo "-" >> /tmp/status$CURRMODEM.file +echo "-" >> /tmp/status$CURRMODEM.file +echo "-" >> /tmp/status$CURRMODEM.file +echo "-" >> /tmp/status$CURRMODEM.file +echo "-" >> /tmp/status$CURRMODEM.file +echo "-" >> /tmp/status$CURRMODEM.file +echo " " >> /tmp/status$CURRMODEM.file +echo " " >> /tmp/status$CURRMODEM.file +echo "-" >> /tmp/status$CURRMODEM.file +echo "-" >> /tmp/status$CURRMODEM.file +echo "-" >> /tmp/status$CURRMODEM.file +echo "Modem $CURRMODEM" >> /tmp/status$CURRMODEM.file +echo "-" >> /tmp/status$CURRMODEM.file +echo "-" >> /tmp/status$CURRMODEM.file +echo "-" >> /tmp/status$CURRMODEM.file +echo "-" >> /tmp/status$CURRMODEM.file +echo "-" >> /tmp/status$CURRMODEM.file +echo "-" >> /tmp/status$CURRMODEM.file +echo "-" >> /tmp/status$CURRMODEM.file +echo "-" >> /tmp/status$CURRMODEM.file +echo "-" >> /tmp/status$CURRMODEM.file +echo "-" >> /tmp/status$CURRMODEM.file diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/signal/ztehostless.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/signal/ztehostless.sh new file mode 100644 index 0000000..cedd8e9 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/signal/ztehostless.sh @@ -0,0 +1,215 @@ +#!/bin/sh + +ROOTER=/usr/lib/rooter + +log() { + logger -t "hostless " "$@" +} + +TMPFILE="/tmp/XXXXXX" +TMPFILE1="/tmp/XXXXXX1" + +make_status() { + echo "$IP" > /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "$CSQ" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "$MODEM" >> /tmp/status$CURRMODEM.file + echo "$PROV" >> /tmp/status$CURRMODEM.file + echo "$NETWORK" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo " " >> /tmp/status$CURRMODEM.file + echo " " >> /tmp/status$CURRMODEM.file + echo "$MONSTAT" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "$CONN" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "Hostless/Phone" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file + echo "-" >> /tmp/status$CURRMODEM.file +} + +handle_timeout(){ + local wget_pid="$1" + local count=0 + ps | grep -v grep | grep $wget_pid + res="$?" + while [ "$res" = 0 -a $count -lt "$((TIMEOUT))" ]; do + sleep 1 + count=$((count+1)) + ps | grep -v grep | grep $wget_pid + res="$?" + done + + if [ "$res" = 0 ]; then + log "Killing process on timeout" + kill "$wget_pid" 2> /dev/null + ps | grep -v grep | grep $wget_pid + res="$?" + if [ "$res" = 0 ]; then + log "Killing process on timeout" + kill -9 $wget_pid 2> /dev/null + fi + fi +} + +get_zte_model() { + uci set modem.modem$CURRMODEM.ztemodel=UNKNOWN + uci commit modem + SERIAL=$(uci get modem.modem$CURRMODEM.serial) + if [ $PROD = 1405 ]; then + if [ "`echo $SERIAL | grep P680A1ZTED`" != "" ]; then + uci set modem.modem$CURRMODEM.ztemodel=MF669 + uci set modem.modem$CURRMODEM.model=MF669/MF70 + uci commit modem + else + uci set modem.modem$CURRMODEM.ztemodel=V5 + uci set modem.modem$CURRMODEM.model=MF823/MF825/MF93D + uci commit modem + fi + fi + if [ $PROD = 0349 ]; then + uci set modem.modem$CURRMODEM.ztemodel=MF821D + uci set modem.modem$CURRMODEM.model=MF821D + uci commit modem + fi + if [ $PROD = 0166 ]; then + if [ "`echo $MODEL | grep MF91`" != "" ]; then + uci set modem.modem$CURRMODEM.ztemodel=MF91D + uci set modem.modem$CURRMODEM.model=MF91D + uci commit modem + else + if [ "`echo $MODEL | grep MF91`" != "" ]; then + uci set modem.modem$CURRMODEM.ztemodel=MF91 + uci set modem.modem$CURRMODEM.model=MF91 + uci commit modem + fi + fi + fi + if [ $PROD = 1408 ]; then + if [ "`echo $SERIAL | grep P680A1ZTED`" != "" ]; then + uci set modem.modem$CURRMODEM.ztemodel=V5 + uci set modem.modem$CURRMODEM.model=MF93D + uci commit modem + fi + fi +} + +get_basic(){ + ZTEMOD=$(uci get modem.modem$CURRMODEM.ztemodel) + TIMEOUT=3 + case $ZTEMOD in + "MF669" ) + wget http://$IP/logo_data.asp -O $TMPFILE > /dev/null 2>&1 & + handle_timeout "$!" + LUCKNUM="`cat $TMPFILE | grep lucknum | cut -d \' -f 2`" + ;; + "V5" ) + wget "http://$IP/goform/goform_get_cmd_process?isTest=false&cmd=network_type%2Cwan_ipaddr%2Cppp_status%2Cprefer_dns_auto%2Cstandby_dns_auto%2Csignalbar&multi_data=1&_=1376406501348" -O $TMPFILE > /dev/null 2>&1 & + handle_timeout "$!" + ;; + "MF821D"|"MF91D"|"MF91" ) + wget http://$IP/goform/status_update -O $TMPFILE > /dev/null 2>&1 & + handle_timeout "$!" + ;; + esac + PROV="`cat $TMPFILE | grep network_provider | cut -d \' -f 2`" + [ -z $PROV ] && PROV="-" + rm -f $TMPFILE +} + +get_signal(){ + TIMEOUT=3 + case $ZTEMOD in + "MF669" ) + wget http://$IP/logo_data.asp -O $TMPFILE > /dev/null 2>&1 & + handle_timeout "$!" + SIGNAL="`cat $TMPFILE | grep signalbar | cut -d \' -f 2`" + NETWORK="`cat $TMPFILE | grep network_type | cut -d \' -f 2`" + ;; + "V5" ) + wget "http://$IP/goform/goform_get_cmd_process?isTest=false&cmd=signalbar,wan_csq,network_type,network_provider,ppp_status,modem_main_state,rmcc,rmnc,,domain_stat,cell_id,rssi,rscp,lte_rssi,lte_rsrq,lte_rsrp,lte_snr,ecio,sms_received_flag,sts_received_flag,simcard_roam&multi_data=1&sms_received_flag_flag=0&sts_received_flag_flag=0" -O $TMPFILE > /dev/null 2>&1 & + handle_timeout "$!" + SIGNAL="`cat $TMPFILE | grep signalbar'\"\:\"[^\"]*' -o | cut -d'"' -f 3`" + NETWORK="`cat $TMPFILE | grep network_type'\"\:\"[^\"]*' -o | cut -d'"' -f 3`" + ;; + "MF821D"|"MF91D"|"MF91" ) + wget http://$IP/goform/status_update -O $TMPFILE > /dev/null 2>&1 & + handle_timeout "$!" + SIGNAL="`cat $TMPFILE | cut -d \; -f 1-1`" + net="`cat $TMPFILE | cut -d \; -f 4-4`" + if [ -z $net ]; then + NETWORK="-" + else + [ "$net" = "0" ] && NETWORK="No Service" + [ "$net" = "1" ] && NETWORK="LTE" + [ "$net" = "2" ] && NETWORK="EVDO" + [ "$net" = "3" ] && NETWORK="CDMA" + [ "$net" = "4" ] && NETWORK="WCDMA" + [ "$net" = "5" ] && NETWORK="GSM" + [ "$net" = "6" ] && NETWORK="HSDPA" + [ "$net" = "7" ] && NETWORK="HUSPA" + [ "$net" = "8" ] && NETWORK="HSPA+" + [ "$net" = "10" ] && NETWORK="EDGE" + [ "$net" = "11" ] && NETWORK="GPRS" + fi + ;; + esac + [ -z $SIGNAL ] && SIGNAL=0 + [ -z $NETWORK ] && NETWORK="-" + rm -f $TMPFILE +} + +CURRMODEM=$1 +PROTO=$2 +CONN="Modem #"$CURRMODEM + +PROD=$(uci get modem.modem$CURRMODEM.idP) +get_zte_model +MANUF=$(uci get modem.modem$CURRMODEM.manuf) +MODEL=$(uci get modem.modem$CURRMODEM.model) +MODEM=$MANUF" "$MODEL +IP=$(uci get modem.modem$CURRMODEM.ip) + +get_basic + +STARTIMEX=$(date +%s) +MONSTAT="Unknown" +rm -f /tmp/monstat$CURRMODEM + +while [ 1 = 1 ]; do + get_signal + CSQ="$SIGNAL Bars" + if [ -e /tmp/monstat$CURRMODEM ]; then + source /tmp/monstat$CURRMODEM + fi + if [ -z $MONSTAT ]; then + MONSTAT="Unknown" + fi + make_status + CURRTIME=$(date +%s) + let ELAPSE=CURRTIME-STARTIMEX + while [ $ELAPSE -lt 10 ]; do + sleep 2 + CURRTIME=$(date +%s) + let ELAPSE=CURRTIME-STARTIMEX + done + STARTIMEX=$CURRTIME +done diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/simlock.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/simlock.sh new file mode 100644 index 0000000..f79b761 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/simlock.sh @@ -0,0 +1,56 @@ +#!/bin/sh + +ROOTER=/usr/lib/rooter + +log() { + modlog "SimLock $CURRMODEM" "$@" +} + +CURRMODEM=$1 +CPORT=$(uci get modem.modem$CURRMODEM.commport) + +ATCMDD="at+cpin?" +OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") +ERR=$(echo "$OX" | grep "ERROR") +if [ ! -z "$ERR" ]; then # No SIM + log "No SIM" + echo "2" > /tmp/simpin$CURRMODEM + exit 0 +fi +RDY=$(echo "$OX" | grep "READY") +if [ -z "$RDY" ]; then # SIM Locked + spin=$(uci -q get custom.simpin.pin) # SIM Pin + if [ -z "$spin" ]; then + spin=$(uci -q get modem.modeminfo$CURRMODEM.pincode) # Profile Pin + if [ -z "$spin" ]; then + spin=$(uci -q get profile.simpin.pin) # Default profile Pin + if [ -z "$spin" ]; then + echo "0" > /tmp/simpin$CURRMODEM # Locked/No Pin + log "Locked/No Pin" + exit 0 + fi + fi + fi + export PINCODE="$spin" # Use Pin to unlock + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "setpin.gcom" "$CURRMODEM") + sleep 5 + ATCMDD="at+cpin?" + OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") + RDY=$(echo "$OX" | grep "READY") + if [ -z "$RDY" ]; then # sim locked + echo "1" > /tmp/simpin$CURRMODEM # Incorrect Pin + log "Incorrect Pin" + exit 0 + fi + log "Correct Pin" +else + log "Not Locked" + sblk=$(uci -q get custom.simpin.block) + if [ "$sblk" = "1" ]; then + echo "4" > /tmp/simpin$CURRMODEM + log "Unlocked not allowed" + exit 0 + fi +fi +rm -f /tmp/simpin$CURRMODEM # not locked + diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/simlockc.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/simlockc.sh new file mode 100644 index 0000000..af4651d --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/simlockc.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +ROOTER=/usr/lib/rooter +ROOTER_LINK="/tmp/links" + +log() { + logger -t "SIM Lock" "$@" +} diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/sms/check_sms.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/sms/check_sms.sh new file mode 100644 index 0000000..0475e85 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/sms/check_sms.sh @@ -0,0 +1,32 @@ +#!/bin/sh + +ROOTER=/usr/lib/rooter +ROOTER_LINK="/tmp/links" + +CURRMODEM=$1 + +if [ -e /etc/nosms ]; then + uci set modem.modem$CURRMODEM.sms=0 + uci commit modem + exit 0 +fi + +CPORT=$(uci get modem.modem$CURRMODEM.commport) +sleep 10 +OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "smschk.gcom" "$CURRMODEM") + +ERROR="ERROR" +if `echo ${OX} | grep "${ERROR}" 1>/dev/null 2>&1` +then + uci set modem.modem$CURRMODEM.sms=0 + uci commit modem +else + uci set modem.modem$CURRMODEM.sms=1 + uci commit modem + if [ -e /usr/lib/sms/processsms ]; then + if [ ! -e $ROOTER_LINK/processsms$CURRMODEM ]; then + ln -s /usr/lib/sms/processsms $ROOTER_LINK/processsms$CURRMODEM + $ROOTER_LINK/processsms$CURRMODEM $CURRMODEM & + fi + fi +fi diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/timezone.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/timezone.sh new file mode 100644 index 0000000..a0f1800 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/timezone.sh @@ -0,0 +1,19 @@ +#!/bin/sh + +sleep 10 +rm -f /tmp/timez +wget --no-check-certificate -O /tmp/timez http://ip-api.com/json > /dev/null 2>&1 +OX=$(cat /tmp/timez) + +TZ=$(echo $OX" " | tr -d '"' | grep -o 'timezone:[^;]*' | tr ":" ",") +ZONEN=$(echo "$TZ" | cut -d, -f2) + +/usr/lib/rooter/tzone.lua "$ZONEN" +source /tmp/tzone + +uci set system.@system[-1].timezone="$ZNAME" +uci set system.@system[-1].zonename="$ZONEN" +uci commit system +/etc/init.d/system restart + + diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/tzone.lua b/rooter/ext-rooter-basic/files/usr/lib/rooter/tzone.lua new file mode 100644 index 0000000..279ad3c --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/tzone.lua @@ -0,0 +1,478 @@ +#!/usr/bin/lua + +TZ = { + { 'Africa/Abidjan', 'GMT0' }, + { 'Africa/Accra', 'GMT0' }, + { 'Africa/Addis Ababa', 'EAT-3' }, + { 'Africa/Algiers', 'CET-1' }, + { 'Africa/Asmara', 'EAT-3' }, + { 'Africa/Bamako', 'GMT0' }, + { 'Africa/Bangui', 'WAT-1' }, + { 'Africa/Banjul', 'GMT0' }, + { 'Africa/Bissau', 'GMT0' }, + { 'Africa/Blantyre', 'CAT-2' }, + { 'Africa/Brazzaville', 'WAT-1' }, + { 'Africa/Bujumbura', 'CAT-2' }, + { 'Africa/Cairo', 'EET-2' }, + { 'Africa/Casablanca', '<+01>-1' }, + { 'Africa/Ceuta', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Africa/Conakry', 'GMT0' }, + { 'Africa/Dakar', 'GMT0' }, + { 'Africa/Dar es Salaam', 'EAT-3' }, + { 'Africa/Djibouti', 'EAT-3' }, + { 'Africa/Douala', 'WAT-1' }, + { 'Africa/El Aaiun', '<+01>-1' }, + { 'Africa/Freetown', 'GMT0' }, + { 'Africa/Gaborone', 'CAT-2' }, + { 'Africa/Harare', 'CAT-2' }, + { 'Africa/Johannesburg', 'SAST-2' }, + { 'Africa/Juba', 'EAT-3' }, + { 'Africa/Kampala', 'EAT-3' }, + { 'Africa/Khartoum', 'CAT-2' }, + { 'Africa/Kigali', 'CAT-2' }, + { 'Africa/Kinshasa', 'WAT-1' }, + { 'Africa/Lagos', 'WAT-1' }, + { 'Africa/Libreville', 'WAT-1' }, + { 'Africa/Lome', 'GMT0' }, + { 'Africa/Luanda', 'WAT-1' }, + { 'Africa/Lubumbashi', 'CAT-2' }, + { 'Africa/Lusaka', 'CAT-2' }, + { 'Africa/Malabo', 'WAT-1' }, + { 'Africa/Maputo', 'CAT-2' }, + { 'Africa/Maseru', 'SAST-2' }, + { 'Africa/Mbabane', 'SAST-2' }, + { 'Africa/Mogadishu', 'EAT-3' }, + { 'Africa/Monrovia', 'GMT0' }, + { 'Africa/Nairobi', 'EAT-3' }, + { 'Africa/Ndjamena', 'WAT-1' }, + { 'Africa/Niamey', 'WAT-1' }, + { 'Africa/Nouakchott', 'GMT0' }, + { 'Africa/Ouagadougou', 'GMT0' }, + { 'Africa/Porto-Novo', 'WAT-1' }, + { 'Africa/Sao Tome', 'GMT0' }, + { 'Africa/Tripoli', 'EET-2' }, + { 'Africa/Tunis', 'CET-1' }, + { 'Africa/Windhoek', 'CAT-2' }, + { 'America/Adak', 'HST10HDT,M3.2.0,M11.1.0' }, + { 'America/Anchorage', 'AKST9AKDT,M3.2.0,M11.1.0' }, + { 'America/Anguilla', 'AST4' }, + { 'America/Antigua', 'AST4' }, + { 'America/Araguaina', '<-03>3' }, + { 'America/Argentina/Buenos Aires', '<-03>3' }, + { 'America/Argentina/Catamarca', '<-03>3' }, + { 'America/Argentina/Cordoba', '<-03>3' }, + { 'America/Argentina/Jujuy', '<-03>3' }, + { 'America/Argentina/La Rioja', '<-03>3' }, + { 'America/Argentina/Mendoza', '<-03>3' }, + { 'America/Argentina/Rio Gallegos', '<-03>3' }, + { 'America/Argentina/Salta', '<-03>3' }, + { 'America/Argentina/San Juan', '<-03>3' }, + { 'America/Argentina/San Luis', '<-03>3' }, + { 'America/Argentina/Tucuman', '<-03>3' }, + { 'America/Argentina/Ushuaia', '<-03>3' }, + { 'America/Aruba', 'AST4' }, + { 'America/Asuncion', '<-04>4<-03>,M10.1.0/0,M3.4.0/0' }, + { 'America/Atikokan', 'EST5' }, + { 'America/Bahia', '<-03>3' }, + { 'America/Bahia Banderas', 'CST6CDT,M4.1.0,M10.5.0' }, + { 'America/Barbados', 'AST4' }, + { 'America/Belem', '<-03>3' }, + { 'America/Belize', 'CST6' }, + { 'America/Blanc-Sablon', 'AST4' }, + { 'America/Boa Vista', '<-04>4' }, + { 'America/Bogota', '<-05>5' }, + { 'America/Boise', 'MST7MDT,M3.2.0,M11.1.0' }, + { 'America/Cambridge Bay', 'MST7MDT,M3.2.0,M11.1.0' }, + { 'America/Campo Grande', '<-04>4' }, + { 'America/Cancun', 'EST5' }, + { 'America/Caracas', '<-04>4' }, + { 'America/Cayenne', '<-03>3' }, + { 'America/Cayman', 'EST5' }, + { 'America/Chicago', 'CST6CDT,M3.2.0,M11.1.0' }, + { 'America/Chihuahua', 'MST7MDT,M4.1.0,M10.5.0' }, + { 'America/Costa Rica', 'CST6' }, + { 'America/Creston', 'MST7' }, + { 'America/Cuiaba', '<-04>4' }, + { 'America/Curacao', 'AST4' }, + { 'America/Danmarkshavn', 'GMT0' }, + { 'America/Dawson', 'MST7' }, + { 'America/Dawson Creek', 'MST7' }, + { 'America/Denver', 'MST7MDT,M3.2.0,M11.1.0' }, + { 'America/Detroit', 'EST5EDT,M3.2.0,M11.1.0' }, + { 'America/Dominica', 'AST4' }, + { 'America/Edmonton', 'MST7MDT,M3.2.0,M11.1.0' }, + { 'America/Eirunepe', '<-05>5' }, + { 'America/El Salvador', 'CST6' }, + { 'America/Fort Nelson', 'MST7' }, + { 'America/Fortaleza', '<-03>3' }, + { 'America/Glace Bay', 'AST4ADT,M3.2.0,M11.1.0' }, + { 'America/Goose Bay', 'AST4ADT,M3.2.0,M11.1.0' }, + { 'America/Grand Turk', 'EST5EDT,M3.2.0,M11.1.0' }, + { 'America/Grenada', 'AST4' }, + { 'America/Guadeloupe', 'AST4' }, + { 'America/Guatemala', 'CST6' }, + { 'America/Guayaquil', '<-05>5' }, + { 'America/Guyana', '<-04>4' }, + { 'America/Halifax', 'AST4ADT,M3.2.0,M11.1.0' }, + { 'America/Havana', 'CST5CDT,M3.2.0/0,M11.1.0/1' }, + { 'America/Hermosillo', 'MST7' }, + { 'America/Indiana/Indianapolis', 'EST5EDT,M3.2.0,M11.1.0' }, + { 'America/Indiana/Knox', 'CST6CDT,M3.2.0,M11.1.0' }, + { 'America/Indiana/Marengo', 'EST5EDT,M3.2.0,M11.1.0' }, + { 'America/Indiana/Petersburg', 'EST5EDT,M3.2.0,M11.1.0' }, + { 'America/Indiana/Tell City', 'CST6CDT,M3.2.0,M11.1.0' }, + { 'America/Indiana/Vevay', 'EST5EDT,M3.2.0,M11.1.0' }, + { 'America/Indiana/Vincennes', 'EST5EDT,M3.2.0,M11.1.0' }, + { 'America/Indiana/Winamac', 'EST5EDT,M3.2.0,M11.1.0' }, + { 'America/Inuvik', 'MST7MDT,M3.2.0,M11.1.0' }, + { 'America/Iqaluit', 'EST5EDT,M3.2.0,M11.1.0' }, + { 'America/Jamaica', 'EST5' }, + { 'America/Juneau', 'AKST9AKDT,M3.2.0,M11.1.0' }, + { 'America/Kentucky/Louisville', 'EST5EDT,M3.2.0,M11.1.0' }, + { 'America/Kentucky/Monticello', 'EST5EDT,M3.2.0,M11.1.0' }, + { 'America/Kralendijk', 'AST4' }, + { 'America/La Paz', '<-04>4' }, + { 'America/Lima', '<-05>5' }, + { 'America/Los Angeles', 'PST8PDT,M3.2.0,M11.1.0' }, + { 'America/Lower Princes', 'AST4' }, + { 'America/Maceio', '<-03>3' }, + { 'America/Managua', 'CST6' }, + { 'America/Manaus', '<-04>4' }, + { 'America/Marigot', 'AST4' }, + { 'America/Martinique', 'AST4' }, + { 'America/Matamoros', 'CST6CDT,M3.2.0,M11.1.0' }, + { 'America/Mazatlan', 'MST7MDT,M4.1.0,M10.5.0' }, + { 'America/Menominee', 'CST6CDT,M3.2.0,M11.1.0' }, + { 'America/Merida', 'CST6CDT,M4.1.0,M10.5.0' }, + { 'America/Metlakatla', 'AKST9AKDT,M3.2.0,M11.1.0' }, + { 'America/Mexico City', 'CST6CDT,M4.1.0,M10.5.0' }, + { 'America/Miquelon', '<-03>3<-02>,M3.2.0,M11.1.0' }, + { 'America/Moncton', 'AST4ADT,M3.2.0,M11.1.0' }, + { 'America/Monterrey', 'CST6CDT,M4.1.0,M10.5.0' }, + { 'America/Montevideo', '<-03>3' }, + { 'America/Montserrat', 'AST4' }, + { 'America/Nassau', 'EST5EDT,M3.2.0,M11.1.0' }, + { 'America/New York', 'EST5EDT,M3.2.0,M11.1.0' }, + { 'America/Nipigon', 'EST5EDT,M3.2.0,M11.1.0' }, + { 'America/Nome', 'AKST9AKDT,M3.2.0,M11.1.0' }, + { 'America/Noronha', '<-02>2' }, + { 'America/North Dakota/Beulah', 'CST6CDT,M3.2.0,M11.1.0' }, + { 'America/North Dakota/Center', 'CST6CDT,M3.2.0,M11.1.0' }, + { 'America/North Dakota/New Salem', 'CST6CDT,M3.2.0,M11.1.0' }, + { 'America/Nuuk', '<-03>3<-02>,M3.5.0/-2,M10.5.0/-1' }, + { 'America/Ojinaga', 'MST7MDT,M3.2.0,M11.1.0' }, + { 'America/Panama', 'EST5' }, + { 'America/Pangnirtung', 'EST5EDT,M3.2.0,M11.1.0' }, + { 'America/Paramaribo', '<-03>3' }, + { 'America/Phoenix', 'MST7' }, + { 'America/Port of Spain', 'AST4' }, + { 'America/Port-au-Prince', 'EST5EDT,M3.2.0,M11.1.0' }, + { 'America/Porto Velho', '<-04>4' }, + { 'America/Puerto Rico', 'AST4' }, + { 'America/Punta Arenas', '<-03>3' }, + { 'America/Rainy River', 'CST6CDT,M3.2.0,M11.1.0' }, + { 'America/Rankin Inlet', 'CST6CDT,M3.2.0,M11.1.0' }, + { 'America/Recife', '<-03>3' }, + { 'America/Regina', 'CST6' }, + { 'America/Resolute', 'CST6CDT,M3.2.0,M11.1.0' }, + { 'America/Rio Branco', '<-05>5' }, + { 'America/Santarem', '<-03>3' }, + { 'America/Santiago', '<-04>4<-03>,M9.1.6/24,M4.1.6/24' }, + { 'America/Santo Domingo', 'AST4' }, + { 'America/Sao Paulo', '<-03>3' }, + { 'America/Scoresbysund', '<-01>1<+00>,M3.5.0/0,M10.5.0/1' }, + { 'America/Sitka', 'AKST9AKDT,M3.2.0,M11.1.0' }, + { 'America/St Barthelemy', 'AST4' }, + { 'America/St Johns', 'NST3:30NDT,M3.2.0,M11.1.0' }, + { 'America/St Kitts', 'AST4' }, + { 'America/St Lucia', 'AST4' }, + { 'America/St Thomas', 'AST4' }, + { 'America/St Vincent', 'AST4' }, + { 'America/Swift Current', 'CST6' }, + { 'America/Tegucigalpa', 'CST6' }, + { 'America/Thule', 'AST4ADT,M3.2.0,M11.1.0' }, + { 'America/Thunder Bay', 'EST5EDT,M3.2.0,M11.1.0' }, + { 'America/Tijuana', 'PST8PDT,M3.2.0,M11.1.0' }, + { 'America/Toronto', 'EST5EDT,M3.2.0,M11.1.0' }, + { 'America/Tortola', 'AST4' }, + { 'America/Vancouver', 'PST8PDT,M3.2.0,M11.1.0' }, + { 'America/Whitehorse', 'MST7' }, + { 'America/Winnipeg', 'CST6CDT,M3.2.0,M11.1.0' }, + { 'America/Yakutat', 'AKST9AKDT,M3.2.0,M11.1.0' }, + { 'America/Yellowknife', 'MST7MDT,M3.2.0,M11.1.0' }, + { 'Antarctica/Casey', '<+08>-8' }, + { 'Antarctica/Davis', '<+07>-7' }, + { 'Antarctica/DumontDUrville', '<+10>-10' }, + { 'Antarctica/Macquarie', '<+11>-11' }, + { 'Antarctica/Mawson', '<+05>-5' }, + { 'Antarctica/McMurdo', 'NZST-12NZDT,M9.5.0,M4.1.0/3' }, + { 'Antarctica/Palmer', '<-03>3' }, + { 'Antarctica/Rothera', '<-03>3' }, + { 'Antarctica/Syowa', '<+03>-3' }, + { 'Antarctica/Troll', '<+00>0<+02>-2,M3.5.0/1,M10.5.0/3' }, + { 'Antarctica/Vostok', '<+06>-6' }, + { 'Arctic/Longyearbyen', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Asia/Aden', '<+03>-3' }, + { 'Asia/Almaty', '<+06>-6' }, + { 'Asia/Amman', 'EET-2EEST,M3.5.4/24,M10.5.5/1' }, + { 'Asia/Anadyr', '<+12>-12' }, + { 'Asia/Aqtau', '<+05>-5' }, + { 'Asia/Aqtobe', '<+05>-5' }, + { 'Asia/Ashgabat', '<+05>-5' }, + { 'Asia/Atyrau', '<+05>-5' }, + { 'Asia/Baghdad', '<+03>-3' }, + { 'Asia/Bahrain', '<+03>-3' }, + { 'Asia/Baku', '<+04>-4' }, + { 'Asia/Bangkok', '<+07>-7' }, + { 'Asia/Barnaul', '<+07>-7' }, + { 'Asia/Beirut', 'EET-2EEST,M3.5.0/0,M10.5.0/0' }, + { 'Asia/Bishkek', '<+06>-6' }, + { 'Asia/Brunei', '<+08>-8' }, + { 'Asia/Chita', '<+09>-9' }, + { 'Asia/Choibalsan', '<+08>-8' }, + { 'Asia/Colombo', '<+0530>-5:30' }, + { 'Asia/Damascus', 'EET-2EEST,M3.5.5/0,M10.5.5/0' }, + { 'Asia/Dhaka', '<+06>-6' }, + { 'Asia/Dili', '<+09>-9' }, + { 'Asia/Dubai', '<+04>-4' }, + { 'Asia/Dushanbe', '<+05>-5' }, + { 'Asia/Famagusta', 'EET-2EEST,M3.5.0/3,M10.5.0/4' }, + { 'Asia/Gaza', 'EET-2EEST,M3.5.5/0,M10.5.6/1' }, + { 'Asia/Hebron', 'EET-2EEST,M3.5.5/0,M10.5.6/1' }, + { 'Asia/Ho Chi Minh', '<+07>-7' }, + { 'Asia/Hong Kong', 'HKT-8' }, + { 'Asia/Hovd', '<+07>-7' }, + { 'Asia/Irkutsk', '<+08>-8' }, + { 'Asia/Jakarta', 'WIB-7' }, + { 'Asia/Jayapura', 'WIT-9' }, + { 'Asia/Jerusalem', 'IST-2IDT,M3.4.4/26,M10.5.0' }, + { 'Asia/Kabul', '<+0430>-4:30' }, + { 'Asia/Kamchatka', '<+12>-12' }, + { 'Asia/Karachi', 'PKT-5' }, + { 'Asia/Kathmandu', '<+0545>-5:45' }, + { 'Asia/Khandyga', '<+09>-9' }, + { 'Asia/Kolkata', 'IST-5:30' }, + { 'Asia/Krasnoyarsk', '<+07>-7' }, + { 'Asia/Kuala Lumpur', '<+08>-8' }, + { 'Asia/Kuching', '<+08>-8' }, + { 'Asia/Kuwait', '<+03>-3' }, + { 'Asia/Macau', 'CST-8' }, + { 'Asia/Magadan', '<+11>-11' }, + { 'Asia/Makassar', 'WITA-8' }, + { 'Asia/Manila', 'PST-8' }, + { 'Asia/Muscat', '<+04>-4' }, + { 'Asia/Nicosia', 'EET-2EEST,M3.5.0/3,M10.5.0/4' }, + { 'Asia/Novokuznetsk', '<+07>-7' }, + { 'Asia/Novosibirsk', '<+07>-7' }, + { 'Asia/Omsk', '<+06>-6' }, + { 'Asia/Oral', '<+05>-5' }, + { 'Asia/Phnom Penh', '<+07>-7' }, + { 'Asia/Pontianak', 'WIB-7' }, + { 'Asia/Pyongyang', 'KST-9' }, + { 'Asia/Qatar', '<+03>-3' }, + { 'Asia/Qostanay', '<+06>-6' }, + { 'Asia/Qyzylorda', '<+05>-5' }, + { 'Asia/Riyadh', '<+03>-3' }, + { 'Asia/Sakhalin', '<+11>-11' }, + { 'Asia/Samarkand', '<+05>-5' }, + { 'Asia/Seoul', 'KST-9' }, + { 'Asia/Shanghai', 'CST-8' }, + { 'Asia/Singapore', '<+08>-8' }, + { 'Asia/Srednekolymsk', '<+11>-11' }, + { 'Asia/Taipei', 'CST-8' }, + { 'Asia/Tashkent', '<+05>-5' }, + { 'Asia/Tbilisi', '<+04>-4' }, + { 'Asia/Tehran', '<+0330>-3:30<+0430>,J79/24,J263/24' }, + { 'Asia/Thimphu', '<+06>-6' }, + { 'Asia/Tokyo', 'JST-9' }, + { 'Asia/Tomsk', '<+07>-7' }, + { 'Asia/Ulaanbaatar', '<+08>-8' }, + { 'Asia/Urumqi', '<+06>-6' }, + { 'Asia/Ust-Nera', '<+10>-10' }, + { 'Asia/Vientiane', '<+07>-7' }, + { 'Asia/Vladivostok', '<+10>-10' }, + { 'Asia/Yakutsk', '<+09>-9' }, + { 'Asia/Yangon', '<+0630>-6:30' }, + { 'Asia/Yekaterinburg', '<+05>-5' }, + { 'Asia/Yerevan', '<+04>-4' }, + { 'Atlantic/Azores', '<-01>1<+00>,M3.5.0/0,M10.5.0/1' }, + { 'Atlantic/Bermuda', 'AST4ADT,M3.2.0,M11.1.0' }, + { 'Atlantic/Canary', 'WET0WEST,M3.5.0/1,M10.5.0' }, + { 'Atlantic/Cape Verde', '<-01>1' }, + { 'Atlantic/Faroe', 'WET0WEST,M3.5.0/1,M10.5.0' }, + { 'Atlantic/Madeira', 'WET0WEST,M3.5.0/1,M10.5.0' }, + { 'Atlantic/Reykjavik', 'GMT0' }, + { 'Atlantic/South Georgia', '<-02>2' }, + { 'Atlantic/St Helena', 'GMT0' }, + { 'Atlantic/Stanley', '<-03>3' }, + { 'Australia/Adelaide', 'ACST-9:30ACDT,M10.1.0,M4.1.0/3' }, + { 'Australia/Brisbane', 'AEST-10' }, + { 'Australia/Broken Hill', 'ACST-9:30ACDT,M10.1.0,M4.1.0/3' }, + { 'Australia/Currie', 'AEST-10AEDT,M10.1.0,M4.1.0/3' }, + { 'Australia/Darwin', 'ACST-9:30' }, + { 'Australia/Eucla', '<+0845>-8:45' }, + { 'Australia/Hobart', 'AEST-10AEDT,M10.1.0,M4.1.0/3' }, + { 'Australia/Lindeman', 'AEST-10' }, + { 'Australia/Lord Howe', '<+1030>-10:30<+11>-11,M10.1.0,M4.1.0' }, + { 'Australia/Melbourne', 'AEST-10AEDT,M10.1.0,M4.1.0/3' }, + { 'Australia/Perth', 'AWST-8' }, + { 'Australia/Sydney', 'AEST-10AEDT,M10.1.0,M4.1.0/3' }, + { 'Etc/GMT', 'GMT0' }, + { 'Etc/GMT+1', '<-01>1' }, + { 'Etc/GMT+10', '<-10>10' }, + { 'Etc/GMT+11', '<-11>11' }, + { 'Etc/GMT+12', '<-12>12' }, + { 'Etc/GMT+2', '<-02>2' }, + { 'Etc/GMT+3', '<-03>3' }, + { 'Etc/GMT+4', '<-04>4' }, + { 'Etc/GMT+5', '<-05>5' }, + { 'Etc/GMT+6', '<-06>6' }, + { 'Etc/GMT+7', '<-07>7' }, + { 'Etc/GMT+8', '<-08>8' }, + { 'Etc/GMT+9', '<-09>9' }, + { 'Etc/GMT-1', '<+01>-1' }, + { 'Etc/GMT-10', '<+10>-10' }, + { 'Etc/GMT-11', '<+11>-11' }, + { 'Etc/GMT-12', '<+12>-12' }, + { 'Etc/GMT-13', '<+13>-13' }, + { 'Etc/GMT-14', '<+14>-14' }, + { 'Etc/GMT-2', '<+02>-2' }, + { 'Etc/GMT-3', '<+03>-3' }, + { 'Etc/GMT-4', '<+04>-4' }, + { 'Etc/GMT-5', '<+05>-5' }, + { 'Etc/GMT-6', '<+06>-6' }, + { 'Etc/GMT-7', '<+07>-7' }, + { 'Etc/GMT-8', '<+08>-8' }, + { 'Etc/GMT-9', '<+09>-9' }, + { 'Europe/Amsterdam', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Andorra', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Astrakhan', '<+04>-4' }, + { 'Europe/Athens', 'EET-2EEST,M3.5.0/3,M10.5.0/4' }, + { 'Europe/Belgrade', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Berlin', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Bratislava', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Brussels', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Bucharest', 'EET-2EEST,M3.5.0/3,M10.5.0/4' }, + { 'Europe/Budapest', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Busingen', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Chisinau', 'EET-2EEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Copenhagen', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Dublin', 'IST-1GMT0,M10.5.0,M3.5.0/1' }, + { 'Europe/Gibraltar', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Guernsey', 'GMT0BST,M3.5.0/1,M10.5.0' }, + { 'Europe/Helsinki', 'EET-2EEST,M3.5.0/3,M10.5.0/4' }, + { 'Europe/Isle of Man', 'GMT0BST,M3.5.0/1,M10.5.0' }, + { 'Europe/Istanbul', '<+03>-3' }, + { 'Europe/Jersey', 'GMT0BST,M3.5.0/1,M10.5.0' }, + { 'Europe/Kaliningrad', 'EET-2' }, + { 'Europe/Kiev', 'EET-2EEST,M3.5.0/3,M10.5.0/4' }, + { 'Europe/Kirov', '<+03>-3' }, + { 'Europe/Lisbon', 'WET0WEST,M3.5.0/1,M10.5.0' }, + { 'Europe/Ljubljana', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/London', 'GMT0BST,M3.5.0/1,M10.5.0' }, + { 'Europe/Luxembourg', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Madrid', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Malta', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Mariehamn', 'EET-2EEST,M3.5.0/3,M10.5.0/4' }, + { 'Europe/Minsk', '<+03>-3' }, + { 'Europe/Monaco', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Moscow', 'MSK-3' }, + { 'Europe/Oslo', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Paris', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Podgorica', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Prague', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Riga', 'EET-2EEST,M3.5.0/3,M10.5.0/4' }, + { 'Europe/Rome', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Samara', '<+04>-4' }, + { 'Europe/San Marino', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Sarajevo', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Saratov', '<+04>-4' }, + { 'Europe/Simferopol', 'MSK-3' }, + { 'Europe/Skopje', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Sofia', 'EET-2EEST,M3.5.0/3,M10.5.0/4' }, + { 'Europe/Stockholm', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Tallinn', 'EET-2EEST,M3.5.0/3,M10.5.0/4' }, + { 'Europe/Tirane', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Ulyanovsk', '<+04>-4' }, + { 'Europe/Uzhgorod', 'EET-2EEST,M3.5.0/3,M10.5.0/4' }, + { 'Europe/Vaduz', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Vatican', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Vienna', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Vilnius', 'EET-2EEST,M3.5.0/3,M10.5.0/4' }, + { 'Europe/Volgograd', '<+04>-4' }, + { 'Europe/Warsaw', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Zagreb', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Zaporozhye', 'EET-2EEST,M3.5.0/3,M10.5.0/4' }, + { 'Europe/Zurich', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Indian/Antananarivo', 'EAT-3' }, + { 'Indian/Chagos', '<+06>-6' }, + { 'Indian/Christmas', '<+07>-7' }, + { 'Indian/Cocos', '<+0630>-6:30' }, + { 'Indian/Comoro', 'EAT-3' }, + { 'Indian/Kerguelen', '<+05>-5' }, + { 'Indian/Mahe', '<+04>-4' }, + { 'Indian/Maldives', '<+05>-5' }, + { 'Indian/Mauritius', '<+04>-4' }, + { 'Indian/Mayotte', 'EAT-3' }, + { 'Indian/Reunion', '<+04>-4' }, + { 'Pacific/Apia', '<+13>-13<+14>,M9.5.0/3,M4.1.0/4' }, + { 'Pacific/Auckland', 'NZST-12NZDT,M9.5.0,M4.1.0/3' }, + { 'Pacific/Bougainville', '<+11>-11' }, + { 'Pacific/Chatham', '<+1245>-12:45<+1345>,M9.5.0/2:45,M4.1.0/3:45' }, + { 'Pacific/Chuuk', '<+10>-10' }, + { 'Pacific/Easter', '<-06>6<-05>,M9.1.6/22,M4.1.6/22' }, + { 'Pacific/Efate', '<+11>-11' }, + { 'Pacific/Enderbury', '<+13>-13' }, + { 'Pacific/Fakaofo', '<+13>-13' }, + { 'Pacific/Fiji', '<+12>-12<+13>,M11.2.0,M1.2.3/99' }, + { 'Pacific/Funafuti', '<+12>-12' }, + { 'Pacific/Galapagos', '<-06>6' }, + { 'Pacific/Gambier', '<-09>9' }, + { 'Pacific/Guadalcanal', '<+11>-11' }, + { 'Pacific/Guam', 'ChST-10' }, + { 'Pacific/Honolulu', 'HST10' }, + { 'Pacific/Kiritimati', '<+14>-14' }, + { 'Pacific/Kosrae', '<+11>-11' }, + { 'Pacific/Kwajalein', '<+12>-12' }, + { 'Pacific/Majuro', '<+12>-12' }, + { 'Pacific/Marquesas', '<-0930>9:30' }, + { 'Pacific/Midway', 'SST11' }, + { 'Pacific/Nauru', '<+12>-12' }, + { 'Pacific/Niue', '<-11>11' }, + { 'Pacific/Norfolk', '<+11>-11<+12>,M10.1.0,M4.1.0/3' }, + { 'Pacific/Noumea', '<+11>-11' }, + { 'Pacific/Pago Pago', 'SST11' }, + { 'Pacific/Palau', '<+09>-9' }, + { 'Pacific/Pitcairn', '<-08>8' }, + { 'Pacific/Pohnpei', '<+11>-11' }, + { 'Pacific/Port Moresby', '<+10>-10' }, + { 'Pacific/Rarotonga', '<-10>10' }, + { 'Pacific/Saipan', 'ChST-10' }, + { 'Pacific/Tahiti', '<-10>10' }, + { 'Pacific/Tarawa', '<+12>-12' }, + { 'Pacific/Tongatapu', '<+13>-13' }, + { 'Pacific/Wake', '<+12>-12' }, + { 'Pacific/Wallis', '<+12>-12' }, +} + +name = arg[1] +TM = nil + +array = {} +i = 1 +repeat + array = TZ[i] + if array[1] == name then + TM = array[2] + break + end + i = i+1 +until(array == nil) + +local tfile = io.open("/tmp/tzone", "w") +if TM ~= nil then + tfile:write("ZNAME=\"", TM, "\"\n") + tfile:write("ZONEN=\"", name, "\"\n") +end +tfile:close() + diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/ussd.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/ussd.sh new file mode 100644 index 0000000..fb685b0 --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/lib/rooter/ussd.sh @@ -0,0 +1,67 @@ +#!/bin/sh + +CURRMODEM=$(uci get modem.general.modemnum) +COMMPORT="/dev/ttyUSB"$(uci get modem.modem$CURRMODEM.commport) +ROOTER=/usr/lib/rooter + +if [ -n "$1" ]; then + echo "$1" > /tmp/ussd_arg$CURRMODEM +fi + +while true; do + if [ -e /tmp/ussd_arg$CURRMODEM ]; then + read USSDSTR < /tmp/ussd_arg$CURRMODEM + rm /tmp/ussd_arg$CURRMODEM + fi + if [ -n "$USSDSTR" ]; then + ATCMDD="AT+CUSD=1,\"$USSDSTR\",15" + OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "ussd.gcom" "$CURRMODEM" "$ATCMDD" | tr "\n" "\v") + USSD=$(echo "$OX" | grep -o "+CUSD: .\+\",[0-9]\+" | tr "\v" "\n") + USSDL=${#USSD} + USSDLx=$((USSDL - 2)) + DCS=$(printf "${USSD:$USSDLx:2}") + if [ $USSDL -ge 14 ]; then + USSDL=$((USSDL - 14)) + USSD=$(printf "${USSD:10:$USSDL}") + if [ $DCS -eq "72" ]; then + USSDx="" + USSDL=${#USSD} + nV=0 + until [ $nV -ge $USSDL ]; do + UU=$(printf "%d" "0x"${USSD:$nV:4}) + if [[ $UU -lt 128 ]]; then + USSDx="$USSDx"$(printf "%b" "\\$(printf "0%o" "$UU")") + elif [[ $UU -lt 2048 ]]; then + UUU=$(((($UU & 1984) >> 6) | 192)) + USSDx="$USSDx"$(printf "%b" "\\$(printf "0%o" "$UUU")") + UUU=$((($UU & 63) | 128)) + USSDx="$USSDx"$(printf "%b" "\\$(printf "0%o" "$UUU")") + else + UUU=$(((($UU & 61440) >> 12) | 224)) + USSDx="$USSDx"$(printf "%b" "\\$(printf "0%o" "$UUU")") + UUU=$(((($UU & 4032) >> 6) | 128)) + USSDx="$USSDx"$(printf "%b" "\\$(printf "0%o" "$UUU")") + UUU=$((($UU & 63) | 128)) + USSDx="$USSDx"$(printf "%b" "\\$(printf "0%o" "$UUU")") + fi + nV=$(( $nV + 4 )) + done + USSD="$USSDx" + fi + else + USSD=$(echo "$OX" | tr "\v" "\n") + fi + echo + echo "-----------------------------------------------------------" + echo "$USSD" + echo "-----------------------------------------------------------" + echo + fi + printf "Enter blank to quit, or a USSD string to send: "; read USSDSTR + if [ -z "$USSDSTR" ]; then + break + fi +done +ATCMDD="AT+CUSD=2" +OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") +exit 0 diff --git a/rooter/ext-rooter-basic/files/usr/sbin/modlog b/rooter/ext-rooter-basic/files/usr/sbin/modlog new file mode 100644 index 0000000..46a614f --- /dev/null +++ b/rooter/ext-rooter-basic/files/usr/sbin/modlog @@ -0,0 +1,7 @@ +#!/bin/sh + +name=$1 +text=$2 + +logger -t "$name" "$text" +/usr/lib/rooter/log/modlogger.sh "$name $text" \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/www/luci-static/background/main_bg.jpg b/rooter/ext-rooter-basic/files/www/luci-static/background/main_bg.jpg new file mode 100644 index 0000000..66222dc Binary files /dev/null and b/rooter/ext-rooter-basic/files/www/luci-static/background/main_bg.jpg differ diff --git a/rooter/ext-rooter-basic/files/www/luci-static/css/cascade.css b/rooter/ext-rooter-basic/files/www/luci-static/css/cascade.css new file mode 100644 index 0000000..19b2b1e --- /dev/null +++ b/rooter/ext-rooter-basic/files/www/luci-static/css/cascade.css @@ -0,0 +1,3266 @@ +@import url(fonts.css?v=3); + +@import url(pure-min.css?v=1); + +:root { + --primary: #5e72e4; + --dark-primary: #483d8b; + --main-color: #09c; + --header-bg: #09c; + --header-color: #fff; + --bar-bg: #5e72e4; + --menu-bg-color: #fff; + --menu-color: #5f6368; + --menu-color-hover: #202124; + --main-menu-color: #202124; + --submenu-bg-hover: #d4d4d4; + --submenu-bg-hover-active: #09c; + --blue: #5e72e4; + --indigo: #5603ad; + --purple: #8965e0; + --pink: #f3a4b5; + --red: #f5365c; + --orange: #fb6340; + --yellow: #ffd600; + --green: #2dce89; + --teal: #11cdef; + --cyan: #2bffc6; + --gray: #8898aa; + --gray-dark: #32325d; + --lighter: #e9ecef; + --secondary: #f7fafc; + --success: #2dce89; + --info: #11cdef; + --warning: #fb6340; + --danger: #f5365c; + --light: #adb5bd; + --dark: #212529; + --default: #172b4d; + --white: #fff; + --neutral: #fff; + --darker: #000; + --background-color: #f4f5f7; + --login-form-bg-color: rgba(244,245,247,0.8); + --breakpoint-xs: 0; + --breakpoint-sm: 576px; + --breakpoint-md: 768px; + --breakpoint-lg: 992px; + --breakpoint-xl: 1200px; + --blur-radius: 10px; + --blur-opacity: .5; + --blur-radius-dark: 10px; + --blur-opacity-dark: .5; + --font-family-sans-serif: "Google Sans","Microsoft Yahei","WenQuanYi Micro Hei",sans-serif,"Helvetica Neue",Helvetica,"Hiragino Sans GB"; + --font-family-monospace: SFMono-Regular,Menlo,Monaco,Consolas,'Liberation Mono','Courier New',monospace; + --font-family-normal: Open Sans,PingFangSC-Regular,Microsoft Yahei,WenQuanYi Micro Hei,"Helvetica Neue",Helvetica,Hiragino Sans GB,sans-serif; +} + +html,body { + height: 100%; + font-size: 16px; + font-family: var(--font-family-sans-serif); + margin: 0px; + padding: 0px; +} + +html { + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100%; +} + +body { + font-size: .875rem; + background-color: var(--background-color); + color: var(--gray-dark); +} + +* { + box-sizing: border-box; + margin: 0; + padding: 0; +} + +::selection { + background-color: var(--primary); + color: var(--white); +} + +a:link,a:visited,a:active { + color: var(--primary); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +li { + list-style-type: none; +} + +.table { + position: relative; + display: table; +} + +.tr { + display: table-row; +} + +.thead { + display: table-header-group; +} + +.tbody { + display: table-row-group; +} + +.tfoot { + display: table-footer-group; +} + +.td,.th { + line-height: normal; + display: table-cell; + text-align: center; + vertical-align: middle; + padding: .5em; +} + +.th { + font-weight: 700; + white-space: nowrap; +} + +.tr.placeholder { + height: 4em; +} + +.tr.placeholder>.td { + line-height: 3; + position: absolute; + right: 0; + bottom: 0; + left: 0; + text-align: center!important; + background: inherit; + padding: .4rem 0!important; +} + +.td[width="33%"] { + padding: 1.1em 1.5rem; +} + +.table[width="33%"],.th[width="33%"],.td[width="33%"] { + width: 33%; +} + +.col-1 { + flex: 1 1 30px!important; +} + +.col-2 { + flex: 2 2 60px!important; +} + +.col-3 { + flex: 3 3 90px!important; +} + +.col-4 { + flex: 4 4 120px!important; +} + +.col-5 { + flex: 5 5 150px!important; +} + +.col-6 { + flex: 6 6 180px!important; +} + +.col-7 { + flex: 7 7 210px!important; +} + +.col-8 { + flex: 8 8 240px!important; +} + +.col-9 { + flex: 9 9 270px!important; +} + +.col-10 { + flex: 10 10 300px!important; +} + +.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6 { + font-family: inherit; + font-weight: 400; + line-height: 1.1!important; + color: inherit; +} + +select { + color: #555; + border: thin solid #ccc; + background-color: #fff; + background-image: none; + padding: .36rem .8rem; +} + +.btn,button,select,input,.cbi-dropdown { + line-height: 1.5rem; + color: #8898aa; + border: 1px solid #dee2e6; + border-radius: .25rem; + outline: 0; + background-image: none; + box-shadow: none; + transition: box-shadow .15s ease; + margin: .25rem .1rem; + padding: .5rem .75rem; +} + +select,.cbi-dropdown { + width: inherit; + cursor: default; +} + +select:not([multiple="multiple"]):focus,input:not(.cbi-button):focus,.cbi-dropdown:focus { + box-shadow: 0 3px 9px rgba(50,50,9,0),3px 4px 8px rgba(94,114,228,0.1); + border-color: var(--primary); +} + +pre { + overflow: auto; +} + +code { + font-size: 1rem; + font-size-adjust: .35; + color: #101010; + border-radius: 2px; + background: #ddd; + padding: 1px 3px; +} + +abbr { + cursor: help; + text-decoration: underline; + color: var(--primary); +} + +hr { + opacity: .1; + border-color: #eee; + margin: 1rem 0; +} + +.login-page { + height: 95vh; + width: 95vw; +} + +.login-page .video { + position: absolute; + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: center; + background-color: var(--darker); + overflow: hidden; +} + +.login-page .video video { + width: 100%; + height: auto; +} + +.login-page .volume-control { + position: fixed; + right: 1rem; + top: 1rem; + width: 1.5rem; + height: 1.5rem; + z-index: 5000; + cursor: pointer; + background-size: contain; + background-image: url(../img/volume_high.svg); +} + +.login-page .volume-control.mute { + background-image: url(../img/volume_off.svg); +} + +.login-page .main-bg { + position: absolute; + width: 101vw; + height: 101vh; + left: 0; + top: 0; + background-image: url(../img/blank.png); + background-repeat: no-repeat; + background-position: center; + background-size: cover; + transition: all .5s; + background-color: rgba(255,255,255,1); +} + + +.login-page .status-container { + height: 100%; + position: absolute; + top: 0px; + + right: 0px; + display: flex; + flex-direction: column; + -webkit-box-pack: center; + justify-content: center; + align-items: flex-start; + min-height: 100%; + z-index: 2; + width: 800px; + box-shadow: rgba(0,0,0,0.75) 0 0 35px -5px; + margin-left: 5%; + background: transparent; +} + +.login-page .status-container .status-form { + display: flex; + flex-direction: column; + -webkit-box-align: center; + align-items: right; + position: absolute; + top: 0px; + width: 100%; + min-height: 100%; + max-width: 800px; + background-color: rgba(224,224,224,0); +} + +.login-page .login-container { + height: 100%; + position: absolute; + top: 0px; + display: flex; + flex-direction: column; + -webkit-box-pack: center; + justify-content: center; + align-items: flex-start; + min-height: 100%; + z-index: 2; + width: 20vw; + box-shadow: rgba(0,0,0,0.75) 0 0 35px -5px; + margin-left: 4%; + background: transparent; +} + +/* color of login panel */ +.login-page .login-container .login-form { + display: flex; + flex-direction: column; + -webkit-box-align: center; + align-items: center; + position: absolute; + top: 0px; + width: 100%; + min-height: 100%; + max-width: 100%; + background-color: rgba(224,224,224,0.7); +} + +/* change for login box */ +.login-page .login-container .login-form .brand { + display: flex; + -webkit-box-align: center; + align-items: center; + color: var(--default); + margin: 20px auto 5px 10px; +} + +.login-page .login-container .login-form .brandim { + display: flex; + -webkit-box-align: center; + align-items: center; + color: var(--default); + margin: 12vh 0px 30px 0px; +} + +.login-page .login-container .login-form .brandim .icon-im { + width: 19vw; + height: auto; + margin-right: 0px; +} + +.login-page .login-iframe { + height: 12vh; + position: absolute; + top: 85vh; + left: 0; + display: flex; + flex-direction: column; + -webkit-box-pack: center; + justify-content: center; + align-items: flex-start; + min-height: 12vh; + z-index: 2; + width: 18vw; + margin-left: 1vw; + background: transparent; +} +.login-page .login-iframe .login-iform { + display: flex; + flex-direction: column; + -webkit-box-align: center; + align-items: center; + position: absolute; + top: 0px; + width: 100%; + min-height: 12vh; + max-width: 100%; +} + +.login-page .login-iframe .login-iform .ifframe { + width: 100vw; + max-width: 100%; + height: 50vh; + max-height: 100%; + left: 0px; + position: absolute; + top: 0px; +} + +.login-page .login-bframe { + height: 45vh; + position: absolute; + top: 52vh; + left: 0; + display: flex; + flex-direction: column; + -webkit-box-pack: center; + justify-content: center; + align-items: flex-start; + min-height: 45vh; + z-index: 2; + width: 24vw; + margin-left: -2vw; + background: transparent; +} +.login-page .login-bframe .login-bform { + display: flex; + flex-direction: column; + -webkit-box-align: center; + align-items: center; + position: absolute; + top: 0px; + width: 100%; + min-height: 45vh; + max-width: 100%; +} + +.login-page .login-bframe .login-bform .ibframe { + width: 100vw; + max-width: 100%; + height: 50vh; + max-height: 100%; + left: 0px; + position: absolute; + top: 0px; +} + +/* size of logo displayed */ +.login-page .login-container .login-form .brand .icon-lg { + width: 19vw; + height: auto; + margin-right: 10px; +} + +.login-page .login-container .login-form .brand .icon { + width: 7vw; + height: auto; + margin-right: 10px; +} + +.login-page .login-container .login-form .brand .brand-text { + font-size: 1.2vw; + font-weight: 700; + font-family: TypoGraphica; +} + +.login-page .login-container .login-form .brand .brand-textlg { + font-size: 1.2vw; + font-weight: 700; + font-family: TypoGraphica; + margin-left: 2vw; +} + +.login-page .login-container .login-form .form-login { + width: 100%; + box-sizing: border-box; + padding: 20px 50px; +} + +.login-page .login-container .login-form .form-login .errorbox { + text-align: center; + color: var(--warning); + padding-bottom: 2rem; +} + +.login-page .login-container .login-form .form-login .input-group { + margin-bottom: 1.25rem; + position: relative; +} + +.login-page .login-container .login-form .form-login .input-group::before { + font-family: argon!important; + font-style: normal; + font-weight: 400; + font-variant: normal; + text-transform: none; + line-height: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + color: var(--default); + font-size: 1.5rem; + position: absolute; + z-index: 100; + left: 10px; + top: 10px; +} + +.login-page .login-container .login-form .form-login .input-group .border { + position: absolute; + width: 100%; + height: 1px; + bottom: 0; + border-bottom: 1px var(--primary) solid; + transform: scaleX(0); + transition: transform .3s; +} + +.login-page .login-container .login-form .form-login .input-group input { + font-size: 1rem; + line-height: 1.5em; + display: block; + width: 100%; + box-sizing: border-box; + transition: all .3s cubic-bezier(.68,-0.55,.265,1.55); + color: var(--default); + border: 0; + border-radius: 0; + border-bottom: 1px solid var(--white); + background-color: transparent; + background-clip: padding-box; + box-shadow: 0 3px 2px rgba(233,236,239,0.05); + outline: none; + margin: .825rem 0; + padding: .5rem .75rem .5rem 3rem; +} + +.login-page .login-container .login-form .form-login .input-group input:focus+.border { + transform: scaleX(1); +} + +.login-page .login-container .login-form .form-login .input-group .cbi-input-password { + margin-bottom: 2rem; + position: relative; +} + +.login-page .login-container .login-form .form-login .user-icon::before { + content: "\e971"; +} + +.login-page .login-container .login-form .form-login .pass-icon::before { + content: "\e910"; +} + +.login-page .login-container .login-form .cbi-button-apply { + width: 100%!important; + box-shadow: rgba(0,0,0,0.1) 0 0 50px 0; + font-weight: 600; + font-size: 15px; + color: var(--white); + text-align: center; + cursor: pointer; + min-height: 50px; + background-color: var(--primary)!important; + border-radius: 6px; + outline: none; + border-image: initial; + transition: all .3s!important; + letter-spacing: .8rem; + border-color: initial; + border-style: none; + border-width: initial; + margin: 30px 0px 20px; + padding: 10px 0px; +} + +.login-page .login-container .login-form .cbi-button-apply:hover,.login-page .login-container .login-form .cbi-button-apply :focus { + opacity: .9; +} + +.login-page .login-container footer { + box-sizing: border-box; + width: 100%; + text-align: center; + line-height: 1.6rem; + display: flex; + justify-content: space-evenly; + margin-top: auto; + z-index: 10; + color: var(--default); + position: absolute; + bottom: 0; + padding: 0px 0px 30px; +} + +.login-page .login-container footer .ftc { + position: absolute; + bottom: 30px; + width: 100%; +} + +footer { + font-size: .8rem; + overflow: hidden; + text-align: right; + white-space: nowrap; + color: #aaa; + padding: 1rem; +} + +footer>a { + text-decoration: none; + color: #aaa; +} + +small { + font-size: 90%; + line-height: 1.42857143; + white-space: normal; +} + +.main { + position: relative; + top: 0; + bottom: 0; + overflow-y: auto; + height: 100%; +} + +.main-left { + top: 0; + float: left; + width: calc(0% + 15rem); + height: 100%; + background-color: var(--menu-bg-color); + box-shadow: rgba(0,0,0,0.75) 0 0 15px -5px; + overflow-x: auto; + position: fixed; + z-index: 100; +} + +.main-left .sidenav-header { + text-align: center; + padding: 1.5rem; +} + +.main-left .sidenav-header .brand { + font-size: 1.8rem; + color: var(--primary); + font-family: TypoGraphica; + text-decoration: none; + text-align: center; + cursor: default; + vertical-align: text-bottom; + white-space: nowrap; +} + +.main-left::-webkit-scrollbar { + width: 5px; + height: 1px; +} + +.main-right { + float: right; + width: calc(100% - 15rem); + height: 100%; + transition: all .2s; +} + +.main-right>#maincontent { + position: relative; + z-index: 50; +} + +.pull-right { + float: right; +} + +.nowrap:not(.td) { + white-space: nowrap; +} + +[disabled="disabled"] { + pointer-events: none; +} + +header { + color: var(--header-color); + position: relative; + padding: 0; +} + +header.bg-primary { + background-color: var(--primary)!important; +} + +header::after { + content: ""; + position: absolute; + height: 2rem; + width: 100%; + background-color: var(--primary)!important; +} + +header .fill { + border-bottom: 0 solid rgba(255,255,255,0.08)!important; + padding: .8rem 0; +} + +header .fill .container { + height: 2rem; + padding: 0 1.25rem; +} + +header .fill .container .showSide { + display: none; + color: #fff; + font-size: 1.4rem; +} + +header .fill .container .brand { + font-size: 1.5rem; + color: #fff; + font-family: TypoGraphica; + text-decoration: none; + padding-left: 1rem; + cursor: default; + vertical-align: text-bottom; + display: none; +} + +header .fill .container .pull-right { + float: right; + margin-top: 0rem; + display: flex; +} + +header .fill .status { + position: absolute; + top: 25%; + right: 1.25rem; + float: right; +} + +header .fill .status span[data-indicator="poll-status"] { + display: block; + font-size: .8rem; + font-weight: 700; + white-space: nowrap; + text-decoration: none; + text-transform: uppercase; + text-shadow: none; + border-radius: 3px; + cursor: pointer; + transition: all .3s; + padding: .3rem .8rem; +} + +header .fill .status span[data-style="active"] { + color: #32325d!important; + background-color: #fff; +} + +header .fill .status span[data-style="inactive"] { + color: #FFF!important; + background-color: #32325d; +} + +#xhr_poll_status { + display: flex; + margin-left: .5rem; +} + +div[style="width:100%;height:300px;border:1px solid #000;background:#fff"] { + border: 0!important; +} + +.danger { + background-color: #ff7d60!important; +} + +.warning { + background-color: #f0e68c!important; +} + +.success { + background-color: #5cb85c!important; +} + +.notice { + background-color: #11cdef!important; + color: #fff; +} + +.error { + color: red; +} + +.alert,.alert-message { + font-weight: 700; + margin-bottom: 1em; + border: 0; + border-radius: .375rem!important; + background-color: #fff; + box-shadow: 0 2px 2px 0 rgba(0,0,0,0.16),0 0 2px 0 rgba(0,0,0,0.12); + text-shadow: 1px 1px rgba(0,0,0,0.1); + padding: 1rem; +} + +.alert.error,.alert-message.error { + background-color: #ffd600; +} + +.alert h4,.alert-message h4 { + padding: 0 1.5rem .75rem 0; +} + +.alert-message>h4 { + font-size: 110%; + font-weight: 700; +} + +.alert-message>* { + margin: .5rem 0; +} + +.alert-message .btn { + padding: .3rem .6rem; +} + +.main .main-left { + transition: all .2s; +} + +.main .main-left .nav li { + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + padding: 0; +} + +.main .main-left .nav li a { + display: block; + color: var(--menu-color); +} + +.main .main-left .nav li.slide .slide-menu { + margin: 0 .5rem 0 2.5rem; + padding: 0 .5rem; +} + +.main .main-left .nav li.slide .slide-menu li { + position: relative; + border-radius: .375rem; + background: none; + list-style: none; + margin: 0; + padding: .5rem 0; +} + +.main .main-left .nav li.slide .slide-menu li a { + white-space: nowrap; + text-decoration: none; +} + +.main .main-left .nav li.slide .slide-menu li::after { + content: ""; + position: absolute; + left: 0; + bottom: 0; + width: 0; + height: 2px; + background-color: var(--primary); + transition: all .2s; +} + +.main .main-left .nav li.slide .slide-menu .active { + background: none; + color: var(--menu-color); +} + +.main .main-left .nav li.slide .slide-menu .active a { + color: var(--menu-color); +} + +.main .main-left .nav li.slide .slide-menu .active::after { + content: ""; + position: absolute; + left: 0; + bottom: 0; + width: 100%; + height: 2px; + background-color: var(--primary); + transition: all .2s; +} + +.main .main-left .nav li .menu::after { + position: absolute; + right: .5rem; + top: .8rem; + font-family: argon!important; + font-style: normal; + font-weight: 400; + font-variant: normal; + text-transform: none; + line-height: 1; + -moz-osx-font-smoothing: grayscale; + content: '\e90f'; + color: #ced4da; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + transition: all .3s; +} + +.main .main-left .nav li .menu[data-title=Status]:before { + content: "\e906"; + color: var(--primary); +} + +.main .main-left .nav li .menu[data-title=System]:before { + content: "\e90a"; + color: #fb6340; +} + +.main .main-left .nav li .menu[data-title=Services]:before { + content: "\e909"; + color: #11cdef; +} + +.main .main-left .nav li .menu[data-title=NAS]:before { + content: "\e90c"; + color: #f3a4b5; +} + +.main .main-left .nav li .menu[data-title=VPN]:before { + content: "\e90b"; + color: #8965e0; +} + +.main .main-left .nav li .menu[data-title=Network]:before { + content: "\e908"; + color: #8965e0; +} + +.main .main-left .nav li .menu[data-title=Bandwidth_Monitor]:before { + content: "\e90d"; + color: #2dce89; +} + +.main .main-left .nav li .menu[data-title=Docker]:before { + content: "\e911"; + color: #69F; +} + +.main .main-left .nav li .menu[data-title=Statistics]:before { + content: "\e913"; + color: #8965e0; +} + +.main .main-left .nav li .menu[data-title=Control]:before { + content: "\e912"; + color: var(--primary); +} + +.main .main-left .nav li .menu[data-title=Asterisk]:before { + content: "\e914"; + color: #fb6340; +} + +.main .main-left .nav li a[data-title=Logout]:before { + content: "\e907"; + color: #adb5bd; +} + +.lg { + margin: 0; + padding: 0!important; +} + +.logout { + display: block; + border-radius: .375rem; + text-decoration: none; + font-size: 1rem; + transition: all .2s; + position: relative; + margin: .8rem .5rem .1rem; + padding: .675rem 0 .675rem 2.5rem; +} + +.logout:before { + font-family: argon!important; + font-style: normal; + font-weight: 400; + font-variant: normal; + text-transform: none; + line-height: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + position: absolute; + left: .8rem; + padding-top: 3px; + transition: all .3s; + content: "\e907"; + color: #32325d!important; +} + +body[class*="node-"]>.main>.main-left>.nav>.slide>.menu::before { + transition: transform .1s ease-in-out; +} + +body[class*="node-"]>.main>.main-left>.nav>.slide>.menu.active::before { + transition: transform .2s ease-in-out; +} + +#maincontent>.container { + margin: 0 1.25rem 1rem; +} + +ul { + line-height: normal; +} + +h1 { + font-size: 2rem; + padding-bottom: 10px; + border-bottom: thin solid #eee; +} + +h2 { + font-size: 1.25rem; + letter-spacing: .1rem; + color: #32325d; + border-radius: .375rem; + background: #fff; + box-shadow: 0 4px 8px rgba(0,0,0,0.03); + margin: 0 0 1rem; + padding: 1rem 1.5rem; +} + +h3 { + font-size: 1.1rem; + line-height: 1; + display: block; + width: 100%; + color: var(--gray-dark); + border-radius: .375rem; + background: #fff; + margin: 0; + padding: .8755rem 1.5rem; +} + +h4 { + font-size: .7rem; + font-weight: 600; + color: #525f7f; + background-color: var(--lighter); + margin: 0; + padding: .75rem 1.5rem; +} + +h4 em { + padding: 0 .5rem; +} + +h5 { + font-size: 1rem; + padding-bottom: 10px; + margin: 2rem 0 0; +} + +.cbi-section,.cbi-section-error,#iptables,.Firewall form,#cbi-network>.cbi-section-node,#cbi-wireless>.cbi-section-node,#cbi-wireless>#wifi_assoclist_table,[data-tab-title],[data-page^="admin-system-admin"]:not(.node-main-login) .cbi-map:not(#cbi-dropbear),[data-page="admin-system-opkg"] #maincontent>.container { + font-family: inherit; + font-weight: 400; + font-style: normal; + line-height: normal; + min-width: inherit; + border: 0; + border-radius: .375rem; + background-color: #fff; + box-shadow: 0 0 1rem 0 rgba(136,152,170,0.15); + margin: 1.5rem 0; + padding: 0rem; +} + +.cbi-modal .cbi-section,.cbi-section .cbi-section { + box-shadow: none; + padding: 0; +} + +.cbi-modal .cbi-tabmenu { + margin-left: 0; +} + +.cbi-map-descr,.cbi-section-descr { + font-size: small; + line-height: 1.42857143; + padding: .5rem 1.5rem; +} + +.cbi-map-descr>abbr { + cursor: help; + text-decoration: underline; +} + +.cbi-section>legend { + display: none!important; +} + +fieldset>fieldset,.cbi-section>.cbi-section { + border: 0; + box-shadow: none; + margin: 0; + padding: 0; +} + +.cbi-section>h3:first-child,.panel-title { + font-size: 1.1rem; + line-height: 1; + display: block; + width: 100%; + color: var(--gray-dark); + margin: 0; + padding: .8755rem 1.5rem; +} + +table { + border-spacing: 0; + border-collapse: collapse; +} + +table,.table { + overflow-y: hidden; + width: 100%; + font-size: 90%; +} + +.table .table-titles th { + background-color: var(--lighter); +} + +.container>.cbi-section:first-of-type>.table[width="100%"]>.tr>.td { + padding: .6rem; +} + +.cbi-section-table-cell { + line-height: 1.1; + align-self: flex-end; + flex: 1 1 auto; +} + +tr>td,tr>th,.tr>.td,.tr>.th,.cbi-section-table-row::before,#cbi-wireless>#wifi_assoclist_table>.tr:nth-child(2) { + border-top: thin solid #ddd; + padding: 1.1em 1.5rem; +} + +#cbi-wireless .td,#cbi-network .tr:first-child>.td,.table[width="100%"]>.tr:first-child>.td,[data-page="admin-network-diagnostics"] .tr>.td,.tr.table-titles>.th,.tr.cbi-section-table-titles>.th { + border-top: 0!important; + background-color: #f6f9fc; + line-height: 1.3rem; + padding: 1.1em 1.5rem; +} + +.table[width="100%"]>.tr:first-child>.td { + margin: auto 0; +} + +.cbi-section-table-row { + margin-bottom: 1rem; + text-align: center!important; + background: #f4f4f4; +} + +.cbi-section-table-row:last-child { + margin-bottom: 0; +} + +.cbi-section-table-row>.cbi-value-field [data-dynlist]>input,.cbi-section-table-row>.cbi-value-field input.cbi-input-password { + width: calc(100% - 1.5rem); +} + +table table,.table .table,.cbi-value-field table,.cbi-value-field .table,td>table>tbody>tr>td,.td>.table>.tbody>.tr>.td,.cbi-value-field>table>tbody>tr>td,.cbi-value-field>.table>.tbody>.tr>.td { + border: 0; +} + +.btn,.cbi-button,.item::after { + font-size: .8rem; + display: inline-block; + width: auto!important; + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + transition: all .2s ease-in-out; + text-align: center; + vertical-align: middle; + white-space: nowrap; + text-decoration: none; + text-transform: uppercase; + color: rgba(0,0,0,0.87); + border: 0; + border-radius: .2rem; + background-color: #f0f0f0; + background-image: none; + -webkit-appearance: none; + -ms-touch-action: manipulation; + touch-action: manipulation; + padding: .45rem .8rem; +} + +.cbi-button-up,.cbi-button-down { + font-size: 1.2rem; + display: inline-block; + min-width: 0; + color: transparent!important; + background: url(../icon/arrow.svg) no-repeat center; + background-size: 12px 20px; + padding: .2rem .3rem; +} + +.cbi-button-up { + transform: scaleY(-1); +} + +.cbi-button:not(select) { + -webkit-appearance: none!important; +} + +.btn:hover,.btn:focus,.btn:active,.cbi-button:hover,.cbi-button:focus,.cbi-button:active,.item:hover::after,.item:focus::after,.item:active::after,.cbi-page-actions .cbi-button-apply+.cbi-button-save:hover,.cbi-page-actions .cbi-button-apply+.cbi-button-save:focus,.cbi-page-actions .cbi-button-apply+.cbi-button-save:active { + text-decoration: none; + outline: 0; +} + +.btn:hover,.btn:focus,.cbi-button:hover,.cbi-button:focus,.item:hover::after,.item:focus::after { + box-shadow: 0 0 2px rgba(0,0,0,0.12),0 2px 2px rgba(0,0,0,0.2); +} + +.btn:active,.cbi-button:active,.item:active::after { + box-shadow: 0 10px 20px rgba(0,0,0,0.19),0 6px 6px rgba(0,0,0,0.23); +} + +.cbi-button-up:hover,.cbi-button-up:focus { + box-shadow: 0 0 2px rgba(0,0,0,0.12),0 -2px 2px rgba(0,0,0,0.2); +} + +.cbi-button-up:active { + box-shadow: 0 -10px 20px rgba(0,0,0,0.19),0 -6px 6px rgba(0,0,0,0.23); +} + +.btn:disabled,.cbi-button:disabled { + cursor: not-allowed; + pointer-events: none; + opacity: .5; + box-shadow: none; +} + +.alert-message [class="btn"],.modal div[class="btn"],.cbi-button-find,.cbi-button-link,.cbi-button-up,.cbi-button-down,.cbi-button-neutral,.cbi-button[name="zero"],.cbi-button[name="restart"],.cbi-button[onclick="hide_empty(this)"] { + font-weight: 700; + color: #fff; + border: thin solid #8898aa; + background-color: #8898aa; +} + +.btn.danger,.cbi-section-remove>.cbi-button,.cbi-button-remove,.cbi-button-reset,.cbi-button-negative,.cbi-button[value="Stop"],.cbi-button[value="Kill"],.cbi-button[onclick="reboot(this)"],.cbi-button-neutral[value="Restart"] { + font-weight: 400; + color: #fff; + border: thin solid var(--red); + background-color: var(--red); +} + +.btn[value="Dismiss"],.cbi-button[value="Terminate"],.cbi-button[value="Reset"],.cbi-button[value="Disabled"],.cbi-button[onclick^="iface_reconnect"],.cbi-button[onclick="handleReset(event)"],.cbi-button-neutral[value="Disable"] { + font-weight: 400; + color: #fff; + border: thin solid #eea236; + background-color: #f0ad4e; +} + +.cbi-button-success,.cbi-button-download,.cbi-button[name="backup"],.cbi-button[value="Download"],.cbi-button[value="Save mtdblock"] { + font-weight: 400; + color: #fff; + border: thin solid #4cae4c; + background-color: #5cb85c; +} + +.cbi-value-field .cbi-button-add { + font-weight: 700; + display: flex; + align-items: center; + margin: 4px 0 4px 3px; + padding: 1px 6px; +} + +.tabs { + background-color: #FFF; + border-radius: .375rem; + box-shadow: 0 4px 8px rgba(0,0,0,0.03); + white-space: nowrap; + overflow-x: auto; + margin: 0 0 1rem; + padding: 0 1rem; +} + +.tabs li[class~="active"],.tabs li:hover { + cursor: pointer; + border-bottom: .18751rem solid var(--primary); + color: var(--primary); + background-color: #dce1fe; + margin-bottom: 0; + border-radius: 0; +} + +.tabs li { + font-size: .875rem; + display: inline-block; + border-bottom: .18751rem solid rgba(0,0,0,0); + margin: 0 .2rem; + padding: .875rem 0; +} + +.tabs li:hover { + border-bottom: .18751rem solid var(--primary); +} + +.cbi-tabmenu { + color: #fff; + white-space: nowrap; + overflow-x: auto; + padding: .5rem 1rem 0; +} + +.cbi-tabmenu li { + background: #dce3e9; + display: inline-block; + font-size: .875rem; + border-top-left-radius: .25rem; + border-top-right-radius: .25rem; + border-bottom: .18751rem solid rgba(0,0,0,0); + margin: 0 .2rem; + padding: .5rem 0; +} + +.cbi-tabmenu li:hover { + cursor: pointer; + border-bottom: .18751rem solid var(--primary); + color: var(--primary); + background-color: #dce1fe; + margin-bottom: 0; +} + +.cbi-tabmenu li:hover a { + color: #525f7f; +} + +.cbi-tabmenu li[class~="cbi-tab"] { + border-bottom: .18751rem solid var(--primary); + color: var(--primary); + background-color: #dce1fe; + margin-bottom: 0; +} + +.cbi-tab-descr { + padding: .5rem 1.5rem; +} + +[data-tab-title] { + overflow: hidden; + height: 0; + opacity: 0; + margin: 0; + padding: 0rem!important; +} + +[data-tab-title] p { + margin-left: 1rem; + margin-bottom: 1rem; +} + +[data-tab-active="true"] { + overflow: visible; + height: auto; + opacity: 1; + transition: opacity .25s ease-in; + margin: inherit!important; +} + +.cbi-section-node-tabbed { + margin-top: 0; + border: 0 solid #d4d4d4; + border-radius: .375rem; + padding: 0; +} + +.cbi-value-field,.cbi-value-description { + line-height: 1.25; + display: table-cell; +} + +.cbi-value-field abbr,.cbi-value-description abbr { + color: var(--gray-dark); +} + +.cbi-value-description { + font-size: small; + opacity: .5; + padding: .5rem; +} + +.cbi-value-title { + display: table-cell; + float: left; + width: 23rem; + padding-top: .25rem; + padding-right: 2rem; + text-align: right; + word-wrap: break-word; +} + +.cbi-value { + display: inline-block; + width: 100%; + line-height: 2.4rem; + padding: .35rem 1rem .2rem; +} + +.cbi-value ul { + line-height: 1.25; +} + +.cbi-value-field .cbi-dropdown,.cbi-value-field .cbi-input-select,.cbi-value input[type="text"],.cbi-value input[type="password"] { + min-width: 18rem; +} + +.cbi-value input[type="password"] { + border-bottom-right-radius: 0; + border-top-right-radius: 0; + margin-right: 0; +} + +.cbi-value input[type="password"]+.cbi-button-neutral { + height: 42px; + border-bottom-left-radius: 0; + border-top-left-radius: 0; + margin-left: 0; + border: 0; +} + +#cbi-firewall-zone .cbi-input-select,#cbi-network-switch_vlan .cbi-input-select { + min-width: 11rem; +} + +#cbi-network-switch_vlan .cbi-input-text { + max-width: 3rem; +} + +.cbi-input-invalid { + color: #f5365c; + border-bottom-color: #f5365c; +} + +.cbi-section-error { + font-weight: 700; + line-height: 1.42857143; + border: thin solid #f5365c; + border-radius: 3px; + background-color: #fce6e6; + margin: 18px; + padding: 6px; +} + +.cbi-section-error ul { + margin: 0 0 0 20px; +} + +.cbi-section-error ul li { + font-weight: 700; + color: #f5365c; +} + +.td[data-title]::before { + font-weight: 700; + display: none; + content: attr(data-title) ":\20"; + text-align: left; + white-space: nowrap; + padding: .25rem 0; +} + +.tr[data-title]::before,.tr.cbi-section-table-titles.named::before { + font-weight: 700; + display: table-cell; + align-self: center; + flex: 1 1 5%; + content: attr(data-title) "\20"; + text-align: center; + vertical-align: middle; + white-space: normal; + word-wrap: break-word; + padding: .25rem; +} + +.cbi-rowstyle-2 { + background-color: #eee; +} + +.cbi-rowstyle-2 .cbi-button-up,.cbi-rowstyle-2 .cbi-button-down,body:not(.Interfaces) .cbi-rowstyle-2:first-child { + background-color: #fff!important; +} + +.cbi-section-table .cbi-section-table-titles .cbi-section-table-cell { + width: auto!important; +} + +.td.cbi-section-actions { + text-align: right!important; + vertical-align: middle; +} + +.td.cbi-section-actions>* { + display: inline-flex; +} + +.td.cbi-section-actions>*>*,.td.cbi-section-actions>*>form>* { + display: flex; + align-items: center; + margin: 0 5px; +} + +.td.cbi-section-actions>*>form { + display: inline-flex; + margin: 0; +} + +.cbi-checkbox { + margin: 0 .25rem; +} + +.cbi-dynlist { + line-height: 1.3; + flex-direction: column; + min-height: 30px; + cursor: text; +} + +.cbi-dynlist>.item { + position: relative; + max-width: 25rem; + pointer-events: none; + color: #8898aa; + outline: 0; +} + +.cbi-dynlist[name="sshkeys"]>.item { + max-width: none; +} + +.cbi-dynlist>.item::after { + position: absolute; + width: 2.2rem!important; + height: calc(100% - .5rem - 2px); + right: 0; + bottom: 0; + content: "\00D7"; + pointer-events: auto; + background-color: var(--red); + font-weight: 400; + font-size: 1.2rem; + display: flex; + align-items: center; + justify-content: center; + line-height: 1.5rem; + color: #fff; + border: 1px solid #f5365c; + border-radius: .25rem; + outline: 0; + background-image: none; + box-shadow: none; + border-top-left-radius: 0; + border-bottom-left-radius: 0; + margin: .25rem .1rem .25rem 0; + padding: 0; +} + +.cbi-dynlist>.item>span { + white-space: normal; + word-break: break-word; + line-height: 1.5rem; + color: #8898aa; + border: 1px solid #dee2e6; + border-radius: .25rem; + outline: 0; + background-image: none; + box-shadow: none; + display: block; + transition: box-shadow .15s ease; + box-sizing: border-box; + min-width: 15rem; + margin: .25rem .1rem; + padding: .5rem; +} + +.cbi-dynlist>.add-item { + display: inline-flex; + align-items: center; + width: 100%; + min-width: 16rem; +} + +.cbi-dynlist>.add-item input { + border-top-right-radius: 0; + border-bottom-right-radius: 0; + margin-right: 0; + border-right: none; +} + +.cbi-dynlist>.add-item .cbi-button-add { + font-weight: 400; + font-size: 1.2rem; + display: flex; + align-items: center; + line-height: 1.5rem; + color: #fff; + border: 1px solid var(--primary); + border-radius: .25rem; + outline: 0; + background-image: none; + box-shadow: none; + border-top-left-radius: 0; + border-bottom-left-radius: 0; + margin: .25rem .1rem .25rem 0; + padding: .5rem .75rem; +} + +.cbi-dynlist>.add-item:not([ondrop])>input { + overflow: hidden; + width: 100%; + min-width: 15rem; + white-space: nowrap; + text-overflow: ellipsis; +} + +.cbi-dynlist>.add-item[ondrop]>input { + min-width: 13rem; +} + +.cbi-dynlist,.cbi-dropdown { + position: relative; + display: inline-flex; + padding: .2rem; +} + +.cbi-dropdown[placeholder*="select"] { + max-width: 25rem; + height: auto; + margin-top: -3px; +} + +.cbi-dropdown>ul { + display: flex; + overflow-x: hidden; + overflow-y: auto; + width: 100%; + list-style: none; + outline: 0; + margin: 0!important; + padding: 0; +} + +.cbi-dropdown>.open { + flex-basis: 15px; +} + +.cbi-dropdown>.open,.cbi-dropdown>.more { + font-size: 1rem; + font-weight: 900; + line-height: 2; + display: flex; + flex-direction: column; + flex-grow: 0; + flex-shrink: 0; + justify-content: center; + cursor: default; + text-align: center; + outline: 0; + padding: 0 .25em; +} + +.cbi-dropdown>.more,.cbi-dropdown>ul>li[placeholder] { + font-weight: 700; + display: none; + color: #777; + text-shadow: 1px 1px 0 #fff; +} + +.cbi-dropdown>ul>li { + display: none; + overflow: hidden; + align-items: center; + align-self: center; + flex-grow: 1; + flex-shrink: 1; + min-height: 20px; + white-space: nowrap; + text-overflow: ellipsis; + padding: .25em; +} + +.cbi-dropdown>ul>li[display]:not([display="0"]) { + border-left: thin solid #ccc; +} + +.cbi-dropdown[empty]>ul { + max-width: 1px; +} + +.cbi-dropdown>ul>li>form { + display: none; + pointer-events: none; + margin: 0; + padding: 0; +} + +.cbi-dropdown>ul>li img { + margin-right: .25em; + vertical-align: middle; +} + +.cbi-dropdown>ul>li>form>input[type="checkbox"] { + height: auto; + margin: 0; +} + +.cbi-dropdown>ul>li input[type="text"] { + height: 20px; +} + +.cbi-dropdown[open]>ul.dropdown { + position: absolute; + z-index: 1100; + display: block; + width: auto; + min-width: 100%; + max-width: none; + max-height: 200px!important; + border: 0 solid #918e8c; + background: #FFF; + box-shadow: 0 0 4px #918e8c; + border-bottom-left-radius: .35rem; + border-bottom-right-radius: .35rem; + color: var(--main-menu-color); + margin-left: -0.2rem!important; +} + +.cbi-dropdown[open]>ul.dropdown li { + color: #000; +} + +.cbi-dropdown>ul>li[display],.cbi-dropdown[open]>ul.preview,.cbi-dropdown[open]>ul.dropdown>li,.cbi-dropdown[multiple]>ul>li>label,.cbi-dropdown[multiple][open]>ul.dropdown>li,.cbi-dropdown[multiple][more]>.more,.cbi-dropdown[multiple][empty]>.more { + display: flex; + align-items: center; + flex-grow: 1; +} + +.cbi-dropdown[open]>ul.dropdown>li { + border-bottom: thin solid #ccc; + padding: .5rem .8rem; +} + +.cbi-dropdown[open]>ul.dropdown>li[selected] { + background: #dce1fe; +} + +.cbi-dropdown[open]>ul.dropdown>li.focus { + background: #dce1fe; + outline: none; +} + +.cbi-dropdown[open]>ul.dropdown>li:last-child { + margin-bottom: 0; + border-bottom: 0; +} + +.cbi-dropdown[open]>ul.dropdown>li[unselectable] { + opacity: .7; +} + +.cbi-dropdown[disabled] { + pointer-events: none; + opacity: .6; +} + +.cbi-dropdown[open] .zonebadge { + width: auto; +} + +.cbi-progressbar { + position: relative; + min-width: 170px; + height: 20px; + border: thin solid #999; + background: #eee; + border-radius: .2rem; + overflow: hidden; + margin: 6px 0; +} + +.cbi-progressbar>div { + width: 0; + height: 100%; + transition: width .25s ease-in; + background: var(--bar-bg); +} + +.cbi-progressbar::after { + font-family: monospace; + font-size: 1em; + font-weight: 700; + font-size-adjust: .38; + line-height: normal; + position: absolute; + top: 2px; + right: 0; + bottom: 2px; + left: 0; + overflow: hidden; + content: attr(title); + text-align: center; + white-space: pre; + text-overflow: ellipsis; +} + +#modal_overlay { + position: fixed; + z-index: 900; + top: 0; + right: 10000px; + bottom: 0; + left: -10000px; + overflow-y: scroll; + transition: opacity .125s ease-in; + opacity: 0; + background: rgba(0,0,0,0.7); + -webkit-overflow-scrolling: touch; +} + +.modal { + display: flex; + align-items: center; + flex-wrap: wrap; + width: 90%; + min-width: 270px; + max-width: 600px; + min-height: 32px; + border-radius: 3px!important; + background: #fff; + box-shadow: 0 2px 2px 0 rgba(0,0,0,0.16),0 0 2px 0 rgba(0,0,0,0.12); + margin: 5em auto; + padding: 1em; +} + +.modal>* { + line-height: normal; + flex-basis: 100%; + margin-bottom: .5em; + max-width: 100%; +} + +.modal>pre,.modal>textarea { + font-size: 1rem; + font-size-adjust: .35; + overflow: auto; + margin-bottom: .5em; + cursor: auto; + white-space: pre-wrap; + color: #eee; + outline: 0; + background-color: #101010; + box-shadow: 0 2px 2px 0 rgba(0,0,0,0.16),0 0 2px 0 rgba(0,0,0,0.12); + padding: 8.5px; +} + +.modal>h4 { + margin: .5em 0; +} + +.modal ul { + margin-left: 2.2em; +} + +.modal li { + list-style-type: square; + color: gray; +} + +.modal p { + word-break: break-word; +} + +.modal .label { + font-size: .6rem; + font-weight: 400; + cursor: default; + border-radius: 0; + padding: .1rem .3rem 0; +} + +.modal .label.warning { + background-color: #f0ad4e!important; +} + +.modal .btn { + padding: .45rem .8rem; +} + +.modal.cbi-modal { + max-width: 90%; + max-height: none; +} + +body.modal-overlay-active { + overflow: hidden; + height: 100vh; +} + +body.modal-overlay-active #modal_overlay { + right: 0; + left: 0; + opacity: 1; +} + +.spinning { + position: relative; + padding-left: 32px!important; +} + +.spinning::before { + position: absolute; + top: 0; + bottom: 0; + left: .2em; + width: 32px; + content: ""; + background: url(/luci-static/resources/icons/loading.gif) no-repeat center; + background-size: 16px; +} + +.left,.left::before { + text-align: left!important; +} + +.right,.right::before { + text-align: right!important; +} + +.top { + align-self: flex-start!important; + vertical-align: top!important; +} + +.bottom { + align-self: flex-end!important; + vertical-align: bottom!important; +} + +.inline { + display: inline; +} + +.cbi-page-actions { + padding-top: 1rem; + text-align: right; +} + +.cbi-page-actions>form[method="post"] { + display: inline-block; +} + +.th[data-type="button"],.td[data-type="button"],.th[data-type="fvalue"],.td[data-type="fvalue"] { + flex: 1 1 2em; + text-align: center; +} + +.ifacebadge { + display: inline-flex; + border-bottom: thin solid #ccc; + background: #eee; + box-shadow: inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05); + padding: .5rem .8rem; +} + +td>.ifacebadge,.td>.ifacebadge { + font-size: .8rem; + background-color: #f0f0f0; +} + +.ifacebadge>em,.ifacebadge>img { + display: inline-block; + align-self: flex-start; + margin: 0 .2rem; +} + +.ifacebadge>img+img { + margin: 0 .2rem 0 0; +} + +.network-status-table .ifacebox { + flex-grow: 1; + margin: .5em; +} + +.network-status-table .ifacebox-body { + display: flex; + flex-direction: column; + height: 100%; +} + +.network-status-table .ifacebox-body>span { + flex: 10 10 auto; + height: 100%; +} + +.network-status-table .ifacebox-body .ifacebadge { + align-items: center; + flex: 1 1 auto; + min-width: 220px; + background-color: #fff; + margin: .5em 0 0; + padding: .5em; +} + +.cbi-input-textarea { + font-family: monospace; + width: 100%; + font-size: .875rem; + min-height: 14rem; + color: #000; + padding: .8rem; +} + +#syslog { + font-size: small; + line-height: 1.25; + overflow-y: hidden; + width: 100%; + min-height: 15rem; + resize: none; + color: #242424; + border: 0; + border-radius: .375rem; + background-color: #FFF; + box-shadow: 0 2px 2px 0 rgba(0,0,0,0.16),0 0 2px 0 rgba(0,0,0,0.12); + padding: 1rem; +} + +#syslog:focus { + outline: 0; +} + +.uci-change-list { + font-family: monospace; +} + +.uci-change-list ins,.uci-change-legend-label ins { + display: block; + text-decoration: none; + border: thin solid #0f0; + background-color: #cfc; + padding: 2px; +} + +.uci-change-list del,.uci-change-legend-label del { + font-style: normal; + display: block; + text-decoration: none; + border: thin solid red; + background-color: #fcc; + padding: 2px; +} + +.uci-change-list var,.uci-change-legend-label var { + font-style: normal; + display: block; + text-decoration: none; + border: thin solid #ccc; + background-color: #eee; + padding: 2px; +} + +.uci-change-list var ins,.uci-change-list var del { + font-style: normal; + white-space: pre; + border: 0; + padding: 0; +} + +.uci-change-legend { + padding: 5px; +} + +.uci-change-legend-label { + float: left; + width: 150px; +} + +.uci-change-legend-label>ins,.uci-change-legend-label>del,.uci-change-legend-label>var { + display: block; + float: left; + width: 10px; + height: 10px; + margin-right: 4px; +} + +.uci-change-legend-label var ins,.uci-change-legend-label var del { + line-height: .4; + border: 0; +} + +#iwsvg,#iwsvg2,#bwsvg { + border: thin solid #d4d4d4!important; +} + +#iwsvg,[data-page="admin-status-realtime-bandwidth"] #bwsvg { + border-top: 0!important; +} + +.ifacebox { + line-height: 1.25; + display: inline-flex; + flex-direction: column; + min-width: 100px; + border-bottom: thin solid #ccc; + background-color: #f9f9f9; + box-shadow: inset 0 1px 0 rgba(255,255,255,0.4),0 1px 2px rgba(0,0,0,0.2); +} + +.ifacebox-head { + background: #eee; + padding: .25em; +} + +.ifacebox-head.active { + background: var(--primary); +} + +.ifacebox-head.active * { + color: var(--white); +} + +.ifacebox-body { + line-height: 1.6em; + padding: .5em 1rem; +} + +.zonebadge { + display: inline-block; + padding: .2rem .5rem; +} + +.zonebadge .ifacebadge { + border: thin solid #6c6c6c; + margin: .1rem .2rem; + padding: .2rem .3rem; +} + +.zonebadge>input[type="text"] { + min-width: 10rem; + margin-top: .3rem; + padding: .16rem 1rem; +} + +.zonebadge>em,.zonebadge>strong { + display: inline-block; + margin: 0 .2rem; +} + +.cbi-value-field .cbi-input-checkbox,.cbi-value-field .cbi-input-radio { + margin-top: .1rem; +} + +.cbi-value-field>ul>li { + display: flex; +} + +.cbi-value-field>ul>li .ifacebadge { + margin-top: -0.5rem; + margin-left: .4rem; + background-color: #eee; +} + +.cbi-section-table-row>.cbi-value-field .cbi-dropdown { + min-width: 7rem; +} + +.cbi-section-create { + display: inline-flex; + align-items: center; + margin: .25rem 0 .25rem 1rem; +} + +.cbi-section-create>* { + margin: .5rem; +} + +div.cbi-value var,td.cbi-value-field var,.td.cbi-value-field var { + font-style: italic; + color: #0069d6; +} + +.cbi-optionals { + border-top: thin solid #ccc; + padding: 1rem 1rem 0; +} + +.cbi-dropdown-container { + position: relative; +} + +.cbi-tooltip-container,span[data-tooltip],span[data-tooltip] .label { + cursor: help!important; +} + +.cbi-tooltip { + position: absolute; + z-index: 1000; + left: -1000px; + transition: opacity .25s ease-out; + white-space: pre; + pointer-events: none; + opacity: 0; + border-radius: 3px; + background: #fff; + box-shadow: 0 0 2px #444; + padding: 2px 5px; +} + +.cbi-tooltip-container:hover .cbi-tooltip { + left: auto; + transition: opacity .25s ease-in; + opacity: 1; +} + +.zonebadge .cbi-tooltip { + background: inherit; + margin: -1.5rem 0 0 -0.5rem; + padding: .25rem; +} + +.zonebadge-empty { + color: #404040; + background: repeating-linear-gradient(45deg,rgba(204,204,204,0.5),rgba(204,204,204,0.5) 5px,rgba(255,255,255,0.5) 5px,rgba(255,255,255,0.5) 10px); +} + +.zone-forwards { + display: flex; + min-width: 10rem; +} + +.zone-forwards>* { + flex: 1 1 45%; +} + +.zone-forwards>span { + flex-basis: 10%; + text-align: center; + padding: 0 .25rem; +} + +.zone-forwards .zone-src,.zone-forwards .zone-dest { + display: flex; + flex-direction: column; +} + +.label { + font-size: .8rem; + font-weight: 700; + white-space: nowrap; + text-decoration: none; + text-transform: uppercase; + color: #fff!important; + border-radius: 3px; + background-color: #bfbfbf; + text-shadow: none; + padding: .3rem .8rem; +} + +label>input[type="checkbox"],label>input[type="radio"] { + position: relative; + top: .4rem; + right: .2rem; + vertical-align: bottom; + margin: 0; +} + +label[data-index][data-depends] { + padding-right: 2em; +} + +.darkMask { + position: fixed; + z-index: 99; + display: none; + width: 100%; + height: 100%; + content: ""; + top: 0; + background-color: rgba(0,0,0,0.56); +} + +#diag-rc-output>pre,#command-rc-output>pre,[data-page="admin-services-wol"] .notice code { + font-size: 1.2rem; + font-size-adjust: .35; + line-height: normal; + display: block; + overflow-y: hidden; + width: 100%; + white-space: pre; + color: #eee; + background-color: #101010; + box-shadow: 0 2px 2px 0 rgba(0,0,0,0.16),0 0 2px 0 rgba(0,0,0,0.12); + padding: 8.5px; +} + +[data-page="admin-network-diagnostics"] .table { + box-shadow: none; +} + +input[name="ping"],input[name="traceroute"],input[name="nslookup"] { + width: 80%; +} + +.node-status-overview>.main fieldset:nth-child(4) .td:nth-child(2),.node-status-processes>.main .table .tr .td:nth-child(3) { + white-space: normal; +} + +[data-page="admin-system-reboot"] .cbi-button { + background: #fb6340!important; +} + +[data-page="admin-system-reboot"] p>span { + position: relative; + top: .1rem; + left: 1rem; +} + +[data-page="admin-vpn-passwall"] h4 { + background: transparent; +} + +#cbi-samba [data-tab="template"] .cbi-value-title { + width: auto; + padding-bottom: .6rem; +} + +.controls { + margin: .5em 1rem 1em!important; +} + +.controls>*>.btn:not([aria-label$="page"]) { + flex-grow: initial!important; + margin-top: .25rem; +} + +.controls>#pager>.btn[aria-label$="page"] { + font-size: 1.4rem; + font-weight: 700; +} + +.controls>*>label { + margin-bottom: .2rem; +} + +[data-page="admin-system-opkg"] div.btn { + line-height: 3; + display: inline; + padding: .3rem .6rem; +} + +[data-page^="admin-system-admin"]:not(.node-main-login) .cbi-map:not(#cbi-dropbear),[data-page="admin-system-opkg"] #maincontent>.container { + margin-top: 2rem; + padding-top: .1rem; +} + +[data-page="admin-system-opkg"] #maincontent>.container { + margin: 0 1.25rem 1rem; +} + +.td.version,.td.size { + white-space: normal!important; + word-break: break-word; +} + +[data-page="admin-system-crontab"] #view p { + margin-bottom: 1rem; +} + +[data-page="admin-system-flash"] .cbi-map-tabbed { + border-radius: .375rem; +} + +[data-page="admin-system-flash"] legend { + display: block!important; + font-size: 1.2rem; + width: 100%; + border-bottom: 1px solid rgba(0,0,0,0.05); + line-height: 1.5; + margin-bottom: 0rem; + letter-spacing: .1rem; + color: #32325d; + font-weight: 700; + padding: 1rem 0 1rem 1.5rem; +} + +[data-page="admin-system-flash"] .cbi-section-descr { + font-weight: 600; + color: #525f7f; + padding: 1rem 0 1rem 1.5rem; +} + +[data-page="admin-system-flash"] .modal label>input[type="checkbox"] { + top: -0.35rem; +} + +[data-page="admin-system-flash"] .modal .btn { + white-space: normal!important; +} + +#cbi-wireless>#wifi_assoclist_table>.tr { + box-shadow: inset 1px -1px 0 #ddd,inset -1px -1px 0 #ddd; +} + +#cbi-wireless>#wifi_assoclist_table>.tr.placeholder>.td { + right: 33px; + bottom: 33px; + left: 33px; + border-top: thin solid #ddd!important; +} + +#cbi-wireless>#wifi_assoclist_table>.tr.table-titles { + box-shadow: inset 1px 0 0 #ddd,inset -1px 0 0 #ddd; +} + +#cbi-wireless>#wifi_assoclist_table>.tr.table-titles>.th { + border-bottom: thin solid #ddd; + box-shadow: 0 -1px 0 0 #ddd; +} + +#wifi_assoclist_table>.tr>.td[data-title="RX Rate / TX Rate"] { + width: 23rem; +} + +[data-page="admin-network-dhcp"] [data-tab-active="true"] { + padding: 1rem 0!important; +} + +#iptables { + margin: 0; +} + +.Firewall form { + box-shadow: none; + margin: 2rem 2rem 0 0; + padding: 0; +} + +#cbi-firewall-redirect table *,#cbi-network-switch_vlan table *,#cbi-firewall-zone table * { + font-size: small; +} + +#cbi-firewall-redirect table input[type="text"],#cbi-network-switch_vlan table input[type="text"],#cbi-firewall-zone table input[type="text"] { + width: 5rem; +} + +#cbi-firewall-redirect table select,#cbi-network-switch_vlan table select,#cbi-firewall-zone table select { + min-width: 3.5rem; +} + +#cbi-network-switch_vlan .th,#cbi-network-switch_vlan .td { + flex-basis: 12%; +} + +[data-page="admin-network-firewall-custom"] #view p,[data-page="admin-status-routes"] #view p { + margin-bottom: 1rem; + padding: 0 1.5rem; +} + +[data-page="admin-network-firewall-custom"] #view p textarea,[data-page="admin-status-routes"] #view p textarea { + border-radius: .375rem; + padding: 1rem; +} + +#applyreboot-container { + margin: 2rem; +} + +#applyreboot-section { + line-height: 300%; + margin: 2rem; +} + +.OpenVPN a { + line-height: initial!important; +} + +.commandbox { + width: 24%!important; + border-bottom: thin solid #ccc; + background: #eee; + box-shadow: inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05); + margin: 10px 0 0 10px!important; + padding: .5rem 1rem; +} + +.commandbox h3 { + line-height: normal!important; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + margin: 6px 0!important; +} + +.commandbox div { + left: auto!important; +} + +.commandbox code { + position: absolute; + overflow: hidden; + max-width: 60%; + margin-left: 4px; + white-space: nowrap; + text-overflow: ellipsis; + padding: 2px 3px; +} + +.commandbox code:hover { + overflow-y: auto; + max-height: 50px; + white-space: normal; +} + +.commandbox p:first-of-type { + margin-top: -6px; +} + +.commandbox p:nth-of-type(2) { + margin-top: 2px; +} + +#command-rc-output .alert-message { + line-height: 1.42857143; + position: absolute; + top: 40px; + right: 32px; + max-width: 40%; + animation: anim-fade-in 1.5s forwards; + word-break: break-word; + opacity: 0; + margin: 0; +} + +input[type="checkbox"] { + appearance: none!important; + -webkit-appearance: none!important; + border: 1px solid #dee2e6; + width: 16px!important; + height: 16px!important; + cursor: pointer; + transition: all .2s; + margin: 1rem 0 0; + padding: 0; +} + +input[type="checkbox"]:checked { + border: 1px solid var(--primary); + background-image: url('data:image/svg+xml,%3csvg xmlns=\'http://www.w3.org/2000/svg\' viewBox=\'0 0 8 8\'%3e%3cpath fill=\'%23fff\' d=\'M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z\'/%3e%3c/svg%3e')!important; + background-color: var(--primary); + background-size: 70%; + background-repeat: no-repeat; + background-position: center; +} + +.fb-container .cbi-button { + height: auto!important; +} + +#cbi-usb_printer-printer em { + display: block; + text-align: center; + padding: 1rem; +} + +pre.command-output { + padding: 1.5rem; +} + +[data-page="admin-nlbw-display"] .cbi-section[data-tab="export"] { + padding: 1.5rem!important; +} + +[data-page="admin-status-iptables"] .right { + margin-bottom: 0!important; +} + +.table[width="100%"],.th[width="100%"],.td[width="100%"],header,.main,.main .main-left .nav li.slide .slide-menu li:hover::after,.main .main-left .nav li.slide .slide-menu .active:hover::after,.cbi-section-table-row>.cbi-value-field .cbi-dropdown,.cbi-section-table-row>.cbi-value-field .cbi-input-select,.cbi-section-table-row>.cbi-value-field .cbi-input-text,.cbi-section-table-row>.cbi-value-field .cbi-input-password,.cbi-dropdown[open]>ul.dropdown>li>input.create-item-input:first-child:last-child,.cbi-dropdown .zonebadge,#cbi-firewall-zone .td,#cbi-network-switch_vlan .td { + width: 100%; +} + +.cbi-dropdown,select[multiple="multiple"],.alert .btn,.alert-message .btn { + height: auto; +} + +.login-page .login-container .login-form .brand:hover,header .fill .container .showSide:hover,.a-to-btn { + text-decoration: none; +} + +.login-page .login-container footer .luci-link,.cbi-dropdown[empty]>ul>li,.cbi-dropdown[optional][open]>ul.dropdown>li[placeholder],.cbi-dropdown[multiple][open]>ul.dropdown>li>form,#cbi-samba [data-tab="template"] .cbi-value-field,#cbi-firewall-zone .table,#cbi-network-switch_vlan .table { + display: block; +} + +.main-left::-webkit-scrollbar-thumb,.tabs::-webkit-scrollbar-thumb,.cbi-tabmenu::-webkit-scrollbar-thumb { + background-color: #f6f9fc; +} + +.main-left::-webkit-scrollbar-track,.tabs::-webkit-scrollbar-track,.cbi-tabmenu::-webkit-scrollbar-track { + background-color: #fff; +} + +.pull-left,.cbi-page-actions .cbi-button-link:first-child { + float: left; +} + +#xhr_poll_status *,.cbi-button-apply>ul.preview li,.cbi-button-apply>ul:first-child li { + color: #fff; +} + +.container .alert,.container .alert-message,.cbi-map-descr+fieldset { + margin-top: 1rem; +} + +.main .main-left .nav,.cbi-value-field>ul>li>label { + margin-top: .5rem; +} + +.main .main-left .nav>li>a:first-child,.main .main-left .nav li .menu { + border-radius: .375rem; + cursor: default; + display: block; + font-size: 1rem; + position: relative; + text-decoration: none; + transition: all .2s; + margin: .1rem .5rem; + padding: .675rem 0 .675rem 2.5rem; +} + +.main .main-left .nav>li>a:first-child.active,.main .main-left .nav li .menu.active { + background: var(--primary); + color: #fff; +} + +.main .main-left .nav>li>a:first-child.active::before,.main .main-left .nav>li>a:first-child:hover::before,.main .main-left .nav li .menu.active::before,.main .main-left .nav li .menu:hover::before { + color: #fff!important; +} + +.main .main-left .nav>li>a:first-child.active::after,.main .main-left .nav li .menu.active::after { + color: #fff!important; + transform: rotate(90deg); +} + +.main .main-left .nav>li>a:first-child:hover,.main .main-left .nav li .menu:hover { + background: var(--primary); + color: #fff; + cursor: pointer; +} + +.main .main-left .nav>li>a:first-child::before,.main .main-left .nav li .menu::before { + -moz-osx-font-smoothing: grayscale; + -webkit-font-smoothing: antialiased; + color: var(--primary); + content: "\e915"; + font-family: argon!important; + font-style: normal; + font-variant: normal; + font-weight: 400; + left: .8rem; + line-height: 1; + padding-top: 3px; + position: absolute; + text-transform: none; + transition: all .3s; +} + +.main .main-left .nav li.slide,[data-page="admin-system-flash"] .cbi-value,[data-page="admin-network-dhcp"] .cbi-value { + padding: 0; +} + +.main .main-left .nav li.slide ul,.main>.main-left[style*="overflow: hidden"]>.nav>.slide>.menu::before,.tr.placeholder .td[data-title]::before,.cbi-dropdown>ul.preview,.cbi-button-apply>ul.preview,.cbi-dropdown>ul>li .hide-close,.cbi-dropdown[open]>ul.dropdown>li .hide-open,.hidden,.showSide,[data-page^="admin-system-commands"] .panel-title,[data-page^="command-cfg"] .mobile-hide,[data-page^="command-cfg"] .showSide { + display: none; +} + +.main .main-left .nav li.slide:hover,.main .main-left .nav li.slide .slide-menu li:hover,.main .main-left .nav li.slide .slide-menu .active:hover { + background: none; +} + +.cbi-section>h3:first-child,.cbi-section>h4:first-child,.cbi-section>p:first-child,[data-tab-title]>h3:first-child,[data-tab-title]>h4:first-child,[data-tab-title]>p:first-child,.cbi-section p { + padding: 1rem; +} + +table>tbody>tr>td,table>tbody>tr>th,table>tfoot>tr>td,table>tfoot>tr>th,table>thead>tr>td,table>thead>tr>th,.table>.tbody>.tr>.td,.table>.tbody>.tr>.th,.table>.tfoot>.tr>.td,.table>.tfoot>.tr>.th,.table>.thead>.tr>.td,.table>.thead>.tr>.th,.table>.tr>.td.cbi-value-field,.table>.tr>.th.cbi-section-table-cell,.uci-change-list var,.uci-change-list del,.uci-change-list ins,.cbi-section-remove { + padding: .5rem; +} + +.cbi-section-table-row .td,.center,.center::before { + text-align: center!important; +} + +div>table>tbody>tr:nth-of-type(2n),div>.table>.tr:nth-of-type(2n),.cbi-section .cbi-section-remove:nth-of-type(2n),.container>.cbi-section .cbi-section-node:nth-of-type(2n),.cbi-section[id] .cbi-section-remove:nth-of-type(4n+3),.cbi-section[id] .cbi-section-node:nth-of-type(4n+4),.cbi-tabcontainer>.cbi-value:nth-of-type(2n),.cbi-rowstyle-1 { + background-color: #f9f9f9; +} + +.btn.primary,.cbi-page-actions .cbi-button-save,.cbi-page-actions .cbi-button-apply+.cbi-button-save,.cbi-button-add,.cbi-button-save,.cbi-button-positive,.cbi-button-link,.cbi-button[value="Enable"],.cbi-button[value="Scan"],.cbi-button[value^="Back"],.cbi-button-neutral[onclick="handleConfig(event)"],.cbi-page-actions .cbi-button-apply,.cbi-section-actions .cbi-button-edit,.cbi-button-edit,.cbi-button-apply,.cbi-button-reload,.cbi-button-action,.cbi-button[value="Submit"],.cbi-button[value="Upload"],.cbi-button[value$="Apply"],.cbi-button[onclick="addKey(event)"] { + background-color: var(--primary); + border: thin solid var(--primary); + color: #fff!important; + font-weight: 400; +} + +.tabs::-webkit-scrollbar,.cbi-tabmenu::-webkit-scrollbar { + height: 5px; + width: 1px; +} + +.tabs li[class~="active"] a,.tabs li:hover a,.cbi-tabmenu li[class~="cbi-tab"] a { + color: var(--primary); +} + +.tabs li a,.cbi-tabmenu li a { + color: #404040; + text-decoration: none; + padding: .5rem .8rem; +} + +.cbi-dropdown>ul>li .hide-open,.cbi-dropdown[open]>ul.dropdown>li .hide-close { + display: initial; +} + +.cbi-dropdown[open]>ul.dropdown>li label,.cbi-image-button { + margin-left: .5rem; +} + +.network-status-table,.network-status-table .ifacebox-body>div { + display: flex; + flex-wrap: wrap; +} + +[data-page="admin-system-reboot"] p,[data-page="admin-nlbw-backup"] form { + padding-left: 1.5rem; +} + +[data-page="admin-system-admin"] .cbi-map h2,[data-page="admin-system-admin-password"] .cbi-map h2,[data-page="admin-system-admin"] .cbi-map .cbi-map-descr,[data-page="admin-system-admin-password"] .cbi-map .cbi-map-descr,[data-page="admin-system-opkg"] h2 { + color: var(--gray-dark); + margin-left: 0; +} + +.cbi-tabmenu+.cbi-section,[data-page="admin-system-flash"] .cbi-section .cbi-section { + margin-top: 0; +} + +@keyframes anim-fade-in { + 100% { + opacity: 1; + } +} + +@media all and (-ms-high-contrast:none) { + .main>.main-left>.nav>.slide>.menu::before { + top: 30.25%; + } + + .main>.main-left>.nav>li:last-child::before { + top: 20%; + } + + .showSide::before { + top: -12px; + } +} + +@media screen and (max-width:1600px) { + header>.fill>.container>#logo { + margin: 0 2.5rem 0 .5rem; + } + + .main-left { + width: calc(0% + 13rem); + } + + .main-right { + width: calc(100% - 13rem); + } + + .btn:not(button),.cbi-button { + font-size: .8rem; + } + + .label { + padding: .2rem .6rem; + } + + .cbi-value-title { + width: 15rem; + padding-right: .6rem; + } + + .cbi-value-field .cbi-dropdown,.cbi-value-field .cbi-input-select,.cbi-value input[type="text"],.cbi-value input[type="password"] { + min-width: 18rem; + } + + #cbi-firewall-zone .cbi-input-select { + min-width: 9rem; + } + + .cbi-input-textarea { + font-size: small; + } + + .node-admin-status>.main fieldset li>a { + padding: .3rem .6rem; + } +} + +@media screen and (max-width:1366px) { + header>.fill>.container { + cursor: default; + } + + .main-left { + width: calc(0% + 13rem); + } + + .main-right { + width: calc(100% - 13rem); + } + + .tabs>li>a,.cbi-tabmenu>li>a { + padding: .2rem .8rem; + } + + .panel-title { + font-size: 1.1rem; + padding-bottom: 1rem; + } + + table { + font-size: .7rem!important; + width: 100%!important; + } + + .table .cbi-input-text { + width: 100%; + } + + .cbi-value-field .cbi-dropdown,.cbi-value-field .cbi-input-select,.cbi-value input[type="text"],.cbi-value input[type="password"] { + min-width: 16rem; + } + + #cbi-firewall-zone .cbi-input-select { + min-width: 4rem; + } + + .main>.main-left>.nav>li,.main>.main-left>.nav>li>a,.main .main-left .nav>li>a:first-child,.main>.main-left>.nav>.slide>.menu,.main>.main-left>.nav>li>[data-title="Logout"] { + font-size: .9rem; + } + + .main>.main-left>.nav>.slide>.slide-menu>li>a { + font-size: .7rem; + } + + #modal_overlay { + top: 0rem; + } + + [data-page="admin-network-firewall-forwards"] .table:not(.cbi-section-table) { + display: block; + } + + [data-page="admin-network-firewall-forwards"] .table:not(.cbi-section-table),[data-page="admin-network-firewall-rules"] .table:not(.cbi-section-table),[data-page="admin-network-hosts"] .table,[data-page="admin-network-routes"] .table { + overflow-y: visible; + } + + .commandbox { + width: 32%!important; + } + + .btn:not(button),.cbi-button { + font-size: .8rem; + } +} + +@media screen and (max-width:1152px) { + header>.fill>.container>.brand { + position: relative; + } + + html,.main { + overflow-y: visible; + } + + .main>.loading>span { + top: 25%; + } + + .main-left { + width: calc(0% + 13rem); + } + + .main-right { + width: calc(100% - 13rem); + } + + body:not(.logged-in) .showSide { + visibility: hidden; + width: 0; + margin: 0; + } + + .cbi-value-title { + width: 12rem; + padding-right: 1rem; + } + + .cbi-value-field .cbi-dropdown,.cbi-value-field .cbi-input-select,.cbi-value input[type="text"] { + width: 16rem; + min-width: 16rem; + } + + .cbi-value input[name^="pw"],.cbi-value input[data-update="change"]:nth-child(2) { + width: 13rem!important; + min-width: 13rem; + } + + #diag-rc-output>pre,#command-rc-output>pre,[data-page="admin-services-wol"] .notice code { + font-size: 1rem; + } + + .Interfaces .table { + overflow-x: hidden; + } + + #packages.table { + display: grid; + } + + .tr { + display: flex; + flex-direction: row; + flex-wrap: wrap; + } + + .Overview .table[width="100%"]>.tr { + flex-wrap: nowrap; + } + + .tr.placeholder { + border-bottom: thin solid #ddd; + } + + .tr.placeholder>.td,#cbi-firewall .tr>.td,#cbi-network .tr:nth-child(2)>.td,.cbi-section #wifi_assoclist_table .tr>.td { + border-top: 0; + } + + .th,.td { + display: inline-block; + align-self: flex-start; + flex: 2 2 10%; + text-overflow: ellipsis; + word-wrap: break-word; + } + + .td select,.td input[type="text"] { + width: 100%; + word-wrap: normal; + } + + .td [data-dynlist]>input,.td input.cbi-input-password { + width: calc(100% - 1.5rem); + } + + .td[data-type="button"],.td[data-type="fvalue"] { + flex: 1 1 12.5%; + text-align: left; + } + + .th.cbi-value-field,.td.cbi-value-field,.th.cbi-section-table-cell,.td.cbi-section-table-cell { + flex-basis: auto; + padding-top: 1rem; + } + + .cbi-section-table-row { + display: flex; + flex-direction: row; + flex-wrap: wrap; + justify-content: space-between; + box-shadow: 0 2px 2px 0 rgba(0,0,0,0.16),0 0 2px 0 rgba(0,0,0,0.12); + } + + .td.cbi-value-field,.cbi-section-table-cell { + display: inline-block; + flex: 10 10 auto; + flex-basis: 50%; + text-align: center; + } + + .td.cbi-section-actions { + vertical-align: bottom; + } + + .tr[data-title]::before,.tr.cbi-section-table-titles.named::before { + font-size: .9rem; + display: block; + flex: 1 1 100%; + border-bottom: thin solid rgba(0,0,0,0.26); + background: #e9ecef; + } + + .cbi-button+.cbi-button { + margin-left: 0; + } + + .td.cbi-section-actions>*>*,.td.cbi-section-actions>*>form>* { + margin: 2.1px 3px; + } + + .Firewall form { + position: static!important; + box-shadow: 0 2px 2px 0 rgba(0,0,0,0.16),0 0 2px 0 rgba(0,0,0,0.12); + margin: 0 0 2rem; + padding: 2rem; + } + + .Firewall form input { + width: 100%!important; + margin: 1rem 0 0; + } + + .Firewall .center,.Firewall .center::before { + text-align: left!important; + } + + .commandbox { + width: 100%!important; + margin-left: 0!important; + } + + .btn:not(button),.cbi-button { + font-size: .8rem; + } + + header>.fill>.container>#logo,.tr.table-titles,.tr.cbi-section-table-titles,.tr.cbi-section-table-descr { + display: none; + } + + .node-main-login>.main .cbi-value-title,.td[data-title],[data-page^="admin-status-realtime"] .td[id] { + text-align: left; + } + + .table,.td[data-title]::before { + display: block; + } +} + +@media screen and (max-width:768px) { + .cbi-progressbar::after { + font-size: .5rem; + line-height: 1.5; + } + + .main-left { + position: fixed; + z-index: 100; + width: 0; + } + + .main-right { + width: 100%; + } + + .showSide { + position: relative; + z-index: 99; + display: inline-block!important; + padding: .1rem; + } + + .showSide::before { + font-family: argon!important; + font-style: normal!important; + font-weight: 400!important; + font-variant: normal!important; + text-transform: none!important; + line-height: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + content: "\e20e"; + font-size: 1.7rem; + } + + header>.fill>.container>.brand { + display: inline-block; + } + + body,.main>.main-left>.nav>.slide>.slide-menu>li>a { + font-size: .8rem; + } +} + +@media screen and (max-width:600px) { + #maincontent>.container { + margin: 0 1rem 1rem; + } + + .cbi-value-title { + text-align: left; + } + + [data-page="admin-system-flash"] .cbi-value { + padding: 0 1rem; + } + + [data-page="admin-network-dhcp"] [data-tab-active="true"] { + padding: 1rem!important; + } + + .cbi-dynlist p { + padding: .5rem 1rem; + } + + body { + overflow-x: hidden; + } + + .node-main-login .main .main-right #maincontent .container .cbi-map .cbi-section .cbi-section-node .cbi-value .cbi-value-field { + width: 16rem; + } + + .tabs::-webkit-scrollbar,.cbi-tabmenu::-webkit-scrollbar { + width: 0px; + height: 0px; + } + + .cbi-value-field,.cbi-value-description { + display: block!important; + padding-left: 0!important; + padding-right: 0!important; + } + + [data-page="admin-system-admin-password"] .cbi-value-field { + display: table-cell!important; + } + + .modal.cbi-modal { + max-width: 100%; + max-height: none; + } + + .modal { + display: flex; + align-items: center; + flex-wrap: wrap; + width: 100%; + min-width: 270px; + max-width: 600px; + min-height: 32px; + border-radius: 3px!important; + background: #fff; + box-shadow: 0 2px 2px 0 rgba(0,0,0,0.16),0 0 2px 0 rgba(0,0,0,0.12); + margin: 5em auto; + padding: 1em; + } + + .cbi-dropdown[open]>ul.dropdown { + left: .2rem!important; + right: 0!important; + margin-bottom: 1rem; + } + + .mobile-hide,.node-main-login footer { + display: none; + } + + [data-page="admin-system-flash"] legend,[data-page="admin-system-flash"] .cbi-section-descr { + padding: 1rem 0 1rem 1rem; + } +} + +@media screen and (min-width:600px) { + ::-webkit-scrollbar { + width: 10px; + height: 10px; + } + + ::-webkit-scrollbar,::-webkit-scrollbar-corner { + background: transparent; + } + + ::-webkit-scrollbar-thumb { + background: #9e9e9e; + } + + ::-webkit-scrollbar-thumb:hover { + background: #757575; + } + + ::-webkit-scrollbar-thumb:active { + background: #424242; + } +} + +@media screen and (max-width:480px) { + .mobile-hide { + display: none; + } + + .login-page .login-container { + margin-left: 0rem!important; + width: 100%; + } + + .login-page .login-container .login-form .form-login .input-group::before { + color: #525461; + } + + .login-page .login-container .login-form .form-login .input-group input { + color: #525461; + border-bottom: var(--white) 1px solid; + border-radius: 0; + } +} \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/www/luci-static/css/dark.css b/rooter/ext-rooter-basic/files/www/luci-static/css/dark.css new file mode 100644 index 0000000..885b575 --- /dev/null +++ b/rooter/ext-rooter-basic/files/www/luci-static/css/dark.css @@ -0,0 +1 @@ +body{background:#1e1e1e;color:#CCC}.login-page .login-container .login-form .form-login .input-group input{background-color:transparent!important;color:#adb5bd;border-bottom:#adb5bd 1px solid!important;border-radius:0!important;border-top:none!important;border-left:none!important;border-right:none!important;box-shadow:none}.login-page .login-container .login-form .form-login .cbi-button-apply:hover,.login-page .login-container .login-form .form-login .cbi-button-apply:focus{opacity:.9}.main .main-left{background-color:#333!important;box-shadow:0 0 .5rem 0 rgba(0,0,0,0.15)}.main .main-left .nav .slide .slide-menu li a:hover{background:none!important}.main .main-left .nav li a{color:#CCC!important}.main .main-left::-webkit-scrollbar-thumb{background-color:#252526!important}h2{color:#ccc;background:#333}h3{color:#ccc;border-bottom:0;background:#333}a:-webkit-any-link{cursor:pointer;color:var(--dark-primary)}input:-webkit-autofill{background-color:#3c3c3c!important}.cbi-value-field .cbi-input-apply,.cbi-button-apply,.cbi-button-edit{color:#fff!important;background-color:var(--dark-primary)!important;border-color:var(--dark-primary)!important}.cbi-section{background:none;box-shadow:0 0 .5rem 0 rgba(0,0,0,0.35)}.panel-title{color:#ccc;background-color:#333;border-bottom:0px}table>tbody>tr>td,table>tfoot>tr>td,table>thead>tr>td{color:#ccc;border-top:1px solid #252526}.node-system-packages>.main .cbi-section-node:first-child .cbi-value-last{line-height:1.8em}.node-system-packages>.main .cbi-section-node:first-child .cbi-value-last div[style="margin:3px 0; width:300px; height:10px; border:1px solid #000000; background-color:#80C080"]{border:1px solid #999!important;background-color:transparent!important}tr>td,tr>th,.tr>.td,.tr>.th,.cbi-section-table-row::before,#cbi-wireless>#wifi_assoclist_table>.tr:nth-child(2){border-top:0}.cbi-section>h3:first-child,.panel-title,h3{color:#ccc;border-bottom:0;border-bottom-left-radius:0;border-bottom-right-radius:0}.cbi-progressbar{position:relative;min-width:170px;height:20px;border:thin solid #999;background:transparent;border-radius:.2rem;overflow:hidden;margin:6px 0}.cbi-button{color:#ccc!important;background-color:var(--dark-primary)}.cbi-section-node{background:none;border-radius:0 0 .375rem .375rem;padding:0rem}#content_syslog{box-shadow:0 0 .5rem 0 rgba(0,0,0,0.35)}#iwsvg,#iwsvg2,#bwsvg{overflow:hidden;box-shadow:0 0 .5rem 0 rgba(0,0,0,0.35);background-color:#1e1e1e!important}.tabs>li[class~="active"],.tabs>li:hover{border-bottom:.18751rem solid var(--dark-primary);color:#ccc;background-color:#181819}.cbi-tabmenu>li{background:#2d2d2d}.cbi-tabmenu>li:hover{color:#ccc;background:#2d2d2d}.cbi-tabmenu>li[class~="cbi-tab"]{background-color:#181819}select,input{color:#ccc;background-color:transparent!important;border:1px solid #252526;box-shadow:none}select:not([multiple="multiple"]):focus,input:focus{outline:0;border-color:var(--dark-primary)!important}.cbi-section-node .cbi-value{padding:1rem 1rem .3rem}.ifacebox{background-color:none;border:1px solid #1e1e1e}.ifacebox-head{color:#666}.zonebadge strong{color:#333}.node-services-vssr .block{background-color:#3c3c3c!important;box-shadow:0 0 .5rem 0 rgba(0,0,0,0.35)}.node-services-vssr .status-bar{color:#ccc;box-shadow:0 0 .5rem 0 rgba(0,0,0,0.35);background-color:#1e1e1e}.node-services-vssr .cbi-section-table-row{color:#ccc;background-color:#3c3c3c!important;box-shadow:0 0 5px 0 rgba(0,0,0,0.35)}.node-services-vssr .cbi-section-table-row.fast{background:var(--dark-primary)!important;color:#fff}.node-services-vssr .incon:nth-child(2){border-right:#1e1e1e 1px solid}.cbi-input-find,.cbi-input-save,.cbi-button-add,.cbi-button-save,.cbi-button-find,.cbi-input-reload,.cbi-button-reload{color:#fff!important;background:#556B2F!important;border-color:#556B2F!important}.cbi-button-reset,.cbi-input-remove{color:#fff!important;background-color:#FF8C00!important;border-color:#FF8C00!important}.cbi-page-actions .cbi-button-apply,.cbi-section-actions .cbi-button-edit,.cbi-button-edit.important,.cbi-button-apply.important,.cbi-button-reload.important,.cbi-button-action.important{border:1px var(--dark-primary) solid!important}.btn[value="Dismiss"],.cbi-button[value="Terminate"],.cbi-button[value="Reset"],.cbi-button[value="Disabled"],.cbi-button[onclick^="iface_reconnect"],.cbi-button[onclick="handleReset(event)"],.cbi-button-neutral[value="Disable"]{font-weight:400;color:#fff;border:thin solid #FF8C00!important;background-color:#FF8C00!important}#detail-bubble>div{border:1px solid #ccc;border-radius:2px;background:#252525;padding:5px}.network-status-table .ifacebox-body .ifacebadge{background-color:#252526;border-bottom:0;box-shadow:none}td>.ifacebadge,.td>.ifacebadge{background-color:var(--dark-primary);border:0}.cbi-section,.cbi-section-error,#iptables,.Firewall form,#cbi-network>.cbi-section-node,#cbi-wireless>.cbi-section-node,#cbi-wireless>#wifi_assoclist_table,[data-tab-title],[data-page^="admin-system-admin"]:not(.node-main-login) .cbi-map:not(#cbi-dropbear),[data-page="admin-system-opkg"] #maincontent>.container{background:#1e1e1e!important;box-shadow:0 0 .5rem 0 rgba(0,0,0,0.35)}div[style="width:100%;height:300px;border:1px solid #000;background:#fff"]{background:transparent!important}[data-page="admin-system-flash"] .modal label>input[type="checkbox"]{top:-0.35rem}[data-page="admin-system-flash"] .modal .btn{white-space:normal!important;background-color:#8FBC8F}[data-page="admin-system-flash"] .modal .alert-message{background-color:transparent!important}.cbi-button-positive{color:#fff!important;background-color:#556B2F!important}.logout:before{color:#adb5bd!important}.cbi-dropdown[open]{border-color:var(--dark-primary)!important}.cbi-dropdown[open]>ul.dropdown{background:#252526!important;color:#ccc!important;box-shadow:none;border:1px solid #3c3c3c!important}.cbi-dropdown[open]>ul.dropdown li{color:#ccc;border-bottom:1px solid #3c3c3c!important}.cbi-dropdown[open]>ul.dropdown>li[selected]{background-color:var(--dark-primary)!important;border-bottom:1px solid #3c3c3c!important}.cbi-dropdown[open]>ul.dropdown>li.focus{background:var(--dark-primary);outline:none}.cbi-page-actions .cbi-button-apply,.cbi-section-actions .cbi-button-edit,.cbi-button-edit,.cbi-button-apply,.cbi-button-reload,.cbi-button-action,.cbi-button[value="Submit"],.cbi-button[value="Upload"],.cbi-button[value$="Apply"],.cbi-button[onclick="addKey(event)"]{background:var(--dark-primary)!important}.btn.primary,.cbi-page-actions .cbi-button-save,.cbi-page-actions .cbi-button-apply+.cbi-button-save,.cbi-button-add,.cbi-button-save,.cbi-button-positive,.cbi-button-link,.cbi-button[value="Enable"],.cbi-button[value="Scan"],.cbi-button[value^="Back"],.cbi-button-neutral[onclick="handleConfig(event)"]{background:var(--dark-primary)}.login-page .login-container .login-form,.main .main-right,.cbi-rowstyle-2,.cbi-section-remove:nth-of-type(2n),.cbi-section-node:nth-of-type(2n),.modal{background-color:#1e1e1e}.login-page .login-container .login-form .brand,.login-page .login-container .login-form .form-login .input-group::before{color:#adb5bd}.login-page .login-container .login-form .form-login .cbi-button-apply,.notice,.cbi-value input[type="password"]+.cbi-button-neutral{background-color:var(--dark-primary)!important}header::after,header.bg-primary,select,.cbi-section-table-row{background-color:#1e1e1e!important}.main .main-left .sidenav-header .brand,.cbi-section em,.cbi-map-descr,.tabs>li[class~="active"]>a,.cbi-tabmenu>li>a,.tabs>li>a,.cbi-tabmenu>li>a:hover,.tabs>li>a:hover,.cbi-tabmenu li[class~="cbi-tab"] a,.cbi-value-title,.cbi-section-descr,.node-system-packages>.main table tr td:nth-last-child(1),.node-services-vssr .ssr-button,[data-page="admin-system-admin"] .cbi-map h2,[data-page="admin-system-admin-password"] .cbi-map h2,[data-page="admin-system-admin"] .cbi-map .cbi-map-descr,[data-page="admin-system-admin-password"] .cbi-map .cbi-map-descr,.cbi-dropdown .preview,[data-page="admin-system-flash"] legend{color:#ccc}.main .main-left .nav .slide .slide-menu .active a,.main .main-left .nav .slide .slide-menu li a{color:#CCC}.main .main-left .nav .slide .slide-menu .active a::after,.main .main-left .nav .slide .menu.active a::after{background-color:#CCC!important}.main .main-left .nav .slide .menu.active,.main .main-left .nav li a:hover{background-color:var(--dark-primary)!important;color:#CCC!important}.main .main-left::-webkit-scrollbar-track,.ifacebox-body,fieldset[id^="cbi-apply-"],.ifacebadge{background-color:#333}div>table>tbody>tr:nth-of-type(2n),div>.table>.tr:nth-of-type(2n),fieldset>table>tbody>tr:nth-of-type(2n),.cbi-rowstyle-1,div>table>tbody>tr:nth-of-type(2n),div>.table>.tbody>.tr:nth-of-type(2n),.tabs,.cbi-tabcontainer>.cbi-value:nth-of-type(2n){background-color:#252526}#swaptotal>div>div,#swapfree>div>div,#memfree>div>div,#membuff>div>div,#conns>div>div,#memtotal>div>div,.node-system-packages>.main .cbi-section-node:first-child .cbi-value-last div[style="margin:3px 0; width:300px; height:10px; border:1px solid #000000; background-color:#80C080"] div,.cbi-progressbar div,.ifacebox-head.active{background-color:#32325d!important}#swaptotal>div>div>div>small,#swapfree>div>div>div>small,#memfree>div>div>div>small,#membuff>div>div>div>small,#conns>div>div>div>small,#memtotal>div>div>div>small,#cbi-dropbear h2,#cbi-dropbear .cbi-map-descr,#cbi-dropbear .cbi-map-descr abbr,#cbi-rc h2,#cbi-rc .cbi-map-descr,#cbi-distfeedconf h2,#cbi-distfeedconf .cbi-map-descr,#cbi-customfeedconf h2,#cbi-customfeedconf .cbi-map-descr,#cbi-download h2,#cbi-filelist h2,.node-services-vssr .block h4,[data-page="admin-system-opkg"] h2{color:#ccc!important}table>tbody>tr>th,table>tfoot>tr>th,table>thead>tr>th,#cbi-wireless .td,#cbi-network .tr:first-child>.td,.table[width="100%"]>.tr:first-child>.td,[data-page="admin-network-diagnostics"] .tr>.td,.tr.table-titles>.th,.tr.cbi-section-table-titles>.th{background-color:#252526;border-bottom:#000 1px solid!important}h4,.cbi-section-table .cbi-section-table-titles .cbi-section-table-cell{background-color:#1e1e1f}abbr,div.cbi-value var,td.cbi-value-field var{color:#5e72e4}.cbi-value-field>ul>li .ifacebadge,.zonebadge>.ifacebadge{background-color:#3c3c3c}.cbi-input-textarea,#syslog,#diag-rc-output>pre{background-color:#1e1e1e;color:#ccc}#xhr_poll_status>.label.success,header .fill .status span[data-style="active"]{background-color:#556B2F!important;color:#ccc!important}.btn.danger,.cbi-section-remove>.cbi-button,.cbi-button-remove,.cbi-button-reset,.cbi-button-negative,.cbi-button[value="Stop"],.cbi-button[value="Kill"],.cbi-button[onclick="reboot(this)"],.cbi-button-neutral[value="Restart"],[data-page="admin-system-flash"] .modal .danger{background-color:#FF8C00!important;border:thin solid #FF8C00!important}.btn,button,select,input,.cbi-dropdown,.cbi-dynlist>.item>span{border:1px solid #3c3c3c!important}@media screen and (max-width:480px){.node-status-iptables>.main div>.cbi-map>form{background-color:#1e1e1e;box-shadow:0 0 .5rem 0 rgba(0,0,0,0.35)}} \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/www/luci-static/css/fonts.css b/rooter/ext-rooter-basic/files/www/luci-static/css/fonts.css new file mode 100644 index 0000000..20dd22e --- /dev/null +++ b/rooter/ext-rooter-basic/files/www/luci-static/css/fonts.css @@ -0,0 +1 @@ +@font-face{font-family:argon;src:url(../fonts/argon.eot?u6kthm#iefix) format('embedded-opentype'),url(../fonts/argon.ttf?u6kthm) format('truetype'),url(../fonts/argon.woff?u6kthm) format('woff'),url(../fonts/argon.svg?u6kthm#argon) format('svg');font-weight:400;font-style:normal;font-display:block}[class^="icon-"],[class*=" icon-"]{font-family:argon!important;font-style:normal;font-weight:400;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.icon-expand_more:before{content:"\e20b"}.icon-menu:before{content:"\e20e"}.icon-favorite:before{content:"\e291"}.icon-spinner:before{content:"\e603"}.icon-delete:before{content:"\e900"}.icon-edit:before{content:"\e901"}.icon-use:before{content:"\e902"}.icon-loading:before{content:"\e903"}.icon-switch:before{content:"\e904"}.icon-error:before{content:"\e905"}.icon-dashboard:before{content:"\e906"}.icon-logout:before{content:"\e907"}.icon-Network:before{content:"\e908"}.icon-services:before{content:"\e909"}.icon-system:before{content:"\e90a"}.icon-vpn:before{content:"\e90b"}.icon-storage:before{content:"\e90c"}.icon-statistics:before{content:"\e90d"}.icon-hello-world:before{content:"\e90e"}.icon-angle-right:before{content:"\e90f"}.icon-password:before{content:"\e910"}.icon-user:before{content:"\e971"}.icon-question:before{content:"\f059"}.icon-docker:before{content:"\e911"}.icon-control:before{content:"\e912"}.icon-statistics1:before{content:"\e913"}.icon-asterisk:before{content:"\e914"}.icon-app:before{content:"\e915"} \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/www/luci-static/css/pure-min.css b/rooter/ext-rooter-basic/files/www/luci-static/css/pure-min.css new file mode 100644 index 0000000..43786a7 --- /dev/null +++ b/rooter/ext-rooter-basic/files/www/luci-static/css/pure-min.css @@ -0,0 +1 @@ +html{line-height:1.15;-webkit-text-size-adjust:100%;font-family:sans-serif}body{margin:0}h1{font-size:2em;margin:.67em 0}hr{-webkit-box-sizing:content-box;box-sizing:content-box;height:0;overflow:visible}abbr[title]{border-bottom:none;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{-webkit-box-sizing:border-box;box-sizing:border-box;color:inherit;display:table;max-width:100%;white-space:normal;padding:0}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{-webkit-box-sizing:border-box;box-sizing:border-box;padding:0}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}.hidden,[hidden]{display:none!important}.pure-img{max-width:100%;height:auto}.pure-g{letter-spacing:-.31em;text-rendering:optimizespeed;font-family:FreeSans,Arimo,"Droid Sans",Helvetica,Arial,sans-serif;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-flow:row wrap;flex-flow:row wrap;-ms-flex-line-pack:start;align-content:flex-start}.pure-g [class*=pure-u]{font-family:sans-serif}.pure-u-1-24{width:4.1667%}.pure-u-1-12,.pure-u-2-24{width:8.3333%}.pure-u-1-8,.pure-u-3-24{width:12.5%}.pure-u-1-6,.pure-u-4-24{width:16.6667%}.pure-u-1-5{width:20%}.pure-u-5-24{width:20.8333%}.pure-u-7-24{width:29.1667%}.pure-u-1-3,.pure-u-8-24{width:33.3333%}.pure-u-3-8,.pure-u-9-24{width:37.5%}.pure-u-2-5{width:40%}.pure-u-10-24,.pure-u-5-12{width:41.6667%}.pure-u-11-24{width:45.8333%}.pure-u-13-24{width:54.1667%}.pure-u-14-24,.pure-u-7-12{width:58.3333%}.pure-u-3-5{width:60%}.pure-u-15-24,.pure-u-5-8{width:62.5%}.pure-u-16-24,.pure-u-2-3{width:66.6667%}.pure-u-17-24{width:70.8333%}.pure-u-19-24{width:79.1667%}.pure-u-4-5{width:80%}.pure-u-20-24,.pure-u-5-6{width:83.3333%}.pure-u-21-24,.pure-u-7-8{width:87.5%}.pure-u-11-12,.pure-u-22-24{width:91.6667%}.pure-u-23-24{width:95.8333%}.pure-button{display:inline-block;line-height:normal;white-space:nowrap;vertical-align:middle;text-align:center;cursor:pointer;-webkit-user-drag:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-box-sizing:border-box;box-sizing:border-box;font-family:inherit;font-size:100%;color:rgba(0,0,0,.8);border:none transparent;background-color:#e6e6e6;text-decoration:none;border-radius:2px;padding:.5em 1em}.pure-button::-moz-focus-inner{border:0;padding:0}.pure-button-group{letter-spacing:-.31em;text-rendering:optimizespeed}.pure-button-group .pure-button{letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto;border-radius:0;border-right:1px solid rgba(0,0,0,.2);margin:0}.pure-button-hover,.pure-button:focus,.pure-button:hover{background-image:linear-gradient(transparent,rgba(0,0,0,.05) 40%,rgba(0,0,0,.1))}.pure-button:focus{outline:0}.pure-button-active,.pure-button:active{-webkit-box-shadow:0 0 0 1px rgba(0,0,0,.15) inset,0 0 6px rgba(0,0,0,.2) inset;box-shadow:0 0 0 1px rgba(0,0,0,.15) inset,0 0 6px rgba(0,0,0,.2) inset;border-color:#000}.pure-button-disabled,.pure-button-disabled:active,.pure-button-disabled:focus,.pure-button-disabled:hover,.pure-button[disabled]{border:none;background-image:none;opacity:.4;cursor:not-allowed;-webkit-box-shadow:none;box-shadow:none;pointer-events:none}.pure-button-primary,.pure-button-selected,a.pure-button-primary,a.pure-button-selected{background-color:#0078e7;color:#fff}.pure-button-group .pure-button:first-child{border-top-left-radius:2px;border-bottom-left-radius:2px}.pure-button-group .pure-button:last-child{border-top-right-radius:2px;border-bottom-right-radius:2px;border-right:none}.pure-form input[type=color],.pure-form input[type=date],.pure-form input[type=datetime-local],.pure-form input[type=datetime],.pure-form input[type=email],.pure-form input[type=month],.pure-form input[type=number],.pure-form input[type=password],.pure-form input[type=search],.pure-form input[type=tel],.pure-form input[type=text],.pure-form input[type=time],.pure-form input[type=url],.pure-form input[type=week],.pure-form select,.pure-form textarea{display:inline-block;border:1px solid #ccc;-webkit-box-shadow:inset 0 1px 3px #ddd;box-shadow:inset 0 1px 3px #ddd;border-radius:4px;vertical-align:middle;-webkit-box-sizing:border-box;box-sizing:border-box;padding:.5em .6em}.pure-form input:not([type]){display:inline-block;border:1px solid #ccc;-webkit-box-shadow:inset 0 1px 3px #ddd;box-shadow:inset 0 1px 3px #ddd;border-radius:4px;-webkit-box-sizing:border-box;box-sizing:border-box;padding:.5em .6em}.pure-form input[type=color]{padding:.2em .5em}.pure-form input[type=checkbox]:focus,.pure-form input[type=file]:focus,.pure-form input[type=radio]:focus{outline:1px auto #129fea}.pure-form .pure-checkbox,.pure-form .pure-radio{display:block;margin:.5em 0}.pure-form input[readonly],.pure-form select[readonly],.pure-form textarea[readonly]{background-color:#eee;color:#777;border-color:#ccc}.pure-form input:focus:invalid,.pure-form select:focus:invalid,.pure-form textarea:focus:invalid{color:#b94a48;border-color:#e9322d}.pure-form input[type=checkbox]:focus:invalid:focus,.pure-form input[type=file]:focus:invalid:focus,.pure-form input[type=radio]:focus:invalid:focus{outline-color:#e9322d}.pure-form select{height:2.25em;border:1px solid #ccc;background-color:#fff}.pure-form label{margin:.5em 0 .2em}.pure-form fieldset{border:0;margin:0;padding:.35em 0 .75em}.pure-form legend{display:block;width:100%;margin-bottom:.3em;color:#333;border-bottom:1px solid #e5e5e5;padding:.3em 0}.pure-form-aligned textarea{vertical-align:top}.pure-form-aligned .pure-control-group{margin-bottom:.5em}.pure-form-aligned .pure-control-group label{text-align:right;display:inline-block;vertical-align:middle;width:10em;margin:0 1em 0 0}.pure-form-aligned .pure-controls{margin:1.5em 0 0 11em}.pure-form .pure-input-rounded,.pure-form input.pure-input-rounded{border-radius:2em;padding:.5em 1em}.pure-form .pure-group fieldset{margin-bottom:10px}.pure-form .pure-group input,.pure-form .pure-group textarea{display:block;border-radius:0;position:relative;top:-1px;margin:0 0 -1px;padding:10px}.pure-form .pure-group input:focus,.pure-form .pure-group textarea:focus{z-index:3}.pure-form .pure-group input:first-child,.pure-form .pure-group textarea:first-child{top:1px;border-radius:4px 4px 0 0;margin:0}.pure-form .pure-group input:first-child:last-child,.pure-form .pure-group textarea:first-child:last-child{top:1px;border-radius:4px;margin:0}.pure-form .pure-group input:last-child,.pure-form .pure-group textarea:last-child{top:-2px;border-radius:0 0 4px 4px;margin:0}.pure-form .pure-group button{margin:.35em 0}.pure-form .pure-input-2-3{width:66%}.pure-form .pure-input-1-3{width:33%}.pure-form-message-inline{display:inline-block;padding-left:.3em;color:#666;vertical-align:middle;font-size:.875em}.pure-form-message{display:block;color:#666;font-size:.875em}.pure-menu{-webkit-box-sizing:border-box;box-sizing:border-box}.pure-menu-fixed{position:fixed;left:0;top:0;z-index:3}.pure-menu-item,.pure-menu-list{position:relative}.pure-menu-list{list-style:none;margin:0;padding:0}.pure-menu-item{height:100%;margin:0;padding:0}.pure-menu-heading,.pure-menu-link{display:block;text-decoration:none;white-space:nowrap}.pure-menu-horizontal{width:100%;white-space:nowrap}.pure-menu-children{display:none;position:absolute;left:100%;top:0;z-index:3;background-color:#fff;margin:0;padding:0}.pure-menu-horizontal .pure-menu-children{left:0;top:auto;width:inherit}.pure-menu-active>.pure-menu-children,.pure-menu-allow-hover:hover>.pure-menu-children{display:block;position:absolute}.pure-menu-has-children>.pure-menu-link:after{padding-left:.5em;content:"\25B8";font-size:small}.pure-menu-horizontal .pure-menu-has-children>.pure-menu-link:after{content:"\25BE"}.pure-menu-scrollable{overflow-y:scroll;overflow-x:hidden}.pure-menu-horizontal.pure-menu-scrollable{white-space:nowrap;overflow-y:hidden;overflow-x:auto;padding:.5em 0}.pure-menu-horizontal .pure-menu-children .pure-menu-separator,.pure-menu-separator{background-color:#ccc;height:1px;margin:.3em 0}.pure-menu-horizontal .pure-menu-separator{width:1px;height:1.3em;margin:0 .3em}.pure-menu-horizontal .pure-menu-children .pure-menu-separator{display:block;width:auto}.pure-menu-heading{text-transform:uppercase;color:#565d64}.pure-menu-link{color:#777}.pure-menu-disabled,.pure-menu-heading,.pure-menu-link{padding:.5em 1em}.pure-menu-disabled{opacity:.5}.pure-menu-active>.pure-menu-link,.pure-menu-link:focus,.pure-menu-link:hover{background-color:#eee}.pure-menu-selected>.pure-menu-link,.pure-menu-selected>.pure-menu-link:visited{color:#000}.pure-table{border-collapse:collapse;border-spacing:0;empty-cells:show;border:1px solid #cbcbcb}.pure-table caption{color:#000;font:italic 85%/1 arial,sans-serif;text-align:center;padding:1em 0}.pure-table td,.pure-table th{border-left:1px solid #cbcbcb;font-size:inherit;overflow:visible;border-width:0 0 0 1px;margin:0;padding:.5em 1em}.pure-table thead{background-color:#e0e0e0;color:#000;text-align:left;vertical-align:bottom}.pure-table-bordered td{border-bottom:1px solid #cbcbcb}.pure-table-horizontal td,.pure-table-horizontal th{border-bottom:1px solid #cbcbcb;border-width:0 0 1px}main,details,.pure-menu-item .pure-menu-item,.pure-menu-scrollable .pure-menu-list{display:block}pre,code,kbd,samp{font-family:monospace,monospace;font-size:1em}a,.pure-menu-disabled .pure-menu-link:hover,.pure-table td{background-color:transparent}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button,.pure-form select[multiple]{height:auto}template,[hidden],.pure-button-hidden{display:none}.opera-only :-o-prefocus,.pure-g,.opera-only :-o-prefocus,.pure-button-group{word-spacing:-.43em}.pure-u,.pure-u-1,.pure-u-1-1,.pure-u-1-12,.pure-u-1-2,.pure-u-1-24,.pure-u-1-3,.pure-u-1-4,.pure-u-1-5,.pure-u-1-6,.pure-u-1-8,.pure-u-10-24,.pure-u-11-12,.pure-u-11-24,.pure-u-12-24,.pure-u-13-24,.pure-u-14-24,.pure-u-15-24,.pure-u-16-24,.pure-u-17-24,.pure-u-18-24,.pure-u-19-24,.pure-u-2-24,.pure-u-2-3,.pure-u-2-5,.pure-u-20-24,.pure-u-21-24,.pure-u-22-24,.pure-u-23-24,.pure-u-24-24,.pure-u-3-24,.pure-u-3-4,.pure-u-3-5,.pure-u-3-8,.pure-u-4-24,.pure-u-4-5,.pure-u-5-12,.pure-u-5-24,.pure-u-5-5,.pure-u-5-6,.pure-u-5-8,.pure-u-6-24,.pure-u-7-12,.pure-u-7-24,.pure-u-7-8,.pure-u-8-24,.pure-u-9-24{display:inline-block;letter-spacing:normal;text-rendering:auto;vertical-align:top;word-spacing:normal}.pure-u-1-4,.pure-u-6-24,.pure-form .pure-input-1-4{width:25%}.pure-u-1-2,.pure-u-12-24,.pure-form .pure-input-1-2{width:50%}.pure-u-18-24,.pure-u-3-4,.pure-form .pure-input-3-4{width:75%}.pure-u-1,.pure-u-1-1,.pure-u-24-24,.pure-u-5-5,.pure-form .pure-input-1{width:100%}.pure-form input[type=color]:focus,.pure-form input[type=date]:focus,.pure-form input[type=datetime-local]:focus,.pure-form input[type=datetime]:focus,.pure-form input[type=email]:focus,.pure-form input[type=month]:focus,.pure-form input[type=number]:focus,.pure-form input[type=password]:focus,.pure-form input[type=search]:focus,.pure-form input[type=tel]:focus,.pure-form input[type=text]:focus,.pure-form input[type=time]:focus,.pure-form input[type=url]:focus,.pure-form input[type=week]:focus,.pure-form select:focus,.pure-form textarea:focus,.pure-form input:not([type]):focus{outline:0;border-color:#129fea}.pure-form input[type=color][disabled],.pure-form input[type=date][disabled],.pure-form input[type=datetime-local][disabled],.pure-form input[type=datetime][disabled],.pure-form input[type=email][disabled],.pure-form input[type=month][disabled],.pure-form input[type=number][disabled],.pure-form input[type=password][disabled],.pure-form input[type=search][disabled],.pure-form input[type=tel][disabled],.pure-form input[type=text][disabled],.pure-form input[type=time][disabled],.pure-form input[type=url][disabled],.pure-form input[type=week][disabled],.pure-form select[disabled],.pure-form textarea[disabled],.pure-form input:not([type])[disabled]{background-color:#eaeded;color:#cad2d3;cursor:not-allowed}.pure-form-stacked input[type=color],.pure-form-stacked input[type=date],.pure-form-stacked input[type=datetime-local],.pure-form-stacked input[type=datetime],.pure-form-stacked input[type=email],.pure-form-stacked input[type=file],.pure-form-stacked input[type=month],.pure-form-stacked input[type=number],.pure-form-stacked input[type=password],.pure-form-stacked input[type=search],.pure-form-stacked input[type=tel],.pure-form-stacked input[type=text],.pure-form-stacked input[type=time],.pure-form-stacked input[type=url],.pure-form-stacked input[type=week],.pure-form-stacked label,.pure-form-stacked select,.pure-form-stacked textarea,.pure-form-stacked input:not([type]){display:block;margin:.25em 0}.pure-form-aligned input,.pure-form-aligned select,.pure-form-aligned textarea,.pure-form-message-inline,.pure-menu-horizontal .pure-menu-heading,.pure-menu-horizontal .pure-menu-item,.pure-menu-horizontal .pure-menu-separator{display:inline-block;vertical-align:middle}.pure-menu-horizontal .pure-menu-list,.pure-menu-horizontal.pure-menu-scrollable .pure-menu-list{display:inline-block}.pure-table-odd td,.pure-table-striped tr:nth-child(2n-1) td{background-color:#f2f2f2}.pure-table-bordered tbody>tr:last-child>td,.pure-table-horizontal tbody>tr:last-child>td{border-bottom-width:0}@media all and (-ms-high-contrast:none),(-ms-high-contrast:active){table .pure-g{display:block}}@media only screen and (max-width :480px){.pure-form button[type=submit]{margin:.7em 0 0}.pure-form input:not([type]),.pure-form input[type=color],.pure-form input[type=date],.pure-form input[type=datetime-local],.pure-form input[type=datetime],.pure-form input[type=email],.pure-form input[type=month],.pure-form input[type=number],.pure-form input[type=password],.pure-form input[type=search],.pure-form input[type=tel],.pure-form input[type=text],.pure-form input[type=time],.pure-form input[type=url],.pure-form input[type=week],.pure-form label{margin-bottom:.3em;display:block}.pure-group input:not([type]),.pure-group input[type=color],.pure-group input[type=date],.pure-group input[type=datetime-local],.pure-group input[type=datetime],.pure-group input[type=email],.pure-group input[type=month],.pure-group input[type=number],.pure-group input[type=password],.pure-group input[type=search],.pure-group input[type=tel],.pure-group input[type=text],.pure-group input[type=time],.pure-group input[type=url],.pure-group input[type=week]{margin-bottom:0}.pure-form-aligned .pure-control-group label{margin-bottom:.3em;text-align:left;display:block;width:100%}.pure-form-aligned .pure-controls{margin:1.5em 0 0}.pure-form-message,.pure-form-message-inline{display:block;font-size:.75em;padding:.2em 0 .8em}} \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/www/luci-static/fonts/Roboto-Medium-webfont.woff b/rooter/ext-rooter-basic/files/www/luci-static/fonts/Roboto-Medium-webfont.woff new file mode 100644 index 0000000..9024fae Binary files /dev/null and b/rooter/ext-rooter-basic/files/www/luci-static/fonts/Roboto-Medium-webfont.woff differ diff --git a/rooter/ext-rooter-basic/files/www/luci-static/fonts/Roboto-Regular-webfont.woff b/rooter/ext-rooter-basic/files/www/luci-static/fonts/Roboto-Regular-webfont.woff new file mode 100644 index 0000000..5413a37 Binary files /dev/null and b/rooter/ext-rooter-basic/files/www/luci-static/fonts/Roboto-Regular-webfont.woff differ diff --git a/rooter/ext-rooter-basic/files/www/luci-static/fonts/TypoGraphica.eot b/rooter/ext-rooter-basic/files/www/luci-static/fonts/TypoGraphica.eot new file mode 100644 index 0000000..efce636 Binary files /dev/null and b/rooter/ext-rooter-basic/files/www/luci-static/fonts/TypoGraphica.eot differ diff --git a/rooter/ext-rooter-basic/files/www/luci-static/fonts/TypoGraphica.svg b/rooter/ext-rooter-basic/files/www/luci-static/fonts/TypoGraphica.svg new file mode 100644 index 0000000..c555b75 --- /dev/null +++ b/rooter/ext-rooter-basic/files/www/luci-static/fonts/TypoGraphica.svg @@ -0,0 +1,1191 @@ + + + + +Created by FontForge 20090622 at Tue Jul 23 03:29:07 2019 + By deploy user +TypoGraphica ©Sharkshock Productions 2015. All Rights Reserved + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/rooter/ext-rooter-basic/files/www/luci-static/fonts/TypoGraphica.ttf b/rooter/ext-rooter-basic/files/www/luci-static/fonts/TypoGraphica.ttf new file mode 100644 index 0000000..e11f89a Binary files /dev/null and b/rooter/ext-rooter-basic/files/www/luci-static/fonts/TypoGraphica.ttf differ diff --git a/rooter/ext-rooter-basic/files/www/luci-static/fonts/TypoGraphica.woff b/rooter/ext-rooter-basic/files/www/luci-static/fonts/TypoGraphica.woff new file mode 100644 index 0000000..fef38ca Binary files /dev/null and b/rooter/ext-rooter-basic/files/www/luci-static/fonts/TypoGraphica.woff differ diff --git a/rooter/ext-rooter-basic/files/www/luci-static/fonts/advancedtomato.eot b/rooter/ext-rooter-basic/files/www/luci-static/fonts/advancedtomato.eot new file mode 100644 index 0000000..f85324a Binary files /dev/null and b/rooter/ext-rooter-basic/files/www/luci-static/fonts/advancedtomato.eot differ diff --git a/rooter/ext-rooter-basic/files/www/luci-static/fonts/advancedtomato.svg b/rooter/ext-rooter-basic/files/www/luci-static/fonts/advancedtomato.svg new file mode 100644 index 0000000..a4ae739 --- /dev/null +++ b/rooter/ext-rooter-basic/files/www/luci-static/fonts/advancedtomato.svg @@ -0,0 +1,53 @@ + + + +Generated by Fontastic.me + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/rooter/ext-rooter-basic/files/www/luci-static/fonts/advancedtomato.ttf b/rooter/ext-rooter-basic/files/www/luci-static/fonts/advancedtomato.ttf new file mode 100644 index 0000000..0f59478 Binary files /dev/null and b/rooter/ext-rooter-basic/files/www/luci-static/fonts/advancedtomato.ttf differ diff --git a/rooter/ext-rooter-basic/files/www/luci-static/fonts/advancedtomato.woff b/rooter/ext-rooter-basic/files/www/luci-static/fonts/advancedtomato.woff new file mode 100644 index 0000000..4251248 Binary files /dev/null and b/rooter/ext-rooter-basic/files/www/luci-static/fonts/advancedtomato.woff differ diff --git a/rooter/ext-rooter-basic/files/www/luci-static/fonts/argon.eot b/rooter/ext-rooter-basic/files/www/luci-static/fonts/argon.eot new file mode 100644 index 0000000..e28f6db Binary files /dev/null and b/rooter/ext-rooter-basic/files/www/luci-static/fonts/argon.eot differ diff --git a/rooter/ext-rooter-basic/files/www/luci-static/fonts/argon.svg b/rooter/ext-rooter-basic/files/www/luci-static/fonts/argon.svg new file mode 100644 index 0000000..1e12b5f --- /dev/null +++ b/rooter/ext-rooter-basic/files/www/luci-static/fonts/argon.svg @@ -0,0 +1,38 @@ + + + +Generated by IcoMoon + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/www/luci-static/fonts/argon.ttf b/rooter/ext-rooter-basic/files/www/luci-static/fonts/argon.ttf new file mode 100644 index 0000000..3d062dc Binary files /dev/null and b/rooter/ext-rooter-basic/files/www/luci-static/fonts/argon.ttf differ diff --git a/rooter/ext-rooter-basic/files/www/luci-static/fonts/argon.woff b/rooter/ext-rooter-basic/files/www/luci-static/fonts/argon.woff new file mode 100644 index 0000000..ef1e9c2 Binary files /dev/null and b/rooter/ext-rooter-basic/files/www/luci-static/fonts/argon.woff differ diff --git a/rooter/ext-rooter-basic/files/www/luci-static/fonts/font.eot b/rooter/ext-rooter-basic/files/www/luci-static/fonts/font.eot new file mode 100644 index 0000000..9e6ffc9 Binary files /dev/null and b/rooter/ext-rooter-basic/files/www/luci-static/fonts/font.eot differ diff --git a/rooter/ext-rooter-basic/files/www/luci-static/fonts/font.svg b/rooter/ext-rooter-basic/files/www/luci-static/fonts/font.svg new file mode 100644 index 0000000..d38d057 --- /dev/null +++ b/rooter/ext-rooter-basic/files/www/luci-static/fonts/font.svg @@ -0,0 +1,16 @@ + + + +Generated by IcoMoon + + + + + + + + + + + + \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/www/luci-static/fonts/font.ttf b/rooter/ext-rooter-basic/files/www/luci-static/fonts/font.ttf new file mode 100644 index 0000000..8466932 Binary files /dev/null and b/rooter/ext-rooter-basic/files/www/luci-static/fonts/font.ttf differ diff --git a/rooter/ext-rooter-basic/files/www/luci-static/fonts/font.woff b/rooter/ext-rooter-basic/files/www/luci-static/fonts/font.woff new file mode 100644 index 0000000..00cf84e Binary files /dev/null and b/rooter/ext-rooter-basic/files/www/luci-static/fonts/font.woff differ diff --git a/rooter/ext-rooter-basic/files/www/luci-static/fonts/fonts.css b/rooter/ext-rooter-basic/files/www/luci-static/fonts/fonts.css new file mode 100644 index 0000000..bff3e98 --- /dev/null +++ b/rooter/ext-rooter-basic/files/www/luci-static/fonts/fonts.css @@ -0,0 +1,38 @@ +/* + * Font generate by Icomoon + */ + +@font-face { + font-family: 'Roboto'; + src: local('Roboto Medium'), local('Roboto-Medium'), url('Roboto-Medium-webfont.woff') format('woff'); + font-weight: 500; + font-style: normal; +} + +@font-face { + font-family: 'Roboto'; + src: local('Roboto'), local('Roboto Regular'), local('Roboto-Regular'), url('Roboto-Regular-webfont.woff') format('woff'); + font-weight: normal; + font-style: normal; +} + +@font-face { + font-family: 'icomoon'; + src: url('font.eot'); + src: url('font.eot') format('embedded-opentype'), + url('font.ttf') format('truetype'), + url('font.woff') format('woff'), + url('font.svg') format('svg'); + font-weight: normal; + font-style: normal; +} +@font-face { + font-family: "advancedtomato"; + src:url("advancedtomato.eot"); + src:url("advancedtomato.eot?#iefix") format("embedded-opentype"), + url("advancedtomato.woff") format("woff"), + url("advancedtomato.ttf") format("truetype"), + url("advancedtomato.svg#advancedtomato") format("svg"); + font-weight: normal; + font-style: normal; +} diff --git a/rooter/ext-rooter-basic/files/www/luci-static/icon/android-icon-192x192.png b/rooter/ext-rooter-basic/files/www/luci-static/icon/android-icon-192x192.png new file mode 100644 index 0000000..7c17009 Binary files /dev/null and b/rooter/ext-rooter-basic/files/www/luci-static/icon/android-icon-192x192.png differ diff --git a/rooter/ext-rooter-basic/files/www/luci-static/icon/apple-icon-144x144.png b/rooter/ext-rooter-basic/files/www/luci-static/icon/apple-icon-144x144.png new file mode 100644 index 0000000..5308d66 Binary files /dev/null and b/rooter/ext-rooter-basic/files/www/luci-static/icon/apple-icon-144x144.png differ diff --git a/rooter/ext-rooter-basic/files/www/luci-static/icon/apple-icon-60x60.png b/rooter/ext-rooter-basic/files/www/luci-static/icon/apple-icon-60x60.png new file mode 100644 index 0000000..f18dfa4 Binary files /dev/null and b/rooter/ext-rooter-basic/files/www/luci-static/icon/apple-icon-60x60.png differ diff --git a/rooter/ext-rooter-basic/files/www/luci-static/icon/apple-icon-72x72.png b/rooter/ext-rooter-basic/files/www/luci-static/icon/apple-icon-72x72.png new file mode 100644 index 0000000..bb3e242 Binary files /dev/null and b/rooter/ext-rooter-basic/files/www/luci-static/icon/apple-icon-72x72.png differ diff --git a/rooter/ext-rooter-basic/files/www/luci-static/icon/browserconfig.xml b/rooter/ext-rooter-basic/files/www/luci-static/icon/browserconfig.xml new file mode 100644 index 0000000..c554148 --- /dev/null +++ b/rooter/ext-rooter-basic/files/www/luci-static/icon/browserconfig.xml @@ -0,0 +1,2 @@ + +#ffffff \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/www/luci-static/icon/favicon-16x16.png b/rooter/ext-rooter-basic/files/www/luci-static/icon/favicon-16x16.png new file mode 100644 index 0000000..308843a Binary files /dev/null and b/rooter/ext-rooter-basic/files/www/luci-static/icon/favicon-16x16.png differ diff --git a/rooter/ext-rooter-basic/files/www/luci-static/icon/favicon-32x32.png b/rooter/ext-rooter-basic/files/www/luci-static/icon/favicon-32x32.png new file mode 100644 index 0000000..bfcd097 Binary files /dev/null and b/rooter/ext-rooter-basic/files/www/luci-static/icon/favicon-32x32.png differ diff --git a/rooter/ext-rooter-basic/files/www/luci-static/icon/favicon-96x96.png b/rooter/ext-rooter-basic/files/www/luci-static/icon/favicon-96x96.png new file mode 100644 index 0000000..d0fe1ed Binary files /dev/null and b/rooter/ext-rooter-basic/files/www/luci-static/icon/favicon-96x96.png differ diff --git a/rooter/ext-rooter-basic/files/www/luci-static/icon/manifest.json b/rooter/ext-rooter-basic/files/www/luci-static/icon/manifest.json new file mode 100644 index 0000000..2817bc8 --- /dev/null +++ b/rooter/ext-rooter-basic/files/www/luci-static/icon/manifest.json @@ -0,0 +1,41 @@ +{ + "name": "Openwrt", + "icons": [ + { + "src": "\/android-icon-36x36.png", + "sizes": "36x36", + "type": "image\/png", + "density": "0.75" + }, + { + "src": "\/android-icon-48x48.png", + "sizes": "48x48", + "type": "image\/png", + "density": "1.0" + }, + { + "src": "\/android-icon-72x72.png", + "sizes": "72x72", + "type": "image\/png", + "density": "1.5" + }, + { + "src": "\/android-icon-96x96.png", + "sizes": "96x96", + "type": "image\/png", + "density": "2.0" + }, + { + "src": "\/android-icon-144x144.png", + "sizes": "144x144", + "type": "image\/png", + "density": "3.0" + }, + { + "src": "\/android-icon-192x192.png", + "sizes": "192x192", + "type": "image\/png", + "density": "4.0" + } + ] +} \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/www/luci-static/icon/ms-icon-144x144.png b/rooter/ext-rooter-basic/files/www/luci-static/icon/ms-icon-144x144.png new file mode 100644 index 0000000..5308d66 Binary files /dev/null and b/rooter/ext-rooter-basic/files/www/luci-static/icon/ms-icon-144x144.png differ diff --git a/rooter/ext-rooter-basic/files/www/luci-static/icons/arrow.svg b/rooter/ext-rooter-basic/files/www/luci-static/icons/arrow.svg new file mode 100644 index 0000000..be864c5 --- /dev/null +++ b/rooter/ext-rooter-basic/files/www/luci-static/icons/arrow.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/www/luci-static/icons/logout.svg b/rooter/ext-rooter-basic/files/www/luci-static/icons/logout.svg new file mode 100644 index 0000000..d529b94 --- /dev/null +++ b/rooter/ext-rooter-basic/files/www/luci-static/icons/logout.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/www/luci-static/icons/menu.svg b/rooter/ext-rooter-basic/files/www/luci-static/icons/menu.svg new file mode 100644 index 0000000..46bd0ae --- /dev/null +++ b/rooter/ext-rooter-basic/files/www/luci-static/icons/menu.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/www/luci-static/icons/spinner.svg b/rooter/ext-rooter-basic/files/www/luci-static/icons/spinner.svg new file mode 100644 index 0000000..6ddd3b3 --- /dev/null +++ b/rooter/ext-rooter-basic/files/www/luci-static/icons/spinner.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/www/luci-static/img/argon.svg b/rooter/ext-rooter-basic/files/www/luci-static/img/argon.svg new file mode 100644 index 0000000..654e2fe --- /dev/null +++ b/rooter/ext-rooter-basic/files/www/luci-static/img/argon.svg @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/rooter/ext-rooter-basic/files/www/luci-static/img/blank.png b/rooter/ext-rooter-basic/files/www/luci-static/img/blank.png new file mode 100644 index 0000000..9f4100e Binary files /dev/null and b/rooter/ext-rooter-basic/files/www/luci-static/img/blank.png differ diff --git a/rooter/ext-rooter-basic/files/www/luci-static/img/open.png b/rooter/ext-rooter-basic/files/www/luci-static/img/open.png new file mode 100644 index 0000000..7c92fbe Binary files /dev/null and b/rooter/ext-rooter-basic/files/www/luci-static/img/open.png differ diff --git a/rooter/ext-rooter-basic/files/www/luci-static/img/volume_high.svg b/rooter/ext-rooter-basic/files/www/luci-static/img/volume_high.svg new file mode 100644 index 0000000..f01ad5c --- /dev/null +++ b/rooter/ext-rooter-basic/files/www/luci-static/img/volume_high.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/www/luci-static/img/volume_off.svg b/rooter/ext-rooter-basic/files/www/luci-static/img/volume_off.svg new file mode 100644 index 0000000..0598d58 --- /dev/null +++ b/rooter/ext-rooter-basic/files/www/luci-static/img/volume_off.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/www/luci-static/resources/buttons/buttons.css b/rooter/ext-rooter-basic/files/www/luci-static/resources/buttons/buttons.css new file mode 100644 index 0000000..9f4b624 --- /dev/null +++ b/rooter/ext-rooter-basic/files/www/luci-static/resources/buttons/buttons.css @@ -0,0 +1,702 @@ +/* Buttons CSS */ + +:root { + --green-color: rgb(44,187,99); + --red-color: rgb(218,42,42); +} + +/* +
                                                                        <%:Exit%>
                                                                        +*/ + +.button-73 { + appearance: none; + background-color: #FFFFFF; + border-radius: 40em; + border-style: none; + box-shadow: #ADCFFF 0 -12px 6px inset; + box-sizing: border-box; + color: #000000; + cursor: pointer; + display: inline-block; + font-family: -apple-system,sans-serif; + font-size: 1.2rem; + font-weight: 700; + letter-spacing: -.24px; + margin: 0; + outline: none; + padding: 1rem 1.3rem; + quotes: auto; + text-align: center; + text-decoration: none; + transition: all .15s; + user-select: none; + -webkit-user-select: none; + touch-action: manipulation; +} + +.button-73:hover { + background-color: #FFC229; + box-shadow: #FF6314 0 -6px 8px inset; + transform: scale(1.125); +} + +.button-73:active { + transform: scale(1.025); +} + +@media (min-width: 768px) { + .button-73 { + font-size: 1.5rem; + padding: .75rem 2rem; + } +} + +/* +
                                                                        <%:Exit%>
                                                                        +*/ +.button-71 { + background-color: #0078d0; + border: 0; + border-radius: 56px; + color: #fff; + cursor: pointer; + display: inline-block; + font-family: system-ui,-apple-system,system-ui,"Segoe UI",Roboto,Ubuntu,"Helvetica Neue",sans-serif; + font-size: 1.25rem; + font-weight: 600; + outline: 0; + padding: 16px 21px; + position: relative; + text-align: center; + text-decoration: none; + transition: all .3s; + user-select: none; + -webkit-user-select: none; + touch-action: manipulation; +} + +.button-71:before { + background-color: initial; + background-image: linear-gradient(#fff 0, rgba(255, 255, 255, 0) 100%); + border-radius: 125px; + content: ""; + height: 50%; + left: 4%; + opacity: .5; + position: absolute; + top: 0; + transition: all .3s; + width: 92%; +} + +.button-71:hover { + box-shadow: rgba(255, 255, 255, .2) 0 3px 15px inset, rgba(0, 0, 0, .1) 0 3px 5px, rgba(0, 0, 0, .1) 0 10px 13px; + transform: scale(1.05); +} + +@media (min-width: 768px) { + .button-71 { + padding: 16px 48px; + } +} + +/* +
                                                                        <%:Exit%>
                                                                        +*/ +.button-62 { + background: linear-gradient(to bottom right, #EF4765, #FF9A5A); + border: 0; + border-radius: 12px; + color: #FFFFFF; + cursor: pointer; + display: inline-block; + font-family: -apple-system,system-ui,"Segoe UI",Roboto,Helvetica,Arial,sans-serif; + font-size: 16px; + font-weight: 500; + line-height: 2.5; + outline: transparent; + padding: 0 1rem; + text-align: center; + text-decoration: none; + transition: box-shadow .2s ease-in-out; + user-select: none; + -webkit-user-select: none; + touch-action: manipulation; + white-space: nowrap; +} + +.button-62:not([disabled]):focus { + box-shadow: 0 0 .25rem rgba(0, 0, 0, 0.5), -.125rem -.125rem 1rem rgba(239, 71, 101, 0.5), .125rem .125rem 1rem rgba(255, 154, 90, 0.5); +} + +.button-62:not([disabled]):hover { + box-shadow: 0 0 .25rem rgba(0, 0, 0, 0.5), -.125rem -.125rem 1rem rgba(239, 71, 101, 0.5), .125rem .125rem 1rem rgba(255, 154, 90, 0.5); +} + +/* +
                                                                        + + + + Button 82 + +
                                                                        + + Red button +*/ + +.button-82-pushable { + position: relative; + border: none; + background: transparent; + padding: 0; + cursor: pointer; + outline-offset: 4px; + transition: filter 250ms; + user-select: none; + -webkit-user-select: none; + touch-action: manipulation; +} + +.button-82-shadow { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + border-radius: 12px; + background: hsl(0deg 0% 0% / 0.25); + will-change: transform; + transform: translateY(2px); + transition: + transform + 600ms + cubic-bezier(.3, .7, .4, 1); +} + +.button-82-edge { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + border-radius: 12px; + background: linear-gradient( + to left, + hsl(340deg 100% 16%) 0%, + hsl(340deg 100% 32%) 8%, + hsl(340deg 100% 32%) 92%, + hsl(340deg 100% 16%) 100% + ); +} + +.button-82-front { + display: block; + position: relative; + padding: 12px 27px; + border-radius: 12px; + font-size: 1.1rem; + color: white; + background: hsl(345deg 100% 47%); + will-change: transform; + transform: translateY(-4px); + transition: + transform + 600ms + cubic-bezier(.3, .7, .4, 1); +} + +@media (min-width: 768px) { + .button-82-front { + font-size: 1.25rem; + padding: 12px 42px; + } +} + +.button-82-pushable:hover { + filter: brightness(110%); + -webkit-filter: brightness(110%); +} + +.button-82-pushable:hover .button-82-front { + transform: translateY(-6px); + transition: + transform + 250ms + cubic-bezier(.3, .7, .4, 1.5); +} + +.button-82-pushable:active .button-82-front { + transform: translateY(-2px); + transition: transform 34ms; +} + +.button-82-pushable:hover .button-82-shadow { + transform: translateY(4px); + transition: + transform + 250ms + cubic-bezier(.3, .7, .4, 1.5); +} + +.button-82-pushable:active .button-82-shadow { + transform: translateY(1px); + transition: transform 34ms; +} + +.button-82-pushable:focus:not(:focus-visible) { + outline: none; +} + +/* +
                                                                        <%:Exit%>
                                                                        + Green button +*/ + +.button-33 { + background-color: #c2fbd7; + border-radius: 100px; + box-shadow: rgba(44,187,99, .2) 0 -25px 18px -14px inset,rgba(44,187,99, .15) 0 1px 2px,rgba(44,187,99, .15) 0 2px 4px,rgba(44,187,99, .15) 0 4px 8px,rgba(44,187,99, .15) 0 8px 16px,rgba(44,187,99, .15) 0 16px 32px; + color: green; + cursor: pointer; + display: inline-block; + font-family: CerebriSans-Regular,-apple-system,system-ui,Roboto,sans-serif; + padding: 7px 20px; + text-align: center; + text-decoration: none; + transition: all 250ms; + border: 0; + font-size: 20px; + user-select: none; + -webkit-user-select: none; + touch-action: manipulation; +} + +.button-33:hover { + box-shadow: rgba(44,187,99,.35) 0 -25px 18px -14px inset,rgba(44,187,99,.25) 0 1px 2px,rgba(44,187,99,.25) 0 2px 4px,rgba(44,187,99,.25) 0 4px 8px,rgba(44,187,99,.25) 0 8px 16px,rgba(44,187,99,.25) 0 16px 32px; + transform: scale(1.05) rotate(-1deg); +} + +/* Red button */ + +.button-34 { + background-color: var(--red-color); + border-radius: 100px; + box-shadow: rgba(218,42,42, .2) 0 -25px 18px -14px inset,rgba(218,42,42, .15) 0 1px 2px,rgba(218,42,42, .15) 0 2px 4px,rgba(218,42,42, .15) 0 4px 8px,rgba(218,42,42, .15) 0 8px 16px,rgba(218,42,42, .15) 0 16px 32px; + color: green; + cursor: pointer; + display: inline-block; + font-family: CerebriSans-Regular,-apple-system,system-ui,Roboto,sans-serif; + padding: 7px 20px; + text-align: center; + text-decoration: none; + transition: all 250ms; + border: 0; + font-size: 20px; + user-select: none; + -webkit-user-select: none; + touch-action: manipulation; +} + +.button-34:hover { + box-shadow: rgba(218,42,42,.35) 0 -25px 18px -14px inset,rgba(218,42,42,.25) 0 1px 2px,rgba(218,42,42,.25) 0 2px 4px,rgba(218,42,42,.25) 0 4px 8px,rgba(218,42,42,.25) 0 8px 16px,rgba(218,42,42,.25) 0 16px 32px; + transform: scale(1.05) rotate(-1deg); +} + + +.button-40 { + background-color: #0078d0; + border: 1px solid transparent; + border-radius: .75rem; + box-sizing: border-box; + color: #ffffff; + cursor: pointer; + flex: 0 0 auto; + font-family: "Inter var",ui-sans-serif,system-ui,-apple-system,system-ui,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji"; + font-size: 1.80rem; + font-weight: 600; + line-height: 1.5rem; + padding: .75rem 1.2rem; + text-align: center; + text-decoration: none #6B7280 solid; + text-decoration-thickness: auto; + transition-duration: .2s; + transition-property: background-color,border-color,color,fill,stroke; + transition-timing-function: cubic-bezier(.4, 0, 0.2, 1); + user-select: none; + -webkit-user-select: none; + touch-action: manipulation; + width: auto; +} + +.button-40:hover { + +} + +.button-40:focus { + box-shadow: none; + outline: 2px solid transparent; + outline-offset: 2px; +} + +@media (min-width: 768px) { + .button-40 { + padding: .75rem 1.5rem; + } +} + +/* +
                                                                        + +
                                                                        +*/ + +*, +*:before, +*:after { + box-sizing: border-box; +} + +.toggle { + cursor: pointer; + display: inline-block; +} + +.toggle-switch { + display: inline-block; + background: #ccc; + border-radius: 16px; + width: 58px; + height: 32px; + position: relative; + vertical-align: middle; + transition: background 0.25s; +} +.toggle-switch:before, .toggle-switch:after { + content: ""; +} +.toggle-switch:before { + display: block; + background: linear-gradient(to bottom, #fff 0%, #eee 100%); + border-radius: 50%; + box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.25); + width: 24px; + height: 24px; + position: absolute; + top: 4px; + left: 4px; + transition: left 0.25s; +} +.toggle:hover .toggle-switch:before { + background: linear-gradient(to bottom, #fff 0%, #fff 100%); + box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.5); +} +.toggle-checkbox:checked + .toggle-switch { + background: #56c080; +} +.toggle-checkbox:checked + .toggle-switch:before { + left: 30px; +} + +.toggle-checkbox { + position: absolute; + visibility: hidden; +} + +.toggle-label { + margin-left: 5px; + position: relative; + top: 2px; +} + +/* + +*/ +/* The switch - the box around the slider */ +.switch { + position: relative; + display: inline-block; + width: 60px; + height: 34px; +} + +/* Hide default HTML checkbox */ +.switch input { + opacity: 0; + width: 0; + height: 0; +} + +/* The slider */ +.slider { + position: absolute; + cursor: pointer; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: #ccc; + -webkit-transition: .4s; + transition: .4s; +} + +.slider:before { + position: absolute; + content: ""; + height: 26px; + width: 26px; + left: 4px; + bottom: 4px; + background-color: white; + -webkit-transition: .4s; + transition: .4s; +} + +input:checked + .slider { + background-color: #2196F3; +} + +input:focus + .slider { + box-shadow: 0 0 1px #2196F3; +} + +input:checked + .slider:before { + -webkit-transform: translateX(26px); + -ms-transform: translateX(26px); + transform: translateX(26px); +} + +/* Rounded sliders */ +.slider.round { + border-radius: 34px; +} + +.slider.round:before { + border-radius: 50%; +} + +/* +
                                                                        +

                                                                        + +

                                                                        +

                                                                        + +

                                                                        +

                                                                        + +

                                                                        +

                                                                        + +

                                                                        +
                                                                        +*/ + + +/* Toggle Switch */ + +.toggleSwitch span span { + display: none; +} + +@media only screen { + .toggleSwitch { + display: inline-block; + height: 18px; + position: relative; + overflow: visible; + padding: 0; + margin-left: 50px; + cursor: pointer; + width: 40px; + user-select: none; + } + .toggleSwitch * { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + } + .toggleSwitch label, + .toggleSwitch > span { + line-height: 20px; + height: 20px; + vertical-align: middle; + } + .toggleSwitch input:focus ~ a, + .toggleSwitch input:focus + label { + outline: none; + } + .toggleSwitch label { + position: relative; + z-index: 3; + display: block; + width: 100%; + } + .toggleSwitch input { + position: absolute; + opacity: 0; + z-index: 5; + } + .toggleSwitch > span { + position: absolute; + left: -50px; + width: 100%; + margin: 0; + padding-right: 50px; + text-align: left; + white-space: nowrap; + } + .toggleSwitch > span span { + position: absolute; + top: 0; + left: 0; + z-index: 5; + display: block; + width: 50%; + margin-left: 50px; + text-align: left; + font-size: 0.9em; + width: 100%; + left: 15%; + top: -1px; + opacity: 0; + } + .toggleSwitch a { + position: absolute; + right: 50%; + z-index: 4; + display: block; + height: 100%; + padding: 0; + left: 2px; + width: 18px; + background-color: #fff; + border: 1px solid #CCC; + border-radius: 100%; + -webkit-transition: all 0.2s ease-out; + -moz-transition: all 0.2s ease-out; + transition: all 0.2s ease-out; + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); + } + .toggleSwitch > span span:first-of-type { + color: #ccc; + opacity: 1; + left: 45%; + } + .toggleSwitch > span:before { + content: ''; + display: block; + width: 100%; + height: 100%; + position: absolute; + left: 50px; + top: -2px; + background-color: #fafafa; + border: 1px solid #ccc; + border-radius: 30px; + -webkit-transition: all 0.2s ease-out; + -moz-transition: all 0.2s ease-out; + transition: all 0.2s ease-out; + } + .toggleSwitch input:checked ~ a { + border-color: #fff; + left: 100%; + margin-left: -8px; + } + .toggleSwitch input:checked ~ span:before { + border-color: #0097D1; + box-shadow: inset 0 0 0 30px #0097D1; + } + .toggleSwitch input:checked ~ span span:first-of-type { + opacity: 0; + } + .toggleSwitch input:checked ~ span span:last-of-type { + opacity: 1; + color: #fff; + } + /* Switch Sizes */ + .toggleSwitch.large { + width: 60px; + height: 27px; + } + .toggleSwitch.large a { + width: 27px; + } + .toggleSwitch.large > span { + height: 29px; + line-height: 28px; + } + .toggleSwitch.large input:checked ~ a { + left: 41px; + } + .toggleSwitch.large > span span { + font-size: 1.1em; + } + .toggleSwitch.large > span span:first-of-type { + left: 50%; + } + .toggleSwitch.xlarge { + width: 80px; + height: 36px; + } + .toggleSwitch.xlarge a { + width: 36px; + } + .toggleSwitch.xlarge > span { + height: 38px; + line-height: 37px; + } + .toggleSwitch.xlarge input:checked ~ a { + left: 52px; + } + .toggleSwitch.xlarge > span span { + font-size: 1.4em; + } + .toggleSwitch.xlarge > span span:first-of-type { + left: 50%; + } +} + + +/* End Toggle Switch */ diff --git a/rooter/ext-rooter-basic/files/www/luci-static/resources/icons/lock1.png b/rooter/ext-rooter-basic/files/www/luci-static/resources/icons/lock1.png new file mode 100644 index 0000000..0e650f3 Binary files /dev/null and b/rooter/ext-rooter-basic/files/www/luci-static/resources/icons/lock1.png differ diff --git a/rooter/ext-rooter-basic/files/www/luci-static/resources/icons/unlock1.png b/rooter/ext-rooter-basic/files/www/luci-static/resources/icons/unlock1.png new file mode 100644 index 0000000..0839da5 Binary files /dev/null and b/rooter/ext-rooter-basic/files/www/luci-static/resources/icons/unlock1.png differ diff --git a/rooter/ext-rooter-basic/files/www/luci-static/resources/img/header.png b/rooter/ext-rooter-basic/files/www/luci-static/resources/img/header.png new file mode 100644 index 0000000..aec18a2 Binary files /dev/null and b/rooter/ext-rooter-basic/files/www/luci-static/resources/img/header.png differ diff --git a/rooter/ext-rooter-basic/files/www/luci-static/resources/img/rooter.png b/rooter/ext-rooter-basic/files/www/luci-static/resources/img/rooter.png new file mode 100644 index 0000000..630f30d Binary files /dev/null and b/rooter/ext-rooter-basic/files/www/luci-static/resources/img/rooter.png differ diff --git a/rooter/ext-rooter-basic/files/www/luci-static/resources/img/rosy.png b/rooter/ext-rooter-basic/files/www/luci-static/resources/img/rosy.png new file mode 100644 index 0000000..44c71ce Binary files /dev/null and b/rooter/ext-rooter-basic/files/www/luci-static/resources/img/rosy.png differ