OpenWrt_Luci_Lua/Mi_Lua/xiaoqiang/module/XQPortForward.lua
2015-05-09 18:48:46 +08:00

266 lines
7.3 KiB
Lua
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

module ("xiaoqiang.module.XQPortForward", package.seeall)
local XQFunction = require("xiaoqiang.common.XQFunction")
local XQConfigs = require("xiaoqiang.common.XQConfigs")
--
-- Event
--
function hookLanIPChangeEvent(ip)
if XQFunction.isStrNil(ip) then
return
end
local uci = require("luci.model.uci").cursor()
local lan = ip:gsub(".%d+$","")
uci:foreach("firewall", "redirect",
function(s)
local ftype = tonumber(s.ftype)
if ftype then
local destip = s.dest_ip
destip = lan.."."..destip:match(".(%d+)$")
uci:set("firewall", s[".name"], "dest_ip", destip)
end
end
)
uci:commit("firewall")
end
-- proto
-- 1: tcp
-- 2: udp
-- 3: tcp and udp
-- default: 1/tcp
function _protoHelper(proto)
if proto and type(proto) == "number" then
if proto == 1 then
return "tcp"
elseif proto == 2 then
return "udp"
elseif proto == 3 then
return "tcpudp"
else
return "tcp"
end
end
if proto and type("proto") == "string" then
if proto == "tcp" then
return 1
elseif proto == "udp" then
return 2
elseif proto == "tcpudp" then
return 3
else
return 1
end
end
return nil
end
function _portCheck(port)
if port and type(port) == "number" and port > 0 then
return true
else
return false
end
end
function _portRangeOverlap(port1, port2)
local LuciUtil = require("luci.util")
if port1 and port2 then
port1 = tostring(port1)
port2 = tostring(port2)
if port1 == port2 then
return false
end
local range1 = {}
local range2 = {}
if port1:match("-") then
local sp = LuciUtil.split(port1, "-")
range1["f"] = tonumber(sp[1])
range1["t"] = tonumber(sp[2])
else
range1["f"] = tonumber(port1)
range1["t"] = tonumber(port1)
end
if port2:match("-") then
local sp = LuciUtil.split(port2, "-")
range2["f"] = tonumber(sp[1])
range2["t"] = tonumber(sp[2])
else
range2["f"] = tonumber(port2)
range2["t"] = tonumber(port2)
end
if (range1.f >= range2.f and range1.f <= range2.t) or
(range1.t >= range2.f and range1.t <= range2.t) then
return true
end
end
return false
end
function _portConflictCheck(port)
local uci = require("luci.model.uci").cursor()
local result = false
uci:foreach("firewall", "redirect",
function(s)
if _portRangeOverlap(port, s.src_dport) then
result = true
end
end
)
return result
end
function moduleOn()
return #portForwards(0) > 0
end
-- status
-- 0:关闭
-- 1:开启
-- 2:冲突(DMZ功能开启NAT功能就不能开启)
function portForwardInfo()
local XQDMZModule = require("xiaoqiang.module.XQDMZModule")
local info = {}
if XQDMZModule.moduleOn() then
info["status"] = 2
else
info["status"] = moduleOn() and 1 or 0
end
return info
end
-- ftype
-- 0: all
-- 1: port
-- 2: range
function portForwards(ftype)
local uci = require("luci.model.uci").cursor()
local portforwards = {}
local forwardtype = tonumber(ftype) or 0
uci:foreach("firewall", "redirect",
function(s)
local ftype = tonumber(s.ftype)
if ftype and forwardtype == 0 or forwardtype == ftype then
local item = {}
item.name = s.name
item.destip = s.dest_ip
item.proto = _protoHelper(s.proto) or 1
if ftype == 1 then
item.srcport = tonumber(s.src_dport)
item.destport = s.dest_port
item.ftype = 1
elseif ftype == 2 then
item.ftype = 2
local portrange = {}
local LuciUtil = require("luci.util")
local sp = LuciUtil.split(s.src_dport, "-")
item.srcport = {
["f"] = tonumber(sp[1]),
["t"] = tonumber(sp[2])
}
end
table.insert(portforwards, item)
end
end
)
return portforwards
end
-- return
-- 0: 设置成功
-- 1: 参数不合法
-- 2: 端口冲突(设置的端口和已有端口有重叠)
-- 3: 功能冲突由于DMZ开启
function setPortForward(name, ip, sport, dport, proto)
if not XQFunction.isStrNil(ip) and _portCheck(tonumber(sport)) and _portCheck(tonumber(dport)) then
local uci = require("luci.model.uci").cursor()
if portForwardInfo().status == 2 then
return 3
end
if _portConflictCheck(sport) then
return 2
end
local sname = string.format("wan%srdr", tostring(sport))
local options = {
["src"] = "wan",
["src_dport"] = sport,
["proto"] = _protoHelper(tonumber(proto)) or "tcp",
["target"] = "DNAT",
["dest"] = "lan",
["dest_port"] = dport,
["dest_ip"] = ip,
["ftype"] = 1,
["name"] = name or ""
}
uci:section("firewall", "redirect", sname, options)
uci:commit("firewall")
return 0
end
return 1
end
-- return
-- 0: 设置成功
-- 1: 参数不合法
-- 2: 端口冲突(设置的端口和已有端口有重叠)
function setRangePortForward(name, ip, fport, tport, proto)
if not XQFunction.isStrNil(ip) and _portCheck(tonumber(fport)) and _portCheck(tonumber(tport)) then
if tonumber(fport) > tonumber(tport) then
return 1
end
local uci = require("luci.model.uci").cursor()
local sport = tostring(fport).."-"..tostring(tport)
if portForwardInfo().status == 2 then
return 3
end
if _portConflictCheck(sport) then
return 2
end
local sname = string.format("wan%srdr", tostring(fport))
local options = {
["src"] = "wan",
["src_dport"] = sport,
["proto"] = _protoHelper(tonumber(proto)) or "tcp",
["target"] = "DNAT",
["dest"] = "lan",
["dest_ip"] = ip,
["ftype"] = 2,
["name"] = name or ""
}
uci:section("firewall", "redirect", sname, options)
uci:commit("firewall")
return 0
end
return 1
end
function deletePortForward(port)
if _portCheck(tonumber(port)) then
local uci = require("luci.model.uci").cursor()
local sname = string.format("wan%srdr", tostring(port))
uci:delete("firewall", sname)
uci:commit("firewall")
return true
end
return false
end
function deleteAllPortForward()
local uci = require("luci.model.uci").cursor()
uci:delete_all("firewall", "redirect",
function(s)
if s.ftype then
return true
else
return false
end
end
)
uci:commit("firewall")
return true
end
function restart()
os.execute("/etc/init.d/firewall restart")
end